from typing import List
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()
# 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.6")
ma.fillParticleLists(
decayStringsWithCuts=[electrons, muons, pions],
path=main_path,
)
ma.addInclusiveDstarReconstruction(
DstarCut="M > 1.96 and M < 2.06",
decayString="D*+:pi -> pi+:rec",
slowPionCut="",
path=main_path,
)
# B0 reconstruction
ma.reconstructDecay(
decayString="B0:e_rec -> D*-:pi e+:rec",
cut="",
dmID=1,
path=main_path,
)
ma.reconstructDecay(
decayString="B0:mu_rec -> D*-:pi 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"
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)
# save variables
B_vars = [
"isSignal",
"Mbc",
"deltaE",
"beamE",
"p",
"E",
"mcPDG",
"decayTypeRecoil",
"cosThetaBetweenParticleAndNominalB",
"isSignalAcceptMissingNeutrino",
("Mbc_corr_noCuts", "weMbc(m0, 0)"),
("Mbc_corr_nominalMask", "weMbc(m1, 0)"),
("DeltaE_corr_noCuts", "weDeltae(m0, 0)"),
("DeltaE_corr_nominalMask", "weDeltae(m1, 0)"),
]
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, 10),
),
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) -> float:
return df["isSignalAcceptMissingNeutrino"].sum()