Belle II Software development
trackIsolationVariables.py
1#!/usr/bin/env python3
2
3
10
11"""
12Example script to calculate isolation variables per particle.
13
14For each particle in the input charged stable particle list,
15calculate the distance to the closest candidate in the reference list at a given detector layer surface.
16The calculation of the distance is based on the particles' track helices extrapolation.
17"""
18
19
20import argparse
21
22
23def argparser():
24 """ Argument parser
25 """
26
27 import stdCharged as stdc
28 from modularAnalysis import getAnalysisGlobaltag
29
30 parser = argparse.ArgumentParser(description=__doc__,
31 formatter_class=argparse.RawTextHelpFormatter)
32
33 parser.add_argument("--std_charged_ref",
34 type=str,
35 choices=stdc._chargednames,
36 default="pi",
37 help="The base name of the reference standard charged particle list\n"
38 "that will be considered for the distance calculation.\n"
39 "Default: %(default)s.")
40 parser.add_argument("--detectors",
41 type=str,
42 nargs="+",
43 default=["CDC", "TOP", "ARICH", "ECL", "KLM"],
44 choices=["CDC", "TOP", "ARICH", "ECL", "KLM"],
45 help="List of detectors at whose entry surface the isolation variables will be calculated.\n"
46 "Pass a space-separated list of names.\n"
47 "Default: %(default)s.")
48 parser.add_argument("--use_pid_det_weights",
49 action="store_true",
50 default=False,
51 help="Include the PID detector weights (taken from the CDB) in the isolation score calculation.\n"
52 "Default: %(default)s.")
53 parser.add_argument("--global_tag_append",
54 type=str,
55 nargs="+",
56 default=[getAnalysisGlobaltag()],
57 help="List of names of conditions DB global tag(s) to append on top of GT replay.\n"
58 "NB: these GTs will have lowest priority over GT replay.\n"
59 "The order of the sequence passed determines the priority of the GTs, w/ the highest coming first.\n"
60 "Pass a space-separated list of names.\n"
61 "Default: %(default)s.")
62 parser.add_argument("--global_tag_prepend",
63 type=str,
64 nargs="+",
65 default=None,
66 help="List of names of conditions DB global tag(s) to prepend to GT replay.\n"
67 "NB: these GTs will have highest priority over GT replay.\n"
68 "The order of the sequence passed determines the priority of the GTs, w/ the highest coming first.\n"
69 "Pass a space-separated list of names.")
70 parser.add_argument("-d", "--debug",
71 action="store",
72 default=0,
73 type=int,
74 choices=list(range(11, 20)),
75 help="Run the TrackIsoCalculator module in debug mode. Pass the desired DEBUG level integer.")
76
77 return parser
78
79
80if __name__ == "__main__":
81
82 # Argparse options.
83 # NB: Command line arguments are parsed before importing basf2, to avoid PyROOT hijacking them
84 # in case of overlapping option names.
85 args = argparser().parse_args()
86
87 import basf2 as b2
88 import modularAnalysis as ma
89 import stdV0s as stdv0
90 from variables import variables as vm
91 import variables.utils as vu
92 import variables.collections as vc
93 import pdg
94 from ROOT import Belle2
95 Const = Belle2.Const
96
97 for tag in args.global_tag_append:
98 b2.conditions.append_globaltag(tag)
99 print(f"Appending GTs:\n{args.global_tag_append}")
100
101 if args.global_tag_prepend:
102 for tag in reversed(args.global_tag_prepend):
103 b2.conditions.prepend_globaltag(tag)
104 print(f"Prepending GTs:\n{args.global_tag_prepend}")
105
106 # Create path. Register necessary modules to this path.
107 path = b2.create_path()
108
109 # Add input data and ParticleLoader modules to the path.
110 ma.inputMdst(filename=b2.find_file("mdst16.root", "validation"), path=path)
111
112 # -------------------------------------------------------------------
113
114 # ---------
115 # EXAMPLE 1
116 # ---------
117
118 # Fill a particle list of muons, with some quality selection.
119 base_trk_selection = "[dr < 3] and [abs(dz) < 5] and [thetaInCDCAcceptance] and [pt > 0.1]"
120 ma.fillParticleList("mu+:muons", f"{base_trk_selection} and [muonID > 0.5]", path=path)
121
122 # Reconstruct a J/psi decay.
123 jpsimumu = "J/psi:mumu -> mu+:muons mu-:muons"
124 jpsi_cuts = [
125 "[2.8 < M < 3.3]",
126 "[daughterSumOf(charge) == 0]",
127 ]
128 jpsi_cut = " and ".join(jpsi_cuts)
129
130 ma.reconstructDecay(jpsimumu, jpsi_cut, path=path)
131
132 # Fill a reference charged stable particle list to calculate the distances against.
133 # Generally, this list should have a very loose selection applied (if none at all).
134 ref = f"{args.std_charged_ref}+:ref"
135 ref_pdg = pdg.from_name(f"{args.std_charged_ref}+")
136 ma.fillParticleList(ref, f"{base_trk_selection}", path=path)
137
138 # Calculate the track isolation variables
139 # on the muon daughters in the decay.
140 # Use the default setting where the module takes the mass hypothesis w/ highest probability for the track extrapolation.
141 # The helper returns a dictionary w/ the list of metavariables for each of the reference particle lists (using PDG as key).
142 # In this case, we pass explicitly a particle list of our choice.
143 trackiso_vars_mu = ma.calculateTrackIsolation("J/psi:mumu -> ^mu+ ^mu-",
144 path,
145 *args.detectors,
146 vars_for_nearest_part=vc.mc_variables,
147 # Calculate also the chosen variables for the nearest particle at each layer.
148 reference_list_name=ref,
149 # Include/exclude the PID detector weights in the score calculation.
150 exclude_pid_det_weights=not args.use_pid_det_weights)
151
152 # Variables and aliases for the J/psi candidates.
153 variables_jpsi = vc.kinematics + ["daughterDiffOf(0, 1, phi)"]
154 variables_jpsi += vu.create_aliases(variables_jpsi, "useCMSFrame({variable})", "CMS")
155 variables_jpsi += vc.inv_mass
156 aliases_jpsi = vu.create_aliases_for_selected(variables_jpsi,
157 "^J/psi:mumu -> mu+ mu-",
158 prefix=["jpsi"])
159
160 # Variables and aliases for the J/psi daughters.
161 # Since we passed explicitly a reference list, we use its associated PDG code to get the list of metavariables.
162 variables_mu = vc.kinematics + ["theta", "phi", "clusterE", "nCDCHits"] + trackiso_vars_mu[ref_pdg]
163 aliases_mu = vu.create_aliases_for_selected(variables_mu,
164 "J/psi:mumu -> ^mu+ ^mu-",
165 use_names=True)
166
167 # Variables and aliases for the event.
168 vm.addAlias("nReferenceTracks", f"nCleanedTracks({base_trk_selection})")
169 aliases_event = ["nReferenceTracks"]
170
171 # Saving variables to ntuple
172 ma.variablesToNtuple(decayString="J/psi:mumu",
173 variables=aliases_event+aliases_jpsi+aliases_mu,
174 treename="jpsimumu",
175 filename="TrackIsolationVariables.root",
176 path=path)
177
178 # ---------
179 # EXAMPLE 2
180 # ---------
181
182 # Reconstruct standard Lambda0 -> p+ pi- decays.
183 stdv0.stdLambdas(path=path)
184
185 # Calculate the track isolation variables
186 # on the proton and pion daughters in the decay.
187 #
188 # In this configuration, the mass hypothesis for the extrapolation is the one matching each particle's PDG.
189 #
190 # Note that no reference list is passed: it will use by default the `:all` ParticleList of the same type
191 # of the selected particle(s) in the decay string.
192 trackiso_vars_p_pi = ma.calculateTrackIsolation("Lambda0:merged -> ^p+ ^pi-",
193 path,
194 *args.detectors,
195 vars_for_nearest_part=vc.mc_variables,
196 # Calculate also the chosen variables for the nearest particle at each layer.
197 highest_prob_mass_for_ext=False,
198 exclude_pid_det_weights=not args.use_pid_det_weights)
199
200 # Variables and aliases for the Lambda0 candidates.
201 variables_lambda0 = vc.kinematics + ["daughterDiffOf(0, 1, phi)"]
202 variables_lambda0 += vu.create_aliases(variables_lambda0, "useCMSFrame({variable})", "CMS")
203 variables_lambda0 += vc.inv_mass
204 aliases_lambda0 = vu.create_aliases_for_selected(variables_lambda0,
205 "^Lambda0:merged -> p+ pi-",
206 prefix=["lambda0"])
207
208 # Variables and aliases for the Lambda0 daughters.
209 # - Protons
210 variables_p = vc.kinematics + \
211 ["theta", "phi", "clusterE", "nCDCHits"] + \
212 trackiso_vars_p_pi[Const.proton.getPDGCode()] # Use the proton PDG to get the associated list of metavariables.
213 aliases_p = vu.create_aliases_for_selected(variables_p,
214 "Lambda0:merged -> ^p+ pi-",
215 use_names=True)
216 # - Pions
217 variables_pi = vc.kinematics + \
218 ["theta", "phi", "clusterE", "nCDCHits"] + \
219 trackiso_vars_p_pi[Const.pion.getPDGCode()] # Use the pion PDG to get the associated list of metavariables.
220 aliases_pi = vu.create_aliases_for_selected(variables_pi,
221 "Lambda0:merged -> p+ ^pi-",
222 use_names=True)
223
224 # Saving variables to ntuple
225 ma.variablesToNtuple(decayString="Lambda0:merged",
226 variables=aliases_lambda0+aliases_p+aliases_pi,
227 treename="lambda0ppi",
228 filename="TrackIsolationVariables.root",
229 path=path)
230
231 # -------------------------------------------------------------------
232
233 vm.printAliases()
234
235 # Optionally activate debug mode for the TrackIsoCalculator module(s).
236 if args.debug:
237 for m in path.modules():
238 if "TrackIsoCalculator" in m.name():
239 m.set_log_level(b2.LogLevel.DEBUG)
240 m.set_debug_level(args.debug)
241
242 path.add_module("Progress")
243
244 # Process the data.
245 b2.process(path)
This class provides a set of constants for the framework.
Definition Const.h:34
from_name(name)
Definition pdg.py:63