from typing import List
import pandas as pd
import basf2
import modularAnalysis as ma
import vertex as vx
import variables.utils as vu
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__ = [
"BtoJpsiKJpsitoeeValidationMode",
]
[docs]
@fancy_validation_mode_header
class BtoJpsiKJpsitoeeValidationMode(ValidationModeBaseClass):
name = "BtoJpsiKJpsitoee"
latex_str = r"$B^{+} \rightarrow J/\psi K^{+}, J/\psi \rightarrow e^{+} e^{-}$"
[docs]
def create_basf2_path(self):
main_path = basf2.Path()
# fsp selection
electrons = ("e+:unrec", "abs(dz) < 4.0 and dr < 2.0 and electronID > 0.5")
kaons = ("K+:rec", "abs(dz) < 4.0 and dr < 2.0 and kaonID > 0.2")
gammas = ("gamma:bremsinput", "E < 1.0")
ma.fillParticleLists(
decayStringsWithCuts=[electrons, kaons, gammas],
path=main_path,
)
ma.correctBrems(
outputList="e+:rec",
inputList="e+:unrec",
gammaList="gamma:bremsinput",
path=main_path,
)
# J/psi reconstruction
ma.reconstructDecay(
decayString="J/psi:e_rec -> e+:rec e-:rec",
cut="2.92 < M < 3.22",
path=main_path,
)
# B+ reconstruction
ma.reconstructDecay(
decayString="B+:rec -> J/psi:e_rec K+:rec",
cut="",
path=main_path,
)
# MC matching + vertex + kinematic cuts
ma.matchMCTruth(
"B+:rec",
path=main_path,
)
vx.treeFit("B+:rec", conf_level=0.00, massConstraint=["J/psi"], path=main_path)
ma.applyCuts("B+:rec", "Mbc>5.24 and abs(deltaE)<0.2", path=main_path)
Bp_vars = ["Mbc", "deltaE", "chiProb", "isSignal", "isSignalAcceptBremsPhotons"]
Jpsi_vars = vu.create_aliases_for_selected(
list_of_variables=["InvM", "M"], decay_string="B+ -> ^J/psi K+", prefix="jpsi"
)
self.variables_to_validation_ntuple(
decay_str="B+:rec",
variables=Bp_vars + Jpsi_vars,
path=main_path,
)
return main_path
@property
def analysis_validation_histograms(self) -> List[Histogram]:
return [
Histogram(
name="Mbc",
title=r"$B^{+} \rightarrow J/\psi K^{+}, J/\psi \rightarrow e^{+} e^{-}$",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="Mbc"),
label=r"$M_{bc}$",
unit=r"GeV/$c^2$",
bins=50,
scope=(5.24, 5.29),
),
hist_components=[
HistComponent(
label="All",
),
],
),
Histogram(
name="Mbc_matched",
title=r"$B^{+} \rightarrow J/\psi K^{+}, J/\psi \rightarrow e^{+} e^{-}$",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="Mbc"),
label=r"$M_{bc}$",
unit=r"GeV/$c^2$",
bins=50,
scope=(5.24, 5.29),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="isSignal == 1",
color="purple",
),
HistComponent(
label="Background",
additional_cut_str="isSignal != 1",
color="cyan",
),
],
),
Histogram(
name="deltaE",
title=r"$B^{+} \rightarrow J/\psi K^{+}, J/\psi \rightarrow e^{+} e^{-}$",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="deltaE"),
label=r"$\Delta(E)$",
unit=r"GeV",
bins=100,
scope=(-0.1, 0.1),
),
hist_components=[
HistComponent(
label="All",
),
],
),
Histogram(
name="deltaE_matched",
title=r"$B^{+} \rightarrow J/\psi K^{+}, J/\psi \rightarrow e^{+} e^{-}$",
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="isSignal == 1",
color="purple",
),
HistComponent(
label="Background",
additional_cut_str="isSignal != 1",
color="cyan",
),
],
),
Histogram(
name="mJpsi",
title=r"$B^{+} \rightarrow J/\psi K^{+}, J/\psi \rightarrow e^{+} e^{-}$",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="jpsi_M"),
label=r"$M(e^{+}e^{-})$",
unit=r"GeV",
bins=120,
scope=(2.96, 3.2),
),
hist_components=[
HistComponent(
label="All",
),
],
),
Histogram(
name="mJpsi_matched",
title=r"$B^{+} \rightarrow J/\psi K^{+}, J/\psi \rightarrow e^{+} e^{-}$",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="jpsi_M"),
label=r"$M(e^{+}e^{-})$",
unit=r"GeV",
bins=120,
scope=(2.96, 3.2),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="isSignal == 1",
color="purple",
),
HistComponent(
label="Background",
additional_cut_str="isSignal != 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["isSignal"].sum()