Source code for vibe.analysis_validation_modes.physics.btoDstlnu_validation_mode

from typing import List, Optional
import pandas as pd

import basf2
import modularAnalysis as ma
import vertex as vx
from variables import variables as vm

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__ = [
    "BtoDstLNuValidationMode",
]

# D* are reconstructed from the slow pion
# in their decay to D pi


[docs] @fancy_validation_mode_header class BtoDstLNuValidationMode(ValidationModeBaseClass): name = "BtoDstLNu" latex_str = r"B^0 \rightarrow D^{*-} \ell \nu, D^{*-} \rightarrow \bar{D^0} \pi^+"
[docs] def create_basf2_path(self): main_path = basf2.Path() # NOTE: standard lepton/hadron cuts for semileptonic analyses, shall we loosen them ? good_track_cut = "[thetaInCDCAcceptance] and [abs(dr) < 2] and [abs(dz) < 4]" electrons = ("e-:rec", f"[{good_track_cut}] and [electronID_noTOP > 0.5]") muons = ("mu-:rec", f"[{good_track_cut}] and [muonID > 0.5]") pions = ("pi-:rec", f"[{good_track_cut}] and [pionID > 0.4]") kaons = ("K-:rec", f"[{good_track_cut}] and [kaonID > 0.4]") ma.fillParticleLists( decayStringsWithCuts=[electrons, muons, pions, kaons], path=main_path, ) # D0 reconstruction ma.reconstructDecay( decayString="D0:rec -> K-:rec pi+:rec", cut="InvM > 1.80 and InvM < 1.92", path=main_path, ) # D* reconstruction ma.reconstructDecay( decayString="D*+:D0 -> D0:rec pi+:rec", cut="massDifference(0) < 0.17", path=main_path, ) # B0 reconstruction ma.reconstructDecay( decayString="B0:e_rec -> D*-:D0 e+:rec", cut="", dmID=1, path=main_path, ) ma.reconstructDecay( decayString="B0:mu_rec -> D*-:D0 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, ) ma.buildRestOfEvent("B0:sl_rec", path=main_path) # define ROE mask cuts tracksCut = "abs(d0) < 10.0 and abs(z0) < 20.0 and thetaInCDCAcceptance" clustersCut1 = "thetaInCDCAcceptance and abs(clusterTiming) < 200 and " clustersCut2 = "[[E > 0.08 and clusterReg==1] or [E > 0.05 and clusterReg==2] or [E > 0.08 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) # save variables B_vars = [ "isSignal", "Mbc", "deltaE", "beamE", "p", "E", "mcPDG", "decayTypeRecoil", "cosThetaBetweenParticleAndNominalB", "isSignalAcceptMissingNeutrino", ("Mbc_corr_noCuts", "weMbc(m0)"), ("Mbc_corr_nominalMask", "weMbc(m1)"), ("DeltaE_corr_noCuts", "weDeltae(m0)"), ("DeltaE_corr_nominalMask", "weDeltae(m1)"), ] Dst_vars = [ ("Dst_p", "daughter(0, p)"), ("Dst_E", "daughter(0, E)"), ("Dst_M", "daughter(0, M)"), ("Dst_PDG", "daughter(0, PDG)"), ("Dst_mcPDG", "daughter(0, mcPDG)"), ] lep_vars = [ ("lep_p", "daughter(1, p)"), ("lep_E", "daughter(1, E)"), ("lep_PDG", "daughter(1, PDG)"), ("lep_mcPDG", "daughter(1, mcPDG)"), ("lep_eID", "daughter(1, electronID)"), ("lep_muID", "daughter(1, muonID)"), # leptonic system variables ("q2_noCuts", "weQ2lnuSimple(m0, 0)"), ("q2_nominalMask", "weQ2lnuSimple(m1, 0)"), ] ROE_vars = [ ("MM2_noCuts", "weMissM2(m0, 0)"), ("MM2_nominalMask", "weMissM2(m1, 0)"), ("ROE_Q_noCuts", "roeCharge(m0)"), ("ROE_Q_nominalMask", "roeCharge(m1)"), ] pion_vars = [("pion_pionID", "daughter(0, daughter(0, pionID))")] list_vars_alias = [] list_vars = B_vars + Dst_vars + lep_vars + ROE_vars + pion_vars for var in list_vars: if type(var) == tuple: alias, name = var vm.addAlias(alias, name) list_vars_alias.append(alias) else: list_vars_alias.append(var) self.variables_to_validation_ntuple( decay_str="B0:sl_rec", variables=list_vars_alias, path=main_path, ) return main_path
@property def analysis_validation_histograms(self) -> List[Histogram]: return [ Histogram( name="Mbc", title=r"$B \rightarrow D^* \ell \nu$", hist_variable=HistVariable( df_label=makeROOTCompatible(variable="Mbc"), label=r"$M_{bc}$", unit=r"GeV", bins=50, scope=(5.24, 5.29), ), hist_components=[ HistComponent( label="Signal", additional_cut_str="isSignalAcceptMissingNeutrino == 1", color="purple", ), HistComponent( label="Background", additional_cut_str="isSignalAcceptMissingNeutrino != 1", color="cyan", ), ], ), Histogram( name="Mbc_corr_noCuts", title=r"$B \rightarrow D^* \ell \nu$", hist_variable=HistVariable( df_label=makeROOTCompatible(variable="Mbc_corr_noCuts"), label=r"$M_{bc} corrected$", unit=r"GeV", bins=50, scope=(5.24, 5.29), ), hist_components=[ HistComponent( label="Signal", additional_cut_str="isSignalAcceptMissingNeutrino == 1", color="purple", ), HistComponent( label="Background", additional_cut_str="isSignalAcceptMissingNeutrino != 1", color="cyan", ), ], ), Histogram( name="Mbc_corr_nominalMask", title=r"$B \rightarrow D^* \ell \nu$", hist_variable=HistVariable( df_label=makeROOTCompatible(variable="Mbc_corr_nominalMask"), label=r"$M_{bc} corrected, cleaned ROE$", unit=r"GeV", bins=50, scope=(5.24, 5.29), ), hist_components=[ HistComponent( label="Signal", additional_cut_str="isSignalAcceptMissingNeutrino == 1", color="purple", ), HistComponent( label="Background", additional_cut_str="isSignalAcceptMissingNeutrino != 1", color="cyan", ), ], ), Histogram( name="deltaE", title=r"$B \rightarrow D^* \ell \nu$", hist_variable=HistVariable( df_label=makeROOTCompatible(variable="deltaE"), label=r"$\Delta E$", unit=r"GeV", bins=100, scope=(-0.2, 0.2), ), hist_components=[ HistComponent( label="Signal", additional_cut_str="isSignalAcceptMissingNeutrino == 1", color="purple", ), HistComponent( label="Background", additional_cut_str="isSignalAcceptMissingNeutrino != 1", color="cyan", ), ], ), Histogram( name="DeltaE_corr_noCuts", title=r"$B \rightarrow D^* \ell \nu$", hist_variable=HistVariable( df_label=makeROOTCompatible(variable="DeltaE_corr_noCuts"), label=r"$\Delta E corrected$", unit=r"GeV", bins=100, scope=(-0.2, 0.2), ), hist_components=[ HistComponent( label="Signal", additional_cut_str="isSignalAcceptMissingNeutrino == 1", color="purple", ), HistComponent( label="Background", additional_cut_str="isSignalAcceptMissingNeutrino != 1", color="cyan", ), ], ), Histogram( name="DeltaE_corr_nominalMask", title=r"$B \rightarrow D^* \ell \nu$", hist_variable=HistVariable( df_label=makeROOTCompatible(variable="DeltaE_corr_nominalMask"), label=r"$\Delta E corrected, cleaned ROE$", unit=r"GeV", bins=100, scope=(-0.2, 0.2), ), hist_components=[ HistComponent( label="Signal", additional_cut_str="isSignalAcceptMissingNeutrino == 1", color="purple", ), HistComponent( label="Background", additional_cut_str="isSignalAcceptMissingNeutrino != 1", color="cyan", ), ], ), Histogram( name="lep_p", title=r"$B \rightarrow D^* \ell \nu$", hist_variable=HistVariable( df_label=makeROOTCompatible(variable="lep_p"), label=r"$p_{\ell}$", unit="GeV", bins=100, scope=(0.5, 4), ), hist_components=[ HistComponent( label="Signal", additional_cut_str="isSignalAcceptMissingNeutrino == 1", color="purple", ), HistComponent( label="Background", additional_cut_str="isSignalAcceptMissingNeutrino != 1", color="cyan", ), ], ), Histogram( name="q2_noCuts", title=r"$B \rightarrow D^* \ell \nu$", hist_variable=HistVariable( df_label=makeROOTCompatible(variable="q2_noCuts"), label=r"$q^2$ no cuts", unit=r"Gev$^2$", bins=100, scope=(0, 25), ), hist_components=[ HistComponent( label="Signal", additional_cut_str="isSignalAcceptMissingNeutrino == 1", color="purple", ), HistComponent( label="Background", additional_cut_str="isSignalAcceptMissingNeutrino != 1", color="cyan", ), ], ), Histogram( name="q2_nominalMask", title=r"$B \rightarrow D^* \ell \nu$", hist_variable=HistVariable( df_label=makeROOTCompatible(variable="q2_nominalMask"), label=r"$q^2$ cleaned ROE", unit=r"Gev$^2$", bins=100, scope=(0, 25), ), hist_components=[ HistComponent( label="Signal", additional_cut_str="isSignalAcceptMissingNeutrino == 1", color="purple", ), HistComponent( label="Background", additional_cut_str="isSignalAcceptMissingNeutrino != 1", color="cyan", ), ], ), Histogram( name="MM2_noCuts", title=r"$B \rightarrow D^* \ell \nu$", hist_variable=HistVariable( df_label=makeROOTCompatible(variable="MM2_noCuts"), label=r"$MM^2$ no cuts", unit=r"Gev$^2$", bins=100, scope=(-5, 15), ), hist_components=[ HistComponent( label="Signal", additional_cut_str="isSignalAcceptMissingNeutrino == 1", color="purple", ), HistComponent( label="Background", additional_cut_str="isSignalAcceptMissingNeutrino != 1", color="cyan", ), ], ), Histogram( name="MM2_nominalMask", title=r"$B \rightarrow D^* \ell \nu$", hist_variable=HistVariable( df_label=makeROOTCompatible(variable="MM2_nominalMask"), label=r"$MM^2$ cleaned ROE", unit=r"Gev$^2$", bins=100, scope=(-5, 15), ), hist_components=[ HistComponent( label="Signal", additional_cut_str="isSignalAcceptMissingNeutrino == 1", color="purple", ), HistComponent( label="Background", additional_cut_str="isSignalAcceptMissingNeutrino != 1", color="cyan", ), ], ), Histogram( name="ROE_Q_noCuts", title=r"$B \rightarrow D^* \ell \nu$", hist_variable=HistVariable( df_label=makeROOTCompatible(variable="ROE_Q_noCuts"), label=r"$Q_{\mathrm{ROE}} no cuts$", unit="", bins=5, scope=(-2.5, 2.5), ), hist_components=[ HistComponent( label="Signal", additional_cut_str="isSignalAcceptMissingNeutrino == 1", color="purple", ), HistComponent( label="Background", additional_cut_str="isSignalAcceptMissingNeutrino != 1", color="cyan", ), ], ), Histogram( name="ROE_Q_nominalMask", title=r"$B \rightarrow D^* \ell \nu$", hist_variable=HistVariable( df_label=makeROOTCompatible(variable="ROE_Q_nominalMask"), label=r"$Q_{\mathrm{ROE}} cleaned ROE$", unit="", bins=5, scope=(-2.5, 2.5), ), hist_components=[ HistComponent( label="Signal", additional_cut_str="isSignalAcceptMissingNeutrino == 1", color="purple", ), HistComponent( label="Background", additional_cut_str="isSignalAcceptMissingNeutrino != 1", color="cyan", ), ], ), ]
[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, particle_list: Optional[str] = None) -> float: return df["isSignalAcceptMissingNeutrino"].sum()