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