Source code for vibe.analysis_validation_modes.physics.btopilnu_validation_mode

from typing import List
import pandas as pd

import basf2
import modularAnalysis as ma
import vertex as vx


from vibe.core.utils.misc import fancy_validation_mode_header
from vibe.core.validation_mode import ValidationModeBaseClass
from vibe.core.helper.histogram_tools import HistVariable, Histogram, HistComponent
from vibe.core.helper.root_helper import makeROOTCompatible

__all__ = [
    "BtoPiLNuValidationMode",
]

[docs] @fancy_validation_mode_header class BtoPiLNuValidationMode(ValidationModeBaseClass): name = "BtoPiLNu" latex_str = r"$B \rightarrow \pi \ell \nu$"
[docs] def create_basf2_path(self): main_path = basf2.Path() # fsp selection electrons = ("e-:rec", "useCMSFrame(p) > 1.0 and electronID > 0.8") muons = ("mu-:rec", "useCMSFrame(p) > 1.0 and muonID > 0.8") pions = ("pi-:rec", "pionID > 0.8") ma.fillParticleLists( decayStringsWithCuts=[electrons, muons, pions], path=main_path, ) # B meson reconstruction ma.reconstructDecay( decayString="B0:e_rec -> pi-:rec e+:rec", cut="", dmID=1, path=main_path, ) ma.reconstructDecay( decayString="B0:mu_rec -> pi-:rec mu+:rec", cut="", dmID=2, path=main_path, ) # merge + MC matching + vertex ma.copyLists( outputListName="B0:sl_rec", inputListNames=["B0:e_rec", "B0:mu_rec"], path=main_path, ) ma.matchMCTruth( "B0:sl_rec", path=main_path, ) vx.treeFit("B0:sl_rec", 0.001, ipConstraint=True, path=main_path) # select signal + build ROE ma.buildRestOfEvent("B0:sl_rec", path=main_path) # define ROE mask cuts tracksCut = "abs(d0) < 10.0 and abs(z0) < 20.0" clustersCut1 = "[clusterE1E9 > 0.4 or E > 0.075] and [[E > 0.062 and abs(clusterTiming)<18 and clusterReg==1] or " clustersCut2 = ( "[E > 0.060 and abs(clusterTiming)<20 and clusterReg==2]" " or [E > 0.056 and abs(clusterTiming)<44 and clusterReg==3]]" ) clustersCut = clustersCut1 + clustersCut2 # define and append ROE masks m0 = ("m0", "", "") m1 = ("m1", tracksCut, clustersCut) ma.appendROEMasks("B0:sl_rec", [m0, m1], path=main_path) ma.buildEventShape(inputListNames=["B0:sl_rec"], path=main_path) ma.buildEventKinematics(inputListNames=["B0:sl_rec"], path=main_path) self.variables_to_validation_ntuple( decay_str="B0:sl_rec", variables=list( { "cosThetaBetweenParticleAndNominalB", "isSignalAcceptMissingNeutrino", "decayTypeRecoil", "roeCharge(m0)", "roeCharge(m1)", "roeMC_MissFlags(m0)", "roeMC_MissFlags(m1)", "weDeltae(m0, 0)", "weDeltae(m1, 0)", "weMbc(m0, 0)", "weMbc(m1, 0)", "weMissM2OverMissE(m0)", "weMissM2OverMissE(m1)", "weMissM2(m0,0)", "weMissM2(m1,0)", } ), path=main_path, ) return main_path
@property def analysis_validation_histograms(self) -> List[Histogram]: return [ Histogram( name="Mbc", title="", hist_variable=HistVariable( df_label=makeROOTCompatible(variable="weMbc(m1, 0)"), label=r"$M_{bc}$ (cleaned ROE)", unit=r"GeV/$c^2$", bins=50, scope=(5.24, 5.29), ), hist_components=[ HistComponent( label="All", ), ], ) ]
[docs] def offline_df_manipulation(self, df: pd.DataFrame) -> pd.DataFrame: df = df.sample(frac=1.0).groupby(by=["__event__"]).head(1) # Applying rand BCS offline return df
[docs] def get_number_of_signal_for_efficiency(self, df: pd.DataFrame) -> float: return df["isSignalAcceptMissingNeutrino"].sum()