from typing import List
from copy import deepcopy
import basf2
import kinfit # type: ignore
import modularAnalysis as ma # type: ignore
import variables.collections as vc # type: ignore
from stdPhotons import stdPhotons # type: ignore
import stdV0s # type: ignore
from variables import variables as vm # type: ignore
import variables.utils as vu # type: ignore
import pdg # type: ignore
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__ = [
"K0K0bar",
]
[docs]
@fancy_validation_mode_header
class K0K0bar(ValidationModeBaseClass):
name = "K0K0bar"
latex_str = r"$e^+ e^- \rightarrow K_S^0 K_L^0 \gamma$"
plotting_strategies = ["multi_comparison_binned"]
[docs]
def create_basf2_path(self, **kwargs):
main = basf2.Path()
# Fill ISR photon list
stdPhotons(
listtype="all",
beamBackgroundMVAWeight="MC15rd",
fakePhotonMVAWeight="MC15rd",
path=main,
)
ma.cutAndCopyList(
outputListName="gamma:ISR",
inputListName="gamma:all",
cut=("clusterNHits >= 1.5 and " "abs(clusterTiming) < 400 and " "thetaInCDCAcceptance and " "E > 1"),
path=main,
)
vm.addAlias("beamBackgroundSuppressionScore", "extraInfo(beamBackgroundSuppression)")
vm.addAlias("fakePhotonSuppressionScore", "extraInfo(fakePhotonSuppression)")
# Fill Kshort list
stdV0s.stdKshorts(path=main)
# Apply tighter selection on the Kshorts
ma.cutAndCopyList("K_S0:tight", "K_S0:merged", "M > 0.48 and M < 0.52", path=main)
# Fill Klong from ECL objects
ma.fillParticleList("gamma:K_0L", "", path=main)
# reconstruct tag
ma.reconstructDecay("vpho:tag -> gamma:ISR K_S0:tight", cut="", path=main)
# reconstruct beam
ma.reconstructDecay("Upsilon(4S):pseudo_tight -> vpho:tag gamma:K_0L", cut="", path=main)
kinfit.fitKinematic4C(
"Upsilon(4S):pseudo_tight",
daughtersUpdate=True,
path=main,
decayStringForAlternateMassParticles="Upsilon(4S):pseudo_tight -> vpho:tag ^gamma:K_0L",
alternateMassHypos=[310],
)
# Reconstruct the K_L0 recoil
ma.reconstructRecoil("K_L0:recoil -> gamma:ISR K_S0:tight", cut="M > 0.3", path=main)
# keep only the K_L0 recoil closest to the KLong mass
ma.rankByLowest(
"K_L0:recoil",
f"abs(M-{pdg.get(130).Mass()})",
outputVariable="recoil_m_diff_rank",
path=main,
)
ma.cutAndCopyList(
"K_L0:best_recoil",
"K_L0:recoil",
cut="extraInfo(recoil_m_diff_rank) == 1",
path=main,
)
# get the best reco candidate by smallest angle to recoil K_L0
vm.addAlias("angleToPMiss", "angleToClosestInList(K_L0:best_recoil)")
# reconstruct beam object from reconstructed K_L0 and the tag K_L0
ma.reconstructDecay("Upsilon(4S):final -> gamma:K_0L K_L0:best_recoil", cut="", path=main)
ma.matchMCTruth(list_name="Upsilon(4S):final", path=main)
### Variables
base_particle_vars = self.base_particle_vars
cluster_vars = self.cluster_vars
# gamma
daughter_vars = self.generate_variables_for_list(
"Upsilon(4S):final -> gamma:K_0L [K_L0:best_recoil -> ^gamma:ISR K_S0:tight]",
["ISR"],
True,
base_particle_vars + cluster_vars + ["beamBackgroundSuppressionScore", "fakePhotonSuppressionScore"],
)
# K short
daughter_vars += self.generate_variables_for_list(
"Upsilon(4S):final -> gamma:K_0L [K_L0:best_recoil -> gamma:ISR ^K_S0:tight]",
["K_S0"],
True,
base_particle_vars + cluster_vars + vc.vertex,
)
# pis from K short
daughter_vars += self.generate_variables_for_list(
"Upsilon(4S):final -> gamma:K_0L [K_L0:best_recoil -> gamma:ISR [K_S0:tight -> ^pi+ ^pi-]]",
["pi_p", "pi_m"],
True,
base_particle_vars + cluster_vars + vc.vertex,
)
# K_L0 reco
daughter_vars += self.generate_variables_for_list(
"Upsilon(4S):final -> ^gamma:K_0L [K_L0:best_recoil -> gamma:ISR K_S0:tight]",
["K_L0_reco"],
True,
base_particle_vars
+ cluster_vars
+ vc.klm_cluster
+ ["particleSource", "angleToPMiss", "klmClusterTrackDistance", "isSignal"],
)
# K_L0 tag
daughter_vars += self.generate_variables_for_list(
"Upsilon(4S):final -> gamma:K_0L [^K_L0:best_recoil -> gamma:ISR K_S0:tight]",
["K_L0_tag"],
False,
base_particle_vars + vc.recoil_kinematics + ["chiProb"],
)
# beam
daughter_vars += self.generate_variables_for_list(
"^Upsilon(4S):final -> gamma:K_0L [K_L0:best_recoil -> gamma:ISR K_S0:tight]",
["beam"],
True,
base_particle_vars + vc.vertex,
)
photon_vars = self.generate_variables_for_list(
"^gamma:all",
names=["gamma"],
add_mc_matching=True,
variables=base_particle_vars
+ cluster_vars
+ vc.vertex
+ [
"beamBackgroundSuppressionScore",
"fakePhotonSuppressionScore",
],
)
self.variables_to_validation_ntuple(
decay_str="Upsilon(4S):final",
variables=daughter_vars,
path=main,
)
self.variables_to_validation_ntuple(
decay_str="gamma:all",
variables=photon_vars,
path=main,
)
return main
@property
def base_particle_vars(self):
return vc.kinematics + vc.inv_mass + vc.momentum_uncertainty + vc.pid
@property
def cluster_vars(self):
return vc.cluster + [
"clusterE",
"clusterUncorrE",
"clusterThetaID",
"clusterMdstIndex",
"clusterCellID",
"clusterSecondMoment",
"clusterTrackMatch",
]
[docs]
def generate_variables_for_list(
self,
particle_list: str,
names: List[str],
add_mc_matching: bool,
variables: List[str],
):
variables_to_store = deepcopy(variables)
if add_mc_matching:
variables_to_store += vc.mc_truth + vc.mc_kinematics + vc.mc_variables
return vu.create_aliases_for_selected(variables_to_store, particle_list, names)
@property
def analysis_validation_histograms(self) -> List[Histogram]:
return [
Histogram(
name="ClusterPhi_K0L",
title="Cluster Phi of Reconstructed K0L",
particle_list="Upsilon(4S):final",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="K_L0_reco_clusterPhi"),
label=r"$\phi_{\mathrm{reco}}^{K_L^0}$",
unit="rad",
bins=50,
scope=(-3.1416, 3.1416),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="K_L0_reco_isSignal == 1.0",
),
],
),
Histogram(
name="ClusterTheta_K0L",
title="Cluster Theta of Reconstructed K0L",
particle_list="Upsilon(4S):final",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="K_L0_reco_clusterTheta"),
label=r"$\theta_{\mathrm{reco}}^{K_L^0}$",
unit="rad",
bins=50,
scope=(0.0, 3.1416),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="K_L0_reco_isSignal == 1.0",
),
],
),
Histogram(
name="ClusterTiming_K0L",
title="Cluster Timing of Reconstructed K0L",
particle_list="Upsilon(4S):final",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="K_L0_reco_clusterTiming"),
label="clusterTiming",
unit="ns",
bins=50,
scope=(-100, 100),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="K_L0_reco_isSignal == 1.0",
),
],
),
Histogram(
name="ClusterE_K0L",
title="Cluster Energy of Reconstructed K0L",
particle_list="Upsilon(4S):final",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="K_L0_reco_clusterE"),
label="clusterE",
unit="GeV",
bins=50,
scope=(0, 2),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="K_L0_reco_isSignal == 1.0",
),
],
),
Histogram(
name="ClusterNHits_K0L",
title="Cluster Number of Hits of Reconstructed K0L",
particle_list="Upsilon(4S):final",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="K_L0_reco_clusterNHits"),
label="clusterNHits",
unit="",
bins=30,
scope=(0, 30),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="K_L0_reco_isSignal == 1.0",
),
],
),
Histogram(
name="ClusterReg_K0L",
title="Cluster Region of Reconstructed K0L",
particle_list="Upsilon(4S):final",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="K_L0_reco_clusterReg"),
label="clusterReg",
unit="",
bins=13,
scope=(0, 13),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="K_L0_reco_isSignal == 1.0",
),
],
),
Histogram(
name="ClusterHasFailedTiming_K0L",
title="Cluster Has Failed Timing of Reconstructed K0L",
particle_list="Upsilon(4S):final",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="K_L0_reco_clusterHasFailedTiming"),
label="clusterHasFailedTiming",
unit="",
bins=2,
scope=(0, 1),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="K_L0_reco_isSignal == 1.0",
),
],
),
Histogram(
name="ClusterHasFailedErrorTiming_K0L",
title="Cluster Has Failed Error Timing of Reconstructed K0L",
particle_list="Upsilon(4S):final",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="K_L0_reco_clusterHasFailedErrorTiming"),
label="clusterHasFailedErrorTiming",
unit="",
bins=2,
scope=(0, 1),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="K_L0_reco_isSignal == 1.0",
),
],
),
Histogram(
name="ClusterHasNPhotons_K0L",
title="Cluster Has N Photons of Reconstructed K0L",
particle_list="Upsilon(4S):final",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="K_L0_reco_clusterHasNPhotons"),
label="clusterHasNPhotons",
unit="",
bins=2,
scope=(0, 1),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="K_L0_reco_isSignal == 1.0",
),
],
),
Histogram(
name="ClusterHasNeutralHadron_K0L",
title="Cluster Has Neutral Hadron of Reconstructed K0L",
particle_list="Upsilon(4S):final",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="K_L0_reco_clusterHasNeutralHadron"),
label="clusterHasNeutralHadron",
unit="",
bins=2,
scope=(0, 1),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="K_L0_reco_isSignal == 1.0",
),
],
),
Histogram(
name="ClusterHasPulseShapeDiscrimination_K0L",
title="Cluster Has Pulse Shape Discrimination of Reconstructed K0L",
particle_list="Upsilon(4S):final",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="K_L0_reco_clusterHasPulseShapeDiscrimination"),
label="clusterHasPulseShapeDiscrimination",
unit="",
bins=2,
scope=(0, 1),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="K_L0_reco_isSignal == 1.0",
),
],
),
Histogram(
name="NECLClusterTrackMatches_K0L",
title="Number of ECL Cluster Track Matches of Reconstructed K0L",
particle_list="Upsilon(4S):final",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="K_L0_reco_nECLClusterTrackMatches"),
label="nECLClusterTrackMatches",
unit="",
bins=10,
scope=(0, 10),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="K_L0_reco_isSignal == 1.0",
),
],
),
]