from typing import List
import basf2
import modularAnalysis as ma
import variables.collections as vc
import variables.utils as vu
import variables as va
from stdV0s import stdKshorts
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__ = [
"DtoKsPiPiSystValidationMode",
]
[docs]
@fancy_validation_mode_header
class DtoKsPiPiSystValidationMode(ValidationModeBaseClass):
name = "DtoKsPiPiSyst"
latex_str = r"$D^{*+}\rightarrow (D^0 \rightarrow K_S^0 \pi^+ \pi^-) \pi^+$"
[docs]
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.h_1D_hist_list = [
("ks_goodBelleKshort", 2, -0.5, 1.5, "", "$\\text{Good}\\ K_S$"),
("ks_chiProb", 250, 0, 1, "", "$K_S\\ \\text{Fit Quality}$"),
("ks_p", 125, 0, 5, "GeV", "$K_S\\ p$"),
("ks_theta", 180, 0, 3.141593, "Rad", "$K_S\\ \\theta$"),
("ks_phi", 90, -3.141593, 3.141593, "Rad", "$K_S\\ \\phi$"),
("ks_dr", 150, 0, 30, "cm", "$K_S\\ dr$"),
("ks_dz", 250, -25, 25, "cm", "$K_S\\ dz$"),
("ks_InvM", 180, 0.48, 0.516, "GeV", "${K_S}\\ \\text{Invariant Mass}$"),
("ks_dphi", 90, -3.141593, 3.141593, "Rad", "$K_S\\ \\Delta \\phi$"),
("ks_flightTime", 250, -0.25, 1, "ns", "$K_S\\ t_{flight}$"),
("ks_flightDistance", 250, -20, 50, "cm", "$K_S\\ d_{flight}$"),
("ks_cosAngleBetweenMomentumAndVertexVectorInXYPlane", 100, -1, 1, "", "$\\cos\\theta_{XY}$"),
("ks_particleSource", 7, -0.5, 6.5, "", "$K_S\\ \\text{Particle Source}$"),
("ks_significanceOfDistance", 125, 0, 1000, "", "$K_S\\ \\text{Distance Significance}$"),
("t0_nCDCHits", 141, -0.5, 140, "", "$K_s\\ \\text{daughter}_0\\ \\text{CDC hits}$"),
("t0_nPXDHits", 5, -0.5, 4.5, "", "$K_s\\ \\text{daughter}_0\\ \\text{PXD hits}$"),
("t0_nSVDHits", 21, -0.5, 20.5, "", "$K_s\\ \\text{daughter}_0\\ \\text{SVD hits}$"),
("t0_theta", 180, 0, 3.141593, "Rad", "$K_s\\ \\text{daughter}_0\\ \\theta$"),
("t1_nCDCHits", 141, -0.5, 140, "", "$K_s\\ \\text{daughter}_1\\ \\text{CDC hits}$"),
("t1_nPXDHits", 5, -0.5, 4.5, "", "$K_s\\ \\text{daughter}_1\\ \\text{PXD hits}$"),
("t1_nSVDHits", 21, -0.5, 20.5, "", "$K_s\\ \\text{daughter}_1\\ \\text{SVD hits}$"),
("t1_theta", 180, 0, 3.141593, "Rad", "$K_s\\ \\text{daughter}_1\\ \\theta$"),
("pi_s_p", 120, 0, 0.6, "GeV", "$\\pi_s\\ p$"),
("pi_s_theta", 90, 0, 3.141593, "Rad", "$\\pi_s\\ \\theta$"),
("pi_s_phi", 90, -3.141593, 3.141593, "Rad", "$\\pi_s\\ \\phi$"),
]
[docs]
def create_basf2_path(self, is_data=0):
main_path = basf2.Path()
ma.fillParticleList("pi+:D0", "abs(dr) < 2 and abs(dz) < 4 and pt > 0.1", path=main_path)
ma.fillParticleList("pi+:slow", "abs(dr) < 2 and abs(dz) < 4", path=main_path)
stdKshorts(prioritiseV0=True, fitter="TreeFit", updateAllDaughters=True, path=main_path)
ma.applyCuts("K_S0:merged", "0.480 < M < 0.516", path=main_path)
ma.reconstructDecay("D0:Kspipi -> K_S0:merged pi+:D0 pi-:D0", "1.82 < M < 1.91", path=main_path)
ma.reconstructDecay(
"D*+:Dpi -> D0:Kspipi pi+:slow", "0.144 < massDifference(0) < 0.147 and useCMSFrame(p) > 1.6", path=main_path
)
if not is_data:
ma.matchMCTruth("D*+:Dpi", path=main_path)
# aliases
va.variables.addAlias("p_cm", "useCMSFrame(p)")
va.variables.addAlias("E_cm", "useCMSFrame(E)")
va.variables.addAlias("theta_cm", "useCMSFrame(theta)")
va.variables.addAlias("deltaM", "massDifference(0)")
va.variables.addAlias("motherPDG", "genMotherPDG(0)")
va.variables.addAlias("grandmotherPDG", "genMotherPDG(1)")
va.variables.addAlias("unqId", "formula(runNum+evtNum*10000)")
va.variables.addAlias("pointAngle", "daughter(0,pointingAngle(0))")
va.variables.addAlias("V0d0_0", "V0d0(0)")
va.variables.addAlias("V0d0_1", "V0d0(1)")
va.variables.addAlias("V0z0_0", "V0z0(0)")
va.variables.addAlias("V0z0_1", "V0z0(1)")
va.variables.addAlias("ancDz", "hasAncestor(421)")
va.variables.addAlias("ancDstp", "hasAncestor(413)")
va.variables.addAlias("hlt_hadron", "SoftwareTriggerResult(software_trigger_cut&skim&accept_hadron)")
va.variables.addAlias("nCleanedTracks", "nCleanedTracks(abs(dr) < 2 and abs(dz) < 4)")
va.variables.addAlias("deltaM_dist", "abs(deltaM-0.1455)")
va.variables.addAlias("deltaM_rank", "extraInfo(deltaM_rank)")
ma.rankByLowest(particleList="D*+:Dpi", variable="deltaM_dist", outputVariable="deltaM_rank", path=main_path)
# variables
part_vars = ["charge"]
v0_mc = []
if not is_data:
part_vars += ["motherPDG", "grandmotherPDG", "mcPDG", "mcErrors", "isSignal"]
v0_mc += ["mcSecPhysProc"]
kin_vars = ["p", "p_cm", "px", "py", "pz", "E", "E_cm", "theta", "theta_cm", "phi", "InvM", "M"]
track_vars = (
["d0", "z0", "dr", "dz"] + vc.track_hits + ["firstPXDLayer", "firstSVDLayer", "firstCDCLayer"] + kin_vars
)
v0_vars = (
part_vars
+ kin_vars
+ v0_mc
+ [
"dr",
"ancDz",
"ancDstp",
"cosAngleBetweenMomentumAndVertexVector",
"cosAngleBetweenMomentumAndVertexVectorInXYPlane",
"V0Deltad0",
"V0Deltaz0",
"particleSource",
"isFromV0",
"V0d0_0",
"V0d0_1",
"V0z0_0",
"V0z0_1",
"goodBelleKshort",
]
+ vc.vertex
+ vc.flight_info
)
if not is_data:
v0_vars += vc.mc_vertex + vc.mc_kinematics
bg_vars = [
"nECLOutOfTimeCrystals",
"nECLOutOfTimeCrystalsBWDEndcap",
"nECLOutOfTimeCrystalsFWDEndcap",
"nECLOutOfTimeCrystalsBarrel",
"nExtraCDCHitsPostCleaning",
"nExtraCDCHits",
"nExtraCDCSegments",
"timeSinceLastInjectionSignalMicroSeconds",
"timeSinceLastInjectionSignalClockTicks",
"hasRecentInjection",
"injectionInHER",
"isPoissonTriggerInInjectionVeto",
"hasRecentInjection",
"injectionInHER",
]
dstar_vars = (
part_vars
+ kin_vars
+ ["deltaM", "unqId", "pointAngle", "hlt_hadron", "deltaM_rank"]
+ ["nTracks", "nCleanedTracks"]
+ vu.create_daughter_aliases(v0_vars, [0, 0], prefix="ks", include_indices=False)
+ vu.create_daughter_aliases(track_vars, [0, 1], prefix="pi_1", include_indices=False)
+ vu.create_daughter_aliases(track_vars, [0, 2], prefix="pi_2", include_indices=False)
+ vu.create_daughter_aliases(part_vars + kin_vars, 0, prefix="dz", include_indices=False)
+ vu.create_daughter_aliases(track_vars, 1, prefix="pi_s", include_indices=False)
+ vu.create_daughter_aliases(kin_vars, 0, prefix="d", include_indices=False)
+ vu.create_daughter_aliases(track_vars + ["phi", "charge"], [0, 0, 0], prefix="t0", include_indices=False)
+ vu.create_daughter_aliases(track_vars + ["phi", "charge"], [0, 0, 1], prefix="t1", include_indices=False)
+ bg_vars
)
self.variables_to_validation_ntuple(
decay_str="D*+:Dpi",
variables=dstar_vars,
path=main_path,
)
# 1D histograms
h_1D_DstP_Dpi = [entry[:4] for entry in self.h_1D_hist_list]
# 2D histograms
h_2D_DstP_Dpi = [
("t0_firstPXDLayer", 4, -1.5, 2.5, "t1_firstPXDLayer", 4, -1.5, 2.5),
("t0_firstSVDLayer", 8, -1.5, 6.5, "t1_firstSVDLayer", 8, -1.5, 6.5),
("t0_firstCDCLayer", 52, -1.5, 50.5, "t1_firstCDCLayer", 52, -1.5, 50.5),
]
self.variables_to_validation_histogram(
decay_str="D*+:Dpi",
variables=h_1D_DstP_Dpi,
variables_2d=h_2D_DstP_Dpi,
path=main_path,
)
return main_path
@property
def analysis_validation_histograms(self) -> List[Histogram]:
return [
Histogram(
name=f"h_{var}",
title="$D^0 \\to K_s \\pi \\pi$",
hist_variable=HistVariable(
df_label=makeROOTCompatible(variable=""),
label=title,
unit=unit,
bins=bins,
scope=(low, high),
),
hist_components=[
HistComponent(
label=var,
additional_cut_str=None,
color="black",
variable=var,
),
],
)
for var, bins, low, high, unit, title in self.h_1D_hist_list
]