from typing import List, Optional
from copy import deepcopy
import basf2
import modularAnalysis as ma # type: ignore
import variables.collections as vc # type: ignore
from variables import variables as vm # type: ignore
import variables.utils as vu # type: ignore
import vertex as vtx
import pandas as pd # 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__ = [
"bhabhaISR",
]
[docs]
@fancy_validation_mode_header
class bhabhaISR(ValidationModeBaseClass):
name = "bhabhaISR"
latex_str = r"$e^+ e^- \rightarrow e^+ e^- \gamma$"
plotting_strategies = ["multi_comparison_binned"]
[docs]
def create_basf2_path(self, **kwargs):
main = basf2.Path()
# load electron candidates
ma.fillParticleList(
"e+:good",
cut="p>0.3 and thetaInCDCAcceptance and dr < 0.5 and abs(dz) < 2",
path=main,
)
# load photon candidates, as done by Alex in PERC
ma.fillParticleList(
"gamma:reco",
cut="clusterNHits >= 1.5 and abs(clusterTiming) < 200",
path=main,
)
# reconstruct gamma tag and recoil
ma.reconstructDecay("gamma:tag -> e+:good e-:good", "", path=main)
ma.reconstructRecoil("gamma:recoil -> e+:good e-:good", "", path=main)
# perform vertex fit
vtx.treeFit(
"gamma:tag",
updateAllDaughters=True,
massConstraint=[],
ipConstraint=True,
path=main,
)
# get the angle to recoil
vm.addAlias("angleToPMiss", "angleToClosestInList(gamma:recoil)")
# reconstruct beam
ma.reconstructDecay("Upsilon(4S) -> gamma:recoil gamma:reco", "", path=main)
### Variables
base_particle_vars = self.base_particle_vars
cluster_vars = self.cluster_vars
# gamma tag
daughter_vars = self.generate_variables_for_list(
"Upsilon(4S) -> [^gamma -> e+ e-] gamma",
["gamma_tag"],
False,
base_particle_vars + cluster_vars + vc.recoil_kinematics,
)
# gamma reco
vm.addAlias("beamBackgroundSuppressionScore", "extraInfo(beamBackgroundSuppression)")
vm.addAlias("fakePhotonSuppressionScore", "extraInfo(fakePhotonSuppression)")
vm.addAlias("eres", "formula((clusterE-mcE)/mcE)")
daughter_vars += self.generate_variables_for_list(
"Upsilon(4S) -> [gamma -> e+ e-] ^gamma",
["gamma_reco"],
True,
base_particle_vars
+ cluster_vars
+ [
"angleToPMiss",
"beamBackgroundSuppressionScore",
"fakePhotonSuppressionScore",
"eres",
],
)
# electrons
daughter_vars += self.generate_variables_for_list(
"Upsilon(4S) -> [gamma -> ^e+ ^e-]",
["e_p", "e_m"],
True,
base_particle_vars + cluster_vars + vc.vertex + vc.track + vc.track_hits,
)
self.variables_to_validation_ntuple(
decay_str="Upsilon(4S)",
variables=daughter_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="EResolution_ISRPhoton",
title="Energy Resolution of ISR Photon",
particle_list="Upsilon(4S)",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="gamma_reco_eres"),
label=r"$(E_{\mathrm{reco}}-E_{\mathrm{MC}})/E_{\mathrm{MC}}$",
unit="",
bins=50,
scope=(-2.0, 2.0),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="gamma_reco_isSignal == 1.0",
),
],
),
Histogram(
name="ClusterPhi_ISRPhoton",
title="Cluster Phi of ISR Photon",
particle_list="Upsilon(4S)",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="gamma_reco_clusterPhi"),
label=r"$\phi_{\mathrm{reco}}^{\gamma_{\mathrm{ISR}}}$",
unit="rad",
bins=50,
scope=(-3.1416, 3.1416),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="gamma_reco_isSignal == 1.0",
),
],
),
Histogram(
name="ClusterTheta",
title="Cluster Theta of ISR Photon",
particle_list="Upsilon(4S)",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="gamma_reco_clusterTheta"),
label="clusterTheta",
unit="rad",
bins=50,
scope=(0.0, 3.1416),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="gamma_reco_isSignal == 1.0",
),
],
),
Histogram(
name="ClusterTiming",
title="Cluster Timing",
particle_list="Upsilon(4S)",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="gamma_reco_clusterTiming"),
label="clusterTiming",
unit="ns",
bins=50,
scope=(-100, 100),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="gamma_reco_isSignal == 1.0",
),
],
),
Histogram(
name="MinC2TDist",
title="Minimum C2T Distance",
particle_list="Upsilon(4S)",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="gamma_reco_minC2TDist"),
label="minC2TDist",
unit="cm",
bins=50,
scope=(0, 250),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="gamma_reco_isSignal == 1.0",
),
],
),
Histogram(
name="ClusterE1E9",
title="Cluster E1/E9",
particle_list="Upsilon(4S)",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="gamma_reco_clusterE1E9"),
label="clusterE1E9",
unit="",
bins=50,
scope=(0, 1),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="gamma_reco_isSignal == 1.0",
),
],
),
Histogram(
name="Cluster9E21",
title="Cluster E9/E21",
particle_list="Upsilon(4S)",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="gamma_reco_clusterE9E21"),
label="cluster9E21",
unit="",
bins=50,
scope=(0, 1),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="gamma_reco_isSignal == 1.0",
),
],
),
Histogram(
name="ClusterPSDMVA",
title="Cluster PSD MVA",
particle_list="Upsilon(4S)",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="gamma_reco_clusterPulseShapeDiscriminationMVA"),
label="clusterPulseShapeDiscriminationMVA",
unit="",
bins=50,
scope=(0, 1),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="gamma_reco_isSignal == 1.0",
),
],
),
Histogram(
name="ClusterLAT",
title="Cluster LAT",
particle_list="Upsilon(4S)",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="gamma_reco_clusterLAT"),
label="clusterLAT",
unit="",
bins=50,
scope=(0, 1),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="gamma_reco_isSignal == 1.0",
),
],
),
Histogram(
name="ClusterE",
title="Cluster Energy",
particle_list="Upsilon(4S)",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="gamma_reco_clusterE"),
label="clusterE",
unit="GeV",
bins=50,
scope=(0, 2),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="gamma_reco_isSignal == 1.0",
),
],
),
Histogram(
name="ClusterNHits",
title="Cluster Number of Hits",
particle_list="Upsilon(4S)",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="gamma_reco_clusterNHits"),
label="clusterNHits",
unit="",
bins=30,
scope=(0, 30),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="gamma_reco_isSignal == 1.0",
),
],
),
Histogram(
name="ClusterReg",
title="Cluster Region",
particle_list="Upsilon(4S)",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="gamma_reco_clusterReg"),
label="clusterReg",
unit="",
bins=13,
scope=(0, 13),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="gamma_reco_isSignal == 1.0",
),
],
),
Histogram(
name="ClusterSecondMoment",
title="Cluster Second Moment",
particle_list="Upsilon(4S)",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="gamma_reco_clusterSecondMoment"),
label="clusterSecondMoment",
unit="",
bins=50,
scope=(0, 40),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="gamma_reco_isSignal == 1.0",
),
],
),
Histogram(
name="ClusterTrackMatch",
title="Cluster Track Match",
particle_list="Upsilon(4S)",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="gamma_reco_clusterTrackMatch"),
label="clusterTrackMatch",
unit="",
bins=2,
scope=(0, 1),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="gamma_reco_isSignal == 1.0",
),
],
),
Histogram(
name="ClusterZernikeMVA",
title="Cluster Zernike MVA",
particle_list="Upsilon(4S)",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="gamma_reco_clusterZernikeMVA"),
label="clusterZernikeMVA",
unit="",
bins=50,
scope=(0, 1),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="gamma_reco_isSignal == 1.0",
),
],
),
Histogram(
name="ClusterAbsZernikeMoment40",
title="Cluster Abs Zernike Moment 4 0",
particle_list="Upsilon(4S)",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="gamma_reco_clusterAbsZernikeMoment40"),
label="clusterAbsZernikeMoment40",
unit="",
bins=50,
scope=(0, 1.7),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="gamma_reco_isSignal == 1.0",
),
],
),
Histogram(
name="ClusterAbsZernikeMoment51",
title="Cluster Abs Zernike Moment 5 1",
particle_list="Upsilon(4S)",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="gamma_reco_clusterAbsZernikeMoment51"),
label="clusterAbsZernikeMoment51",
unit="",
bins=50,
scope=(0, 1.2),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="gamma_reco_isSignal == 1.0",
),
],
),
Histogram(
name="ClusterEoP",
title="Cluster E over P",
particle_list="Upsilon(4S)",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="gamma_reco_clusterEoP"),
label="clusterEoP",
unit="",
bins=50,
scope=(0, 2),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="gamma_reco_isSignal == 1.0",
),
],
),
Histogram(
name="ClusterHasFailedTiming",
title="Cluster Has Failed Timing",
particle_list="Upsilon(4S)",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="gamma_reco_clusterHasFailedTiming"),
label="clusterHasFailedTiming",
unit="",
bins=2,
scope=(0, 1),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="gamma_reco_isSignal == 1.0",
),
],
),
Histogram(
name="ClusterHasFailedErrorTiming",
title="Cluster Has Failed Error Timing",
particle_list="Upsilon(4S)",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="gamma_reco_clusterHasFailedErrorTiming"),
label="clusterHasFailedErrorTiming",
unit="",
bins=2,
scope=(0, 1),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="gamma_reco_isSignal == 1.0",
),
],
),
Histogram(
name="ClusterHasNPhotons",
title="Cluster Has N Photons",
particle_list="Upsilon(4S)",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="gamma_reco_clusterHasNPhotons"),
label="clusterHasNPhotons",
unit="",
bins=2,
scope=(0, 1),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="gamma_reco_isSignal == 1.0",
),
],
),
Histogram(
name="ClusterHasNeutralHadron",
title="Cluster Has Neutral Hadron",
particle_list="Upsilon(4S)",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="gamma_reco_clusterHasNeutralHadron"),
label="clusterHasNeutralHadron",
unit="",
bins=2,
scope=(0, 1),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="gamma_reco_isSignal == 1.0",
),
],
),
Histogram(
name="ClusterHasPulseShapeDiscrimination",
title="Cluster Has Pulse Shape Discrimination",
particle_list="Upsilon(4S)",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="gamma_reco_clusterHasPulseShapeDiscrimination"),
label="clusterHasPulseShapeDiscrimination",
unit="",
bins=2,
scope=(0, 1),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="gamma_reco_isSignal == 1.0",
),
],
),
Histogram(
name="NECLClusterTrackMatches",
title="Number of ECL Cluster Track Matches",
particle_list="Upsilon(4S)",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable="gamma_reco_nECLClusterTrackMatches"),
label="nECLClusterTrackMatches",
unit="",
bins=10,
scope=(0, 10),
),
hist_components=[
HistComponent(
label="Signal",
additional_cut_str="gamma_reco_isSignal == 1.0",
),
],
),
]
[docs]
def get_number_of_signal_for_efficiency(self, df: pd.DataFrame, particle_list: Optional[str] = None) -> float:
return df["gamma_reco_isSignal"].sum()