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