import basf2 as b2
import modularAnalysis as ma
import variables.collections as vc
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,
) # (new) required for histogram creation
from typing import List
import numpy as np # (new) used to get pi in alias calculation
[docs]
@fancy_validation_mode_header
class PromptTracksDistributions(ValidationModeBaseClass):
name = "PromptTracksDistributions"
[docs]
def create_basf2_path(self, fraction_to_process=0.3):
main = b2.Path()
ma.applyEventCuts(
cut=f"eventRandom < {fraction_to_process}",
path=main,
)
# b2.set_log_level(b2.LogLevel.ERROR) # Uncomment to limit log output
main.add_module("Progress")
track_cuts = "dr < 1.0 and abs(dz) < 2.0"
ma.fillParticleList("pi+:IP", track_cuts, path=main)
vm.addAlias("nIPTracks", f"nCleanedTracks({track_cuts})")
# store if event passed HLT skim
# dimuon event
line_mumu_tight_or_highm = "SoftwareTriggerResult(software_trigger_cut&skim&accept_mumu_tight_or_highm)"
line_mumutight = "SoftwareTriggerResult(software_trigger_cut&skim&accept_mumutight)"
line_mumu_2trk = "SoftwareTriggerResult(software_trigger_cut&skim&accept_mumu_2trk)"
dimuonEventCutString = f"[{line_mumu_tight_or_highm} == 1]"
dimuonEventCutString += f" or [[isNAN({line_mumu_tight_or_highm}) == 1] and [{line_mumutight} == 1]]"
dimuonEventCutString += f" or [[isNAN({line_mumutight}) == 1] and [{line_mumu_2trk} == 1]]"
vm.addAlias("isDimuonEvent", f"passesEventCut({dimuonEventCutString})")
# bhabha
line_bhabha = "SoftwareTriggerResult(software_trigger_cut&skim&accept_bhabha)"
bhabhaEventCutString = f"[{line_bhabha} == 1]"
vm.addAlias("isBhabhaEvent", f"passesEventCut({bhabhaEventCutString})")
# hadron
line_hadron = "SoftwareTriggerResult(software_trigger_cut&skim&accept_hadron)"
hadronEventCutString = f"[{line_hadron} == 1]"
vm.addAlias("isHadronEvent", f"passesEventCut({hadronEventCutString})")
pi = np.pi # (new) used for dip angle alias
vm.addAlias("dip", f"formula(atan(pz/pt)*180/{pi})") # (new) dip angle in degrees
vm.addAlias("logpval", "log10(pValue)") # (new) log scale p-value
vm.addAlias("cdcecl_veto", "L1Input(cdcecl_veto)")
vm.addAlias("passive_veto", "L1Input(passive_veto)")
VARS = ["IPX", "IPY", "IPZ", "nTracks", "nIPTracks"]
VARS += vc.track + vc.kinematics + vc.track_hits + vc.trackfit_parameters
VARS += ["cosTheta", "phi", "charge", "trackTime", "clusterE", "logpval", "dip"]
VARS += ["isTrackFlippedAndRefitted", "isDimuonEvent", "isBhabhaEvent", "isHadronEvent"]
VARS += ["cdcecl_veto", "passive_veto"]
VARS = sorted(list(set(VARS)))
self.variables_to_validation_ntuple(
decay_str="pi+:IP",
variables=VARS,
path=main,
)
return main
# new
@property
def analysis_validation_histograms(self) -> List[Histogram]:
hist = []
# common Selection: tight on dr, dz; reject Bhabha and dimuon events
common_cuts = "dr < 0.2 and abs(dz) < 0.4 and isBhabhaEvent!=1 and isDimuonEvent!=1 and isHadronEvent==1 "
cuts = [ # (new) list of pt and hit-based selection conditions
("pt<0.25 ", "pt<0.25 and no selection on hits"),
("pt>0.25 ", "pt>0.25 and no selection on hits"),
("pt>1.3 ", "pt>1.3 and no selection on hits"),
("pt<0.25 and nCDCHits > 0", "pt<0.25 and nCDCHits > 0"),
("pt>0.25 and nCDCHits > 0", "pt>0.25 and nCDCHits > 0"),
("pt>1.3 and nCDCHits > 0", "pt>1.3 and nCDCHits > 0"),
("pt<0.25 and nSVDHits > 0", "pt<0.25 and nSVDHits > 0"),
("pt>0.25 and nSVDHits > 0", "pt>0.25 and nSVDHits > 0"),
("pt>1.3 and nSVDHits > 0", "pt>1.3 and nSVDHits > 0"),
("pt<0.25 and nPXDHits > 0", "pt<0.25 and nPXDHits > 0"),
("pt>0.25 and nPXDHits > 0", "pt>0.25 and nPXDHits > 0"),
("pt>1.3 and nPXDHits > 0", "pt>1.3 and nPXDHits > 0"),
("pt<0.25 and nSVDHits == 0", "pt<0.25 and nSVDHits == 0"),
("pt>0.25 and nSVDHits == 0", "pt>0.25 and nSVDHits == 0"),
("pt>1.3 and nSVDHits == 0", "pt>1.3 and nSVDHits == 0"),
]
for i, (cut, label_tag) in enumerate(cuts): # (new) loop to generate histograms for each cut
for var, label, unit, scope in [
("phi", "phi", "rad", (-3, 3)),
("dip", "dip", "degree", (-90, 90)),
("pt", "pt", "GeV/C", (0, 2)),
("logpval", "logpval", "", (-50, 0)),
("trackTime", "trackTime", "s", (-100, 100)),
]: # (new) iterate over each variable to be histogrammed
hist.append(
Histogram(
name=f"{var}_all{i}",
title=rf"{label}(all tracks with {label_tag})",
hist_variable=HistVariable(df_label=var, label=label, unit=unit, bins=100, scope=scope),
hist_components=[
HistComponent(
label="all tracks",
additional_cut_str=common_cuts + " and " + cut,
)
],
)
)
hist.append(
Histogram(
name=f"{var}_pm{i}",
title=rf"{label}(+ve/-ve tracks with {label_tag})",
hist_variable=HistVariable(df_label=var, label=label, unit=unit, bins=100, scope=scope),
hist_components=[
HistComponent(
label="positive tracks",
additional_cut_str=rf"{common_cuts} and charge > 0.5 and {cut}",
color="red",
),
HistComponent(
label="negative tracks",
additional_cut_str=rf"{common_cuts} and charge < 0.5 and {cut}",
color="blue",
),
],
)
)
return hist # (new) returns the complete list of histogram configs