Belle II Software light-2509-fornax
stdCharged.py
1#!/usr/bin/env python3
2
3
10
11import re
12
13import basf2 as b2
14import modularAnalysis as ma
15from variables import variables
16import pdg
17
18from ROOT import Belle2
19Const = Belle2.Const
20_TrainingMode = Belle2.ChargedPidMVAWeights.ChargedPidMVATrainingMode
21
22
23# define arrays to interpret cut matrix
24_chargednames = ['pi', 'K', 'p', 'e', 'mu']
25_pidnames = ['pionID', 'kaonID', 'protonID', 'electronID', 'muonID']
26_stdnames = ['all', 'loose', 'loosepid', 'good', 'higheff']
27_effnames = ['95eff', '90eff', '85eff']
28# default particle list for stdPi() and similar functions
29_defaultlist = 'good'
30_mostLikelyList = 'mostlikely'
31
32
33def _stdChargedEffCuts(particletype, listtype):
34 """
35 Provides the PID cut corresponding to a given efficiency percentile
36
37 @param particletype type of charged particle (pi, K, p, e, mu)
38 @param listtype efficiency percentile for the list (95eff, 90eff, 85eff)
39 """
40
41 particleindex = _chargednames.index(particletype)
42 effindex = _effnames.index(listtype)
43
44 # efficiency cuts = [.95,.90,.85] efficiency; values outside (0,1) mean the cut does not exist and an error will be thrown
45 effcuts = [[0.001, 0.019, 0.098],
46 [5e-6, 0.027, 0.167],
47 [0.000, 0.043, 0.251],
48 [0.093, 0.301, 0.709],
49 [0.187, 0.418, 0.909]]
50 #
51 return effcuts[particleindex][effindex]
52
53
54def stdCharged(particletype, listtype, path, writeOut=True):
55 """
56 Function to prepare one of several standardized types of charged particle lists:
57
58 - 'all' with no cuts on track
59 - 'good' high purity lists for data studies
60 - 'loosepid' loose selections for skimming, PID cut only
61 - 'loose' loose selections for skimming
62 - 'higheff' high efficiency list with loose global ID cut for data studies
63 - 'mostlikely' list with the highest PID likelihood
64
65 Also the following lists, which may or may not be available depending on the release
66
67 - '99eff' with 99% selection efficiency (calculated for 1<p<4 GeV) and good track (MC only)
68 - '95eff' with 95% selection efficiency (calculated for 1<p<4 GeV) and good track (MC only)
69 - '90eff' with 90% selection efficiency (calculated for 1<p<4 GeV) and good track (MC only)
70 - '85eff' with 85% selection efficiency (calculated for 1<p<4 GeV) and good track (MC only)
71
72 @param particletype type of charged particle to make a list of
73 @param listtype name of standard list
74 @param path modules are added to this path
75 @param writeOut whether RootOutput module should save the created ParticleList
76 """
77
78 # basic quality cut strings
79 trackQuality = 'thetaInCDCAcceptance'
80 ipCut = 'dr < 0.5 and abs(dz) < 2'
81 goodTrack = trackQuality + ' and ' + ipCut
82
83 if particletype not in _chargednames:
84 b2.B2ERROR("The requested list is not a standard charged particle. Use one of pi, K, e, mu, p.")
85
86 if listtype == 'all':
87 ma.fillParticleList(particletype + '+:all', '', writeOut=writeOut, path=path)
88 elif listtype == 'good':
89 ma.fillParticleList(
90 particletype + '+:good',
91 _pidnames[_chargednames.index(particletype)] + ' > 0.5 and ' + goodTrack,
92 writeOut=writeOut,
93 path=path)
94 elif listtype == 'loose':
95 ma.fillParticleList(
96 particletype + '+:loose',
97 _pidnames[_chargednames.index(particletype)] + ' > 0.1 and ' + goodTrack,
98 writeOut=writeOut,
99 path=path)
100 elif listtype == 'loosepid':
101 ma.fillParticleList(
102 particletype + '+:loosepid',
103 _pidnames[_chargednames.index(particletype)] + ' > 0.1',
104 writeOut=writeOut,
105 path=path)
106 elif listtype == 'higheff':
107 ma.fillParticleList(
108 particletype + '+:higheff',
109 _pidnames[_chargednames.index(particletype)] + ' > 0.002 and ' + goodTrack,
110 writeOut=writeOut,
111 path=path)
112 elif listtype not in _effnames:
113 b2.B2ERROR("The requested list is not defined. Please refer to the stdCharged documentation.")
114 else:
115 pidcut = _stdChargedEffCuts(particletype, listtype)
116 if 0.0 < pidcut < 1.0:
117 ma.fillParticleList(
118 particletype +
119 '+:' +
120 listtype,
121 _pidnames[_chargednames.index(particletype)] +
122 ' > ' +
123 str(pidcut) +
124 ' and ' +
125 goodTrack,
126 writeOut=writeOut,
127 path=path)
128 else:
129 b2.B2ERROR('The requested standard particle list ' + particletype +
130 '+:' + listtype + ' is not available in this release.')
131
132
133def stdPi(listtype=_defaultlist, path=None, writeOut=True):
134 """
135 Function to prepare standard pion lists, refer to `stdCharged` for details
136
137 @param listtype name of standard list
138 @param path modules are added to this path
139 @param writeOut whether RootOutput module should save the created ParticleList
140 """
141 stdCharged('pi', listtype, path, writeOut)
142
143
144def stdK(listtype=_defaultlist, path=None, writeOut=True):
145 """
146 Function to prepare standard kaon lists, refer to `stdCharged` for details
147
148 @param listtype name of standard list
149 @param path modules are added to this path
150 @param writeOut whether RootOutput module should save the created ParticleList
151 """
152 stdCharged('K', listtype, path, writeOut)
153
154
155def stdPr(listtype=_defaultlist, path=None, writeOut=True):
156 """
157 Function to prepare standard proton lists, refer to `stdCharged` for details
158
159 @param listtype name of standard list
160 @param path modules are added to this path
161 @param writeOut whether RootOutput module should save the created ParticleList
162 """
163 stdCharged('p', listtype, path, writeOut)
164
165
166def stdLep(pdgId,
167 working_point,
168 method,
169 classification,
170 lid_weights_gt,
171 release=None,
172 channel_eff="combination",
173 channel_misid_pi="combination",
174 channel_misid_K="combination",
175 inputListName=None,
176 outputListLabel=None,
177 trainingModeMulticlass=_TrainingMode.c_Multiclass,
178 trainingModeBinary=_TrainingMode.c_Classification,
179 path=None):
180 """
181 Function to prepare one of several standardized types of lepton (:math:`e,\\mu`) lists, with the following working points:
182
183 * 'FixedThresh05', PID cut of > 0.5 for each particle in the list.
184 * 'FixedThresh09', PID cut of > 0.9 for each particle in the list.
185 * 'FixedThresh095', PID cut of > 0.95 for each particle in the list.
186 * 'FixedThresh099', PID cut of > 0.99 for each particle in the list.
187 * 'UniformEff60' 60% lepton efficiency list, uniform in a given multi-dimensional parametrisation.
188 * 'UniformEff70' 70% lepton efficiency list, uniform in a given multi-dimensional parametrisation.
189 * 'UniformEff80' 80% lepton efficiency list, uniform in a given multi-dimensional parametrisation.
190 * 'UniformEff90' 90% lepton efficiency list, uniform in a given multi-dimensional parametrisation.
191 * 'UniformEff95' 95% lepton efficiency list, uniform in a given multi-dimensional parametrisation.
192 * 'UniformPiFR5EM1' 50% pion to lepton fake rate, uniform in a given multi-dimensional parametrisation.
193 * 'UniformPiFR1EM1' 10% pion to lepton fake rate, uniform in a given multi-dimensional parametrisation.
194 * 'UniformPiFR5EM2' 5% pion to lepton fake rate, uniform in a given multi-dimensional parametrisation.
195 * 'UniformPiFR1EM2' 1% pion to lepton fake rate, uniform in a given multi-dimensional parametrisation.
196 * 'UniformPiFR5EM3' 0.5% pion to lepton fake rate, uniform in a given multi-dimensional parametrisation.
197 * 'UniformPiFR1EM3' 0.1% pion to lepton fake rate, uniform in a given multi-dimensional parametrisation.
198
199 The function creates a ``ParticleList``, selecting particles according to the chosen ``working_point``,
200 and decorates each candidate in the list with the nominal Data/MC :math:`\\ell` ID efficiency and
201 :math:`\\pi,K` fake rate correction factors and their stat, syst uncertainty, reading the info
202 from the Conditions Database (CDB) according to the chosen input global tag (GT).
203
204 .. note::
205 Particles will **not** be selected if they are outside the Data/MC *efficiency* corrections' phase space coverage
206 for the given working point.
207 In fact, the threshold value for the PID cut in such cases is set to NaN.
208
209 .. warning::
210 At the moment, the only supported *binary* lepton identification is against the **pion** hypothesis.
211 This implies that, if binary classification is chosen, only :math:`\\pi` fake rate corrections will be added to the
212 resulting particle list.
213
214 Parameters:
215 pdgId (int): the lepton pdg code.
216 working_point (str): name of the chosen working point that defines the content of the list. Choose among the above values.
217 method (str): the PID method: 'likelihood' or 'bdt'.
218 classification (str): the type of classifier: 'binary' (one-vs-pion) or 'global' (one-vs-all).
219 lid_weights_gt (str): the name identifier of the global tag with the recommended Data/MC correction weights.
220
221 .. tip::
222 Please refer to the
223 `Charged PID XWiki page <https://xwiki.desy.de/xwiki/rest/p/fab3e>`_
224 for info about the recommended global tags.
225
226 release (Optional[int]): the major release number of the data and MC campaigns considered.
227 If specified, it ensures the correct :math:`\\ell` ID variables are used.
228
229 .. tip::
230 Please refer to the
231 `Charged PID XWiki page <https://xwiki.desy.de/xwiki/rest/p/fab3e>`_
232 for info about lepton identification variables and campaigns.
233
234 channel_eff (Optional[str]): the channel used to derive the :math:`\\ell` ID efficiency corrections.
235 By default, 'combination' is set, meaning they are obtained by combining results
236 of several hadronic and low multiplicity channels, wherever they overlap.
237
238 .. tip::
239 Please refer to the
240 `Charged PID XWiki page <https://xwiki.desy.de/xwiki/rest/p/fab3e>`_
241 for other possible choices (if any).
242
243 channel_misid_pi (Optional[str]): the channel used to derive the :math:`\\pi` fake rate corrections.
244 channel_misid_K (Optional[str]): the channel used to derive the :math:`K` fake rate corrections.
245 inputListName (Optional[str]): the name of a pre-existing ``ParticleList`` object (defined as a full ``decayString``,
246 e.g. 'e-:my_input_electrons') of which the standard lepton list will be a subset.
247 For instance, users might want to apply a Bremsstrahlung correction to electrons first,
248 which modifies their 4-momentum, and only later define the subset passing the PID selection,
249 including the appropriate PID weights and uncertainties (which are :math:`p`-dependent).
250 By default, the standard lepton list is created from all ``Track`` objects in the event.
251
252 .. warning::
253 Do **not** apply any PID selection on the input list, otherwise results could be biased.
254
255 outputListLabel (Optional[str]): the name of the output lepton list label, i.e.,
256 the string that follows the particle identifier ('e-:', 'mu-:').
257 By default, it is assigned as:
258 ``'{method}_{classification}_{working_point}'``.
259
260 trainingModeMulticlass (Optional[``Belle2.ChargedPidMVAWeights.ChargedPidMVATrainingMode``]): enum identifier
261 of the multi-class (global PID) training mode.
262 See `modularAnalysis.applyChargedPidMVA` docs for available options.
263 trainingModeBinary (Optional[``Belle2.ChargedPidMVAWeights.ChargedPidMVATrainingMode``]): enum identifier
264 of the classification (binary PID) training mode.
265 See `modularAnalysis.applyChargedPidMVA` docs for available options.
266 path (basf2.Path): modules are added to this path.
267
268 Returns:
269 tuple(str, list(str)): the alias for the lepton ID variable, and the list of aliases for the weights.
270 """
271
272 working_points = (
273 "FixedThresh05",
274 "FixedThresh09",
275 "FixedThresh095",
276 "FixedThresh099",
277 "UniformEff60",
278 "UniformEff70",
279 "UniformEff80",
280 "UniformEff90",
281 "UniformEff95",
282 "UniformPiFR5EM1",
283 "UniformPiFR1EM1",
284 "UniformPiFR5EM2",
285 "UniformPiFR1EM2",
286 "UniformPiFR5EM3",
287 "UniformPiFR1EM3",
288 )
289
290 available_methods = ("likelihood", "bdt")
291 available_classificators = ("global", "binary")
292
293 if working_point not in working_points:
294 b2.B2ERROR(f"The requested lepton list working point: {working_point} is not defined. \
295 Please refer to the stdLep and stdCharged documentation.")
296 return None
297
298 if method not in available_methods:
299 b2.B2ERROR(f"method: {method}. Must be any of: {available_methods}.")
300 return None
301
302 if classification not in available_classificators:
303 b2.B2ERROR(f"classification: {classification}. Must be any of: {available_classificators}.")
304 return None
305
306 b2.B2INFO(f"Prepending GT with LID corrections: {lid_weights_gt}")
307 b2.conditions.prepend_globaltag(lid_weights_gt)
308
309 # We stick to positive pdgId by convention.
310 # Anyway, the particle list will be filled for anti-particles too.
311 lepton = abs(pdgId)
312 lepton_name = pdg.to_name(lepton)
313 electron = Const.electron.getPDGCode()
314 muon = Const.muon.getPDGCode()
315 pion = Const.pion.getPDGCode()
316
317 if lepton not in (electron, muon):
318 b2.B2ERROR(f"{pdgId} is not that of a light charged lepton.")
319 return None
320
321 # Declare LID variables (as in the VariableManager), and aliases to match the naming scheme used in the payloads.
322 pid_variables = {
323 "likelihood": {
324 "global": {
325 "var": {
326 electron: "electronID",
327 muon: "muonID",
328 },
329 "alias": {
330 electron: "electronID",
331 muon: "muonID",
332 }
333 },
334 "binary": {
335 "var": {
336 electron: f"binaryPID({electron}, {pion})",
337 muon: f"binaryPID({muon}, {pion})",
338 },
339 "alias": {
340 electron: "binaryPID_e_pi",
341 muon: "binaryPID_mu_pi",
342 }
343 }
344 },
345 "bdt": {
346 "global": {
347 "var": {
348 lepton: f"pidChargedBDTScore({lepton}, ALL)",
349 },
350 "alias": {
351 lepton: re.sub(r"\W+", "", f"pidChargedBDTScore_{lepton_name}"),
352 }
353 },
354 "binary": {
355 "var": {
356 lepton: f"pidPairChargedBDTScore({lepton}, {pion}, ALL)",
357 },
358 "alias": {
359 lepton: re.sub(r"\W+", "", f"pidPairChargedBDTScore_{lepton_name}_pi"),
360 }
361 }
362 }
363 }
364
365 # Depending on the release associated to the chosen LID recommendations GT,
366 # some variable names and aliases may need to be reset.
367 if int(release) in [5, 6]:
368 if lepton == electron:
369 b2.B2INFO(f"The likelihood-based electron ID in release {release} samples is defined w/o the SVD and the TOP")
370 pid_variables["likelihood"]["global"]["var"][electron] = "electronID_noSVD_noTOP"
371 pid_variables["likelihood"]["global"]["alias"][electron] = "electronID_noSVD_noTOP"
372 pid_variables["likelihood"]["binary"]["var"][electron] = f"binaryElectronID_noSVD_noTOP({pion})"
373 pid_variables["likelihood"]["binary"]["alias"][electron] = "binaryElectronID_noSVD_noTOP_pi"
374 else:
375 b2.B2INFO(f"The likelihood-based muon ID in release {release} samples is defined w/o the SVD")
376 pid_variables["likelihood"]["global"]["var"][muon] = "muonID_noSVD"
377 pid_variables["likelihood"]["global"]["alias"][muon] = "muonID_noSVD"
378 pid_variables["likelihood"]["binary"]["var"][muon] = f"binaryPID_noSVD({muon}, {pion})"
379 pid_variables["likelihood"]["binary"]["alias"][muon] = "binaryMuonID_noSVD_pi"
380
381 # Create the aliases.
382 pid_var = pid_variables[method][classification]["var"][lepton]
383 pid_alias = pid_variables[method][classification]["alias"][lepton]
384 if pid_alias != pid_var:
385 variables.addAlias(pid_alias, pid_var)
386
387 # Start creating the particle list, w/o any selection.
388 outputListName = f"{lepton_name}:{method}_{classification}_{working_point}"
389 if outputListLabel is not None:
390 outputListName = f"{lepton_name}:{outputListLabel}"
391
392 if inputListName is None:
393 ma.fillParticleList(outputListName, "", path=path)
394 else:
395 b2.B2INFO(
396 f"The standard lepton list: '{outputListName}' will be created as a subset \
397 of the following ParticleList: '{inputListName}'")
398 ma.copyList(outputListName, inputListName, path=path)
399
400 # Here we must run the BDT if requested.
401 if method == "bdt":
402 if classification == "global":
403 ma.applyChargedPidMVA(particleLists=[outputListName],
404 path=path,
405 trainingMode=trainingModeMulticlass)
406 elif classification == "binary":
407 ma.applyChargedPidMVA(particleLists=[outputListName],
408 path=path,
409 binaryHypoPDGCodes=(lepton, pion),
410 trainingMode=trainingModeBinary)
411
412 # The names of the payloads w/ efficiency and mis-id corrections.
413 payload_eff = f"ParticleReweighting:{pid_alias}_eff_{channel_eff}_{working_point}"
414 payload_misid_pi = f"ParticleReweighting:{pid_alias}_misid_pi_{channel_misid_pi}_{working_point}"
415
416 # Configure weighting module(s).
417 path.add_module("ParticleWeighting",
418 particleList=outputListName,
419 tableName=payload_eff).set_name(f"ParticleWeighting_eff_{outputListName}")
420 path.add_module("ParticleWeighting",
421 particleList=outputListName,
422 tableName=payload_misid_pi,
423 allowToSkip=True).set_name(f"ParticleWeighting_misid_pi_{outputListName}")
424
425 if classification == "global":
426 payload_misid_K = f"ParticleReweighting:{pid_alias}_misid_K_{channel_misid_K}_{working_point}"
427 path.add_module("ParticleWeighting",
428 particleList=outputListName,
429 tableName=payload_misid_K,
430 allowToSkip=True).set_name(f"ParticleWeighting_misid_K_{outputListName}")
431
432 # Apply the PID selection cut, which is read from the efficiency payload.
433 # The '>=' handles extreme cases in which the variable and the threshold value are at a boundary of the PID variable range.
434 cut = f"[{pid_alias} >= extraInfo({payload_eff}_threshold)]"
435 ma.applyCuts(outputListName, cut, path=path)
436
437 # Define convenience aliases for the nominal weight and up/dn variations.
438 weight_aliases_to_var = {
439 f"weight_{pid_alias}_eff_{working_point}": f"extraInfo({payload_eff}_data_MC_ratio)",
440 f"weight_{pid_alias}_misid_pi_{working_point}": f"extraInfo({payload_misid_pi}_data_MC_ratio)",
441 # These aliases are *absolute* variations.
442 f"weight_{pid_alias}_eff_{working_point}_stat_up": f"extraInfo({payload_eff}_data_MC_uncertainty_stat_up)",
443 f"weight_{pid_alias}_eff_{working_point}_stat_dn": f"extraInfo({payload_eff}_data_MC_uncertainty_stat_dn)",
444 f"weight_{pid_alias}_eff_{working_point}_sys_up": f"extraInfo({payload_eff}_data_MC_uncertainty_sys_up)",
445 f"weight_{pid_alias}_eff_{working_point}_sys_dn": f"extraInfo({payload_eff}_data_MC_uncertainty_sys_dn)",
446 f"weight_{pid_alias}_misid_pi_{working_point}_stat_up": f"extraInfo({payload_misid_pi}_data_MC_uncertainty_stat_up)",
447 f"weight_{pid_alias}_misid_pi_{working_point}_stat_dn": f"extraInfo({payload_misid_pi}_data_MC_uncertainty_stat_dn)",
448 f"weight_{pid_alias}_misid_pi_{working_point}_sys_up": f"extraInfo({payload_misid_pi}_data_MC_uncertainty_sys_up)",
449 f"weight_{pid_alias}_misid_pi_{working_point}_sys_dn": f"extraInfo({payload_misid_pi}_data_MC_uncertainty_sys_dn)",
450 # These aliases are *relative* variations, so they can be multiplied to the nominal
451 # to get the varied weight:
452 #
453 # w_rel_var_up = (1 + w_up/w_nominal)
454 # w_rel_var_dn = (1 - w_dn/w_nominal)
455 #
456 # w_var_up = w_nominal * w_rel_var_up
457 # w_var_dn = w_nominal * w_rel_var_dn
458 f"weight_{pid_alias}_eff_{working_point}_rel_stat_up":
459 f"formula(1+[extraInfo({payload_eff}_data_MC_uncertainty_stat_up)/extraInfo({payload_eff}_data_MC_ratio)])",
460 f"weight_{pid_alias}_eff_{working_point}_rel_stat_dn":
461 f"formula(1-[extraInfo({payload_eff}_data_MC_uncertainty_stat_dn)/extraInfo({payload_eff}_data_MC_ratio)])",
462 f"weight_{pid_alias}_eff_{working_point}_rel_sys_up":
463 f"formula(1+[extraInfo({payload_eff}_data_MC_uncertainty_sys_up)/extraInfo({payload_eff}_data_MC_ratio)])",
464 f"weight_{pid_alias}_eff_{working_point}_rel_sys_dn":
465 f"formula(1-[extraInfo({payload_eff}_data_MC_uncertainty_sys_dn)/extraInfo({payload_eff}_data_MC_ratio)])",
466 f"weight_{pid_alias}_misid_pi_{working_point}_rel_stat_up":
467 f"formula(1+[extraInfo({payload_misid_pi}_data_MC_uncertainty_stat_up)/extraInfo({payload_misid_pi}_data_MC_ratio)])",
468 f"weight_{pid_alias}_misid_pi_{working_point}_rel_stat_dn":
469 f"formula(1-[extraInfo({payload_misid_pi}_data_MC_uncertainty_stat_dn)/extraInfo({payload_misid_pi}_data_MC_ratio)])",
470 f"weight_{pid_alias}_misid_pi_{working_point}_rel_sys_up":
471 f"formula(1+[extraInfo({payload_misid_pi}_data_MC_uncertainty_sys_up)/extraInfo({payload_misid_pi}_data_MC_ratio)])",
472 f"weight_{pid_alias}_misid_pi_{working_point}_rel_sys_dn":
473 f"formula(1-[extraInfo({payload_misid_pi}_data_MC_uncertainty_sys_dn)/extraInfo({payload_misid_pi}_data_MC_ratio)])",
474 }
475 if classification == "global":
476 weight_aliases_to_var.update({
477 f"weight_{pid_alias}_misid_K_{working_point}": f"extraInfo({payload_misid_K}_data_MC_ratio)",
478 #
479 f"weight_{pid_alias}_misid_K_{working_point}_stat_up": f"extraInfo({payload_misid_K}_data_MC_uncertainty_stat_up)",
480 f"weight_{pid_alias}_misid_K_{working_point}_stat_dn": f"extraInfo({payload_misid_K}_data_MC_uncertainty_stat_dn)",
481 f"weight_{pid_alias}_misid_K_{working_point}_sys_up": f"extraInfo({payload_misid_K}_data_MC_uncertainty_sys_up)",
482 f"weight_{pid_alias}_misid_K_{working_point}_sys_dn": f"extraInfo({payload_misid_K}_data_MC_uncertainty_sys_dn)",
483 #
484 f"weight_{pid_alias}_misid_K_{working_point}_rel_stat_up":
485 f"formula(1+[extraInfo({payload_misid_K}_data_MC_uncertainty_stat_up)/extraInfo({payload_misid_K}_data_MC_ratio)])",
486 f"weight_{pid_alias}_misid_K_{working_point}_rel_stat_dn":
487 f"formula(1-[extraInfo({payload_misid_K}_data_MC_uncertainty_stat_dn)/extraInfo({payload_misid_K}_data_MC_ratio)])",
488 f"weight_{pid_alias}_misid_K_{working_point}_rel_sys_up":
489 f"formula(1+[extraInfo({payload_misid_K}_data_MC_uncertainty_sys_up)/extraInfo({payload_misid_K}_data_MC_ratio)])",
490 f"weight_{pid_alias}_misid_K_{working_point}_rel_sys_dn":
491 f"formula(1-[extraInfo({payload_misid_K}_data_MC_uncertainty_sys_dn)/extraInfo({payload_misid_K}_data_MC_ratio)])",
492 })
493
494 for alias, var in weight_aliases_to_var.items():
495 variables.addAlias(alias, var)
496
497 return pid_alias, list(weight_aliases_to_var.keys())
498
499
500def stdE(listtype=_defaultlist,
501 method=None,
502 classification=None,
503 lid_weights_gt=None,
504 release=None,
505 channel_eff="combination",
506 channel_misid_pi="combination",
507 channel_misid_K="combination",
508 inputListName=None,
509 outputListLabel=None,
510 trainingModeMulticlass=_TrainingMode.c_Multiclass,
511 trainingModeBinary=_TrainingMode.c_Classification,
512 path=None):
513 """ Function to prepare one of several standardized types of electron lists.
514 See the documentation of `stdLep` for details.
515
516 It also accepts any of the legacy definitions
517 for the ``listtype`` parameter (aka ``working_point`` in `stdLep`) to fall back to the `stdCharged` behaviour:
518
519 * 'all'
520 * 'good'
521 * 'loosepid'
522 * 'loose'
523 * 'higheff'
524 * '95eff'
525 * '90eff'
526 * '85eff'
527
528 Returns:
529 tuple(str, list(str)): the alias for the electron ID variable, and the list of aliases for the weights.
530 """
531
532 if listtype in _stdnames + _effnames:
533 stdCharged("e", listtype, path)
534 return _pidnames[_chargednames.index("e")], None
535
536 return stdLep(Const.electron.getPDGCode(), listtype, method, classification, lid_weights_gt,
537 release=release,
538 channel_eff=channel_eff,
539 channel_misid_pi=channel_misid_pi,
540 channel_misid_K=channel_misid_K,
541 inputListName=inputListName,
542 outputListLabel=outputListLabel,
543 trainingModeMulticlass=trainingModeMulticlass,
544 trainingModeBinary=trainingModeBinary,
545 path=path)
546
547
548def stdMu(listtype=_defaultlist,
549 method=None,
550 classification=None,
551 lid_weights_gt=None,
552 release=None,
553 channel_eff="combination",
554 channel_misid_pi="combination",
555 channel_misid_K="combination",
556 inputListName=None,
557 outputListLabel=None,
558 trainingModeMulticlass=_TrainingMode.c_Multiclass,
559 trainingModeBinary=_TrainingMode.c_Classification,
560 path=None):
561 """ Function to prepare one of several standardized types of muon lists.
562 See the documentation of `stdLep` for details.
563
564 It also accepts any of the legacy definitions
565 for the ``listtype`` parameter (aka ``working_point`` in `stdLep`) to fall back to the `stdCharged` behaviour:
566
567 * 'all'
568 * 'good'
569 * 'loosepid'
570 * 'loose'
571 * 'higheff'
572 * '95eff'
573 * '90eff'
574 * '85eff'
575
576 Returns:
577 tuple(str, list(str)): the alias for the muon ID variable, and the list of aliases for the weights.
578 """
579
580 if listtype in _stdnames + _effnames:
581 stdCharged("mu", listtype, path)
582 return _pidnames[_chargednames.index("mu")], None
583
584 return stdLep(Const.muon.getPDGCode(), listtype, method, classification, lid_weights_gt,
585 release=release,
586 channel_eff=channel_eff,
587 channel_misid_pi=channel_misid_pi,
588 channel_misid_K=channel_misid_K,
589 inputListName=inputListName,
590 outputListLabel=outputListLabel,
591 trainingModeMulticlass=trainingModeMulticlass,
592 trainingModeBinary=trainingModeBinary,
593 path=path)
594
595
596def stdMostLikely(pidPriors=None, suffix='', custom_cuts='', path=None, writeOut=True):
597 """
598 Function to prepare most likely particle lists according to PID likelihood, refer to stdCharged for details
599
600 @param pidPriors list of 6 float numbers used to reweight PID likelihoods, for e, mu, pi, K, p and d
601 @param suffix string added to the end of particle list names
602 @param custom_cuts custom selection cut string, if empty, standard track quality cuts will be applied
603 @param path modules are added to this path
604 @param writeOut whether RootOutput module should save the created ParticleList
605 """
606 # Here we need basic track quality cuts to be applied,
607 # otherwise, we get a lot of badly reconstructed particles,
608 # which will end up filled as a random type
609 args = ''
610 if pidPriors is not None:
611 args = str(pidPriors)[1:-1] # remove brackets
612 trackQuality = 'thetaInCDCAcceptance and nCDCHits>20'
613 if custom_cuts != '':
614 trackQuality = custom_cuts
615 for name in _chargednames:
616 ma.fillParticleList(f'{name}+:{_mostLikelyList}{suffix}',
617 f'pidIsMostLikely({args}) > 0 and {trackQuality}', writeOut=writeOut, path=path)
This class provides a set of constants for the framework.
Definition Const.h:34
to_name(pdg)
Definition pdg.py:87