12This module defines wrapper functions around the analysis modules.
16from basf2
import register_module, create_path
17from basf2
import B2INFO, B2WARNING, B2ERROR, B2FATAL
22def setAnalysisConfigParams(configParametersAndValues, path):
24 Sets analysis configuration parameters.
28 - 'tupleStyle': 'Default' (default) or 'Laconic'
30 - defines the style of the branch name in the ntuple
32 - 'mcMatchingVersion': Specifies what version of mc matching algorithm is going to be used:
34 - 'Belle' - analysis of Belle MC
35 - 'BelleII' (default) - all other cases
37 @param configParametersAndValues dictionary of parameters and their values of the form {param1: value, param2: value, ...)
38 @param modules are added to this path
41 conf = register_module(
'AnalysisConfiguration')
43 allParameters = [
'tupleStyle',
'mcMatchingVersion']
45 keys = configParametersAndValues.keys()
47 if key
not in allParameters:
48 allParametersString =
', '.join(allParameters)
49 B2ERROR(
'Invalid analysis configuration parameter: ' + key +
'.\n'
50 'Please use one of the following: ' + allParametersString)
52 for param
in allParameters:
53 if param
in configParametersAndValues:
54 conf.param(param, configParametersAndValues.get(param))
59def inputMdst(filename, path, environmentType='default', skipNEvents=0, entrySequence=None, *, parentLevel=0, **kwargs):
61 Loads the specified :ref:`mDST <mdst>` (or :ref:`uDST <analysis_udstoutput>`) file with the RootInput module.
63 The correct environment (e.g. magnetic field settings) is determined from
64 ``environmentType``. Options are either: 'default' (for Belle II MC and
65 data: falls back to database), 'Belle': for analysis of converted Belle 1
69 filename (str): the name of the file to be loaded
70 path (basf2.Path): modules are added to this path
71 environmentType (str): type of the environment to be loaded (either 'default' or 'Belle')
72 skipNEvents (int): N events of the input file are skipped
73 entrySequence (str): The number sequences (e.g. 23:42,101) defining the entries which are processed.
74 parentLevel (int): Number of generations of parent files (files used as input when creating a file) to be read
78 if filename ==
'default':
80We have simplified the arguments to inputMdst! If you are running on Belle II
81data or MC, you don't have to use "default" any more.
83 inputMdst("default", "/your/input/file.root", path=mypath)
85 inputMdst("/your/input/file.root", path=mypath)
87 elif filename ==
"Belle":
89We have reordered the arguments to inputMdst! If you are running on Belle 1
90data or MC, you need to specify the 'environmentType'.
92 inputMdst("Belle", "/your/input/file.root", path=mypath)
94 inputMdst("/your/input/file.root", path=mypath, environmentType='Belle')
96 elif filename
in [f
"MC{i}" for i
in range(5, 10)]:
97 B2FATAL(f
"We no longer support the MC version {filename}. Sorry.")
99 if entrySequence
is not None:
100 entrySequence = [entrySequence]
102 inputMdstList([filename], path, environmentType, skipNEvents, entrySequence, parentLevel=parentLevel, **kwargs)
108 environmentType='default',
113 useB2BIIDBCache=True):
115 Loads the specified list of :ref:`mDST <mdst>` (or :ref:`uDST <analysis_udstoutput>`) files with the RootInput module.
117 The correct environment (e.g. magnetic field settings) is determined from
118 ``environmentType``. Options are either: 'default' (for Belle II MC and
119 data: falls back to database), 'Belle': for analysis of converted Belle 1
123 filelist (list(str)): the filename list of files to be loaded
124 path (basf2.Path): modules are added to this path
125 environmentType (str): type of the environment to be loaded (either 'default' or 'Belle')
126 skipNEvents (int): N events of the input files are skipped
127 entrySequences (list(str)): The number sequences (e.g. 23:42,101) defining
128 the entries which are processed for each inputFileName.
129 parentLevel (int): Number of generations of parent files (files used as input when creating a file) to be read
130 useB2BIIDBCache (bool): Loading of local KEKCC database (only to be deactivated in very special cases)
134 if filelist ==
'default':
136We have simplified the arguments to inputMdstList! If you are running on
137Belle II data or MC, you don't have to use "default" any more.
139 inputMdstList("default", list_of_your_files, path=mypath)
141 inputMdstList(list_of_your_files, path=mypath)
143 elif filelist ==
"Belle":
145We have reordered the arguments to inputMdstList! If you are running on
146Belle 1 data or MC, you need to specify the 'environmentType'.
148 inputMdstList("Belle", list_of_your_files, path=mypath)
150 inputMdstList(list_of_your_files, path=mypath, environmentType='Belle')
152 elif filelist
in [f
"MC{i}" for i
in range(5, 10)]:
153 B2FATAL(f
"We no longer support the MC version {filelist}. Sorry.")
155 roinput = register_module(
'RootInput')
156 roinput.param(
'inputFileNames', filelist)
157 roinput.param(
'skipNEvents', skipNEvents)
158 if entrySequences
is not None:
159 roinput.param(
'entrySequences', entrySequences)
160 roinput.param(
'parentLevel', parentLevel)
162 path.add_module(roinput)
163 path.add_module(
'ProgressBar')
165 if environmentType ==
'Belle':
170 from ROOT
import Belle2
176 setAnalysisConfigParams({
'mcMatchingVersion':
'Belle'}, path)
179 basf2.conditions.metadata_providers = [
"/sw/belle/b2bii/database/conditions/b2bii.sqlite"]
180 basf2.conditions.payload_locations = [
"/sw/belle/b2bii/database/conditions/"]
183def outputMdst(filename, path):
185 Saves mDST (mini-Data Summary Tables) to the output root file.
189 This function is kept for backward-compatibility.
190 Better to use `mdst.add_mdst_output` directly.
198def outputUdst(filename, particleLists=None, includeArrays=None, path=None, dataDescription=None):
200 Save uDST (user-defined Data Summary Tables) = MDST + Particles + ParticleLists
201 The charge-conjugate lists of those given in particleLists are also stored.
202 Additional Store Arrays and Relations to be stored can be specified via includeArrays
206 This does not reduce the amount of Particle objects saved,
207 see `udst.add_skimmed_udst_output` for a function that does.
213 path=path, filename=filename, particleLists=particleLists,
214 additionalBranches=includeArrays, dataDescription=dataDescription)
217def outputIndex(filename, path, includeArrays=None, keepParents=False, mc=True):
219 Write out all particle lists as an index file to be reprocessed using parentLevel flag.
220 Additional branches necessary for file to be read are automatically included.
221 Additional Store Arrays and Relations to be stored can be specified via includeArrays
224 @param str filename the name of the output index file
225 @param str path modules are added to this path
226 @param list(str) includeArrays: datastore arrays/objects to write to the output
227 file in addition to particle lists and related information
228 @param bool keepParents whether the parents of the input event will be saved as the parents of the same event
229 in the output index file. Useful if you are only adding more information to another index file
230 @param bool mc whether the input data is MC or not
233 if includeArrays
is None:
237 onlyPLists = register_module(
'OnlyWriteOutParticleLists')
238 path.add_module(onlyPLists)
243 'ParticlesToMCParticles',
244 'ParticlesToPIDLikelihoods',
245 'ParticleExtraInfoMap',
248 branches = [
'EventMetaData']
249 persistentBranches = [
'FileMetaData']
253 branches += partBranches
254 branches += includeArrays
256 r1 = register_module(
'RootOutput')
257 r1.param(
'outputFileName', filename)
258 r1.param(
'additionalBranchNames', branches)
259 r1.param(
'branchNamesPersistent', persistentBranches)
260 r1.param(
'keepParents', keepParents)
264def setupEventInfo(noEvents, path):
266 Prepare to generate events. This function sets up the EventInfoSetter.
267 You should call this before adding a generator from generators.
268 The experiment and run numbers are set to 0 (run independent generic MC in phase 3).
269 https://xwiki.desy.de/xwiki/rest/p/59192
272 noEvents (int): number of events to be generated
273 path (basf2.Path): modules are added to this path
276 evtnumbers = register_module(
'EventInfoSetter')
277 evtnumbers.param(
'evtNumList', [noEvents])
278 evtnumbers.param(
'runList', [0])
279 evtnumbers.param(
'expList', [0])
280 path.add_module(evtnumbers)
283def loadGearbox(path, silence_warning=False):
285 Loads Gearbox module to the path.
288 Should be used in a job with *cosmic event generation only*
290 Needed for scripts which only generate cosmic events in order to
293 @param path modules are added to this path
294 @param silence_warning stops a verbose warning message if you know you want to use this function
297 if not silence_warning:
298 B2WARNING(
"""You are overwriting the geometry from the database with Gearbox.
299 This is fine if you're generating cosmic events. But in most other cases you probably don't want this.
301 If you're really sure you know what you're doing you can suppress this message with:
303 >>> loadGearbox(silence_warning=True)
307 paramloader = register_module(
'Gearbox')
308 path.add_module(paramloader)
311def printPrimaryMCParticles(path, **kwargs):
313 Prints all primary MCParticles, that is particles from
314 the physics generator and not particles created by the simulation
316 This is equivalent to `printMCParticles(onlyPrimaries=True, path=path) <printMCParticles>` and additional
317 keyword arguments are just forwarded to that function
320 return printMCParticles(onlyPrimaries=
True, path=path, **kwargs)
323def printMCParticles(onlyPrimaries=False, maxLevel=-1, path=None, *,
324 showProperties=False, showMomenta=False, showVertices=False, showStatus=False, suppressPrint=False):
326 Prints all MCParticles or just primary MCParticles up to specified level. -1 means no limit.
328 By default this will print a tree of just the particle names and their pdg
329 codes in the event, for example ::
331 [INFO] Content of MCParticle list
334 ╰── Upsilon(4S) (300553)
336 │ ├── anti-D_0*0 (-10421)
339 │ │ │ │ ├── anti-K0 (-311)
340 │ │ │ │ │ ╰── K_S0 (310)
341 │ │ │ │ │ ├── pi+ (211)
342 │ │ │ │ │ │ ╰╶╶ p+ (2212)
343 │ │ │ │ │ ╰── pi- (-211)
344 │ │ │ │ │ ├╶╶ e- (11)
345 │ │ │ │ │ ├╶╶ n0 (2112)
346 │ │ │ │ │ ├╶╶ n0 (2112)
347 │ │ │ │ │ ╰╶╶ n0 (2112)
348 │ │ │ │ ╰── pi- (-211)
349 │ │ │ │ ├╶╶ anti-nu_mu (-14)
351 │ │ │ │ ├╶╶ nu_mu (14)
352 │ │ │ │ ├╶╶ anti-nu_e (-12)
356 │ │ │ │ ├── gamma (22)
357 │ │ │ │ ╰── gamma (22)
363 │ │ ├╶╶ anti-nu_mu (-14)
371 There's a distinction between primary and secondary particles. Primary
372 particles are the ones created by the physics generator while secondary
373 particles are ones generated by the simulation of the detector interaction.
375 Secondaries are indicated with a dashed line leading to the particle name
376 and if the output is to the terminal they will be printed in red. If
377 ``onlyPrimaries`` is True they will not be included in the tree.
379 On demand, extra information on all the particles can be displayed by
380 enabling any of the ``showProperties``, ``showMomenta``, ``showVertices``
381 and ``showStatus`` flags. Enabling all of them will look like
386 │ mass=0.14 energy=0.445 charge=-1 lifetime=6.36
387 │ p=(0.257, -0.335, 0.0238) |p|=0.423
388 │ production vertex=(0.113, -0.0531, 0.0156), time=0.00589
389 │ status flags=PrimaryParticle, StableInGenerator, StoppedInDetector
393 mass=0.94 energy=0.94 charge=0 lifetime=5.28e+03
394 p=(-0.000238, -0.0127, 0.0116) |p|=0.0172
395 production vertex=(144, 21.9, -1.29), time=39
396 status flags=StoppedInDetector
397 creation process=HadronInelastic
400 The first line of extra information is enabled by ``showProperties``, the
401 second line by ``showMomenta``, the third line by ``showVertices`` and the
402 last two lines by ``showStatus``. Note that all values are given in Belle II
403 standard units, that is GeV, centimeter and nanoseconds.
405 The depth of the tree can be limited with the ``maxLevel`` argument: If it's
406 bigger than zero it will limit the tree to the given number of generations.
407 A visual indicator will be added after each particle which would have
408 additional daughters that are skipped due to this limit. An example event
409 with ``maxLevel=3`` is given below. In this case only the tau neutrino and
410 the pion don't have additional daughters. ::
412 [INFO] Content of MCParticle list
415 ╰── Upsilon(4S) (300553)
417 │ ├── anti-D*0 (-423) → …
426 The same information will be stored in the branch ``__MCDecayString__`` of
427 TTree created by `VariablesToNtuple` or `VariablesToEventBasedTree` module.
428 This branch is automatically created when `PrintMCParticles` modules is called.
429 Printing the information on the log message can be suppressed if ``suppressPrint``
430 is True, while the branch ``__MCDecayString__``. This option helps to reduce the
431 size of the log message.
434 onlyPrimaries (bool): If True show only primary particles, that is particles coming from
435 the generator and not created by the simulation.
436 maxLevel (int): If 0 or less print the whole tree, otherwise stop after n generations
437 showProperties (bool): If True show mass, energy and charge of the particles
438 showMomenta (bool): if True show the momenta of the particles
439 showVertices (bool): if True show production vertex and production time of all particles
440 showStatus (bool): if True show some status information on the particles.
441 For secondary particles this includes creation process.
442 suppressPrint (bool): if True printing the information on the log message is suppressed.
443 Even if True, the branch ``__MCDecayString__`` is created.
446 return path.add_module(
448 onlyPrimaries=onlyPrimaries,
450 showProperties=showProperties,
451 showMomenta=showMomenta,
452 showVertices=showVertices,
453 showStatus=showStatus,
454 suppressPrint=suppressPrint,
458def correctBrems(outputList,
461 maximumAcceptance=3.0,
462 multiplePhotons=False,
463 usePhotonOnlyOnce=True,
467 For each particle in the given ``inputList``, copies it to the ``outputList`` and adds the
468 4-vector of the photon(s) in the ``gammaList`` which has(have) a weighted named relation to
469 the particle's track, set by the ``ECLTrackBremFinder`` module during reconstruction.
472 So far, there haven't been any comprehensive comparisons of the performance of the `BremsFinder` module, which
473 is called in this function, with the `BelleBremRecovery` module, which is called via the `correctBremsBelle`
474 function. If your analysis is very sensitive to the Bremsstrahlung corrections, it is currently advised to use
477 The reason is that studies by the tau WG revealed that in the past the cuts applied by the
478 ``ECLTrackBremFinder`` module were too tight. They were only loosened for proc16 and MC16. New performance
479 studies are needed to verify that now this module outperforms the Belle-like approach.
482 A detailed description of how the weights are set can be found directly at the documentation of the
483 `BremsFinder` module.
485 Please note that a new particle is always generated, with the old particle and -if found- one or more
486 photons as daughters.
488 The ``inputList`` should contain particles with associated tracks. Otherwise, the module will exit with an error.
490 The ``gammaList`` should contain photons. Otherwise, the module will exit with an error.
492 @param outputList The output particle list name containing the corrected particles
493 @param inputList The initial particle list name containing the particles to correct. *It should already exist.*
494 @param gammaList The photon list containing possibly bremsstrahlung photons; *It should already exist.*
495 @param maximumAcceptance Maximum value of the relation weight. Should be a number between [0,3)
496 @param multiplePhotons Whether to use only one photon (the one with the smallest acceptance) or as many as possible
497 @param usePhotonOnlyOnce If true, each brems candidate is used to correct only the track with the smallest relation weight
498 @param writeOut Whether `RootOutput` module should save the created ``outputList``
499 @param path The module is added to this path
504 B2ERROR(
"The BremsFinder can only be run over Belle II data.")
506 bremscorrector = register_module(
'BremsFinder')
507 bremscorrector.set_name(
'bremsCorrector_' + outputList)
508 bremscorrector.param(
'inputList', inputList)
509 bremscorrector.param(
'outputList', outputList)
510 bremscorrector.param(
'gammaList', gammaList)
511 bremscorrector.param(
'maximumAcceptance', maximumAcceptance)
512 bremscorrector.param(
'multiplePhotons', multiplePhotons)
513 bremscorrector.param(
'usePhotonOnlyOnce', usePhotonOnlyOnce)
514 bremscorrector.param(
'writeOut', writeOut)
515 path.add_module(bremscorrector)
518def copyList(outputListName, inputListName, writeOut=False, path=None):
520 Copy all Particle indices from input ParticleList to the output ParticleList.
521 Note that the Particles themselves are not copied. The original and copied
522 ParticleLists will point to the same Particles.
524 @param ouputListName copied ParticleList
525 @param inputListName original ParticleList to be copied
526 @param writeOut whether RootOutput module should save the created ParticleList
527 @param path modules are added to this path
530 copyLists(outputListName, [inputListName], writeOut, path)
533def correctBremsBelle(outputListName,
536 multiplePhotons=True,
538 usePhotonOnlyOnce=False,
542 Run the Belle - like brems finding on the ``inputListName`` of charged particles.
543 Adds all photons in ``gammaListName`` to a copy of the charged particle that are within
547 Studies by the tau WG show that using a rather wide opening angle (up to
548 0.2 rad) and rather low energetic photons results in good correction.
549 However, this should only serve as a starting point for your own studies
550 because the optimal criteria are likely mode-dependent
553 outputListName (str): The output charged particle list containing the corrected charged particles
554 inputListName (str): The initial charged particle list containing the charged particles to correct.
555 gammaListName (str): The gammas list containing possibly radiative gammas, should already exist.
556 multiplePhotons (bool): How many photons should be added to the charged particle? nearest one -> False,
557 add all the photons within the cone -> True
558 angleThreshold (float): The maximum angle in radians between the charged particle and the (radiative)
559 gamma to be accepted.
560 writeOut (bool): whether RootOutput module should save the created ParticleList
561 usePhotonOnlyOnce (bool): If true, a photon is used for correction of the closest charged particle in the inputList.
562 If false, a photon is allowed to be used for correction multiple times (Default).
565 One cannot use a photon twice to reconstruct a composite particle. Thus, for example, if ``e+`` and ``e-`` are corrected
566 with a ``gamma``, the pair of ``e+`` and ``e-`` cannot form a ``J/psi -> e+ e-`` candidate.
568 path (basf2.Path): modules are added to this path
571 fsrcorrector = register_module(
'BelleBremRecovery')
572 fsrcorrector.set_name(
'BelleFSRCorrection_' + outputListName)
573 fsrcorrector.param(
'inputListName', inputListName)
574 fsrcorrector.param(
'outputListName', outputListName)
575 fsrcorrector.param(
'gammaListName', gammaListName)
576 fsrcorrector.param(
'multiplePhotons', multiplePhotons)
577 fsrcorrector.param(
'angleThreshold', angleThreshold)
578 fsrcorrector.param(
'usePhotonOnlyOnce', usePhotonOnlyOnce)
579 fsrcorrector.param(
'writeOut', writeOut)
580 path.add_module(fsrcorrector)
583def copyLists(outputListName, inputListNames, writeOut=False, path=None):
585 Copy all Particle indices from all input ParticleLists to the
586 single output ParticleList.
587 Note that the Particles themselves are not copied.
588 The original and copied ParticleLists will point to the same Particles.
590 Duplicates are removed based on the first-come, first-served principle.
591 Therefore, the order of the input ParticleLists matters.
594 If you want to select the best duplicate based on another criterion, have
595 a look at the function `mergeListsWithBestDuplicate`.
598 Two particles that differ only by the order of their daughters are
599 considered duplicates and one of them will be removed.
601 @param ouputListName copied ParticleList
602 @param inputListName vector of original ParticleLists to be copied
603 @param writeOut whether RootOutput module should save the created ParticleList
604 @param path modules are added to this path
607 pmanipulate = register_module(
'ParticleListManipulator')
608 pmanipulate.set_name(
'PListCopy_' + outputListName)
609 pmanipulate.param(
'outputListName', outputListName)
610 pmanipulate.param(
'inputListNames', inputListNames)
611 pmanipulate.param(
'writeOut', writeOut)
612 path.add_module(pmanipulate)
615def copyParticles(outputListName, inputListName, writeOut=False, path=None):
617 Create copies of Particles given in the input ParticleList and add them to the output ParticleList.
619 The existing relations of the original Particle (or it's (grand-)^n-daughters)
620 are copied as well. Note that only the relation is copied and that the related
621 object is not. Copied particles are therefore related to the *same* object as
624 @param ouputListName new ParticleList filled with copied Particles
625 @param inputListName input ParticleList with original Particles
626 @param writeOut whether RootOutput module should save the created ParticleList
627 @param path modules are added to this path
631 pmanipulate = register_module(
'ParticleListManipulator')
632 pmanipulate.set_name(
'PListCopy_' + outputListName)
633 pmanipulate.param(
'outputListName', outputListName)
634 pmanipulate.param(
'inputListNames', [inputListName])
635 pmanipulate.param(
'writeOut', writeOut)
636 path.add_module(pmanipulate)
639 pcopy = register_module(
'ParticleCopier')
640 pcopy.param(
'inputListNames', [outputListName])
641 path.add_module(pcopy)
644def cutAndCopyLists(outputListName, inputListNames, cut, writeOut=False, path=None):
646 Copy candidates from all lists in ``inputListNames`` to
647 ``outputListName`` if they pass ``cut`` (given selection criteria).
650 Note that the Particles themselves are not copied.
651 The original and copied ParticleLists will point to the same Particles.
654 Require energetic pions safely inside the cdc
656 .. code-block:: python
658 cutAndCopyLists("pi+:energeticPions", ["pi+:good", "pi+:loose"], "[E > 2] and thetaInCDCAcceptance", path=mypath)
661 You must use square braces ``[`` and ``]`` for conditional statements.
664 outputListName (str): the new ParticleList name
665 inputListName (list(str)): list of input ParticleList names
666 cut (str): Candidates that do not pass these selection criteria are removed from the ParticleList
667 writeOut (bool): whether RootOutput module should save the created ParticleList
668 path (basf2.Path): modules are added to this path
671 pmanipulate = register_module(
'ParticleListManipulator')
672 pmanipulate.set_name(
'PListCutAndCopy_' + outputListName)
673 pmanipulate.param(
'outputListName', outputListName)
674 pmanipulate.param(
'inputListNames', inputListNames)
675 pmanipulate.param(
'cut', cut)
676 pmanipulate.param(
'writeOut', writeOut)
677 path.add_module(pmanipulate)
680def cutAndCopyList(outputListName, inputListName, cut, writeOut=False, path=None):
682 Copy candidates from ``inputListName`` to ``outputListName`` if they pass
683 ``cut`` (given selection criteria).
686 Note the Particles themselves are not copied.
687 The original and copied ParticleLists will point to the same Particles.
690 require energetic pions safely inside the cdc
692 .. code-block:: python
694 cutAndCopyList("pi+:energeticPions", "pi+:loose", "[E > 2] and thetaInCDCAcceptance", path=mypath)
697 You must use square braces ``[`` and ``]`` for conditional statements.
700 outputListName (str): the new ParticleList name
701 inputListName (str): input ParticleList name
702 cut (str): Candidates that do not pass these selection criteria are removed from the ParticleList
703 writeOut (bool): whether RootOutput module should save the created ParticleList
704 path (basf2.Path): modules are added to this path
707 cutAndCopyLists(outputListName, [inputListName], cut, writeOut, path)
710def removeTracksForTrackingEfficiencyCalculation(inputListNames, fraction, path=None):
712 Randomly remove tracks from the provided particle lists to estimate the tracking efficiency.
713 Takes care of the duplicates, if any.
716 inputListNames (list(str)): input particle list names
717 fraction (float): fraction of particles to be removed randomly
718 path (basf2.Path): module is added to this path
721 trackingefficiency = register_module(
'TrackingEfficiency')
722 trackingefficiency.param(
'particleLists', inputListNames)
723 trackingefficiency.param(
'frac', fraction)
724 path.add_module(trackingefficiency)
727def scaleTrackMomenta(inputListNames, scale=float(
'nan'), payloadName=
"", scalingFactorName=
"SF", path=
None):
729 Scale momenta of the particles according to a scaling factor scale.
730 This scaling factor can either be given as constant number or as the name of the payload which contains
731 the variable scale factors.
732 If the particle list contains composite particles, the momenta of the track-based daughters are scaled.
733 Subsequently, the momentum of the mother particle is updated as well.
736 inputListNames (list(str)): input particle list names
737 scale (float): scaling factor (1.0 -- no scaling)
738 payloadName (str): name of the payload which contains the phase-space dependent scaling factors
739 scalingFactorName (str): name of scaling factor variable in the payload.
740 path (basf2.Path): module is added to this path
745 B2ERROR(
"The tracking momentum scaler can only be run over Belle II data.")
747 TrackingMomentumScaleFactors = register_module(
'TrackingMomentumScaleFactors')
748 TrackingMomentumScaleFactors.param(
'particleLists', inputListNames)
749 TrackingMomentumScaleFactors.param(
'scale', scale)
750 TrackingMomentumScaleFactors.param(
'payloadName', payloadName)
751 TrackingMomentumScaleFactors.param(
'scalingFactorName', scalingFactorName)
753 path.add_module(TrackingMomentumScaleFactors)
756def correctTrackEnergy(inputListNames, correction=float(
'nan'), payloadName=
"", correctionName=
"SF", path=
None):
758 Correct the energy loss of tracks according to a 'correction' value.
759 This correction can either be given as constant number or as the name of the payload which contains
760 the variable corrections.
761 If the particle list contains composite particles, the momenta of the track-based daughters are corrected.
762 Subsequently, the momentum of the mother particle is updated as well.
765 inputListNames (list(str)): input particle list names
766 correction (float): correction value to be subtracted to the particle energy (0.0 -- no correction)
767 payloadName (str): name of the payload which contains the phase-space dependent scaling factors
768 correctionName (str): name of correction variable in the payload.
769 path (basf2.Path): module is added to this path
774 B2ERROR(
"The tracking energy correction can only be run over Belle II data.")
776 TrackingEnergyLossCorrection = register_module(
'TrackingEnergyLossCorrection')
777 TrackingEnergyLossCorrection.param(
'particleLists', inputListNames)
778 TrackingEnergyLossCorrection.param(
'correction', correction)
779 TrackingEnergyLossCorrection.param(
'payloadName', payloadName)
780 TrackingEnergyLossCorrection.param(
'correctionName', correctionName)
782 path.add_module(TrackingEnergyLossCorrection)
785def smearTrackMomenta(inputListNames, payloadName="", smearingFactorName="smear", path=None):
787 Smear the momenta of the particles according the values read from the given payload.
788 If the particle list contains composite particles, the momenta of the track-based daughters are smeared.
789 Subsequently, the momentum of the mother particle is updated as well.
792 inputListNames (list(str)): input particle list names
793 payloadName (str): name of the payload which contains the smearing values
794 smearingFactorName (str): name of smearing factor variable in the payload.
795 path (basf2.Path): module is added to this path
798 TrackingMomentumScaleFactors = register_module(
'TrackingMomentumScaleFactors')
799 TrackingMomentumScaleFactors.param(
'particleLists', inputListNames)
800 TrackingMomentumScaleFactors.param(
'payloadName', payloadName)
801 TrackingMomentumScaleFactors.param(
'smearingFactorName', smearingFactorName)
803 path.add_module(TrackingMomentumScaleFactors)
806def mergeListsWithBestDuplicate(outputListName,
811 ignoreMotherFlavor=False,
814 Merge input ParticleLists into one output ParticleList. Only the best
815 among duplicates is kept. The lowest or highest value (configurable via
816 preferLowest) of the provided variable determines which duplicate is the
819 @param ouputListName name of merged ParticleList
820 @param inputListName vector of original ParticleLists to be merged
821 @param variable variable to determine best duplicate
822 @param preferLowest whether lowest or highest value of variable should be preferred
823 @param writeOut whether RootOutput module should save the created ParticleList
824 @param ignoreMotherFlavor whether the flavor of the mother particle is ignored when trying to find duplicates
825 @param path modules are added to this path
828 pmanipulate = register_module(
'ParticleListManipulator')
829 pmanipulate.set_name(
'PListMerger_' + outputListName)
830 pmanipulate.param(
'outputListName', outputListName)
831 pmanipulate.param(
'inputListNames', inputListNames)
832 pmanipulate.param(
'variable', variable)
833 pmanipulate.param(
'preferLowest', preferLowest)
834 pmanipulate.param(
'writeOut', writeOut)
835 pmanipulate.param(
'ignoreMotherFlavor', ignoreMotherFlavor)
836 path.add_module(pmanipulate)
839def fillSignalSideParticleList(outputListName, decayString, path):
841 This function should only be used in the ROE path, that is a path
842 that is executed for each ROE object in the DataStore.
844 Example: fillSignalSideParticleList('gamma:sig','B0 -> K*0 ^gamma', roe_path)
846 Function will create a ParticleList with name 'gamma:sig' which will be filled
847 with the existing photon Particle, being the second daughter of the B0 candidate
848 to which the ROE object has to be related.
850 @param ouputListName name of the created ParticleList
851 @param decayString specify Particle to be added to the ParticleList
854 pload = register_module(
'SignalSideParticleListCreator')
855 pload.set_name(
'SSParticleList_' + outputListName)
856 pload.param(
'particleListName', outputListName)
857 pload.param(
'decayString', decayString)
858 path.add_module(pload)
861def fillParticleLists(decayStringsWithCuts, writeOut=False, path=None, enforceFitHypothesis=False,
862 loadPhotonsFromKLM=False):
864 Creates Particles of the desired types from the corresponding ``mdst`` dataobjects,
865 loads them to the ``StoreArray<Particle>`` and fills the ParticleLists.
867 The multiple ParticleLists with their own selection criteria are specified
868 via list tuples (decayString, cut), for example
870 .. code-block:: python
872 kaons = ('K+:mykaons', 'kaonID>0.1')
873 pions = ('pi+:mypions','pionID>0.1')
874 fillParticleLists([kaons, pions], path=mypath)
876 If you are unsure what selection you want, you might like to see the
877 :doc:`StandardParticles` functions.
879 The type of the particles to be loaded is specified via the decayString module parameter.
880 The type of the ``mdst`` dataobject that is used as an input is determined from the type of
881 the particle. The following types of the particles can be loaded:
883 * charged final state particles (input ``mdst`` type = Tracks)
884 - e+, mu+, pi+, K+, p, deuteron (and charge conjugated particles)
886 * neutral final state particles
887 - "gamma" (input ``mdst`` type = ECLCluster)
888 - "K_S0", "Lambda0" (input ``mdst`` type = V0)
889 - "K_L0", "n0" (input ``mdst`` type = KLMCluster or ECLCluster)
892 For "K_S0" and "Lambda0" you must specify the daughter ordering.
894 For example, to load V0s as :math:`\\Lambda^0\\to p^+\\pi^-` decays from V0s:
896 .. code-block:: python
898 v0lambdas = ('Lambda0 -> p+ pi-', '0.9 < M < 1.3')
899 fillParticleLists([kaons, pions, v0lambdas], path=mypath)
902 Gammas can also be loaded from KLMClusters by explicitly setting the
903 parameter ``loadPhotonsFromKLM`` to True. However, this should only be
904 done in selected use-cases and the effect should be studied carefully.
907 For "K_L0" it is now possible to load from ECLClusters, to revert to
908 the old (Belle) behavior, you can require ``'isFromKLM > 0'``.
910 .. code-block:: python
912 klongs = ('K_L0', 'isFromKLM > 0')
913 fillParticleLists([kaons, pions, klongs], path=mypath)
915 * Charged kinks final state particles (input ``mdst`` type = Kink)
918 To reconstruct charged particle kink you must specify the daughter.
920 For example, to load Kinks as :math:`K^- \\to \\pi^-\\pi^0` decays from Kinks:
922 .. code-block:: python
924 kinkKaons = ('K- -> pi-', yourCut)
925 fillParticleLists([kaons, pions, v0lambdas, kinkKaons], path=mypath)
929 decayStringsWithCuts (list): A list of python ntuples of (decayString, cut).
930 The decay string determines the type of Particle
931 and the name of the ParticleList.
932 If the input MDST type is V0 the whole
933 decay chain needs to be specified, so that
934 the user decides and controls the daughters
935 ' order (e.g. ``K_S0 -> pi+ pi-``).
936 If the input MDST type is Kink the decay chain needs to be specified
937 with only one daughter (e.g. ``K- -> pi-``).
938 The cut is the selection criteria
939 to be added to the ParticleList. It can be an empty string.
940 writeOut (bool): whether RootOutput module should save the created ParticleList
941 path (basf2.Path): modules are added to this path
942 enforceFitHypothesis (bool): If true, Particles will be created only for the tracks which have been fitted
943 using a mass hypothesis of the exact type passed to fillParticleLists().
944 If enforceFitHypothesis is False (the default) the next closest fit hypothesis
945 in terms of mass difference will be used if the fit using exact particle
946 type is not available.
947 loadPhotonsFromKLM (bool): If true, photon candidates will be created from KLMClusters as well.
950 pload = register_module(
'ParticleLoader')
951 pload.set_name(
'ParticleLoader_' +
'PLists')
952 pload.param(
'decayStrings', [decayString
for decayString, cut
in decayStringsWithCuts])
953 pload.param(
'writeOut', writeOut)
954 pload.param(
"enforceFitHypothesis", enforceFitHypothesis)
955 path.add_module(pload)
957 from ROOT
import Belle2
959 for decayString, cut
in decayStringsWithCuts:
960 if not decayDescriptor.init(decayString):
961 raise ValueError(
"Invalid decay string")
963 if decayDescriptor.getNDaughters() > 0:
968 if (decayDescriptor.getNDaughters() == 1)
and (decayDescriptor.getMother().getLabel() !=
'kink'):
969 copyList(decayDescriptor.getMother().getFullName(), decayDescriptor.getMother().getName() +
':kink',
971 if (decayDescriptor.getNDaughters() > 1)
and (decayDescriptor.getMother().getLabel() !=
'V0'):
972 copyList(decayDescriptor.getMother().getFullName(), decayDescriptor.getMother().getName() +
':V0', writeOut, path)
973 elif (decayDescriptor.getMother().getLabel() !=
'all' and
974 abs(decayDescriptor.getMother().getPDGCode()) != Belle2.Const.neutron.getPDGCode()):
977 copyList(decayString, decayDescriptor.getMother().getName() +
':all', writeOut, path)
981 applyCuts(decayDescriptor.getMother().getFullName(), cut, path)
983 if decayString.startswith(
"gamma"):
986 if not loadPhotonsFromKLM:
987 applyCuts(decayString,
'isFromECL', path)
990def fillParticleList(decayString, cut, writeOut=False, path=None, enforceFitHypothesis=False,
991 loadPhotonsFromKLM=False):
993 Creates Particles of the desired type from the corresponding ``mdst`` dataobjects,
994 loads them to the StoreArray<Particle> and fills the ParticleList.
997 the :doc:`StandardParticles` functions.
999 The type of the particles to be loaded is specified via the decayString module parameter.
1000 The type of the ``mdst`` dataobject that is used as an input is determined from the type of
1001 the particle. The following types of the particles can be loaded:
1003 * charged final state particles (input ``mdst`` type = Tracks)
1004 - e+, mu+, pi+, K+, p, deuteron (and charge conjugated particles)
1006 * neutral final state particles
1007 - "gamma" (input ``mdst`` type = ECLCluster)
1008 - "K_S0", "Lambda0" (input ``mdst`` type = V0)
1009 - "K_L0", "n0" (input ``mdst`` type = KLMCluster or ECLCluster)
1012 For "K_S0" and "Lambda0" you must specify the daughter ordering.
1014 For example, to load V0s as :math:`\\Lambda^0\\to p^+\\pi^-` decays from V0s:
1016 .. code-block:: python
1018 fillParticleList('Lambda0 -> p+ pi-', '0.9 < M < 1.3', path=mypath)
1021 Gammas can also be loaded from KLMClusters by explicitly setting the
1022 parameter ``loadPhotonsFromKLM`` to True. However, this should only be
1023 done in selected use-cases and the effect should be studied carefully.
1026 For "K_L0" it is now possible to load from ECLClusters, to revert to
1027 the old (Belle) behavior, you can require ``'isFromKLM > 0'``.
1029 .. code-block:: python
1031 fillParticleList('K_L0', 'isFromKLM > 0', path=mypath)
1033 * Charged kinks final state particles (input ``mdst`` type = Kink)
1036 To reconstruct charged particle kink you must specify the daughter.
1038 For example, to load Kinks as :math:`K^- \\to \\pi^-\\pi^0` decays from Kinks:
1040 .. code-block:: python
1042 fillParticleList('K- -> pi-', yourCut, path=mypath)
1046 decayString (str): Type of Particle and determines the name of the ParticleList.
1047 If the input MDST type is V0 the whole decay chain needs to be specified, so that
1048 the user decides and controls the daughters' order (e.g. ``K_S0 -> pi+ pi-``).
1049 If the input MDST type is Kink the decay chain needs to be specified
1050 with only one daughter (e.g. ``K- -> pi-``).
1051 cut (str): Particles need to pass these selection criteria to be added to the ParticleList
1052 writeOut (bool): whether RootOutput module should save the created ParticleList
1053 path (basf2.Path): modules are added to this path
1054 enforceFitHypothesis (bool): If true, Particles will be created only for the tracks which have been fitted
1055 using a mass hypothesis of the exact type passed to fillParticleLists().
1056 If enforceFitHypothesis is False (the default) the next closest fit hypothesis
1057 in terms of mass difference will be used if the fit using exact particle
1058 type is not available.
1059 loadPhotonsFromKLM (bool): If true, photon candidates will be created from KLMClusters as well.
1062 pload = register_module(
'ParticleLoader')
1063 pload.set_name(
'ParticleLoader_' + decayString)
1064 pload.param(
'decayStrings', [decayString])
1065 pload.param(
'writeOut', writeOut)
1066 pload.param(
"enforceFitHypothesis", enforceFitHypothesis)
1067 path.add_module(pload)
1070 from ROOT
import Belle2
1072 if not decayDescriptor.init(decayString):
1073 raise ValueError(
"Invalid decay string")
1074 if decayDescriptor.getNDaughters() > 0:
1079 if (decayDescriptor.getNDaughters() == 1)
and (decayDescriptor.getMother().getLabel() !=
'kink'):
1080 copyList(decayDescriptor.getMother().getFullName(), decayDescriptor.getMother().getName() +
':kink',
1082 if (decayDescriptor.getNDaughters() > 1)
and (decayDescriptor.getMother().getLabel() !=
'V0'):
1083 copyList(decayDescriptor.getMother().getFullName(), decayDescriptor.getMother().getName() +
':V0', writeOut,
1085 elif (decayDescriptor.getMother().getLabel() !=
'all' and
1086 abs(decayDescriptor.getMother().getPDGCode()) != Belle2.Const.neutron.getPDGCode()):
1089 copyList(decayString, decayDescriptor.getMother().getName() +
':all', writeOut, path)
1093 applyCuts(decayDescriptor.getMother().getFullName(), cut, path)
1095 if decayString.startswith(
"gamma"):
1098 if not loadPhotonsFromKLM:
1099 applyCuts(decayString,
'isFromECL', path)
1102def fillParticleListWithTrackHypothesis(decayString,
1106 enforceFitHypothesis=False,
1109 As fillParticleList, but if used for a charged FSP, loads the particle with the requested hypothesis if available
1111 @param decayString specifies type of Particles and determines the name of the ParticleList
1112 @param cut Particles need to pass these selection criteria to be added to the ParticleList
1113 @param hypothesis the PDG code of the desired track hypothesis
1114 @param writeOut whether RootOutput module should save the created ParticleList
1115 @param enforceFitHypothesis If true, Particles will be created only for the tracks which have been fitted
1116 using a mass hypothesis of the exact type passed to fillParticleLists().
1117 If enforceFitHypothesis is False (the default) the next closest fit hypothesis
1118 in terms of mass difference will be used if the fit using exact particle
1119 type is not available.
1120 @param path modules are added to this path
1123 pload = register_module(
'ParticleLoader')
1124 pload.set_name(
'ParticleLoader_' + decayString)
1125 pload.param(
'decayStrings', [decayString])
1126 pload.param(
'trackHypothesis', hypothesis)
1127 pload.param(
'writeOut', writeOut)
1128 pload.param(
"enforceFitHypothesis", enforceFitHypothesis)
1129 path.add_module(pload)
1131 from ROOT
import Belle2
1133 if not decayDescriptor.init(decayString):
1134 raise ValueError(
"Invalid decay string")
1135 if decayDescriptor.getMother().getLabel() !=
'all':
1138 copyList(decayString, decayDescriptor.getMother().getName() +
':all', writeOut, path)
1142 applyCuts(decayString, cut, path)
1145def fillConvertedPhotonsList(decayString, cut, writeOut=False, path=None):
1147 Creates photon Particle object for each e+e- combination in the V0 StoreArray.
1150 You must specify the daughter ordering.
1152 .. code-block:: python
1154 fillConvertedPhotonsList('gamma:converted -> e+ e-', '', path=mypath)
1157 decayString (str): Must be gamma to an e+e- pair. You must specify the daughter ordering.
1158 Will also determine the name of the particleList.
1159 cut (str): Particles need to pass these selection criteria to be added to the ParticleList
1160 writeOut (bool): whether RootOutput module should save the created ParticleList
1161 path (basf2.Path): modules are added to this path
1167 B2ERROR(
'For Belle converted photons are available in the pre-defined list "gamma:v0mdst".')
1169 pload = register_module(
'ParticleLoader')
1170 pload.set_name(
'ParticleLoader_' + decayString)
1171 pload.param(
'decayStrings', [decayString])
1172 pload.param(
'addDaughters',
True)
1173 pload.param(
'writeOut', writeOut)
1174 path.add_module(pload)
1176 from ROOT
import Belle2
1178 if not decayDescriptor.init(decayString):
1179 raise ValueError(
"Invalid decay string")
1180 if decayDescriptor.getMother().getLabel() !=
'V0':
1183 copyList(decayDescriptor.getMother().getFullName(), decayDescriptor.getMother().getName() +
':V0', writeOut, path)
1187 applyCuts(decayDescriptor.getMother().getFullName(), cut, path)
1190def fillParticleListFromROE(decayString,
1193 sourceParticleListName='',
1198 Creates Particle object for each ROE of the desired type found in the
1199 StoreArray<RestOfEvent>, loads them to the StoreArray<Particle>
1200 and fills the ParticleList. If useMissing is True, then the missing
1201 momentum is used instead of ROE.
1203 The type of the particles to be loaded is specified via the decayString module parameter.
1205 @param decayString specifies type of Particles and determines the name of the ParticleList.
1206 Source ROEs can be taken as a daughter list, for example:
1207 'B0:tagFromROE -> B0:signal'
1208 @param cut Particles need to pass these selection criteria to be added to the ParticleList
1209 @param maskName Name of the ROE mask to use
1210 @param sourceParticleListName Use related ROEs to this particle list as a source
1211 @param useMissing Use missing momentum instead of ROE momentum
1212 @param writeOut whether RootOutput module should save the created ParticleList
1213 @param path modules are added to this path
1216 pload = register_module(
'ParticleLoader')
1217 pload.set_name(
'ParticleLoader_' + decayString)
1218 pload.param(
'decayStrings', [decayString])
1219 pload.param(
'writeOut', writeOut)
1220 pload.param(
'roeMaskName', maskName)
1221 pload.param(
'useMissing', useMissing)
1222 pload.param(
'sourceParticleListName', sourceParticleListName)
1223 pload.param(
'useROEs',
True)
1224 path.add_module(pload)
1226 from ROOT
import Belle2
1228 if not decayDescriptor.init(decayString):
1229 raise ValueError(
"Invalid decay string")
1233 applyCuts(decayDescriptor.getMother().getFullName(), cut, path)
1236def fillParticleListFromDummy(decayString,
1239 treatAsInvisible=True,
1243 Creates a ParticleList and fills it with dummy Particles. For self-conjugated Particles one dummy
1244 Particle is created, for Particles that are not self-conjugated one Particle and one anti-Particle is
1245 created. The four-momentum is set to zero.
1247 The type of the particles to be loaded is specified via the decayString module parameter.
1249 @param decayString specifies type of Particles and determines the name of the ParticleList
1250 @param mdstIndex sets the mdst index of Particles
1251 @param covMatrix sets the value of the diagonal covariance matrix of Particles
1252 @param treatAsInvisible whether treeFitter should treat the Particles as invisible
1253 @param writeOut whether RootOutput module should save the created ParticleList
1254 @param path modules are added to this path
1257 pload = register_module(
'ParticleLoader')
1258 pload.set_name(
'ParticleLoader_' + decayString)
1259 pload.param(
'decayStrings', [decayString])
1260 pload.param(
'useDummy',
True)
1261 pload.param(
'dummyMDSTIndex', mdstIndex)
1262 pload.param(
'dummyCovMatrix', covMatrix)
1263 pload.param(
'dummyTreatAsInvisible', treatAsInvisible)
1264 pload.param(
'writeOut', writeOut)
1265 path.add_module(pload)
1268def fillParticleListFromMC(decayString,
1271 skipNonPrimaryDaughters=False,
1274 skipNonPrimary=False,
1277 Creates Particle object for each MCParticle of the desired type found in the StoreArray<MCParticle>,
1278 loads them to the StoreArray<Particle> and fills the ParticleList.
1280 The type of the particles to be loaded is specified via the decayString module parameter.
1282 @param decayString specifies type of Particles and determines the name of the ParticleList
1283 @param cut Particles need to pass these selection criteria to be added to the ParticleList
1284 @param addDaughters adds the bottom part of the decay chain of the particle to the datastore and
1285 sets mother-daughter relations
1286 @param skipNonPrimaryDaughters if true, skip non primary daughters, useful to study final state daughter particles
1287 @param writeOut whether RootOutput module should save the created ParticleList
1288 @param path modules are added to this path
1289 @param skipNonPrimary if true, skip non primary particle
1290 @param skipInitial if true, skip initial particles
1293 pload = register_module(
'ParticleLoader')
1294 pload.set_name(
'ParticleLoader_' + decayString)
1295 pload.param(
'decayStrings', [decayString])
1296 pload.param(
'addDaughters', addDaughters)
1297 pload.param(
'skipNonPrimaryDaughters', skipNonPrimaryDaughters)
1298 pload.param(
'writeOut', writeOut)
1299 pload.param(
'useMCParticles',
True)
1300 pload.param(
'skipNonPrimary', skipNonPrimary)
1301 pload.param(
'skipInitial', skipInitial)
1302 path.add_module(pload)
1304 from ROOT
import Belle2
1306 if not decayDescriptor.init(decayString):
1307 raise ValueError(
"Invalid decay string")
1311 applyCuts(decayString, cut, path)
1314def fillParticleListsFromMC(decayStringsWithCuts,
1316 skipNonPrimaryDaughters=False,
1319 skipNonPrimary=False,
1322 Creates Particle object for each MCParticle of the desired type found in the StoreArray<MCParticle>,
1323 loads them to the StoreArray<Particle> and fills the ParticleLists.
1325 The types of the particles to be loaded are specified via the (decayString, cut) tuples given in a list.
1328 .. code-block:: python
1330 kaons = ('K+:gen', '')
1331 pions = ('pi+:gen', 'pionID>0.1')
1332 fillParticleListsFromMC([kaons, pions], path=mypath)
1335 Daughters of ``Lambda0`` are not primary, but ``Lambda0`` is not final state particle.
1336 Thus, when one reconstructs a particle from ``Lambda0``, that is created with
1337 ``addDaughters=True`` and ``skipNonPrimaryDaughters=True``, the particle always has ``isSignal==0``.
1338 Please set options for ``Lambda0`` to use MC-matching variables properly as follows,
1339 ``addDaughters=True`` and ``skipNonPrimaryDaughters=False``.
1341 @param decayString specifies type of Particles and determines the name of the ParticleList
1342 @param cut Particles need to pass these selection criteria to be added to the ParticleList
1343 @param addDaughters adds the bottom part of the decay chain of the particle to the datastore and
1344 sets mother-daughter relations
1345 @param skipNonPrimaryDaughters if true, skip non primary daughters, useful to study final state daughter particles
1346 @param writeOut whether RootOutput module should save the created ParticleList
1347 @param path modules are added to this path
1348 @param skipNonPrimary if true, skip non primary particle
1349 @param skipInitial if true, skip initial particles
1352 pload = register_module(
'ParticleLoader')
1353 pload.set_name(
'ParticleLoader_' +
'PLists')
1354 pload.param(
'decayStrings', [decayString
for decayString, cut
in decayStringsWithCuts])
1355 pload.param(
'addDaughters', addDaughters)
1356 pload.param(
'skipNonPrimaryDaughters', skipNonPrimaryDaughters)
1357 pload.param(
'writeOut', writeOut)
1358 pload.param(
'useMCParticles',
True)
1359 pload.param(
'skipNonPrimary', skipNonPrimary)
1360 pload.param(
'skipInitial', skipInitial)
1361 path.add_module(pload)
1363 from ROOT
import Belle2
1365 for decayString, cut
in decayStringsWithCuts:
1366 if not decayDescriptor.init(decayString):
1367 raise ValueError(
"Invalid decay string")
1371 applyCuts(decayString, cut, path)
1374def fillParticleListFromChargedCluster(outputParticleList,
1377 useOnlyMostEnergeticECLCluster=True,
1381 Creates the Particle object from ECLCluster and KLMCluster that are being matched with the Track of inputParticleList.
1383 @param outputParticleList The output ParticleList. Only neutral final state particles are supported.
1384 @param inputParticleList The input ParticleList that is required to have the relation to the Track object.
1385 @param cut Particles need to pass these selection criteria to be added to the ParticleList
1386 @param useOnlyMostEnergeticECLCluster If True, only the most energetic ECLCluster among ones that are matched with the Track is
1387 used. If False, all matched ECLClusters are loaded. The default is True. Regardless of
1388 this option, the KLMCluster is loaded.
1389 @param writeOut whether RootOutput module should save the created ParticleList
1390 @param path modules are added to this path
1393 pload = register_module(
'ParticleLoader')
1394 pload.set_name(
'ParticleLoader_' + outputParticleList)
1396 pload.param(
'decayStrings', [outputParticleList])
1397 pload.param(
'sourceParticleListName', inputParticleList)
1398 pload.param(
'writeOut', writeOut)
1399 pload.param(
'loadChargedCluster',
True)
1400 pload.param(
'useOnlyMostEnergeticECLCluster', useOnlyMostEnergeticECLCluster)
1401 path.add_module(pload)
1405 applyCuts(outputParticleList, cut, path)
1408def extractParticlesFromROE(particleLists,
1409 signalSideParticleList=None,
1414 Extract Particle objects that belong to the Rest-Of-Events and fill them into the ParticleLists.
1415 The types of the particles other than those specified by ``particleLists`` are not stored.
1416 If one creates a ROE with ``fillWithMostLikely=True`` via `buildRestOfEvent`, for example,
1417 one should create particleLists for not only ``pi+``, ``gamma``, ``K_L0`` but also other charged final state particles.
1419 When one calls the function in the main path, one has to set the argument ``signalSideParticleList`` and the signal side
1420 ParticleList must have only one candidate.
1422 .. code-block:: python
1424 buildRestOfEvent('B0:sig', fillWithMostLikely=True, path=mypath)
1426 roe_path = create_path()
1427 deadEndPath = create_path()
1428 signalSideParticleFilter('B0:sig', '', roe_path, deadEndPath)
1430 plists = ['%s:in_roe' % ptype for ptype in ['pi+', 'gamma', 'K_L0', 'K+', 'p+', 'e+', 'mu+']]
1431 extractParticlesFromROE(plists, maskName='all', path=roe_path)
1433 # one can analyze these ParticleLists in the roe_path
1435 mypath.for_each('RestOfEvent', 'RestOfEvents', roe_path)
1437 rankByLowest('B0:sig', 'deltaE', numBest=1, path=mypath)
1438 extractParticlesFromROE(plists, signalSideParticleList='B0:sig', maskName='all', path=mypath)
1440 # one can analyze these ParticleLists in the main path
1443 @param particleLists (str or list(str)) Name of output ParticleLists
1444 @param signalSideParticleList (str) Name of signal side ParticleList
1445 @param maskName (str) Name of the ROE mask to be applied on Particles
1446 @param writeOut (bool) whether RootOutput module should save the created ParticleList
1447 @param path (basf2.Path) modules are added to this path
1450 if isinstance(particleLists, str):
1451 particleLists = [particleLists]
1453 pext = register_module(
'ParticleExtractorFromROE')
1454 pext.set_name(
'ParticleExtractorFromROE_' +
'_'.join(particleLists))
1455 pext.param(
'outputListNames', particleLists)
1456 if signalSideParticleList
is not None:
1457 pext.param(
'signalSideParticleListName', signalSideParticleList)
1458 pext.param(
'maskName', maskName)
1459 pext.param(
'writeOut', writeOut)
1460 path.add_module(pext)
1463def applyCuts(list_name, cut, path):
1465 Removes particle candidates from ``list_name`` that do not pass ``cut``
1466 (given selection criteria).
1469 require energetic pions safely inside the cdc
1471 .. code-block:: python
1473 applyCuts("pi+:mypions", "[E > 2] and thetaInCDCAcceptance", path=mypath)
1476 You must use square braces ``[`` and ``]`` for conditional statements.
1479 list_name (str): input ParticleList name
1480 cut (str): Candidates that do not pass these selection criteria are removed from the ParticleList
1481 path (basf2.Path): modules are added to this path
1484 pselect = register_module(
'ParticleSelector')
1485 pselect.set_name(
'ParticleSelector_applyCuts_' + list_name)
1486 pselect.param(
'decayString', list_name)
1487 pselect.param(
'cut', cut)
1488 path.add_module(pselect)
1491def applyEventCuts(cut, path, metavariables=None):
1493 Removes events that do not pass the ``cut`` (given selection criteria).
1496 continuum events (in mc only) with more than 5 tracks
1498 .. code-block:: python
1500 applyEventCuts("[nTracks > 5] and [isContinuumEvent], path=mypath)
1503 Only event-based variables are allowed in this function
1504 and only square brackets ``[`` and ``]`` for conditional statements.
1507 cut (str): Events that do not pass these selection criteria are skipped
1508 path (basf2.Path): modules are added to this path
1509 metavariables (list(str)): List of meta variables to be considered in decomposition of cut
1513 from variables
import variables
1515 def find_vars(t: tuple, var_list: list, meta_list: list) ->
None:
1516 """ Recursive helper function to find variable names """
1517 if not isinstance(t, tuple):
1519 if t[0] == b2parser.B2ExpressionParser.node_types[
'IdentifierNode']:
1522 if t[0] == b2parser.B2ExpressionParser.node_types[
'FunctionNode']:
1523 meta_list.append(list(t[1:]))
1526 if isinstance(i, tuple):
1527 find_vars(i, var_list, meta_list)
1529 def check_variable(var_list: list, metavar_ids: list) ->
None:
1530 for var_string
in var_list:
1532 orig_name = variables.resolveAlias(var_string)
1533 if orig_name != var_string:
1536 find_vars(
b2parser.parse(orig_name), var_list_temp, meta_list_temp)
1538 check_variable(var_list_temp, metavar_ids)
1539 check_meta(meta_list_temp, metavar_ids)
1542 var = variables.getVariable(var_string)
1543 if event_var_id
not in var.description:
1544 B2ERROR(f
'Variable {var_string} is not an event-based variable! "\
1545 "Please check your inputs to the applyEventCuts method!')
1547 def check_meta(meta_list: list, metavar_ids: list) ->
None:
1548 for meta_string_list
in meta_list:
1550 while meta_string_list[0]
in metavar_ids:
1552 meta_string_list.pop(0)
1553 for meta_string
in meta_string_list[0].split(
","):
1554 find_vars(
b2parser.parse(meta_string), var_list_temp, meta_string_list)
1555 if len(meta_string_list) > 0:
1556 meta_string_list.pop(0)
1557 if len(meta_string_list) == 0:
1559 if len(meta_string_list) > 1:
1560 meta_list += meta_string_list[1:]
1561 if isinstance(meta_string_list[0], list):
1562 meta_string_list = [element
for element
in meta_string_list[0]]
1564 check_variable(var_list_temp, metavar_ids)
1566 if len(meta_string_list) == 0:
1568 elif len(meta_string_list) == 1:
1569 var = variables.getVariable(meta_string_list[0])
1571 var = variables.getVariable(meta_string_list[0], meta_string_list[1].split(
","))
1573 if event_var_id
in var.description:
1576 B2ERROR(f
'Variable {var.name} is not an event-based variable! Please check your inputs to the applyEventCuts method!')
1578 event_var_id =
'[Eventbased]'
1579 metavar_ids = [
'formula',
'abs',
1583 'exp',
'log',
'log10',
1585 'isNAN',
'ifNANgiveX']
1587 metavar_ids += metavariables
1591 find_vars(
b2parser.parse(cut), var_list=var_list, meta_list=meta_list)
1593 if len(var_list) == 0
and len(meta_list) == 0:
1594 B2WARNING(f
'Cut string "{cut}" has no variables for applyEventCuts helper function!')
1596 check_variable(var_list, metavar_ids)
1597 check_meta(meta_list, metavar_ids)
1599 eselect = register_module(
'VariableToReturnValue')
1600 eselect.param(
'variable',
'passesEventCut(' + cut +
')')
1601 path.add_module(eselect)
1602 empty_path = create_path()
1603 eselect.if_value(
'<1', empty_path)
1606def reconstructDecay(decayString,
1611 candidate_limit=None,
1612 ignoreIfTooManyCandidates=True,
1613 chargeConjugation=True,
1614 allowChargeViolation=False):
1616 Creates new Particles by making combinations of existing Particles - it reconstructs unstable particles via their specified
1617 decay mode, e.g. in form of a :ref:`DecayString`: :code:`D0 -> K- pi+` or :code:`B+ -> anti-D0 pi+`, ... All possible
1618 combinations are created (particles are used only once per candidate) and combinations that pass the specified selection
1619 criteria are saved to a newly created (mother) ParticleList. By default the charge conjugated decay is reconstructed as well
1620 (meaning that the charge conjugated mother list is created as well) but this can be deactivated.
1622 One can use an ``@``-sign to mark a particle as unspecified for inclusive analyses,
1623 e.g. in a DecayString: :code:`'@Xsd -> K+ pi-'`.
1625 .. seealso:: :ref:`Marker_of_unspecified_particle`
1628 The input ParticleLists are typically ordered according to the upstream reconstruction algorithm.
1629 Therefore, if you combine two or more identical particles in the decay chain you should not expect to see the same
1630 distribution for the daughter kinematics as they may be sorted by geometry, momentum etc.
1632 For example, in the decay :code:`D0 -> pi0 pi0` the momentum distributions of the two ``pi0`` s are not identical.
1633 This can be solved by manually randomising the lists before combining.
1637 * `Particle combiner how does it work? <https://questions.belle2.org/question/4318/particle-combiner-how-does-it-work/>`_
1638 * `Identical particles in decay chain <https://questions.belle2.org/question/5724/identical-particles-in-decay-chain/>`_
1640 @param decayString :ref:`DecayString` specifying what kind of the decay should be reconstructed
1641 (from the DecayString the mother and daughter ParticleLists are determined)
1642 @param cut created (mother) Particles are added to the mother ParticleList if they
1643 pass give cuts (in VariableManager style) and rejected otherwise
1644 @param dmID user specified decay mode identifier
1645 @param writeOut whether RootOutput module should save the created ParticleList
1646 @param path modules are added to this path
1647 @param candidate_limit Maximum amount of candidates to be reconstructed. If
1648 the number of candidates is exceeded a Warning will be
1650 By default, all these candidates will be removed and event will be ignored.
1651 This behaviour can be changed by \'ignoreIfTooManyCandidates\' flag.
1652 If no value is given the amount is limited to a sensible
1653 default. A value <=0 will disable this limit and can
1654 cause huge memory amounts so be careful.
1655 @param ignoreIfTooManyCandidates whether event should be ignored or not if number of reconstructed
1656 candidates reaches limit. If event is ignored, no candidates are reconstructed,
1657 otherwise, number of candidates in candidate_limit is reconstructed.
1658 @param chargeConjugation boolean to decide whether charge conjugated mode should be reconstructed as well (on by default)
1659 @param allowChargeViolation whether the decay string needs to conserve the electric charge
1662 pmake = register_module(
'ParticleCombiner')
1663 pmake.set_name(
'ParticleCombiner_' + decayString)
1664 pmake.param(
'decayString', decayString)
1665 pmake.param(
'cut', cut)
1666 pmake.param(
'decayMode', dmID)
1667 pmake.param(
'writeOut', writeOut)
1668 if candidate_limit
is not None:
1669 pmake.param(
"maximumNumberOfCandidates", candidate_limit)
1670 pmake.param(
"ignoreIfTooManyCandidates", ignoreIfTooManyCandidates)
1671 pmake.param(
'chargeConjugation', chargeConjugation)
1672 pmake.param(
"allowChargeViolation", allowChargeViolation)
1673 path.add_module(pmake)
1676def combineAllParticles(inputParticleLists, outputList, cut='', writeOut=False, path=None):
1678 Creates a new Particle as the combination of all Particles from all
1679 provided inputParticleLists. However, each particle is used only once
1680 (even if duplicates are provided) and the combination has to pass the
1681 specified selection criteria to be saved in the newly created (mother)
1684 @param inputParticleLists List of input particle lists which are combined to the new Particle
1685 @param outputList Name of the particle combination created with this module
1686 @param cut created (mother) Particle is added to the mother ParticleList if it passes
1687 these given cuts (in VariableManager style) and is rejected otherwise
1688 @param writeOut whether RootOutput module should save the created ParticleList
1689 @param path module is added to this path
1692 pmake = register_module(
'AllParticleCombiner')
1693 pmake.set_name(
'AllParticleCombiner_' + outputList)
1694 pmake.param(
'inputListNames', inputParticleLists)
1695 pmake.param(
'outputListName', outputList)
1696 pmake.param(
'cut', cut)
1697 pmake.param(
'writeOut', writeOut)
1698 path.add_module(pmake)
1701def reconstructMissingKlongDecayExpert(decayString,
1708 Creates a list of K_L0's and of B -> K_L0 + X, with X being a fully-reconstructed state.
1709 The K_L0 momentum is determined from kinematic constraints of the two-body B decay into K_L0 and X
1711 @param decayString DecayString specifying what kind of the decay should be reconstructed
1712 (from the DecayString the mother and daughter ParticleLists are determined)
1713 @param cut Particles are added to the K_L0 and B ParticleList if the B candidates
1714 pass the given cuts (in VariableManager style) and rejected otherwise
1715 @param dmID user specified decay mode identifier
1716 @param writeOut whether RootOutput module should save the created ParticleList
1717 @param path modules are added to this path
1718 @param recoList suffix appended to original K_L0 and B ParticleList that identify the newly created K_L0 and B lists
1721 pcalc = register_module(
'KlongMomentumCalculatorExpert')
1722 pcalc.set_name(
'KlongMomentumCalculatorExpert_' + decayString)
1723 pcalc.param(
'decayString', decayString)
1724 pcalc.param(
'writeOut', writeOut)
1725 pcalc.param(
'recoList', recoList)
1726 path.add_module(pcalc)
1728 rmake = register_module(
'KlongDecayReconstructorExpert')
1729 rmake.set_name(
'KlongDecayReconstructorExpert_' + decayString)
1730 rmake.param(
'decayString', decayString)
1731 rmake.param(
'cut', cut)
1732 rmake.param(
'decayMode', dmID)
1733 rmake.param(
'writeOut', writeOut)
1734 rmake.param(
'recoList', recoList)
1735 path.add_module(rmake)
1738def setBeamConstrainedMomentum(particleList, decayStringTarget, decayStringDaughters, path=None):
1740 Replace the four-momentum of the target Particle by p(beam) - p(selected daughters).
1741 The momentum of the mother Particle will not be changed.
1743 @param particleList mother Particlelist
1744 @param decayStringTarget DecayString specifying the target particle whose momentum
1746 @param decayStringDaughters DecayString specifying the daughter particles used to replace
1747 the momentum of the target particle by p(beam)-p(daughters)
1750 mod = register_module(
'ParticleMomentumUpdater')
1751 mod.set_name(
'ParticleMomentumUpdater' + particleList)
1752 mod.param(
'particleList', particleList)
1753 mod.param(
'decayStringTarget', decayStringTarget)
1754 mod.param(
'decayStringDaughters', decayStringDaughters)
1755 path.add_module(mod)
1758def updateKlongKinematicsExpert(particleList,
1762 Calculates and updates the kinematics of B->K_L0 + something else with same method as
1763 `reconstructMissingKlongDecayExpert`. This helps to revert the kinematics after the vertex fitting.
1765 @param particleList input ParticleList of B meson that decays to K_L0 + X
1766 @param writeOut whether RootOutput module should save the ParticleList
1767 @param path modules are added to this path
1770 mod = register_module(
'KlongMomentumUpdaterExpert')
1771 mod.set_name(
'KlongMomentumUpdaterExpert_' + particleList)
1772 mod.param(
'listName', particleList)
1773 mod.param(
'writeOut', writeOut)
1774 path.add_module(mod)
1777def replaceMass(replacerName, particleLists=None, pdgCode=22, path=None):
1779 replaces the mass of the particles inside the given particleLists
1780 with the invariant mass of the particle corresponding to the given pdgCode.
1782 @param particleLists new ParticleList filled with copied Particles
1783 @param pdgCode PDG code for mass reference
1784 @param path modules are added to this path
1787 if particleLists
is None:
1791 pmassupdater = register_module(
'ParticleMassUpdater')
1792 pmassupdater.set_name(
'ParticleMassUpdater_' + replacerName)
1793 pmassupdater.param(
'particleLists', particleLists)
1794 pmassupdater.param(
'pdgCode', pdgCode)
1795 path.add_module(pmassupdater)
1798def reconstructRecoil(decayString,
1803 candidate_limit=None,
1804 allowChargeViolation=False):
1806 Creates new Particles that recoil against the input particles.
1808 For example the decay string M -> D1 D2 D3 will:
1810 - create mother Particle M for each unique combination of D1, D2, D3 Particles
1811 - Particles D1, D2, D3 will be appended as daughters to M
1812 - the 4-momentum of the mother Particle M is given by
1813 p(M) = p(HER) + p(LER) - Sum_i p(Di)
1815 @param decayString DecayString specifying what kind of the decay should be reconstructed
1816 (from the DecayString the mother and daughter ParticleLists are determined)
1817 @param cut created (mother) Particles are added to the mother ParticleList if they
1818 pass give cuts (in VariableManager style) and rejected otherwise
1819 @param dmID user specified decay mode identifier
1820 @param writeOut whether RootOutput module should save the created ParticleList
1821 @param path modules are added to this path
1822 @param candidate_limit Maximum amount of candidates to be reconstructed. If
1823 the number of candidates is exceeded no candidate will be
1824 reconstructed for that event and a Warning will be
1826 If no value is given the amount is limited to a sensible
1827 default. A value <=0 will disable this limit and can
1828 cause huge memory amounts so be careful.
1829 @param allowChargeViolation whether the decay string needs to conserve the electric charge
1832 pmake = register_module(
'ParticleCombiner')
1833 pmake.set_name(
'ParticleCombiner_' + decayString)
1834 pmake.param(
'decayString', decayString)
1835 pmake.param(
'cut', cut)
1836 pmake.param(
'decayMode', dmID)
1837 pmake.param(
'writeOut', writeOut)
1838 pmake.param(
'recoilParticleType', 1)
1839 if candidate_limit
is not None:
1840 pmake.param(
"maximumNumberOfCandidates", candidate_limit)
1841 pmake.param(
'allowChargeViolation', allowChargeViolation)
1842 path.add_module(pmake)
1845def reconstructRecoilDaughter(decayString,
1850 candidate_limit=None,
1851 allowChargeViolation=False):
1853 Creates new Particles that are daughters of the particle reconstructed in the recoil (always assumed to be the first daughter).
1855 For example the decay string M -> D1 D2 D3 will:
1857 - create mother Particle M for each unique combination of D1, D2, D3 Particles
1858 - Particles D1, D2, D3 will be appended as daughters to M
1859 - the 4-momentum of the mother Particle M is given by
1860 p(M) = p(D1) - Sum_i p(Di), where i>1
1862 @param decayString DecayString specifying what kind of the decay should be reconstructed
1863 (from the DecayString the mother and daughter ParticleLists are determined)
1864 @param cut created (mother) Particles are added to the mother ParticleList if they
1865 pass give cuts (in VariableManager style) and rejected otherwise
1866 @param dmID user specified decay mode identifier
1867 @param writeOut whether RootOutput module should save the created ParticleList
1868 @param path modules are added to this path
1869 @param candidate_limit Maximum amount of candidates to be reconstructed. If
1870 the number of candidates is exceeded no candidate will be
1871 reconstructed for that event and a Warning will be
1873 If no value is given the amount is limited to a sensible
1874 default. A value <=0 will disable this limit and can
1875 cause huge memory amounts so be careful.
1876 @param allowChargeViolation whether the decay string needs to conserve the electric charge taking into account that the first
1877 daughter is actually the mother
1880 pmake = register_module(
'ParticleCombiner')
1881 pmake.set_name(
'ParticleCombiner_' + decayString)
1882 pmake.param(
'decayString', decayString)
1883 pmake.param(
'cut', cut)
1884 pmake.param(
'decayMode', dmID)
1885 pmake.param(
'writeOut', writeOut)
1886 pmake.param(
'recoilParticleType', 2)
1887 if candidate_limit
is not None:
1888 pmake.param(
"maximumNumberOfCandidates", candidate_limit)
1889 pmake.param(
'allowChargeViolation', allowChargeViolation)
1890 path.add_module(pmake)
1893def rankByHighest(particleList,
1897 allowMultiRank=False,
1899 overwriteRank=False,
1902 Ranks particles in the input list by the given variable (highest to lowest), and stores an integer rank for each Particle
1903 in an :b2:var:`extraInfo` field ``${variable}_rank`` starting at 1 (best).
1904 The list is also sorted from best to worst candidate
1905 (each charge, e.g. B+/B-, separately).
1906 This can be used to perform a best candidate selection by cutting on the corresponding rank value, or by specifying
1907 a non-zero value for 'numBest'.
1910 Extra-info fields can be accessed by the :b2:var:`extraInfo` metavariable.
1911 These variable names can become clunky, so it's probably a good idea to set an alias.
1912 For example if you rank your B candidates by momentum,
1916 rankByHighest("B0:myCandidates", "p", path=mypath)
1917 vm.addAlias("momentumRank", "extraInfo(p_rank)")
1920 @param particleList The input ParticleList
1921 @param variable Variable to order Particles by.
1922 @param numBest If not zero, only the $numBest Particles in particleList with rank <= numBest are kept.
1923 @param outputVariable Name for the variable that will be created which contains the rank, Default is '${variable}_rank'.
1924 @param allowMultiRank If true, candidates with the same value will get the same rank.
1925 @param cut Only candidates passing the cut will be ranked. The others will have rank -1
1926 @param overwriteRank If true, the extraInfo of rank is overwritten when the particle has already the extraInfo.
1927 @param path modules are added to this path
1930 bcs = register_module(
'BestCandidateSelection')
1931 bcs.set_name(
'BestCandidateSelection_' + particleList +
'_' + variable)
1932 bcs.param(
'particleList', particleList)
1933 bcs.param(
'variable', variable)
1934 bcs.param(
'numBest', numBest)
1935 bcs.param(
'outputVariable', outputVariable)
1936 bcs.param(
'allowMultiRank', allowMultiRank)
1937 bcs.param(
'cut', cut)
1938 bcs.param(
'overwriteRank', overwriteRank)
1939 path.add_module(bcs)
1942def rankByLowest(particleList,
1946 allowMultiRank=False,
1948 overwriteRank=False,
1951 Ranks particles in the input list by the given variable (lowest to highest), and stores an integer rank for each Particle
1952 in an :b2:var:`extraInfo` field ``${variable}_rank`` starting at 1 (best).
1953 The list is also sorted from best to worst candidate
1954 (each charge, e.g. B+/B-, separately).
1955 This can be used to perform a best candidate selection by cutting on the corresponding rank value, or by specifying
1956 a non-zero value for 'numBest'.
1959 Extra-info fields can be accessed by the :b2:var:`extraInfo` metavariable.
1960 These variable names can become clunky, so it's probably a good idea to set an alias.
1961 For example if you rank your B candidates by :b2:var:`dM`,
1965 rankByLowest("B0:myCandidates", "dM", path=mypath)
1966 vm.addAlias("massDifferenceRank", "extraInfo(dM_rank)")
1969 @param particleList The input ParticleList
1970 @param variable Variable to order Particles by.
1971 @param numBest If not zero, only the $numBest Particles in particleList with rank <= numBest are kept.
1972 @param outputVariable Name for the variable that will be created which contains the rank, Default is '${variable}_rank'.
1973 @param allowMultiRank If true, candidates with the same value will get the same rank.
1974 @param cut Only candidates passing the cut will be ranked. The others will have rank -1
1975 @param overwriteRank If true, the extraInfo of rank is overwritten when the particle has already the extraInfo.
1976 @param path modules are added to this path
1979 bcs = register_module(
'BestCandidateSelection')
1980 bcs.set_name(
'BestCandidateSelection_' + particleList +
'_' + variable)
1981 bcs.param(
'particleList', particleList)
1982 bcs.param(
'variable', variable)
1983 bcs.param(
'numBest', numBest)
1984 bcs.param(
'selectLowest',
True)
1985 bcs.param(
'allowMultiRank', allowMultiRank)
1986 bcs.param(
'outputVariable', outputVariable)
1987 bcs.param(
'cut', cut)
1988 bcs.param(
'overwriteRank', overwriteRank)
1989 path.add_module(bcs)
1992def applyRandomCandidateSelection(particleList, path=None):
1994 If there are multiple candidates in the provided particleList, all but one of them are removed randomly.
1995 This is done on a event-by-event basis.
1997 @param particleList ParticleList for which the random candidate selection should be applied
1998 @param path module is added to this path
2001 rcs = register_module(
'BestCandidateSelection')
2002 rcs.set_name(
'RandomCandidateSelection_' + particleList)
2003 rcs.param(
'particleList', particleList)
2004 rcs.param(
'variable',
'random')
2005 rcs.param(
'selectLowest',
False)
2006 rcs.param(
'allowMultiRank',
False)
2007 rcs.param(
'numBest', 1)
2008 rcs.param(
'cut',
'')
2009 rcs.param(
'outputVariable',
'')
2010 path.add_module(rcs)
2015 Prints the contents of DataStore in the first event (or a specific event number or all events).
2016 Will list all objects and arrays (including size).
2019 The command line tool: ``b2file-size``.
2022 eventNumber (int): Print the datastore only for this event. The default
2023 (-1) prints only the first event, 0 means print for all events (can produce large output)
2024 path (basf2.Path): the PrintCollections module is added to this path
2027 This will print a lot of output if you print it for all events and process many events.
2031 printDS = register_module(
'PrintCollections')
2032 printDS.param(
'printForEvent', eventNumber)
2033 path.add_module(printDS)
2036def printVariableValues(list_name, var_names, path):
2038 Prints out values of specified variables of all Particles included in given ParticleList. For debugging purposes.
2040 @param list_name input ParticleList name
2041 @param var_names vector of variable names to be printed
2042 @param path modules are added to this path
2045 prlist = register_module(
'ParticlePrinter')
2046 prlist.set_name(
'ParticlePrinter_' + list_name)
2047 prlist.param(
'listName', list_name)
2048 prlist.param(
'fullPrint',
False)
2049 prlist.param(
'variables', var_names)
2050 path.add_module(prlist)
2053def printList(list_name, full, path):
2055 Prints the size and executes Particle->print() (if full=True)
2056 method for all Particles in given ParticleList. For debugging purposes.
2058 @param list_name input ParticleList name
2059 @param full execute Particle->print() method for all Particles
2060 @param path modules are added to this path
2063 prlist = register_module(
'ParticlePrinter')
2064 prlist.set_name(
'ParticlePrinter_' + list_name)
2065 prlist.param(
'listName', list_name)
2066 prlist.param(
'fullPrint', full)
2067 path.add_module(prlist)
2070def variablesToNtuple(decayString, variables, treename='variables', filename='ntuple.root', path=None, basketsize=1600,
2071 signalSideParticleList="", filenameSuffix="", useFloat=False, storeEventType=True,
2072 ignoreCommandLineOverride=False):
2074 Creates and fills a flat ntuple with the specified variables from the VariableManager.
2075 If a decayString is provided, then there will be one entry per candidate (for particle in list of candidates).
2076 If an empty decayString is provided, there will be one entry per event (useful for trigger studies, etc).
2079 decayString (str): specifies type of Particles and determines the name of the ParticleList
2080 variables (list(str)): the list of variables (which must be registered in the VariableManager)
2081 treename (str): name of the ntuple tree
2082 filename (str): which is used to store the variables
2083 path (basf2.Path): the basf2 path where the analysis is processed
2084 basketsize (int): size of baskets in the output ntuple in bytes
2085 signalSideParticleList (str): The name of the signal-side ParticleList.
2086 Only valid if the module is called in a for_each loop over the RestOfEvent.
2087 filenameSuffix (str): suffix to be appended to the filename before ``.root``.
2088 useFloat (bool): Use single precision (float) instead of double precision (double)
2089 for floating-point numbers.
2090 storeEventType (bool) : if true, the branch __eventType__ is added for the MC event type information.
2091 The information is available from MC16 on.
2092 ignoreCommandLineOverride (bool) : if true, ignore override of file name via command line argument ``-o``.
2094 .. tip:: The output filename can be overridden using the ``-o`` argument of basf2.
2097 output = register_module(
'VariablesToNtuple')
2098 output.set_name(
'VariablesToNtuple_' + decayString)
2099 output.param(
'particleList', decayString)
2100 output.param(
'variables', variables)
2101 output.param(
'fileName', filename)
2102 output.param(
'treeName', treename)
2103 output.param(
'basketSize', basketsize)
2104 output.param(
'signalSideParticleList', signalSideParticleList)
2105 output.param(
'fileNameSuffix', filenameSuffix)
2106 output.param(
'useFloat', useFloat)
2107 output.param(
'storeEventType', storeEventType)
2108 output.param(
'ignoreCommandLineOverride', ignoreCommandLineOverride)
2109 path.add_module(output)
2115 filename='ntuple.root',
2118 prefixDecayString=False,
2120 ignoreCommandLineOverride=False):
2122 Creates and fills a flat ntuple with the specified variables from the VariableManager
2125 decayString (str): specifies type of Particles and determines the name of the ParticleList
2126 variables (list(tuple))): variables + binning which must be registered in the VariableManager
2127 variables_2d (list(tuple)): pair of variables + binning for each which must be registered in the VariableManager
2128 filename (str): which is used to store the variables
2129 path (basf2.Path): the basf2 path where the analysis is processed
2130 directory (str): directory inside the output file where the histograms should be saved.
2131 Useful if you want to have different histograms in the same file to separate them.
2132 prefixDecayString (bool): If True the decayString will be prepended to the directory name to allow for more
2133 programmatic naming of the structure in the file.
2134 filenameSuffix (str): suffix to be appended to the filename before ``.root``.
2135 ignoreCommandLineOverride (bool) : if true, ignore override of file name via command line argument ``-o``.
2137 .. tip:: The output filename can be overridden using the ``-o`` argument of basf2.
2140 if variables_2d
is None:
2142 output = register_module(
'VariablesToHistogram')
2143 output.set_name(
'VariablesToHistogram_' + decayString)
2144 output.param(
'particleList', decayString)
2145 output.param(
'variables', variables)
2146 output.param(
'variables_2d', variables_2d)
2147 output.param(
'fileName', filename)
2148 output.param(
'fileNameSuffix', filenameSuffix)
2149 output.param(
'ignoreCommandLineOverride', ignoreCommandLineOverride)
2150 if directory
is not None or prefixDecayString:
2151 if directory
is None:
2153 if prefixDecayString:
2154 directory = decayString +
"_" + directory
2155 output.param(
"directory", directory)
2156 path.add_module(output)
2161 For each particle in the input list the selected variables are saved in an extra-info field with the given name.
2162 Can be used when wanting to save variables before modifying them, e.g. when performing vertex fits.
2165 particleList (str): The input ParticleList
2166 variables (dict[str,str]): Dictionary of Variables (key) and extraInfo names (value).
2167 option (int): Option to overwrite an existing extraInfo. Choose among -1, 0, 1, 2.
2168 An existing extra info with the same name will be overwritten if the new
2169 value is lower / will never be overwritten / will be overwritten if the
2170 new value is higher / will always be overwritten (option = -1/0/1/2).
2171 path (basf2.Path): modules are added to this path
2174 mod = register_module(
'VariablesToExtraInfo')
2175 mod.set_name(
'VariablesToExtraInfo_' + particleList)
2176 mod.param(
'particleList', particleList)
2177 mod.param(
'variables', variables)
2178 mod.param(
'overwrite', option)
2179 path.add_module(mod)
2182def variablesToDaughterExtraInfo(particleList, decayString, variables, option=0, path=None):
2184 For each daughter particle specified via decay string the selected variables (estimated for the mother particle)
2185 are saved in an extra-info field with the given name. In other words, the property of mother is saved as extra-info
2186 to specified daughter particle.
2189 particleList (str): The input ParticleList
2190 decayString (str): Decay string that specifies to which daughter the extra info should be appended
2191 variables (dict[str,str]): Dictionary of Variables (key) and extraInfo names (value).
2192 option (int): Option to overwrite an existing extraInfo. Choose among -1, 0, 1, 2.
2193 An existing extra info with the same name will be overwritten if the new
2194 value is lower / will never be overwritten / will be overwritten if the
2195 new value is higher / will always be overwritten (option = -1/0/1/2).
2196 path (basf2.Path): modules are added to this path
2199 mod = register_module(
'VariablesToExtraInfo')
2200 mod.set_name(
'VariablesToDaughterExtraInfo_' + particleList)
2201 mod.param(
'particleList', particleList)
2202 mod.param(
'decayString', decayString)
2203 mod.param(
'variables', variables)
2204 mod.param(
'overwrite', option)
2205 path.add_module(mod)
2208def variablesToEventExtraInfo(particleList, variables, option=0, path=None):
2210 For each particle in the input list the selected variables are saved in an event-extra-info field with the given name,
2211 Can be used to save MC truth information, for example, in a ntuple of reconstructed particles.
2214 When the function is called first time not in the main path but in a sub-path e.g. ``roe_path``,
2215 the eventExtraInfo cannot be accessed from the main path because of the shorter lifetime of the event-extra-info field.
2216 If one wants to call the function in a sub-path, one has to call the function in the main path beforehand.
2219 particleList (str): The input ParticleList
2220 variables (dict[str,str]): Dictionary of Variables (key) and extraInfo names (value).
2221 option (int): Option to overwrite an existing extraInfo. Choose among -1, 0, 1, 2.
2222 An existing extra info with the same name will be overwritten if the new
2223 value is lower / will never be overwritten / will be overwritten if the
2224 new value is higher / will always be overwritten (option = -1/0/1/2).
2225 path (basf2.Path): modules are added to this path
2228 mod = register_module(
'VariablesToEventExtraInfo')
2229 mod.set_name(
'VariablesToEventExtraInfo_' + particleList)
2230 mod.param(
'particleList', particleList)
2231 mod.param(
'variables', variables)
2232 mod.param(
'overwrite', option)
2233 path.add_module(mod)
2236def variableToSignalSideExtraInfo(particleList, varToExtraInfo, path):
2238 Write the value of specified variables estimated for the single particle in the input list (has to contain exactly 1
2239 particle) as an extra info to the particle related to current ROE.
2240 Should be used only in the for_each roe path.
2243 particleList (str): The input ParticleList
2244 varToExtraInfo (dict[str,str]): Dictionary of Variables (key) and extraInfo names (value).
2245 path (basf2.Path): modules are added to this path
2248 mod = register_module(
'SignalSideVariablesToExtraInfo')
2249 mod.set_name(
'SigSideVarToExtraInfo_' + particleList)
2250 mod.param(
'particleListName', particleList)
2251 mod.param(
'variableToExtraInfo', varToExtraInfo)
2252 path.add_module(mod)
2255def signalRegion(particleList, cut, path=None, name="isSignalRegion", blind_data=True):
2257 Define and blind a signal region.
2258 Per default, the defined signal region is cut out if ran on data.
2259 This function will provide a new variable 'isSignalRegion' as default, which is either 0 or 1 depending on the cut
2263 .. code-block:: python
2265 ma.reconstructDecay("B+:sig -> D+ pi0", "Mbc>5.2", path=path)
2266 ma.signalRegion("B+:sig",
2267 "Mbc>5.27 and abs(deltaE)<0.2",
2270 ma.variablesToNtuples("B+:sig", ["isSignalRegion"], path=path)
2273 particleList (str): The input ParticleList
2274 cut (str): Cut string describing the signal region
2275 path (basf2.Path):: Modules are added to this path
2276 name (str): Name of the Signal region in the variable manager
2277 blind_data (bool): Automatically exclude signal region from data
2281 from variables
import variables
2282 mod = register_module(
'VariablesToExtraInfo')
2283 mod.set_name(f
'{name}_' + particleList)
2284 mod.param(
'particleList', particleList)
2285 mod.param(
'variables', {f
"passesCut({cut})": name})
2286 variables.addAlias(name, f
"extraInfo({name})")
2287 path.add_module(mod)
2291 applyCuts(particleList, f
"{name}==0 or isMC==1", path=path)
2294def removeExtraInfo(particleLists=None, removeEventExtraInfo=False, path=None):
2296 Removes the ExtraInfo of the given particleLists. If specified (removeEventExtraInfo = True) also the EventExtraInfo is removed.
2299 if particleLists
is None:
2301 mod = register_module(
'ExtraInfoRemover')
2302 mod.param(
'particleLists', particleLists)
2303 mod.param(
'removeEventExtraInfo', removeEventExtraInfo)
2304 path.add_module(mod)
2307def signalSideParticleFilter(particleList, selection, roe_path, deadEndPath):
2309 Checks if the current ROE object in the for_each roe path (argument roe_path) is related
2310 to the particle from the input ParticleList. Additional selection criteria can be applied.
2311 If ROE is not related to any of the Particles from ParticleList or the Particle doesn't
2312 meet the selection criteria the execution of deadEndPath is started. This path, as the name
2313 suggests should be empty and its purpose is to end the execution of for_each roe path for
2314 the current ROE object.
2316 @param particleList The input ParticleList
2317 @param selection Selection criteria that Particle needs meet in order for for_each ROE path to continue
2318 @param for_each roe path in which this filter is executed
2319 @param deadEndPath empty path that ends execution of or_each roe path for the current ROE object.
2322 mod = register_module(
'SignalSideParticleFilter')
2323 mod.set_name(
'SigSideParticleFilter_' + particleList)
2324 mod.param(
'particleLists', [particleList])
2325 mod.param(
'selection', selection)
2326 roe_path.add_module(mod)
2327 mod.if_false(deadEndPath)
2330def signalSideParticleListsFilter(particleLists, selection, roe_path, deadEndPath):
2332 Checks if the current ROE object in the for_each roe path (argument roe_path) is related
2333 to the particle from the input ParticleList. Additional selection criteria can be applied.
2334 If ROE is not related to any of the Particles from ParticleList or the Particle doesn't
2335 meet the selection criteria the execution of deadEndPath is started. This path, as the name
2336 suggests should be empty and its purpose is to end the execution of for_each roe path for
2337 the current ROE object.
2339 @param particleLists The input ParticleLists
2340 @param selection Selection criteria that Particle needs meet in order for for_each ROE path to continue
2341 @param for_each roe path in which this filter is executed
2342 @param deadEndPath empty path that ends execution of or_each roe path for the current ROE object.
2345 mod = register_module(
'SignalSideParticleFilter')
2346 mod.set_name(
'SigSideParticleFilter_' + particleLists[0])
2347 mod.param(
'particleLists', particleLists)
2348 mod.param(
'selection', selection)
2349 roe_path.add_module(mod)
2350 mod.if_false(deadEndPath)
2359 chargeConjugation=True,
2362 Finds and creates a ``ParticleList`` from given decay string.
2363 ``ParticleList`` of daughters with sub-decay is created.
2365 Only the particles made from MCParticle, which can be loaded by `fillParticleListFromMC`, are accepted as daughters.
2367 Only signal particle, which means :b2:var:`isSignal` is equal to 1, is stored. One can use the decay string grammar
2368 to change the behavior of :b2:var:`isSignal`. One can find detailed information in :ref:`DecayString`.
2371 If one uses same sub-decay twice, same particles are registered to a ``ParticleList``. For example,
2372 ``K_S0:pi0pi0 =direct=> [pi0:gg =direct=> gamma:MC gamma:MC] [pi0:gg =direct=> gamma:MC gamma:MC]``.
2373 One can skip the second sub-decay, ``K_S0:pi0pi0 =direct=> [pi0:gg =direct=> gamma:MC gamma:MC] pi0:gg``.
2376 It is recommended to use only primary particles as daughter particles unless you want to explicitly study the secondary
2377 particles. The behavior of MC-matching for secondary particles from a stable particle decay is not guaranteed.
2378 Please consider to use `fillParticleListFromMC` with ``skipNonPrimary=True`` to load daughter particles.
2379 Moreover, it is recommended to load ``K_S0`` and ``Lambda0`` directly from MCParticle by `fillParticleListFromMC` rather
2380 than reconstructing from two pions or a proton-pion pair, because their direct daughters can be the secondary particle.
2383 @param decayString :ref:`DecayString` specifying what kind of the decay should be reconstructed
2384 (from the DecayString the mother and daughter ParticleLists are determined)
2385 @param cut created (mother) Particles are added to the mother ParticleList if they
2386 pass given cuts (in VariableManager style) and rejected otherwise
2387 isSignal==1 is always required by default.
2388 @param dmID user specified decay mode identifier
2389 @param writeOut whether RootOutput module should save the created ParticleList
2390 @param path modules are added to this path
2391 @param chargeConjugation boolean to decide whether charge conjugated mode should be reconstructed as well (on by default)
2394 pmake = register_module(
'ParticleCombinerFromMC')
2395 pmake.set_name(
'ParticleCombinerFromMC_' + decayString)
2396 pmake.param(
'decayString', decayString)
2397 pmake.param(
'cut', cut)
2398 pmake.param(
'decayMode', dmID)
2399 pmake.param(
'writeOut', writeOut)
2400 pmake.param(
'chargeConjugation', chargeConjugation)
2401 path.add_module(pmake)
2408 appendAllDaughters=False,
2409 skipNonPrimaryDaughters=True,
2413 Finds and creates a ``ParticleList`` for all ``MCParticle`` decays matching a given :ref:`DecayString`.
2414 The decay string is required to describe correctly what you want.
2415 In the case of inclusive decays, you can use :ref:`Grammar_for_custom_MCMatching`
2417 The output particles has only the daughter particles written in the given decay string, if
2418 ``appendAllDaughters=False`` (default). If ``appendAllDaughters=True``, all daughters of the matched MCParticle are
2419 appended in the order defined at the MCParticle level. For example,
2421 .. code-block:: python
2423 findMCDecay('B0:Xee', 'B0 -> e+ e- ... ?gamma', appendAllDaughters=False, path=mypath)
2425 The output ParticleList ``B0:Xee`` will match the inclusive ``B0 -> e+ e-`` decays (but neutrinos are not included),
2426 in both cases of ``appendAllDaughters`` is false and true.
2427 If the ``appendAllDaughters=False`` as above example, the ``B0:Xee`` has only two electrons as daughters.
2428 While, if ``appendAllDaughters=True``, all daughters of the matched MCParticles are appended. When the truth decay mode of
2429 the MCParticle is ``B0 -> [K*0 -> K+ pi-] [J/psi -> e+ e-]``, the first daughter of ``B0:Xee`` is ``K*0`` and ``e+``
2430 will be the first daughter of second daughter of ``B0:Xee``.
2432 The option ``skipNonPrimaryDaughters`` only has an effect if ``appendAllDaughters=True``. If ``skipNonPrimaryDaughters=True``,
2433 all primary daughters are appended but the secondary particles are not.
2436 Daughters of ``Lambda0`` are not primary, but ``Lambda0`` is not a final state particle.
2437 In order for the MCMatching to work properly, the daughters of ``Lambda0`` are appended to
2438 ``Lambda0`` regardless of the value of the option ``skipNonPrimaryDaughters``.
2441 @param list_name The output particle list name
2442 @param decay The decay string which you want
2443 @param writeOut Whether `RootOutput` module should save the created ``outputList``
2444 @param skipNonPrimaryDaughters if true, skip non primary daughters, useful to study final state daughter particles
2445 @param appendAllDaughters if true, not only the daughters described in the decay string but all daughters are appended
2446 @param path modules are added to this path
2449 decayfinder = register_module(
'MCDecayFinder')
2450 decayfinder.set_name(
'MCDecayFinder_' + list_name)
2451 decayfinder.param(
'listName', list_name)
2452 decayfinder.param(
'decayString', decay)
2453 decayfinder.param(
'appendAllDaughters', appendAllDaughters)
2454 decayfinder.param(
'skipNonPrimaryDaughters', skipNonPrimaryDaughters)
2455 decayfinder.param(
'writeOut', writeOut)
2456 path.add_module(decayfinder)
2459def summaryOfLists(particleLists, outputFile=None, path=None):
2461 Prints out Particle statistics at the end of the job: number of events with at
2462 least one candidate, average number of candidates per event, etc.
2463 If an output file name is provided the statistics is also dumped into a json file with that name.
2465 @param particleLists list of input ParticleLists
2466 @param outputFile output file name (not created by default)
2469 particleStats = register_module(
'ParticleStats')
2470 particleStats.param(
'particleLists', particleLists)
2471 if outputFile
is not None:
2472 particleStats.param(
'outputFile', outputFile)
2473 path.add_module(particleStats)
2476def matchMCTruth(list_name, path):
2478 Performs MC matching (sets relation Particle->MCParticle) for
2479 all particles (and its (grand)^N-daughter particles) in the specified
2482 @param list_name name of the input ParticleList
2483 @param path modules are added to this path
2486 mcMatch = register_module(
'MCMatcherParticles')
2487 mcMatch.set_name(
'MCMatch_' + list_name)
2488 mcMatch.param(
'listName', list_name)
2489 path.add_module(mcMatch)
2492def looseMCTruth(list_name, path):
2494 Performs loose MC matching for all particles in the specified
2496 The difference between loose and normal mc matching algorithm is that
2497 the loose algorithm will find the common mother of the majority of daughter
2498 particles while the normal algorithm finds the common mother of all daughters.
2499 The results of loose mc matching algorithm are stored to the following extraInfo
2502 - looseMCMotherPDG: PDG code of most common mother
2503 - looseMCMotherIndex: 1-based StoreArray<MCParticle> index of most common mother
2504 - looseMCWrongDaughterN: number of daughters that don't originate from the most common mother
2505 - looseMCWrongDaughterPDG: PDG code of the daughter that doesn't originate from the most common mother (only if
2506 looseMCWrongDaughterN = 1)
2507 - looseMCWrongDaughterBiB: 1 if the wrong daughter is Beam Induced Background Particle
2509 @param list_name name of the input ParticleList
2510 @param path modules are added to this path
2513 mcMatch = register_module(
'MCMatcherParticles')
2514 mcMatch.set_name(
'LooseMCMatch_' + list_name)
2515 mcMatch.param(
'listName', list_name)
2516 mcMatch.param(
'looseMCMatching',
True)
2517 path.add_module(mcMatch)
2520def buildRestOfEvent(target_list_name, inputParticlelists=None,
2521 fillWithMostLikely=True,
2522 chargedPIDPriors=None, path=None):
2524 Creates for each Particle in the given ParticleList a RestOfEvent
2525 dataobject and makes basf2 relation between them. User can provide additional
2526 particle lists with a different particle hypothesis like ['K+:good, e+:good'], etc.
2528 @param target_list_name name of the input ParticleList
2529 @param inputParticlelists list of user-defined input particle list names, which serve
2530 as source of particles to build the ROE, the FSP particles from
2531 target_list_name are automatically excluded from the ROE object
2532 @param fillWithMostLikely By default the module uses the most likely particle mass hypothesis for charged particles
2533 based on the PID likelihood. Turn this behavior off if you want to configure your own
2534 input particle lists.
2535 @param chargedPIDPriors The prior PID fractions, that are used to regulate the
2536 amount of certain charged particle species, should be a list of
2537 six floats if not None. The order of particle types is
2538 the following: [e-, mu-, pi-, K-, p+, d+]
2539 @param path modules are added to this path
2542 if inputParticlelists
is None:
2543 inputParticlelists = []
2544 fillParticleList(
'pi+:all',
'', path=path)
2545 if fillWithMostLikely:
2546 from stdCharged
import stdMostLikely
2547 stdMostLikely(chargedPIDPriors,
'_roe', path=path)
2548 inputParticlelists = [f
'{ptype}:mostlikely_roe' for ptype
in [
'K+',
'p+',
'e+',
'mu+']]
2551 fillParticleList(
'gamma:all',
'', path=path)
2552 fillParticleList(
'K_L0:roe_default',
'isFromKLM > 0', path=path)
2553 inputParticlelists += [
'pi+:all',
'gamma:all',
'K_L0:roe_default']
2555 inputParticlelists += [
'pi+:all',
'gamma:mdst']
2556 roeBuilder = register_module(
'RestOfEventBuilder')
2557 roeBuilder.set_name(
'ROEBuilder_' + target_list_name)
2558 roeBuilder.param(
'particleList', target_list_name)
2559 roeBuilder.param(
'particleListsInput', inputParticlelists)
2560 roeBuilder.param(
'mostLikely', fillWithMostLikely)
2561 path.add_module(roeBuilder)
2564def buildNestedRestOfEvent(target_list_name, maskName='all', path=None):
2566 Creates for each Particle in the given ParticleList a RestOfEvent
2567 @param target_list_name name of the input ParticleList
2568 @param mask_name name of the ROEMask to be used
2569 @param path modules are added to this path
2572 roeBuilder = register_module(
'RestOfEventBuilder')
2573 roeBuilder.set_name(
'NestedROEBuilder_' + target_list_name)
2574 roeBuilder.param(
'particleList', target_list_name)
2575 roeBuilder.param(
'nestedROEMask', maskName)
2576 roeBuilder.param(
'createNestedROE',
True)
2577 path.add_module(roeBuilder)
2580def buildRestOfEventFromMC(target_list_name, inputParticlelists=None, path=None):
2582 Creates for each Particle in the given ParticleList a RestOfEvent
2583 @param target_list_name name of the input ParticleList
2584 @param inputParticlelists list of input particle list names, which serve
2585 as a source of particles to build ROE, the FSP particles from
2586 target_list_name are excluded from ROE object
2587 @param path modules are added to this path
2590 if inputParticlelists
is None:
2591 inputParticlelists = []
2592 if (len(inputParticlelists) == 0):
2596 types = [
'gamma',
'e+',
'mu+',
'pi+',
'K+',
'p+',
'K_L0',
2597 'n0',
'nu_e',
'nu_mu',
'nu_tau',
2600 fillParticleListFromMC(f
"{t}:roe_default_gen",
'mcPrimary > 0 and nDaughters == 0',
2601 True,
True, path=path)
2602 inputParticlelists += [f
"{t}:roe_default_gen"]
2603 roeBuilder = register_module(
'RestOfEventBuilder')
2604 roeBuilder.set_name(
'MCROEBuilder_' + target_list_name)
2605 roeBuilder.param(
'particleList', target_list_name)
2606 roeBuilder.param(
'particleListsInput', inputParticlelists)
2607 roeBuilder.param(
'fromMC',
True)
2608 path.add_module(roeBuilder)
2611def appendROEMask(list_name,
2614 eclClusterSelection,
2615 klmClusterSelection='',
2618 Loads the ROE object of a particle and creates a ROE mask with a specific name. It applies
2619 selection criteria for tracks and eclClusters which will be used by variables in ROEVariables.cc.
2621 - append a ROE mask with all tracks in ROE coming from the IP region
2623 .. code-block:: python
2625 appendROEMask('B+:sig', 'IPtracks', '[dr < 2] and [abs(dz) < 5]', path=mypath)
2627 - append a ROE mask with only ECL-based particles that pass as good photon candidates
2629 .. code-block:: python
2631 goodPhotons = 'inCDCAcceptance and clusterErrorTiming < 1e6 and [clusterE1E9 > 0.4 or E > 0.075]'
2632 appendROEMask('B+:sig', 'goodROEGamma', '', goodPhotons, path=mypath)
2635 @param list_name name of the input ParticleList
2636 @param mask_name name of the appended ROEMask
2637 @param trackSelection decay string for the track-based particles in ROE
2638 @param eclClusterSelection decay string for the ECL-based particles in ROE
2639 @param klmClusterSelection decay string for the KLM-based particles in ROE
2640 @param path modules are added to this path
2643 roeMask = register_module(
'RestOfEventInterpreter')
2644 roeMask.set_name(
'RestOfEventInterpreter_' + list_name +
'_' + mask_name)
2645 roeMask.param(
'particleList', list_name)
2646 roeMask.param(
'ROEMasks', [(mask_name, trackSelection, eclClusterSelection, klmClusterSelection)])
2647 path.add_module(roeMask)
2650def appendROEMasks(list_name, mask_tuples, path=None):
2652 Loads the ROE object of a particle and creates a ROE mask with a specific name. It applies
2653 selection criteria for track-, ECL- and KLM-based particles which will be used by ROE variables.
2655 The multiple ROE masks with their own selection criteria are specified
2656 via list of tuples (mask_name, trackParticleSelection, eclParticleSelection, klmParticleSelection) or
2657 (mask_name, trackSelection, eclClusterSelection) in case with fractions.
2659 - Example for two tuples, one with and one without fractions
2661 .. code-block:: python
2663 ipTracks = ('IPtracks', '[dr < 2] and [abs(dz) < 5]', '', '')
2664 goodPhotons = 'inCDCAcceptance and [clusterErrorTiming < 1e6] and [clusterE1E9 > 0.4 or E > 0.075]'
2665 goodROEGamma = ('ROESel', '[dr < 2] and [abs(dz) < 5]', goodPhotons, '')
2666 goodROEKLM = ('IPtracks', '[dr < 2] and [abs(dz) < 5]', '', 'nKLMClusterTrackMatches == 0')
2667 appendROEMasks('B+:sig', [ipTracks, goodROEGamma, goodROEKLM], path=mypath)
2669 @param list_name name of the input ParticleList
2670 @param mask_tuples array of ROEMask list tuples to be appended
2671 @param path modules are added to this path
2674 compatible_masks = []
2675 for mask
in mask_tuples:
2678 compatible_masks += [(*mask,
'')]
2680 compatible_masks += [mask]
2681 roeMask = register_module(
'RestOfEventInterpreter')
2682 roeMask.set_name(
'RestOfEventInterpreter_' + list_name +
'_' +
'MaskList')
2683 roeMask.param(
'particleList', list_name)
2684 roeMask.param(
'ROEMasks', compatible_masks)
2685 path.add_module(roeMask)
2688def updateROEMask(list_name,
2691 eclClusterSelection='',
2692 klmClusterSelection='',
2695 Update an existing ROE mask by applying additional selection cuts for
2696 tracks and/or clusters.
2698 See function `appendROEMask`!
2700 @param list_name name of the input ParticleList
2701 @param mask_name name of the ROEMask to update
2702 @param trackSelection decay string for the track-based particles in ROE
2703 @param eclClusterSelection decay string for the ECL-based particles in ROE
2704 @param klmClusterSelection decay string for the KLM-based particles in ROE
2705 @param path modules are added to this path
2708 roeMask = register_module(
'RestOfEventInterpreter')
2709 roeMask.set_name(
'RestOfEventInterpreter_' + list_name +
'_' + mask_name)
2710 roeMask.param(
'particleList', list_name)
2711 roeMask.param(
'ROEMasks', [(mask_name, trackSelection, eclClusterSelection, klmClusterSelection)])
2712 roeMask.param(
'update',
True)
2713 path.add_module(roeMask)
2716def updateROEMasks(list_name, mask_tuples, path):
2718 Update existing ROE masks by applying additional selection cuts for tracks
2721 The multiple ROE masks with their own selection criteria are specified
2722 via list tuples (mask_name, trackSelection, eclClusterSelection, klmClusterSelection)
2724 See function `appendROEMasks`!
2726 @param list_name name of the input ParticleList
2727 @param mask_tuples array of ROEMask list tuples to be appended
2728 @param path modules are added to this path
2731 compatible_masks = []
2732 for mask
in mask_tuples:
2735 compatible_masks += [(*mask,
'')]
2737 compatible_masks += [mask]
2739 roeMask = register_module(
'RestOfEventInterpreter')
2740 roeMask.set_name(
'RestOfEventInterpreter_' + list_name +
'_' +
'MaskList')
2741 roeMask.param(
'particleList', list_name)
2742 roeMask.param(
'ROEMasks', compatible_masks)
2743 roeMask.param(
'update',
True)
2744 path.add_module(roeMask)
2747def keepInROEMasks(list_name, mask_names, cut_string, path=None):
2749 This function is used to apply particle list specific cuts on one or more ROE masks (track or eclCluster).
2750 With this function one can KEEP the tracks/eclclusters used in particles from provided particle list.
2751 This function should be executed only in the for_each roe path for the current ROE object.
2753 To avoid unnecessary computation, the input particle list should only contain particles from ROE
2754 (use cut 'isInRestOfEvent == 1'). To update the ECLCluster masks, the input particle list should be a photon
2755 particle list (e.g. 'gamma:someLabel'). To update the Track masks, the input particle list should be a charged
2756 pion particle list (e.g. 'pi+:someLabel').
2758 Updating a non-existing mask will create a new one.
2760 - keep only those tracks that were used in provided particle list
2762 .. code-block:: python
2764 keepInROEMasks('pi+:goodTracks', 'mask', '', path=mypath)
2766 - keep only those clusters that were used in provided particle list and pass a cut, apply to several masks
2768 .. code-block:: python
2770 keepInROEMasks('gamma:goodClusters', ['mask1', 'mask2'], 'E > 0.1', path=mypath)
2773 @param list_name name of the input ParticleList
2774 @param mask_names array of ROEMasks to be updated
2775 @param cut_string decay string with which the mask will be updated
2776 @param path modules are added to this path
2779 updateMask = register_module(
'RestOfEventUpdater')
2780 updateMask.set_name(
'RestOfEventUpdater_' + list_name +
'_masks')
2781 updateMask.param(
'particleList', list_name)
2782 updateMask.param(
'updateMasks', mask_names)
2783 updateMask.param(
'cutString', cut_string)
2784 updateMask.param(
'discard',
False)
2785 path.add_module(updateMask)
2788def discardFromROEMasks(list_name, mask_names, cut_string, path=None):
2790 This function is used to apply particle list specific cuts on one or more ROE masks (track or eclCluster).
2791 With this function one can DISCARD the tracks/eclclusters used in particles from provided particle list.
2792 This function should be executed only in the for_each roe path for the current ROE object.
2794 To avoid unnecessary computation, the input particle list should only contain particles from ROE
2795 (use cut 'isInRestOfEvent == 1'). To update the ECLCluster masks, the input particle list should be a photon
2796 particle list (e.g. 'gamma:someLabel'). To update the Track masks, the input particle list should be a charged
2797 pion particle list (e.g. 'pi+:someLabel').
2799 Updating a non-existing mask will create a new one.
2801 - discard tracks that were used in provided particle list
2803 .. code-block:: python
2805 discardFromROEMasks('pi+:badTracks', 'mask', '', path=mypath)
2807 - discard clusters that were used in provided particle list and pass a cut, apply to several masks
2809 .. code-block:: python
2811 discardFromROEMasks('gamma:badClusters', ['mask1', 'mask2'], 'E < 0.1', path=mypath)
2814 @param list_name name of the input ParticleList
2815 @param mask_names array of ROEMasks to be updated
2816 @param cut_string decay string with which the mask will be updated
2817 @param path modules are added to this path
2820 updateMask = register_module(
'RestOfEventUpdater')
2821 updateMask.set_name(
'RestOfEventUpdater_' + list_name +
'_masks')
2822 updateMask.param(
'particleList', list_name)
2823 updateMask.param(
'updateMasks', mask_names)
2824 updateMask.param(
'cutString', cut_string)
2825 updateMask.param(
'discard',
True)
2826 path.add_module(updateMask)
2829def optimizeROEWithV0(list_name, mask_names, cut_string, path=None):
2831 This function is used to apply particle list specific cuts on one or more ROE masks for Tracks.
2832 It is possible to optimize the ROE selection by treating tracks from V0's separately, meaning,
2833 taking V0's 4-momentum into account instead of 4-momenta of tracks. A cut for only specific V0's
2834 passing it can be applied.
2836 The input particle list should be a V0 particle list: K_S0 ('K_S0:someLabel', ''),
2837 Lambda ('Lambda:someLabel', '') or converted photons ('gamma:someLabel').
2839 Updating a non-existing mask will create a new one.
2841 - treat tracks from K_S0 inside mass window separately, replace track momenta with K_S0 momentum
2843 .. code-block:: python
2845 optimizeROEWithV0('K_S0:opt', 'mask', '0.450 < M < 0.550', path=mypath)
2847 @param list_name name of the input ParticleList
2848 @param mask_names array of ROEMasks to be updated
2849 @param cut_string decay string with which the mask will be updated
2850 @param path modules are added to this path
2853 updateMask = register_module(
'RestOfEventUpdater')
2854 updateMask.set_name(
'RestOfEventUpdater_' + list_name +
'_masks')
2855 updateMask.param(
'particleList', list_name)
2856 updateMask.param(
'updateMasks', mask_names)
2857 updateMask.param(
'cutString', cut_string)
2858 path.add_module(updateMask)
2861def updateROEUsingV0Lists(target_particle_list, mask_names, default_cleanup=True, selection_cuts=None,
2862 apply_mass_fit=False, fitter='treefit', path=None):
2864 This function creates V0 particle lists (photons, :math:`K^0_S` and :math:`\\Lambda^0`)
2865 and it uses V0 candidates to update the Rest Of Event, which is associated to the target particle list.
2866 It is possible to apply a standard or customized selection and mass fit to the V0 candidates.
2869 @param target_particle_list name of the input ParticleList
2870 @param mask_names array of ROE masks to be applied
2871 @param default_cleanup if True, predefined cuts will be applied on the V0 lists
2872 @param selection_cuts a single string of selection cuts or tuple of three strings (photon_cuts, K_S0_cuts, Lambda0_cuts),
2873 which will be applied to the V0 lists. These cuts will have a priority over the default ones.
2874 @param apply_mass_fit if True, a mass fit will be applied to the V0 particles
2875 @param fitter string, that represent a fitter choice: "treefit" for TreeFitter and "kfit" for KFit
2876 @param path modules are added to this path
2879 roe_path = create_path()
2880 deadEndPath = create_path()
2881 signalSideParticleFilter(target_particle_list,
'', roe_path, deadEndPath)
2883 if (default_cleanup
and selection_cuts
is None):
2884 B2INFO(
"Using default cleanup in updateROEUsingV0Lists.")
2885 selection_cuts =
'abs(dM) < 0.1 '
2886 selection_cuts +=
'and daughter(0,particleID) > 0.2 and daughter(1,particleID) > 0.2 '
2887 selection_cuts +=
'and daughter(0,thetaInCDCAcceptance) and daughter(1,thetaInCDCAcceptance)'
2888 if (selection_cuts
is None or selection_cuts ==
''):
2889 B2INFO(
"No cleanup in updateROEUsingV0Lists.")
2890 selection_cuts = (
'True',
'True',
'True')
2891 if (isinstance(selection_cuts, str)):
2892 selection_cuts = (selection_cuts, selection_cuts, selection_cuts)
2894 roe_cuts =
'isInRestOfEvent > 0'
2895 fillConvertedPhotonsList(
'gamma:v0_roe -> e+ e-', f
'{selection_cuts[0]} and {roe_cuts}',
2897 fillParticleList(
'K_S0:v0_roe -> pi+ pi-', f
'{selection_cuts[1]} and {roe_cuts}',
2899 fillParticleList(
'Lambda0:v0_roe -> p+ pi-', f
'{selection_cuts[2]} and {roe_cuts}',
2901 fitter = fitter.lower()
2902 if (fitter !=
'treefit' and fitter !=
'kfit'):
2903 B2WARNING(
'Argument "fitter" in updateROEUsingV0Lists has only "treefit" and "kfit" options, '
2904 f
'but "{fitter}" was provided! TreeFitter will be used instead.')
2906 from vertex
import kFit, treeFit
2907 for v0
in [
'gamma:v0_roe',
'K_S0:v0_roe',
'Lambda0:v0_roe']:
2908 if (apply_mass_fit
and fitter ==
'kfit'):
2909 kFit(v0, conf_level=0.0, fit_type=
'massvertex', path=roe_path)
2910 if (apply_mass_fit
and fitter ==
'treefit'):
2911 treeFit(v0, conf_level=0.0, massConstraint=[v0.split(
':')[0]], path=roe_path)
2912 optimizeROEWithV0(v0, mask_names,
'', path=roe_path)
2913 path.for_each(
'RestOfEvent',
'RestOfEvents', roe_path)
2916def printROEInfo(mask_names=None, full_print=False,
2917 unpackComposites=True, path=None):
2919 This function prints out the information for the current ROE, so it should only be used in the for_each path.
2920 It prints out basic ROE object info.
2922 If mask names are provided, specific information for those masks will be printed out.
2924 It is also possible to print out all particles in a given mask if the
2925 'full_print' is set to True.
2927 @param mask_names array of ROEMask names for printing out info
2928 @param unpackComposites if true, replace composite particles by their daughters
2929 @param full_print print out particles in mask
2930 @param path modules are added to this path
2933 if mask_names
is None:
2935 printMask = register_module(
'RestOfEventPrinter')
2936 printMask.set_name(
'RestOfEventPrinter')
2937 printMask.param(
'maskNames', mask_names)
2938 printMask.param(
'fullPrint', full_print)
2939 printMask.param(
'unpackComposites', unpackComposites)
2940 path.add_module(printMask)
2943def buildContinuumSuppression(list_name, roe_mask, ipprofile_fit=False, path=None):
2945 Creates for each Particle in the given ParticleList a ContinuumSuppression
2946 dataobject and makes basf2 relation between them.
2948 :param list_name: name of the input ParticleList
2949 :param roe_mask: name of the ROE mask
2950 :param ipprofile_fit: turn on vertex fit of input tracks with IP profile constraint
2951 :param path: modules are added to this path
2954 qqBuilder = register_module(
'ContinuumSuppressionBuilder')
2955 qqBuilder.set_name(
'QQBuilder_' + list_name)
2956 qqBuilder.param(
'particleList', list_name)
2957 qqBuilder.param(
'ROEMask', roe_mask)
2958 qqBuilder.param(
'performIPProfileFit', ipprofile_fit)
2959 path.add_module(qqBuilder)
2964 Removes all Particles that are not in a given list of ParticleLists (or daughters of those).
2965 All relations from/to Particles, daughter indices, and other ParticleLists are fixed.
2967 @param lists_to_keep Keep the Particles and their daughters in these ParticleLists.
2968 @param path modules are added to this path
2971 mod = register_module(
'RemoveParticlesNotInLists')
2972 mod.param(
'particleLists', lists_to_keep)
2973 path.add_module(mod)
2976def inclusiveBtagReconstruction(upsilon_list_name, bsig_list_name, btag_list_name, input_lists_names, path):
2978 Reconstructs Btag from particles in given ParticleLists which do not share any final state particles (mdstSource) with Bsig.
2980 @param upsilon_list_name Name of the ParticleList to be filled with 'Upsilon(4S) -> B:sig anti-B:tag'
2981 @param bsig_list_name Name of the Bsig ParticleList
2982 @param btag_list_name Name of the Bsig ParticleList
2983 @param input_lists_names List of names of the ParticleLists which are used to reconstruct Btag from
2986 btag = register_module(
'InclusiveBtagReconstruction')
2987 btag.set_name(
'InclusiveBtagReconstruction_' + bsig_list_name)
2988 btag.param(
'upsilonListName', upsilon_list_name)
2989 btag.param(
'bsigListName', bsig_list_name)
2990 btag.param(
'btagListName', btag_list_name)
2991 btag.param(
'inputListsNames', input_lists_names)
2992 path.add_module(btag)
2995def selectDaughters(particle_list_name, decay_string, path):
2997 Redefine the Daughters of a particle: select from decayString
2999 @param particle_list_name input particle list
3000 @param decay_string for selecting the Daughters to be preserved
3003 seld = register_module(
'SelectDaughters')
3004 seld.set_name(
'SelectDaughters_' + particle_list_name)
3005 seld.param(
'listName', particle_list_name)
3006 seld.param(
'decayString', decay_string)
3007 path.add_module(seld)
3010def markDuplicate(particleList, prioritiseV0, path):
3012 Call DuplicateVertexMarker to find duplicate particles in a list and
3013 flag the ones that should be kept
3015 @param particleList input particle list
3016 @param prioritiseV0 if true, give V0s a higher priority
3019 markdup = register_module(
'DuplicateVertexMarker')
3020 markdup.param(
'particleList', particleList)
3021 markdup.param(
'prioritiseV0', prioritiseV0)
3022 path.add_module(markdup)
3025PI0ETAVETO_COUNTER = 0
3028def oldwritePi0EtaVeto(
3031 workingDirectory='.',
3032 pi0vetoname='Pi0_Prob',
3033 etavetoname='Eta_Prob',
3039 Give pi0/eta probability for hard photon.
3041 In the default weight files a value of 1.4 GeV is set as the lower limit for the hard photon energy in the CMS frame.
3043 The current default weight files are optimised using MC9.
3044 The input variables are as below. Aliases are set to some variables during training.
3046 * M: pi0/eta candidates Invariant mass
3047 * lowE: soft photon energy in lab frame
3048 * cTheta: soft photon ECL cluster's polar angle
3049 * Zmva: soft photon output of MVA using Zernike moments of the cluster
3050 * minC2Hdist: soft photon distance from eclCluster to nearest point on nearest Helix at the ECL cylindrical radius
3052 If you don't have weight files in your workingDirectory,
3053 these files are downloaded from database to your workingDirectory automatically.
3054 Please refer to analysis/examples/tutorials/B2A306-B02RhoGamma-withPi0EtaVeto.py
3055 about how to use this function.
3058 Please don't use following ParticleList names elsewhere:
3060 ``gamma:HARDPHOTON``, ``pi0:PI0VETO``, ``eta:ETAVETO``,
3061 ``gamma:PI0SOFT + str(PI0ETAVETO_COUNTER)``, ``gamma:ETASOFT + str(PI0ETAVETO_COUNTER)``
3063 Please don't use ``lowE``, ``cTheta``, ``Zmva``, ``minC2Hdist`` as alias elsewhere.
3065 @param particleList The input ParticleList
3066 @param decayString specify Particle to be added to the ParticleList
3067 @param workingDirectory The weight file directory
3068 @param downloadFlag whether download default weight files or not
3069 @param pi0vetoname extraInfo name of pi0 probability
3070 @param etavetoname extraInfo name of eta probability
3071 @param selection Selection criteria that Particle needs meet in order for for_each ROE path to continue
3072 @param path modules are added to this path
3077 B2ERROR(
"The old pi0 / eta veto is not suitable for Belle analyses.")
3082 global PI0ETAVETO_COUNTER
3084 if PI0ETAVETO_COUNTER == 0:
3085 from variables
import variables
3086 variables.addAlias(
'lowE',
'daughter(1,E)')
3087 variables.addAlias(
'cTheta',
'daughter(1,clusterTheta)')
3088 variables.addAlias(
'Zmva',
'daughter(1,clusterZernikeMVA)')
3089 variables.addAlias(
'minC2Tdist',
'daughter(1,minC2TDist)')
3090 variables.addAlias(
'cluNHits',
'daughter(1,clusterNHits)')
3091 variables.addAlias(
'E9E21',
'daughter(1,clusterE9E21)')
3093 PI0ETAVETO_COUNTER = PI0ETAVETO_COUNTER + 1
3095 roe_path = create_path()
3097 deadEndPath = create_path()
3099 signalSideParticleFilter(particleList, selection, roe_path, deadEndPath)
3101 fillSignalSideParticleList(
'gamma:HARDPHOTON', decayString, path=roe_path)
3103 pi0softname =
'gamma:PI0SOFT'
3104 etasoftname =
'gamma:ETASOFT'
3105 softphoton1 = pi0softname + str(PI0ETAVETO_COUNTER)
3106 softphoton2 = etasoftname + str(PI0ETAVETO_COUNTER)
3110 '[clusterReg==1 and E>0.025] or [clusterReg==2 and E>0.02] or [clusterReg==3 and E>0.02]',
3112 applyCuts(softphoton1,
'abs(clusterTiming)<120', path=roe_path)
3115 '[clusterReg==1 and E>0.035] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.03]',
3117 applyCuts(softphoton2,
'abs(clusterTiming)<120', path=roe_path)
3119 reconstructDecay(
'pi0:PI0VETO -> gamma:HARDPHOTON ' + softphoton1,
'', path=roe_path)
3120 reconstructDecay(
'eta:ETAVETO -> gamma:HARDPHOTON ' + softphoton2,
'', path=roe_path)
3122 if not os.path.isdir(workingDirectory):
3123 os.mkdir(workingDirectory)
3124 B2INFO(
'oldwritePi0EtaVeto: ' + workingDirectory +
' has been created as workingDirectory.')
3126 if not os.path.isfile(workingDirectory +
'/pi0veto.root'):
3128 basf2_mva.download(
'Pi0VetoIdentifier', workingDirectory +
'/pi0veto.root')
3129 B2INFO(
'oldwritePi0EtaVeto: pi0veto.root has been downloaded from database to workingDirectory.')
3131 if not os.path.isfile(workingDirectory +
'/etaveto.root'):
3133 basf2_mva.download(
'EtaVetoIdentifier', workingDirectory +
'/etaveto.root')
3134 B2INFO(
'oldwritePi0EtaVeto: etaveto.root has been downloaded from database to workingDirectory.')
3136 roe_path.add_module(
'MVAExpert', listNames=[
'pi0:PI0VETO'], extraInfoName=
'Pi0Veto',
3137 identifier=workingDirectory +
'/pi0veto.root')
3138 roe_path.add_module(
'MVAExpert', listNames=[
'eta:ETAVETO'], extraInfoName=
'EtaVeto',
3139 identifier=workingDirectory +
'/etaveto.root')
3141 rankByHighest(
'pi0:PI0VETO',
'extraInfo(Pi0Veto)', numBest=1, path=roe_path)
3142 rankByHighest(
'eta:ETAVETO',
'extraInfo(EtaVeto)', numBest=1, path=roe_path)
3144 variableToSignalSideExtraInfo(
'pi0:PI0VETO', {
'extraInfo(Pi0Veto)': pi0vetoname}, path=roe_path)
3145 variableToSignalSideExtraInfo(
'eta:ETAVETO', {
'extraInfo(EtaVeto)': etavetoname}, path=roe_path)
3147 path.for_each(
'RestOfEvent',
'RestOfEvents', roe_path)
3153 mode='standardMC16rd',
3157 hardParticle='gamma',
3158 pi0PayloadNameOverride=None,
3159 pi0SoftPhotonCutOverride=None,
3160 etaPayloadNameOverride=None,
3161 etaSoftPhotonCutOverride=None,
3162 requireSoftPhotonIsInROE=False,
3167 Give pi0/eta probability for hard photon.
3169 In the default weight files a value of 1.4 GeV is set as the lower limit for the hard photon energy in the CMS frame.
3170 For MC15rd/MC16rd weight files, the BtoXGamma skim is applied during the MVA training.
3172 The current default weight files are for MC16rd. The weight files for MC15rd/MC12 are still available.
3174 The input variables of the mva training for pi0 veto using MC16rd are:
3176 * M: Invariant mass of pi0 candidates
3177 * cosHelicityAngleMomentum: Cosine of angle between momentum difference of the photons in the pi0 rest frame
3178 and momentum of pi0 in lab frame
3179 * daughter(1,E): soft photon energy in lab frame
3180 * daughter(1,clusterTheta): soft photon ECL cluster's polar angle
3181 * daughter(1,clusterLAT): soft photon lateral energy distribution
3182 * daughter(1,beamBackgroundSuppression): soft photon beam background suppression MVA output
3183 * daughter(1,fakePhotonSuppression): soft photon fake photon suppression MVA output
3185 The input variables of the mva training for eta veto using MC16rd are:
3187 * M: Invariant mass of eta candidates
3188 * cosHelicityAngleMomentum: Cosine of angle between momentum difference of the photons in the eta rest frame
3189 and momentum of eta in lab frame
3190 * daughter(1,E): soft photon energy in lab frame
3191 * daughter(1,clusterTheta): soft photon ECL cluster's polar angle
3192 * daughter(1,clusterLAT): soft photon lateral energy distribution
3193 * daughter(1,clusterNHits): soft photon total crystal weights sum(w_i) with w_i<=1
3194 * daughter(1,clusterE1E9): soft photon ratio between energies of central crystal and inner 3x3 crystals
3195 * daughter(1,clusterE9E21): soft photon ratio of energies in inner 3x3 crystals and 5x5 crystals without corners
3196 * daughter(1,clusterSecondMoment): soft photon second moment
3197 * daughter(1,clusterAbsZernikeMoment40): soft photon Zernike moment 40
3198 * daughter(1,clusterAbsZernikeMoment51): soft photon Zernike moment 51
3199 * daughter(1,beamBackgroundSuppression): soft photon beam background suppression MVA output
3200 * daughter(1,fakePhotonSuppression): soft photon fake photon suppression MVA output
3203 The input variables of the mva training for pi0 veto using MC15rd are:
3205 * M: Invariant mass of pi0 candidates
3206 * cosHelicityAngleMomentum: Cosine of angle between momentum difference of the photons in the pi0 rest frame
3207 and momentum of pi0 in lab frame
3208 * daughter(1,E): soft photon energy in lab frame
3209 * daughter(1,clusterTheta): soft photon ECL cluster's polar angle
3210 * daughter(1,clusterLAT): soft photon lateral energy distribution
3212 The input variables of the mva training for eta veto using MC15rd are:
3214 * M: Invariant mass of eta candidates
3215 * cosHelicityAngleMomentum: Cosine of angle between momentum difference of the photons in the eta rest frame
3216 and momentum of eta in lab frame
3217 * daughter(1,E): soft photon energy in lab frame
3218 * daughter(1,clusterTheta): soft photon ECL cluster's polar angle
3219 * daughter(1,clusterLAT): soft photon lateral energy distribution
3220 * daughter(1,clusterNHits): soft photon total crystal weights sum(w_i) with w_i<=1
3221 * daughter(1,clusterE1E9): soft photon ratio between energies of central crystal and inner 3x3 crystals
3222 * daughter(1,clusterE9E21): soft photon ratio of energies in inner 3x3 crystals and 5x5 crystals without corners
3223 * daughter(1,clusterSecondMoment): soft photon second moment
3224 * daughter(1,clusterAbsZernikeMoment40): soft photon Zernike moment 40
3225 * daughter(1,clusterAbsZernikeMoment51): soft photon Zernike moment 51
3227 The input variables of the mva training using MC12 are:
3229 * M: Invariant mass of pi0/eta candidates
3230 * daughter(1,E): soft photon energy in lab frame
3231 * daughter(1,clusterTheta): soft photon ECL cluster's polar angle
3232 * daughter(1,minC2TDist): soft photon distance from eclCluster to nearest point on nearest Helix at the ECL cylindrical radius
3233 * daughter(1,clusterZernikeMVA): soft photon output of MVA using Zernike moments of the cluster
3234 * daughter(1,clusterNHits): soft photon total crystal weights sum(w_i) with w_i<=1
3235 * daughter(1,clusterE9E21): soft photon ratio of energies in inner 3x3 crystals and 5x5 crystals without corners
3236 * cosHelicityAngleMomentum: Cosine of angle between momentum difference of the photons in the pi0/eta rest frame
3237 and momentum of pi0/eta in lab frame
3239 The following strings are available for mode:
3241 * standard: loose energy cut and no clusterNHits cut are applied to soft photon
3242 * tight: tight energy cut and no clusterNHits cut are applied to soft photon
3243 * cluster: loose energy cut and clusterNHits cut are applied to soft photon
3244 * both: tight energy cut and clusterNHits cut are applied to soft photon
3245 * standardMC15rd: loose energy cut is applied to soft photon and the weight files are trained using MC15rd
3246 * tightMC15rd: tight energy cut is applied to soft photon and the weight files are trained using MC15rd
3247 * standardMC16rd: loose energy cut is applied to soft photon and the weight files are trained using MC16rd
3248 * tightMC16rd: tight energy cut is applied to soft photon and the weight files are trained using MC16rd
3250 The final probability of the pi0/eta veto is stored as an extraInfo. If no suffix is set it can be obtained from the variables
3251 `pi0Prob`/`etaProb`. Otherwise, it is available as '{Pi0, Eta}ProbOrigin', '{Pi0, Eta}ProbTightEnergyThreshold', '{Pi0,
3252 Eta}ProbLargeClusterSize', '{Pi0, Eta}ProbTightEnergyThresholdAndLargeClusterSize', '{Pi0, Eta}ProbOriginMC15rd', or
3253 '{Pi0, Eta}ProbTightEnergyThresholdMC15rd' for the six modes described above, with the chosen suffix appended. If one would
3254 like to call this veto twice in one script, add suffix in the second time!
3255 The second highest probability of the pi0/eta veto also is stored as an extraInfo, with a prefix of 'second' to the previous
3256 ones, e.g. secondPi0ProbOrigin{suffix}. This can be used to do validation/systematics study.
3259 Please don't use following ParticleList names elsewhere:
3261 ``gamma:HardPhoton``,
3262 ``gamma:Pi0Soft + ListName + '_' + particleList.replace(':', '_')``,
3263 ``gamma:EtaSoft + ListName + '_' + particleList.replace(':', '_')``,
3264 ``pi0:EtaVeto + ListName``,
3265 ``eta:EtaVeto + ListName``
3267 @param particleList the input ParticleList
3268 @param decayString specify Particle to be added to the ParticleList
3269 @param mode choose one mode out of 'standardMC16rd', 'tightMC16rd', 'standardMC15rd', 'tightMC15rd',
3270 'standard', 'tight', 'cluster' and 'both'
3271 @param selection selection criteria that Particle needs meet in order for for_each ROE path to continue
3272 @param path modules are added to this path
3273 @param suffix optional suffix to be appended to the usual extraInfo name
3274 @param hardParticle particle name which is used to calculate the pi0/eta probability (default is gamma)
3275 @param pi0PayloadNameOverride specify the payload name of pi0 veto only if one wants to use non-default one. (default is None)
3276 @param pi0SoftPhotonCutOverride specify the soft photon selection criteria of pi0 veto only if one wants to use non-default one.
3278 @param etaPayloadNameOverride specify the payload name of eta veto only if one wants to use non-default one. (default is None)
3279 @param etaSoftPhotonCutOverride specify the soft photon selection criteria of eta veto only if one wants to use non-default one.
3281 @param requireSoftPhotonIsInROE specify if the soft photons used to build pi0 and eta candidates have to be in the current ROE
3282 or not. Default is False, i.e. all soft photons in the event are used.
3283 @param pi0Selection Selection for the pi0 reconstruction. Default is "".
3284 @param etaSelection Selection for the eta reconstruction. Default is "".
3289 B2ERROR(
"The pi0 / eta veto is not suitable for Belle analyses.")
3291 if (requireSoftPhotonIsInROE):
3292 B2WARNING(
"Requiring the soft photon to being in the ROE was not done for the MVA training. "
3293 "Please check the results carefully.")
3296 if (mode ==
'standardMC15rd' or mode ==
'tightMC15rd'):
3297 if (pi0Selection !=
'[0.03 < M < 0.23]' or etaSelection !=
'[0.25 < M < 0.75]'):
3300 if (pi0Selection !=
'' or etaSelection !=
''):
3304 "Selection criteria for the pi0 or the eta during reconstructDecay differ from those used during the MVA training. "
3305 "You may get NAN value. Please check the results carefully.")
3307 renameSuffix =
False
3309 for module
in path.modules():
3310 if module.type() ==
"SubEvent" and not renameSuffix:
3311 for subpath
in [p.values
for p
in module.available_params()
if p.name ==
"path"]:
3314 for submodule
in subpath.modules():
3315 if f
'{hardParticle}:HardPhoton{suffix}' in submodule.name():
3317 B2WARNING(
"Same extension already used in writePi0EtaVeto, append '_0'")
3321 roe_path = create_path()
3322 deadEndPath = create_path()
3323 signalSideParticleFilter(particleList, selection, roe_path, deadEndPath)
3324 fillSignalSideParticleList(f
'{hardParticle}:HardPhoton{suffix}', decayString, path=roe_path)
3326 dictListName = {
'standard':
'Origin',
3327 'tight':
'TightEnergyThreshold',
3328 'cluster':
'LargeClusterSize',
3329 'both':
'TightEnrgyThresholdAndLargeClusterSize',
3330 'standardMC15rd':
'OriginMC15rd',
3331 'tightMC15rd':
'TightEnergyThresholdMC15rd',
3332 'standardMC16rd':
'OriginMC16rd',
3333 'tightMC16rd':
'TightEnergyThresholdMC16rd'}
3335 dictPi0EnergyCut = {
3336 'standard':
'[[clusterReg==1 and E>0.025] or [clusterReg==2 and E>0.02] or [clusterReg==3 and E>0.02]]',
3337 'tight':
'[[clusterReg==1 and E>0.03] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.04]]',
3338 'cluster':
'[[clusterReg==1 and E>0.025] or [clusterReg==2 and E>0.02] or [clusterReg==3 and E>0.02]]',
3339 'both':
'[[clusterReg==1 and E>0.03] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.04]]',
3340 'standardMC15rd':
'[[clusterReg==1 and E>0.0225] or [clusterReg==2 and E>0.02] or [clusterReg==3 and E>0.02]]',
3341 'tightMC15rd':
'[[clusterReg==1 and E>0.03] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.04]]',
3342 'standardMC16rd':
'[[clusterReg==1 and E>0.0225] or [clusterReg==2 and E>0.02] or [clusterReg==3 and E>0.02]]',
3343 'tightMC16rd':
'[[clusterReg==1 and E>0.03] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.04]]'}
3345 dictEtaEnergyCut = {
3346 'standard':
'[[clusterReg==1 and E>0.035] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.03]]',
3347 'tight':
'[[clusterReg==1 and E>0.06] or [clusterReg==2 and E>0.06] or [clusterReg==3 and E>0.06]]',
3348 'cluster':
'[[clusterReg==1 and E>0.035] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.03]]',
3349 'both':
'[[clusterReg==1 and E>0.06] or [clusterReg==2 and E>0.06] or [clusterReg==3 and E>0.06]]',
3350 'standardMC15rd':
'[[clusterReg==1 and E>0.0225] or [clusterReg==2 and E>0.02] or [clusterReg==3 and E>0.02]]',
3351 'tightMC15rd':
'[[clusterReg==1 and E>0.03] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.04]]',
3352 'standardMC16rd':
'[[clusterReg==1 and E>0.0225] or [clusterReg==2 and E>0.02] or [clusterReg==3 and E>0.02]]',
3353 'tightMC16rd':
'[[clusterReg==1 and E>0.03] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.04]]'}
3355 dictNHitsTimingCut = {
'standard':
'clusterNHits >= 0 and abs(clusterTiming)<clusterErrorTiming',
3356 'tight':
'clusterNHits >= 0 and abs(clusterTiming)<clusterErrorTiming',
3357 'cluster':
'clusterNHits >= 2 and abs(clusterTiming)<clusterErrorTiming',
3358 'both':
'clusterNHits >= 2 and abs(clusterTiming)<clusterErrorTiming',
3359 'standardMC15rd':
'clusterNHits > 1.5 and abs(clusterTiming) < 200',
3360 'tightMC15rd':
'clusterNHits > 1.5 and abs(clusterTiming) < 200',
3361 'standardMC16rd':
'clusterNHits > 1.5 and abs(clusterTiming) < 200',
3362 'tightMC16rd':
'clusterNHits > 1.5 and abs(clusterTiming) < 200'}
3364 dictPi0PayloadName = {
'standard':
'Pi0VetoIdentifierStandard',
3365 'tight':
'Pi0VetoIdentifierWithHigherEnergyThreshold',
3366 'cluster':
'Pi0VetoIdentifierWithLargerClusterSize',
3367 'both':
'Pi0VetoIdentifierWithHigherEnergyThresholdAndLargerClusterSize',
3368 'standardMC15rd':
'Pi0VetoIdentifierStandardMC15rd',
3369 'tightMC15rd':
'Pi0VetoIdentifierWithHigherEnergyThresholdMC15rd',
3370 'standardMC16rd':
'Pi0VetoIdentifierStandardMC16rd',
3371 'tightMC16rd':
'Pi0VetoIdentifierWithHigherEnergyThresholdMC16rd'}
3373 dictEtaPayloadName = {
'standard':
'EtaVetoIdentifierStandard',
3374 'tight':
'EtaVetoIdentifierWithHigherEnergyThreshold',
3375 'cluster':
'EtaVetoIdentifierWithLargerClusterSize',
3376 'both':
'EtaVetoIdentifierWithHigherEnergyThresholdAndLargerClusterSize',
3377 'standardMC15rd':
'EtaVetoIdentifierStandardMC15rd',
3378 'tightMC15rd':
'EtaVetoIdentifierWithHigherEnergyThresholdMC15rd',
3379 'standardMC16rd':
'EtaVetoIdentifierStandardMC16rd',
3380 'tightMC16rd':
'EtaVetoIdentifierWithHigherEnergyThresholdMC16rd'}
3382 dictPi0ExtraInfoName = {
'standard':
'Pi0ProbOrigin',
3383 'tight':
'Pi0ProbTightEnergyThreshold',
3384 'cluster':
'Pi0ProbLargeClusterSize',
3385 'both':
'Pi0ProbTightEnergyThresholdAndLargeClusterSize',
3386 'standardMC15rd':
'Pi0ProbOriginMC15rd',
3387 'tightMC15rd':
'Pi0ProbTightEnergyThresholdMC15rd',
3388 'standardMC16rd':
'Pi0ProbOriginMC16rd',
3389 'tightMC16rd':
'Pi0ProbTightEnergyThresholdMC16rd'}
3391 dictEtaExtraInfoName = {
'standard':
'EtaProbOrigin',
3392 'tight':
'EtaProbTightEnergyThreshold',
3393 'cluster':
'EtaProbLargeClusterSize',
3394 'both':
'EtaProbTightEnergyThresholdAndLargeClusterSize',
3395 'standardMC15rd':
'EtaProbOriginMC15rd',
3396 'tightMC15rd':
'EtaProbTightEnergyThresholdMC15rd',
3397 'standardMC16rd':
'EtaProbOriginMC16rd',
3398 'tightMC16rd':
'EtaProbTightEnergyThresholdMC16rd'}
3400 ListName = dictListName[mode]
3401 Pi0EnergyCut = dictPi0EnergyCut[mode]
3402 EtaEnergyCut = dictEtaEnergyCut[mode]
3403 NHitsTimingCut = dictNHitsTimingCut[mode]
3404 Pi0PayloadName = dictPi0PayloadName[mode]
3405 EtaPayloadName = dictEtaPayloadName[mode]
3406 Pi0ExtraInfoName = dictPi0ExtraInfoName[mode]
3407 EtaExtraInfoName = dictEtaExtraInfoName[mode]
3410 if pi0PayloadNameOverride
is not None:
3411 Pi0PayloadName = pi0PayloadNameOverride
3412 B2WARNING(
"You're using personal weight files, be careful. ")
3413 if pi0SoftPhotonCutOverride
is None:
3414 Pi0SoftPhotonCut = Pi0EnergyCut +
' and ' + NHitsTimingCut
3416 Pi0SoftPhotonCut = pi0SoftPhotonCutOverride
3417 B2WARNING(
"You're applying personal cuts on the soft photon candidates, be careful. ")
3419 if requireSoftPhotonIsInROE:
3420 Pi0SoftPhotonCut +=
' and isInRestOfEvent==1'
3423 pi0soft = f
'gamma:Pi0Soft{suffix}' + ListName +
'_' + particleList.replace(
':',
'_')
3425 fillParticleList(pi0soft, Pi0SoftPhotonCut, path=roe_path)
3427 reconstructDecay(
'pi0:Pi0Veto' + ListName + suffix + f
' -> {hardParticle}:HardPhoton{suffix} ' + pi0soft, pi0Selection,
3428 allowChargeViolation=
True, path=roe_path)
3430 roe_path.add_module(
'MVAExpert', listNames=[
'pi0:Pi0Veto' + ListName + suffix],
3431 extraInfoName=Pi0ExtraInfoName, identifier=Pi0PayloadName)
3434 'pi0:Pi0Veto' + ListName + suffix,
3435 'extraInfo(' + Pi0ExtraInfoName +
')',
3437 outputVariable=
"Pi0VetoRank",
3439 cutAndCopyList(outputListName=
'pi0:Pi0VetoFirst' + ListName + suffix,
3440 inputListName=
'pi0:Pi0Veto' + ListName + suffix,
3441 cut=
'extraInfo(Pi0VetoRank)==1',
3443 variableToSignalSideExtraInfo(
'pi0:Pi0VetoFirst' + ListName + suffix,
3444 {
'extraInfo(' + Pi0ExtraInfoName +
')': Pi0ExtraInfoName + suffix}, path=roe_path)
3446 cutAndCopyList(outputListName=
'pi0:Pi0VetoSecond' + ListName + suffix,
3447 inputListName=
'pi0:Pi0Veto' + ListName + suffix,
3448 cut=
'extraInfo(Pi0VetoRank)==2',
3450 variableToSignalSideExtraInfo(
'pi0:Pi0VetoSecond' + ListName + suffix,
3451 {
'extraInfo(' + Pi0ExtraInfoName +
')':
'second' + Pi0ExtraInfoName + suffix}, path=roe_path)
3454 if etaPayloadNameOverride
is not None:
3455 EtaPayloadName = etaPayloadNameOverride
3456 B2WARNING(
"You're using personal weight files, be careful. ")
3457 if etaSoftPhotonCutOverride
is None:
3458 EtaSoftPhotonCut = EtaEnergyCut +
' and ' + NHitsTimingCut
3460 EtaSoftPhotonCut = etaSoftPhotonCutOverride
3461 B2WARNING(
"You're applying personal cuts on the soft photon candidates, be careful. ")
3463 if requireSoftPhotonIsInROE:
3464 EtaSoftPhotonCut +=
' and isInRestOfEvent==1'
3466 etasoft = f
'gamma:EtaSoft{suffix}' + ListName +
'_' + particleList.replace(
':',
'_')
3467 fillParticleList(etasoft, EtaSoftPhotonCut, path=roe_path)
3468 reconstructDecay(
'eta:EtaVeto' + ListName + suffix + f
' -> {hardParticle}:HardPhoton{suffix} ' + etasoft, etaSelection,
3469 allowChargeViolation=
True, path=roe_path)
3470 roe_path.add_module(
'MVAExpert', listNames=[
'eta:EtaVeto' + ListName + suffix],
3471 extraInfoName=EtaExtraInfoName, identifier=EtaPayloadName)
3473 'eta:EtaVeto' + ListName + suffix,
3474 'extraInfo(' + EtaExtraInfoName +
')',
3476 outputVariable=
"EtaVetoRank",
3478 cutAndCopyList(outputListName=
'eta:EtaVetoFirst' + ListName + suffix,
3479 inputListName=
'eta:EtaVeto' + ListName + suffix,
3480 cut=
'extraInfo(EtaVetoRank)==1',
3482 variableToSignalSideExtraInfo(
'eta:EtaVetoFirst' + ListName + suffix,
3483 {
'extraInfo(' + EtaExtraInfoName +
')': EtaExtraInfoName + suffix}, path=roe_path)
3484 cutAndCopyList(outputListName=
'eta:EtaVetoSecond' + ListName + suffix,
3485 inputListName=
'eta:EtaVeto' + ListName + suffix,
3486 cut=
'extraInfo(EtaVetoRank)==2',
3488 variableToSignalSideExtraInfo(
'eta:EtaVetoSecond' + ListName + suffix,
3489 {
'extraInfo(' + EtaExtraInfoName +
')':
'second' + EtaExtraInfoName + suffix}, path=roe_path)
3491 path.for_each(
'RestOfEvent',
'RestOfEvents', roe_path)
3494def lowEnergyPi0Identification(pi0List, gammaList, payloadNameSuffix,
3497 Calculate low-energy pi0 identification.
3498 The result is stored as ExtraInfo ``lowEnergyPi0Identification`` for
3502 pi0List (str): Pi0 list.
3504 gammaList (str): Gamma list. First, an energy cut E > 0.2 is applied to the photons from this list.
3505 Then, all possible combinations with a pi0 daughter photon are formed except the one
3506 corresponding to the reconstructed pi0.
3507 The maximum low-energy pi0 veto value is calculated for such photon pairs
3508 and used as one of the input variables for the identification classifier.
3510 payloadNameSuffix (str): Payload name suffix. The weight payloads are stored in the analysis global
3511 tag and have the following names:\n
3512 * ``'LowEnergyPi0Veto' + payloadNameSuffix``
3513 * ``'LowEnergyPi0Identification' + payloadNameSuffix``\n
3514 The possible suffixes are:\n
3515 * ``'Belle1'`` for Belle data.
3516 * ``'Belle2Release5'`` for Belle II release 5 data (MC14, proc12, buckets 16 - 25).
3517 * ``'Belle2Release6'`` for Belle II release 6 data (MC15, proc13, buckets 26 - 36).
3519 path (basf2.Path): Module path.
3523 gammaListVeto = f
'{gammaList}_pi0veto'
3524 cutAndCopyList(gammaListVeto, gammaList,
'E > 0.2', path=path)
3526 payload_name =
'LowEnergyPi0Veto' + payloadNameSuffix
3527 path.add_module(
'LowEnergyPi0VetoExpert', identifier=payload_name,
3528 VetoPi0Daughters=
True, GammaListName=gammaListVeto,
3530 payload_name =
'LowEnergyPi0Identification' + payloadNameSuffix
3531 path.add_module(
'LowEnergyPi0IdentificationExpert',
3532 identifier=payload_name, Pi0ListName=pi0List,
3536def getNeutralHadronGeomMatches(
3540 efficiencyCorrectionKl=0.83,
3541 efficiencyCorrectionNeutrons=1.0,
3544 For an ECL-based list, assign the mcdistanceKL and mcdistanceNeutron variables that correspond
3545 to the distance to the closest MC KL and neutron, respectively.
3546 @param particleLists the input ParticleLists, must be ECL-based lists (e.g. photons)
3547 @param addKL (default True) add distance to MC KL
3548 @param addNeutrons (default False) add distance to MC neutrons
3549 @param efficiencyCorrectionKl (default 0.83) apply overall efficiency correction
3550 @param efficiencyCorrectionNeutrons (default 1.0) apply overall efficiency correction
3551 @param path modules are added to this path
3553 from ROOT
import Belle2
3558 "NeutralHadronMatcher",
3559 particleLists=particleLists,
3560 mcPDGcode=Const.Klong.getPDGCode(),
3561 efficiencyCorrection=efficiencyCorrectionKl)
3564 "NeutralHadronMatcher",
3565 particleLists=particleLists,
3566 mcPDGcode=Const.neutron.getPDGCode(),
3567 efficiencyCorrection=efficiencyCorrectionNeutrons)
3570def getBeamBackgroundProbability(particleList, weight, path=None):
3572 Assign a probability to each ECL cluster as being signal like (1) compared to beam background like (0)
3573 @param particleList the input ParticleList, must be a photon list
3574 @param weight type of weight file to use
3575 @param path modules are added to this path
3580 B2WARNING(
"weight type must be 'Belle' for b2bii.")
3582 path.add_module(
'MVAExpert',
3583 listNames=particleList,
3584 extraInfoName=
'beamBackgroundSuppression',
3585 identifier=f
'BeamBackgroundMVA_{weight}')
3588def getFakePhotonProbability(particleList, weight, path=None):
3590 Assign a probability to each ECL cluster as being signal like (1) compared to fake photon like (0)
3591 @param particleList the input ParticleList, must be a photon list
3592 @param weight type of weight file to use
3593 @param path modules are added to this path
3598 B2WARNING(
"weight type must be 'Belle' for b2bii.")
3600 path.add_module(
'MVAExpert',
3601 listNames=particleList,
3602 extraInfoName=
'fakePhotonSuppression',
3603 identifier=f
'FakePhotonMVA_{weight}')
3606def buildEventKinematics(inputListNames=None, default_cleanup=True, custom_cuts=None,
3607 chargedPIDPriors=None, fillWithMostLikely=False, path=None):
3609 Calculates the global kinematics of the event (visible energy, missing momentum, missing mass...)
3610 using ParticleLists provided. If no ParticleList is provided, default ParticleLists are used
3611 (all track and all hits in ECL without associated track).
3613 The visible energy missing values are
3614 stored in a EventKinematics dataobject.
3616 @param inputListNames list of ParticleLists used to calculate the global event kinematics.
3617 If the list is empty, default ParticleLists pi+:evtkin and gamma:evtkin are filled.
3618 @param fillWithMostLikely if True, the module uses the most likely particle mass hypothesis for charged particles
3619 according to the PID likelihood and the option inputListNames will be ignored.
3620 @param chargedPIDPriors The prior PID fractions, that are used to regulate
3621 amount of certain charged particle species, should be a list of
3622 six floats if not None. The order of particle types is
3623 the following: [e-, mu-, pi-, K-, p+, d+]
3624 @param default_cleanup if True and either inputListNames empty or fillWithMostLikely True, default clean up cuts are applied
3625 @param custom_cuts tuple of selection cut strings of form (trackCuts, photonCuts), default is None,
3626 which would result in a standard predefined selection cuts
3627 @param path modules are added to this path
3630 if inputListNames
is None:
3632 trackCuts =
'pt > 0.1'
3633 trackCuts +=
' and thetaInCDCAcceptance'
3634 trackCuts +=
' and abs(dz) < 3'
3635 trackCuts +=
' and dr < 0.5'
3637 gammaCuts =
'E > 0.05'
3638 gammaCuts +=
' and thetaInCDCAcceptance'
3640 gammaCuts +=
' and abs(clusterTiming) < 200'
3641 if (custom_cuts
is not None):
3642 trackCuts, gammaCuts = custom_cuts
3644 if fillWithMostLikely:
3645 from stdCharged
import stdMostLikely
3646 stdMostLikely(chargedPIDPriors,
'_evtkin', path=path)
3647 inputListNames = [f
'{ptype}:mostlikely_evtkin' for ptype
in [
'K+',
'p+',
'e+',
'mu+',
'pi+']]
3649 copyList(
'gamma:evtkin',
'gamma:mdst', path=path)
3651 fillParticleList(
'gamma:evtkin',
'', path=path)
3652 inputListNames += [
'gamma:evtkin']
3654 B2INFO(
"Using default cleanup in EventKinematics module.")
3655 for ptype
in [
'K+',
'p+',
'e+',
'mu+',
'pi+']:
3656 applyCuts(f
'{ptype}:mostlikely_evtkin', trackCuts, path=path)
3657 applyCuts(
'gamma:evtkin', gammaCuts, path=path)
3659 B2INFO(
"No cleanup in EventKinematics module.")
3660 if not inputListNames:
3661 B2INFO(
"Creating particle lists pi+:evtkin and gamma:evtkin to get the global kinematics of the event.")
3662 fillParticleList(
'pi+:evtkin',
'', path=path)
3664 copyList(
'gamma:evtkin',
'gamma:mdst', path=path)
3666 fillParticleList(
'gamma:evtkin',
'', path=path)
3667 particleLists = [
'pi+:evtkin',
'gamma:evtkin']
3669 if (custom_cuts
is not None):
3670 B2INFO(
"Using default cleanup in EventKinematics module.")
3671 applyCuts(
'pi+:evtkin', trackCuts, path=path)
3672 applyCuts(
'gamma:evtkin', gammaCuts, path=path)
3674 B2INFO(
"No cleanup in EventKinematics module.")
3676 particleLists = inputListNames
3678 eventKinematicsModule = register_module(
'EventKinematics')
3679 eventKinematicsModule.set_name(
'EventKinematics_reco')
3680 eventKinematicsModule.param(
'particleLists', particleLists)
3681 path.add_module(eventKinematicsModule)
3684def buildEventKinematicsFromMC(inputListNames=None, selectionCut='', path=None):
3686 Calculates the global kinematics of the event (visible energy, missing momentum, missing mass...)
3687 using generated particles. If no ParticleList is provided, default generated ParticleLists are used.
3689 @param inputListNames list of ParticleLists used to calculate the global event kinematics.
3690 If the list is empty, default ParticleLists are filled.
3691 @param selectionCut optional selection cuts
3692 @param path Path to append the eventKinematics module to.
3695 if inputListNames
is None:
3697 if (len(inputListNames) == 0):
3701 types = [
'gamma',
'e+',
'mu+',
'pi+',
'K+',
'p+',
3704 fillParticleListFromMC(f
"{t}:evtkin_default_gen",
'mcPrimary > 0 and nDaughters == 0',
3705 True,
True, path=path)
3706 if (selectionCut !=
''):
3707 applyCuts(f
"{t}:evtkin_default_gen", selectionCut, path=path)
3708 inputListNames += [f
"{t}:evtkin_default_gen"]
3710 eventKinematicsModule = register_module(
'EventKinematics')
3711 eventKinematicsModule.set_name(
'EventKinematics_gen')
3712 eventKinematicsModule.param(
'particleLists', inputListNames)
3713 eventKinematicsModule.param(
'usingMC',
True)
3714 path.add_module(eventKinematicsModule)
3717def buildEventShape(inputListNames=None,
3718 default_cleanup=True,
3724 harmonicMoments=True,
3728 checkForDuplicates=False,
3731 Calculates the event-level shape quantities (thrust, sphericity, Fox-Wolfram moments...)
3732 using the particles in the lists provided by the user. If no particle list is provided,
3733 the function will internally create a list of good tracks and a list of good photons
3734 with (optionally) minimal quality cuts.
3737 The results of the calculation are then stored into the EventShapeContainer dataobject,
3738 and are accessible using the variables of the EventShape group.
3740 The user can switch the calculation of certain quantities on or off to save computing
3741 time. By default the calculation of the high-order moments (5-8) is turned off.
3742 Switching off an option will make the corresponding variables not available.
3745 The user can provide as many particle lists as needed, using also composite particles.
3746 In these cases, it is recommended to activate the checkForDuplicates flag since it
3747 will eliminate duplicates, e.g., if the same track is provided multiple times
3748 (either with different mass hypothesis or once as an independent particle and once
3749 as daughter of a composite particle). The first occurrence will be used in the
3750 calculations so the order in which the particle lists are given as well as within
3751 the particle lists matters.
3753 @param inputListNames List of ParticleLists used to calculate the
3754 event shape variables. If the list is empty the default
3755 particleLists pi+:evtshape and gamma:evtshape are filled.
3756 @param default_cleanup If True, applies standard cuts on pt and cosTheta when
3757 defining the internal lists. This option is ignored if the
3758 particleLists are provided by the user.
3759 @param custom_cuts tuple of selection cut strings of form (trackCuts, photonCuts), default is None,
3760 which would result in a standard predefined selection cuts
3761 @param path Path to append the eventShape modules to.
3762 @param thrust Enables the calculation of thrust-related quantities (CLEO
3763 cones, Harmonic moments, jets).
3764 @param collisionAxis Enables the calculation of the quantities related to the
3766 @param foxWolfram Enables the calculation of the Fox-Wolfram moments.
3767 @param harmonicMoments Enables the calculation of the Harmonic moments with respect
3768 to both the thrust axis and, if collisionAxis = True, the collision axis.
3769 @param allMoments If True, calculates also the FW and harmonic moments from order
3770 5 to 8 instead of the low-order ones only.
3771 @param cleoCones Enables the calculation of the CLEO cones with respect to both the thrust
3772 axis and, if collisionAxis = True, the collision axis.
3773 @param jets Enables the calculation of the hemisphere momenta and masses.
3774 Requires thrust = True.
3775 @param sphericity Enables the calculation of the sphericity-related quantities.
3776 @param checkForDuplicates Perform a check for duplicate particles before adding them. Regardless of the value of this option,
3777 it is recommended to consider sanitizing the lists you are passing to the function since this will
3778 speed up the processing.
3782 if inputListNames
is None:
3784 trackCuts =
'pt > 0.1'
3785 trackCuts +=
' and thetaInCDCAcceptance'
3786 trackCuts +=
' and abs(dz) < 3.0'
3787 trackCuts +=
' and dr < 0.5'
3789 gammaCuts =
'E > 0.05'
3790 gammaCuts +=
' and thetaInCDCAcceptance'
3792 gammaCuts +=
' and abs(clusterTiming) < 200'
3793 if (custom_cuts
is not None):
3794 trackCuts, gammaCuts = custom_cuts
3796 if not inputListNames:
3797 B2INFO(
"Creating particle lists pi+:evtshape and gamma:evtshape to get the event shape variables.")
3798 fillParticleList(
'pi+:evtshape',
'', path=path)
3800 copyList(
'gamma:evtshape',
'gamma:mdst', path=path)
3806 particleLists = [
'pi+:evtshape',
'gamma:evtshape']
3809 if (custom_cuts
is not None):
3810 B2INFO(
"Applying standard cuts")
3811 applyCuts(
'pi+:evtshape', trackCuts, path=path)
3813 applyCuts(
'gamma:evtshape', gammaCuts, path=path)
3815 B2WARNING(
"Creating the default lists with no cleanup.")
3817 particleLists = inputListNames
3819 eventShapeModule = register_module(
'EventShapeCalculator')
3820 eventShapeModule.set_name(
'EventShape')
3821 eventShapeModule.param(
'particleListNames', particleLists)
3822 eventShapeModule.param(
'enableAllMoments', allMoments)
3823 eventShapeModule.param(
'enableCleoCones', cleoCones)
3824 eventShapeModule.param(
'enableCollisionAxis', collisionAxis)
3825 eventShapeModule.param(
'enableFoxWolfram', foxWolfram)
3826 eventShapeModule.param(
'enableJets', jets)
3827 eventShapeModule.param(
'enableHarmonicMoments', harmonicMoments)
3828 eventShapeModule.param(
'enableSphericity', sphericity)
3829 eventShapeModule.param(
'enableThrust', thrust)
3830 eventShapeModule.param(
'checkForDuplicates', checkForDuplicates)
3832 path.add_module(eventShapeModule)
3835def labelTauPairMC(printDecayInfo=False, path=None, TauolaBelle=False, mapping_minus=None, mapping_plus=None):
3837 Search tau leptons into the MC information of the event. If confirms it's a generated tau pair decay,
3838 labels the decay generated of the positive and negative leptons using the ID of KKMC tau decay table.
3840 @param printDecayInfo: If true, prints ID and prong of each tau lepton in the event.
3841 @param path: module is added to this path
3842 @param TauolaBelle: if False, TauDecayMode is set. If True, TauDecayMarker is set.
3843 @param mapping_minus: if None, the map is the default one, else the path for the map is given by the user for tau-
3844 @param mapping_plus: if None, the map is the default one, else the path for the map is given by the user for tau+
3847 from basf2
import find_file
3853 m_printmode =
'default'
3855 if mapping_minus
is None:
3856 mp_file_minus = find_file(
'data/analysis/modules/TauDecayMode/map_tauminus.txt')
3858 mp_file_minus = mapping_minus
3860 if mapping_plus
is None:
3861 mp_file_plus = find_file(
'data/analysis/modules/TauDecayMode/map_tauplus.txt')
3863 mp_file_plus = mapping_plus
3865 path.add_module(
'TauDecayMode', printmode=m_printmode, file_minus=mp_file_minus, file_plus=mp_file_plus)
3868 tauDecayMarker = register_module(
'TauDecayMarker')
3869 tauDecayMarker.set_name(
'TauDecayMarker_')
3871 path.add_module(tauDecayMarker, printDecayInfo=printDecayInfo)
3874def tagCurlTracks(particleLists,
3884 The cut selector is not calibrated with Belle II data and should not be used without extensive study.
3886 Identifies curl tracks and tags them with extraInfo(isCurl=1) for later removal.
3887 For Belle data with a `b2bii` analysis the available cut based selection is described in `BN1079`_.
3889 .. _BN1079: https://belle.kek.jp/secured/belle_note/gn1079/bn1079.pdf
3892 The module loops over all particles in a given list with a transverse momentum below the pre-selection **ptCut**
3893 and assigns them to bundles based on the response of the chosen **selector** and the required minimum response set by the
3894 **responseCut**. Once all particles are assigned they are ranked by 25dr^2+dz^2. All but the lowest are tagged
3895 with extraInfo(isCurl=1) to allow for later removal by cutting the list or removing these from ROE as
3899 @param particleLists: list of particle lists to check for curls.
3900 @param mcTruth: bool flag to additionally assign particles with extraInfo(isTruthCurl) and
3901 extraInfo(truthBundleSize). To calculate these particles are assigned to bundles by their
3902 genParticleIndex then ranked and tagged as normal.
3903 @param responseCut: float min classifier response that considers two tracks to come from the same particle.
3904 If set to ``-1`` a cut value optimised to maximise the accuracy on a BBbar sample is used.
3905 Note 'cut' selector is binary 0/1.
3906 @param selectorType: string name of selector to use. The available options are 'cut' and 'mva'.
3907 It is strongly recommended to used the 'mva' selection. The 'cut' selection
3908 is based on BN1079 and is only calibrated for Belle data.
3910 @param ptCut: Pre-selection cut on transverse momentum. Only tracks below that are considered as curler candidates.
3912 @param expert_train: flag to set training mode if selector has a training mode (mva).
3913 @param expert_filename: set file name of produced training ntuple (mva).
3914 @param path: module is added to this path.
3920 if (
not isinstance(particleLists, list)):
3921 particleLists = [particleLists]
3923 curlTagger = register_module(
'CurlTagger')
3924 curlTagger.set_name(
'CurlTagger_')
3925 curlTagger.param(
'particleLists', particleLists)
3926 curlTagger.param(
'belle', belle)
3927 curlTagger.param(
'mcTruth', mcTruth)
3928 curlTagger.param(
'responseCut', responseCut)
3929 if abs(responseCut + 1) < 1e-9:
3930 curlTagger.param(
'usePayloadCut',
True)
3932 curlTagger.param(
'usePayloadCut',
False)
3934 curlTagger.param(
'selectorType', selectorType)
3935 curlTagger.param(
'ptCut', ptCut)
3936 curlTagger.param(
'train', expert_train)
3937 curlTagger.param(
'trainFilename', expert_filename)
3939 path.add_module(curlTagger)
3942def applyChargedPidMVA(particleLists, path, trainingMode, chargeIndependent=False, binaryHypoPDGCodes=(0, 0)):
3944 Use an MVA to perform particle identification for charged stable particles, using the `ChargedPidMVA` module.
3946 The module decorates Particle objects in the input ParticleList(s) with variables
3947 containing the appropriate MVA score, which can be used to select candidates by placing a cut on it.
3950 The MVA algorithm used is a gradient boosted decision tree (**TMVA 4.3.0**, **ROOT 6.20/04**).
3952 The module can perform either 'binary' PID between input S, B particle mass hypotheses according to the following scheme:
3954 * e (11) vs. pi (211)
3955 * mu (13) vs. pi (211)
3956 * pi (211) vs. K (321)
3957 * K (321) vs. pi (211)
3959 , or 'global' PID, namely "one-vs-others" separation. The latter exploits an MVA algorithm trained in multi-class mode,
3960 and it's the default behaviour. Currently, the multi-class training separates the following standard charged hypotheses:
3962 - e (11), mu (13), pi (211), K (321)
3965 In order to run the `ChargedPidMVA` and ensure the most up-to-date MVA training weights are applied,
3966 it is necessary to append the latest analysis global tag (GT) to the steering script.
3969 particleLists (list(str)): the input list of DecayStrings, where each selected (^) daughter should correspond to a
3970 standard charged ParticleList, e.g. ``['Lambda0:sig -> ^p+ ^pi-', 'J/psi:sig -> ^mu+ ^mu-']``.
3971 One can also directly pass a list of standard charged ParticleLists,
3972 e.g. ``['e+:my_electrons', 'pi+:my_pions']``.
3973 Note that charge-conjugated ParticleLists will automatically be included.
3974 path (basf2.Path): the module is added to this path.
3975 trainingMode (``Belle2.ChargedPidMVAWeights.ChargedPidMVATrainingMode``): enum identifier of the training mode.
3976 Needed to pick up the correct payload from the DB. Available choices:
3978 * c_Classification=0
3980 * c_ECL_Classification=2
3981 * c_ECL_Multiclass=3
3982 * c_PSD_Classification=4
3983 * c_PSD_Multiclass=5
3984 * c_ECL_PSD_Classification=6
3985 * c_ECL_PSD_Multiclass=7
3987 chargeIndependent (bool, ``optional``): use a BDT trained on a sample of inclusively charged particles.
3988 binaryHypoPDGCodes (tuple(int, int), ``optional``): the pdgIds of the signal, background mass hypothesis.
3989 Required only for binary PID mode.
3994 B2ERROR(
"Charged PID via MVA is not available for Belle data.")
3996 from ROOT
import Belle2
3998 TrainingMode = Belle2.ChargedPidMVAWeights.ChargedPidMVATrainingMode
4001 plSet = set(particleLists)
4005 TrainingMode.c_Classification:
4006 {
"mode":
"Classification",
"detector":
"ALL"},
4007 TrainingMode.c_Multiclass:
4008 {
"mode":
"Multiclass",
"detector":
"ALL"},
4009 TrainingMode.c_ECL_Classification:
4010 {
"mode":
"ECL_Classification",
"detector":
"ECL"},
4011 TrainingMode.c_ECL_Multiclass:
4012 {
"mode":
"ECL_Multiclass",
"detector":
"ECL"},
4013 TrainingMode.c_PSD_Classification:
4014 {
"mode":
"PSD_Classification",
"detector":
"ALL"},
4015 TrainingMode.c_PSD_Multiclass:
4016 {
"mode":
"PSD_Multiclass",
"detector":
"ALL"},
4017 TrainingMode.c_ECL_PSD_Classification:
4018 {
"mode":
"ECL_PSD_Classification",
"detector":
"ECL"},
4019 TrainingMode.c_ECL_PSD_Multiclass:
4020 {
"mode":
"ECL_PSD_Multiclass",
"detector":
"ECL"},
4023 if payloadNames.get(trainingMode)
is None:
4024 B2FATAL(
"The chosen training mode integer identifier:\n", trainingMode,
4025 "\nis not supported. Please choose among the following:\n",
4026 "\n".join(f
"{key}:{val.get('mode')}" for key, val
in sorted(payloadNames.items())))
4028 mode = payloadNames.get(trainingMode).get(
"mode")
4029 detector = payloadNames.get(trainingMode).get(
"detector")
4031 payloadName = f
"ChargedPidMVAWeights_{mode}"
4036 Const.electron.getPDGCode():
4037 {
"pName":
"e",
"pFullName":
"electron",
"pNameBkg":
"pi",
"pdgIdBkg": Const.pion.getPDGCode()},
4038 Const.muon.getPDGCode():
4039 {
"pName":
"mu",
"pFullName":
"muon",
"pNameBkg":
"pi",
"pdgIdBkg": Const.pion.getPDGCode()},
4040 Const.pion.getPDGCode():
4041 {
"pName":
"pi",
"pFullName":
"pion",
"pNameBkg":
"K",
"pdgIdBkg": Const.kaon.getPDGCode()},
4042 Const.kaon.getPDGCode():
4043 {
"pName":
"K",
"pFullName":
"kaon",
"pNameBkg":
"pi",
"pdgIdBkg": Const.pion.getPDGCode()},
4044 Const.proton.getPDGCode():
4045 {
"pName":
"p",
"pFullName":
"proton",
"pNameBkg":
"pi",
"pdgIdBkg": Const.pion.getPDGCode()},
4046 Const.deuteron.getPDGCode():
4047 {
"pName":
"d",
"pFullName":
"deuteron",
"pNameBkg":
"pi",
"pdgIdBkg": Const.pion.getPDGCode()},
4050 if binaryHypoPDGCodes == (0, 0):
4053 chargedpid = register_module(
"ChargedPidMVAMulticlass")
4054 chargedpid.set_name(f
"ChargedPidMVAMulticlass_{mode}")
4061 binaryOpts = [(pdgIdSig, info[
"pdgIdBkg"])
for pdgIdSig, info
in stdChargedMap.items()]
4063 if binaryHypoPDGCodes
not in binaryOpts:
4064 B2FATAL(
"No charged pid MVA was trained to separate ", binaryHypoPDGCodes[0],
" vs. ", binaryHypoPDGCodes[1],
4065 ". Please choose among the following pairs:\n",
4066 "\n".join(f
"{opt[0]} vs. {opt[1]}" for opt
in binaryOpts))
4070 if not decayDescriptor.init(name):
4071 raise ValueError(f
"Invalid particle list {name} in applyChargedPidMVA!")
4072 msg = f
"Input ParticleList: {name}"
4073 pdgs = [abs(decayDescriptor.getMother().getPDGCode())]
4074 daughter_pdgs = decayDescriptor.getSelectionPDGCodes()
4075 if len(daughter_pdgs) > 0:
4076 pdgs = daughter_pdgs
4077 for idaughter, pdg
in enumerate(pdgs):
4078 if abs(pdg)
not in binaryHypoPDGCodes:
4080 msg = f
"Selected daughter {idaughter} in ParticleList: {name}"
4082 f
"{msg} (PDG={pdg}) is neither signal ({binaryHypoPDGCodes[0]}) nor background ({binaryHypoPDGCodes[1]}).")
4084 chargedpid = register_module(
"ChargedPidMVA")
4085 chargedpid.set_name(f
"ChargedPidMVA_{binaryHypoPDGCodes[0]}_vs_{binaryHypoPDGCodes[1]}_{mode}")
4086 chargedpid.param(
"sigHypoPDGCode", binaryHypoPDGCodes[0])
4087 chargedpid.param(
"bkgHypoPDGCode", binaryHypoPDGCodes[1])
4089 chargedpid.param(
"particleLists", list(plSet))
4090 chargedpid.param(
"payloadName", payloadName)
4091 chargedpid.param(
"chargeIndependent", chargeIndependent)
4094 if detector ==
"ECL":
4095 chargedpid.param(
"useECLOnlyTraining",
True)
4097 path.add_module(chargedpid)
4100def calculateTrackIsolation(
4104 reference_list_name=None,
4105 vars_for_nearest_part=[],
4106 highest_prob_mass_for_ext=True,
4107 exclude_pid_det_weights=False):
4109 Given an input decay string, compute variables that quantify track helix-based isolation of the charged
4110 stable particles in the input decay chain.
4113 An "isolation score" can be defined using the distance
4114 of each particle to its closest neighbour, defined as the segment connecting the two
4115 extrapolated track helices intersection points on a given cylindrical surface.
4116 The distance variables defined in the `VariableManager` is named `minET2ETDist`,
4117 the isolation scores are named `minET2ETIsoScore`, `minET2ETIsoScoreAsWeightedAvg`.
4119 The definition of distance and the number of distances that are calculated per sub-detector is based on
4120 the following recipe:
4122 * **CDC**: as the segmentation is very coarse along :math:`z`,
4123 the distance is defined as the cord length on the :math:`(\\rho=R, \\phi)` plane.
4124 A total of 9 distances are calculated: the cylindrical surfaces are defined at radiuses
4125 that correspond to the positions of the 9 CDC wire superlayers: :math:`R_{i}^{\\mathrm{CDC}}~(i \\in \\{0,...,8\\})`.
4127 * **TOP**: as there is no segmentation along :math:`z`,
4128 the distance is defined as the cord length on the :math:`(\\rho=R, \\phi)` plane.
4129 Only one distance at the TOP entry radius :math:`R_{0}^{\\mathrm{TOP}}` is calculated.
4131 * **ARICH**: as there is no segmentation along :math:`z`,
4132 the distance is defined as the distance on the :math:`(\\rho=R, \\phi)` plane at fixed :math:`z=Z`.
4133 Only one distance at the ARICH photon detector entry coordinate :math:`Z_{0}^{\\mathrm{ARICH}}` is calculated.
4135 * **ECL**: the distance is defined on the :math:`(\\rho=R, \\phi, z)` surface in the barrel,
4136 on the :math:`(\\rho, \\phi, z=Z)` surface in the endcaps.
4137 Two distances are calculated: one at the ECL entry surface :math:`R_{0}^{\\mathrm{ECL}}` (barrel),
4138 :math:`Z_{0}^{\\mathrm{ECL}}` (endcaps), and one at :math:`R_{1}^{\\mathrm{ECL}}` (barrel),
4139 :math:`Z_{1}^{\\mathrm{ECL}}` (endcaps), corresponding roughly to the mid-point
4140 of the longitudinal size of the crystals.
4142 * **KLM**: the distance is defined on the :math:`(\\rho=R, \\phi, z)` surface in the barrel,
4143 on the :math:`(\\rho, \\phi, z=Z)` surface in the endcaps.
4144 Only one distance at the KLM first strip entry surface :math:`R_{0}^{\\mathrm{KLM}}` (barrel),
4145 :math:`Z_{0}^{\\mathrm{KLM}}` (endcaps) is calculated.
4148 decay_string (str): name of the input decay string with selected charged stable daughters,
4149 for example: ``Lambda0:merged -> ^p+ ^pi-``.
4150 Alternatively, it can be a particle list for charged stable particles
4151 as defined in ``Const::chargedStableSet``, for example: ``mu+:all``.
4152 The charge-conjugate particle list will be also processed automatically.
4153 path (basf2.Path): path to which module(s) will be added.
4154 *detectors: detectors for which track isolation variables will be calculated.
4155 Choose among: ``{'CDC', 'TOP', 'ARICH', 'ECL', 'KLM'}``.
4156 reference_list_name (Optional[str]): name of the input charged stable particle list for the reference tracks.
4157 By default, the ``:all`` ParticleList of the same type
4158 of the selected particle in ``decay_string`` is used.
4159 The charge-conjugate particle list will be also processed automatically.
4160 vars_for_nearest_part (Optional[list(str)]): a list of variables to calculate for the nearest particle in the reference
4161 list at each detector surface. It uses the metavariable `minET2ETDistVar`.
4162 If unset, only the distances to the nearest neighbour
4163 per detector are calculated.
4164 highest_prob_mass_for_hex (Optional[bool]): if this option is set to True (default), the helix extrapolation
4165 for the particles will use the track fit result for the most
4166 probable mass hypothesis, namely, the one that gives the highest
4167 chi2Prob of the fit. Otherwise, it uses the mass hypothesis that
4168 corresponds to the particle lists PDG.
4169 exclude_pid_det_weights (Optional[bool]): if this option is set to False (default), the isolation score
4170 calculation will take into account the weight that each detector has on the PID
4171 for the particle species of interest.
4174 dict(int, list(str)): a dictionary mapping the PDG of each reference particle list to its isolation variables.
4179 from ROOT
import Belle2, TDatabasePDG
4182 if not decayDescriptor.init(decay_string):
4183 B2FATAL(f
"Invalid particle list {decay_string} in calculateTrackIsolation!")
4184 no_reference_list_name =
not reference_list_name
4187 "CDC": list(range(9)),
4193 if any(d
not in det_and_layers
for d
in detectors):
4195 "Your input detector list: ",
4197 " contains an invalid choice. Please select among: ",
4199 det_and_layers.keys()))
4204 processed_decay_strings = []
4205 if select_symbol
in decay_string:
4206 splitted_ds = decay_string.split(select_symbol)
4207 for i
in range(decay_string.count(select_symbol)):
4208 tmp = list(splitted_ds)
4209 tmp.insert(i+1, select_symbol)
4210 processed_decay_strings += [
''.join(tmp)]
4212 processed_decay_strings += [decay_string]
4214 reference_lists_to_vars = {}
4216 for processed_dec
in processed_decay_strings:
4217 if no_reference_list_name:
4218 decayDescriptor.init(processed_dec)
4219 selected_daughter_pdgs = decayDescriptor.getSelectionPDGCodes()
4220 if len(selected_daughter_pdgs) > 0:
4221 reference_list_name = f
'{TDatabasePDG.Instance().GetParticle(abs(selected_daughter_pdgs[-1])).GetName()}:all'
4223 reference_list_name = f
'{processed_dec.split(":")[0]}:all'
4227 trackiso = path.add_module(
"TrackIsoCalculator",
4228 decayString=processed_dec,
4229 detectorNames=list(detectors),
4230 particleListReference=reference_list_name,
4231 useHighestProbMassForExt=highest_prob_mass_for_ext,
4232 excludePIDDetWeights=exclude_pid_det_weights)
4233 trackiso.set_name(f
"TrackIsoCalculator_{'_'.join(detectors)}_{processed_dec}_VS_{reference_list_name}")
4239 f
"minET2ETDist({d}, {d_layer}, {reference_list_name}, {int(highest_prob_mass_for_ext)})"
4240 for d
in detectors
for d_layer
in det_and_layers[d]]
4243 f
"minET2ETIsoScore({reference_list_name}, {int(highest_prob_mass_for_ext)}, {', '.join(detectors)})",
4244 f
"minET2ETIsoScoreAsWeightedAvg({reference_list_name}, {int(highest_prob_mass_for_ext)}, {', '.join(detectors)})",
4247 if vars_for_nearest_part:
4248 trackiso_vars.extend(
4250 f
"minET2ETDistVar({d}, {d_layer}, {reference_list_name}, {v})"
4251 for d
in detectors
for d_layer
in det_and_layers[d]
for v
in vars_for_nearest_part
4253 trackiso_vars.sort()
4255 reference_lists_to_vars[ref_pdg] = trackiso_vars
4257 return reference_lists_to_vars
4260def calculateDistance(list_name, decay_string, mode='vertextrack', path=None):
4262 Calculates distance between two vertices, distance of closest approach between a vertex and a track,\
4263 distance of closest approach between a vertex and btube. For track, this calculation ignores track curvature,\
4264 it's negligible for small distances.The user should use extraInfo(CalculatedDistance)\
4265 to get it. A full example steering file is at analysis/tests/test_DistanceCalculator.py
4268 .. code-block:: python
4270 from modularAnalysis import calculateDistance
4271 calculateDistance('list_name', 'decay_string', "mode", path=user_path)
4273 @param list_name name of the input ParticleList
4274 @param decay_string select particles between the distance of closest approach will be calculated
4275 @param mode Specifies how the distance is calculated
4276 vertextrack: calculate the distance of closest approach between a track and a\
4277 vertex, taking the first candidate as vertex, default
4278 trackvertex: calculate the distance of closest approach between a track and a\
4279 vertex, taking the first candidate as track
4280 2tracks: calculates the distance of closest approach between two tracks
4281 2vertices: calculates the distance between two vertices
4282 vertexbtube: calculates the distance of closest approach between a vertex and btube
4283 trackbtube: calculates the distance of closest approach between a track and btube
4284 @param path modules are added to this path
4288 dist_mod = register_module(
'DistanceCalculator')
4290 dist_mod.set_name(
'DistanceCalculator_' + list_name)
4291 dist_mod.param(
'listName', list_name)
4292 dist_mod.param(
'decayString', decay_string)
4293 dist_mod.param(
'mode', mode)
4294 path.add_module(dist_mod)
4297def addInclusiveDstarReconstruction(decayString, slowPionCut, DstarCut, path):
4299 Adds the InclusiveDstarReconstruction module to the given path.
4300 This module creates a D* particle list by estimating the D* four momenta
4301 from slow pions, specified by a given cut. The D* energy is approximated
4302 as E(D*) = m(D*)/(m(D*) - m(D)) * E(pi). The absolute value of the D*
4303 momentum is calculated using the D* PDG mass and the direction is collinear
4304 to the slow pion direction. The charge of the given pion list has to be consistent
4307 @param decayString Decay string, must be of form ``D* -> pi``
4308 @param slowPionCut Cut applied to the input pion list to identify slow pions
4309 @param DstarCut Cut applied to the output D* list
4310 @param path the module is added to this path
4313 incl_dstar = register_module(
"InclusiveDstarReconstruction")
4314 incl_dstar.param(
"decayString", decayString)
4315 incl_dstar.param(
"slowPionCut", slowPionCut)
4316 incl_dstar.param(
"DstarCut", DstarCut)
4317 path.add_module(incl_dstar)
4320def scaleError(outputListName, inputListName,
4321 scaleFactors=[1.149631, 1.085547, 1.151704, 1.096434, 1.086659],
4322 scaleFactorsNoPXD=[1.149631, 1.085547, 1.151704, 1.096434, 1.086659],
4323 d0Resolution=[0.00115328, 0.00134704],
4324 z0Resolution=[0.00124327, 0.0013272],
4329 This module creates a new charged particle list.
4330 The helix errors of the new particles are scaled by constant factors.
4331 Two sets of five scale factors are defined for tracks with and without a PXD hit.
4332 The scale factors are in order of (d0, phi0, omega, z0, tanlambda).
4333 For tracks with a PXD hit, in order to avoid severe underestimation of d0 and z0 errors,
4334 lower limits (best resolution) can be set in a momentum-dependent form.
4335 This module is supposed to be used only for TDCPV analysis and for low-momentum (0-3 GeV/c) tracks in BBbar events.
4336 Details will be documented in a Belle II note, BELLE2-NOTE-PH-2021-038.
4338 @param inputListName Name of input charged particle list to be scaled
4339 @param outputListName Name of output charged particle list with scaled error
4340 @param scaleFactors List of five constants to be multiplied to each of helix errors (for tracks with a PXD hit)
4341 @param scaleFactorsNoPXD List of five constants to be multiplied to each of helix errors (for tracks without a PXD hit)
4342 @param d0Resolution List of two parameters, (a [cm], b [cm/(GeV/c)]),
4343 defining d0 best resolution as sqrt{ a**2 + (b / (p*beta*sinTheta**1.5))**2 }
4344 @param z0Resolution List of two parameters, (a [cm], b [cm/(GeV/c)]),
4345 defining z0 best resolution as sqrt{ a**2 + (b / (p*beta*sinTheta**2.5))**2 }
4346 @param d0MomThr d0 best resolution is kept constant below this momentum
4347 @param z0MomThr z0 best resolution is kept constant below this momentum
4351 scale_error = register_module(
"HelixErrorScaler")
4352 scale_error.set_name(
'ScaleError_' + inputListName)
4353 scale_error.param(
'inputListName', inputListName)
4354 scale_error.param(
'outputListName', outputListName)
4355 scale_error.param(
'scaleFactors_PXD', scaleFactors)
4356 scale_error.param(
'scaleFactors_noPXD', scaleFactorsNoPXD)
4357 scale_error.param(
'd0ResolutionParameters', d0Resolution)
4358 scale_error.param(
'z0ResolutionParameters', z0Resolution)
4359 scale_error.param(
'd0MomentumThreshold', d0MomThr)
4360 scale_error.param(
'z0MomentumThreshold', z0MomThr)
4361 path.add_module(scale_error)
4364def estimateAndAttachTrackFitResult(inputListName, path=None):
4366 Create a TrackFitResult from the momentum of the Particle assuming it originates from the IP and make a relation between them.
4367 The covariance, detector hit information, and fit-related information (pValue, NDF) are assigned meaningless values. The input
4368 Particles must not have already Track or TrackFitResult and thus are supposed to be composite particles, recoil, dummy
4369 particles, and so on.
4372 .. warning:: Since the source type is not overwritten as Track, not all track-related variables are guaranteed to be available.
4375 @param inputListName Name of input ParticleList
4378 estimator = register_module(
"TrackFitResultEstimator")
4379 estimator.set_name(
"trackFitResultEstimator_" + inputListName)
4380 estimator.param(
"inputListName", inputListName)
4381 path.add_module(estimator)
4384def correctEnergyBias(inputListNames, tableName, path=None):
4386 Scale energy of the particles according to the scaling factor.
4387 If the particle list contains composite particles, the energy of the daughters are scaled.
4388 Subsequently, the energy of the mother particle is updated as well.
4391 inputListNames (list(str)): input particle list names
4392 tableName : stored in localdb and created using ParticleWeightingLookUpCreator
4393 path (basf2.Path): module is added to this path
4398 B2ERROR(
"The energy bias cannot be corrected with this tool for Belle data.")
4400 correctenergybias = register_module(
'EnergyBiasCorrection')
4401 correctenergybias.param(
'particleLists', inputListNames)
4402 correctenergybias.param(
'tableName', tableName)
4403 path.add_module(correctenergybias)
4406def twoBodyISRPhotonCorrector(outputListName, inputListName, massiveParticle, path=None):
4408 Sets photon kinematics to corrected values in two body decays with an ISR photon
4409 and a massive particle. The original photon kinematics are kept in the input
4410 particleList and can be accessed using the originalParticle() metavariable on the
4413 @param ouputListName new ParticleList filled with copied Particles
4414 @param inputListName input ParticleList with original Particles
4415 @param massiveParticle name or PDG code of massive particle participating in the two
4416 body decay with the ISR photon
4417 @param path modules are added to this path
4421 photon_energy_correction = register_module(
'TwoBodyISRPhotonCorrector')
4422 photon_energy_correction.set_name(
'TwoBodyISRPhotonCorrector_' + outputListName)
4423 photon_energy_correction.param(
'outputGammaList', outputListName)
4424 photon_energy_correction.param(
'inputGammaList', inputListName)
4427 if isinstance(massiveParticle, int):
4428 photon_energy_correction.param(
'massiveParticlePDGCode', massiveParticle)
4430 from ROOT
import Belle2
4432 if not decayDescriptor.init(massiveParticle):
4433 raise ValueError(
"TwoBodyISRPhotonCorrector: value of massiveParticle must be" +
4434 " an int or valid decay string.")
4435 pdgCode = decayDescriptor.getMother().getPDGCode()
4436 photon_energy_correction.param(
'massiveParticlePDGCode', pdgCode)
4438 path.add_module(photon_energy_correction)
4441def addPhotonEfficiencyRatioVariables(inputListNames, tableName, path=None):
4443 Add photon Data/MC detection efficiency ratio weights to the specified particle list
4446 inputListNames (list(str)): input particle list names
4447 tableName : taken from database with appropriate name
4448 path (basf2.Path): module is added to this path
4453 B2ERROR(
"For Belle data the photon data/MC detection efficiency ratio is not available with this tool.")
4455 photon_efficiency_correction = register_module(
'PhotonEfficiencySystematics')
4456 photon_efficiency_correction.param(
'particleLists', inputListNames)
4457 photon_efficiency_correction.param(
'tableName', tableName)
4458 path.add_module(photon_efficiency_correction)
4461def addPi0VetoEfficiencySystematics(particleList, decayString, tableName, threshold, mode='standard', suffix='', path=None):
4463 Add pi0 veto Data/MC efficiency ratio weights to the specified particle list
4465 @param particleList the input ParticleList
4466 @param decayString specify hard photon to be performed pi0 veto (e.g. 'B+:sig -> rho+:sig ^gamma:hard')
4467 @param tableName table name corresponding to payload version (e.g. 'Pi0VetoEfficiencySystematics_Mar2022')
4468 @param threshold pi0 veto threshold (0.10, 0.11, ..., 0.99)
4469 @param mode choose one mode (same as writePi0EtaVeto) out of 'standard', 'tight', 'cluster' and 'both'
4470 @param suffix optional suffix to be appended to the usual extraInfo name
4471 @param path the module is added to this path
4473 The following extraInfo are available related with the given particleList:
4475 * Pi0VetoEfficiencySystematics_{mode}{suffix}_data_MC_ratio : weight of Data/MC for the veto efficiency
4476 * Pi0VetoEfficiencySystematics_{mode}{suffix}_data_MC_uncertainty_stat : the statistical uncertainty of the weight
4477 * Pi0VetoEfficiencySystematics_{mode}{suffix}_data_MC_uncertainty_sys : the systematic uncertainty of the weight
4478 * Pi0VetoEfficiencySystematics_{mode}{suffix}_data_MC_uncertainty_total : the total uncertainty of the weight
4479 * Pi0VetoEfficiencySystematics_{mode}{suffix}_threshold : threshold of the pi0 veto
4484 B2ERROR(
"For Belle data the pi0 veto data/MC efficiency ratio weights are not available via this tool.")
4486 pi0veto_efficiency_correction = register_module(
'Pi0VetoEfficiencySystematics')
4487 pi0veto_efficiency_correction.param(
'particleLists', particleList)
4488 pi0veto_efficiency_correction.param(
'decayString', decayString)
4489 pi0veto_efficiency_correction.param(
'tableName', tableName)
4490 pi0veto_efficiency_correction.param(
'threshold', threshold)
4491 pi0veto_efficiency_correction.param(
'mode', mode)
4492 pi0veto_efficiency_correction.param(
'suffix', suffix)
4493 path.add_module(pi0veto_efficiency_correction)
4496def getAnalysisGlobaltag(timeout=180) -> str:
4498 Returns a string containing the name of the latest and recommended analysis globaltag.
4501 timeout: Seconds to wait for b2conditionsdb-recommend
4506 B2ERROR(
"The getAnalysisGlobaltag() function cannot be used for Belle data.")
4511 tags = subprocess.check_output(
4512 [
'b2conditionsdb-recommend',
'--oneline'],
4514 ).decode(
'UTF-8').rstrip().split(
' ')
4517 if tag.startswith(
'analysis_tools'):
4521 except subprocess.TimeoutExpired
as te:
4522 B2FATAL(f
'A {te} exception was raised during the call of getAnalysisGlobaltag(). '
4523 'The function took too much time to retrieve the requested information '
4524 'from the versioning repository.\n'
4525 'Please try to re-run your job. In case of persistent failures, there may '
4526 'be issues with the DESY collaborative services, so please contact the experts.')
4527 except subprocess.CalledProcessError
as ce:
4528 B2FATAL(f
'A {ce} exception was raised during the call of getAnalysisGlobaltag(). '
4529 'Please try to re-run your job. In case of persistent failures, please contact '
4533def getAnalysisGlobaltagB2BII() -> str:
4535 Get recommended global tag for B2BII analysis.
4540 B2ERROR(
'The getAnalysisGlobaltagB2BII() function cannot be used for Belle II data.')
4541 from versioning
import recommended_b2bii_analysis_global_tag
4542 return recommended_b2bii_analysis_global_tag()
4545def getECLKLID(particleList: str, variable=
'ECLKLID', path=
None):
4547 The function calculates the PID value for Klongs that are constructed from ECL cluster.
4549 @param particleList the input ParticleList
4550 @param variable the variable name for Klong ID
4551 @param path modules are added to this path
4557 B2ERROR(
"The ECL variables based Klong Identification is only available for Belle II data.")
4559 from variables
import variables
4560 path.add_module(
'MVAExpert', listNames=particleList, extraInfoName=
'ECLKLID', identifier=
'ECLKLID')
4562 variables.addAlias(variable,
'conditionalVariableSelector(isFromECL and PDG==130, extraInfo(ECLKLID), constant(NaN))')
4565def getNbarIDMVA(particleList: str, path=
None):
4567 This function can give a score to predict if it is a anti-n0.
4568 It is not used to predict n0.
4569 Currently, this can be used only for ECL cluster.
4570 output will be stored in extraInfo(nbarID); -1 means MVA invalid
4572 @param particleList The input ParticleList name or a decay string which contains a full mother particle list name.
4573 Only one selected daughter is supported.
4574 @param path modules are added to this path
4577 from ROOT
import Belle2
4580 B2ERROR(
"The MVA-based anti-neutron PID is only available for Belle II data.")
4582 from variables
import variables
4584 variables.addAlias(
'V1',
'clusterHasPulseShapeDiscrimination')
4585 variables.addAlias(
'V2',
'clusterE')
4586 variables.addAlias(
'V3',
'clusterLAT')
4587 variables.addAlias(
'V4',
'clusterE1E9')
4588 variables.addAlias(
'V5',
'clusterE9E21')
4589 variables.addAlias(
'V6',
'clusterZernikeMVA')
4590 variables.addAlias(
'V7',
'clusterAbsZernikeMoment40')
4591 variables.addAlias(
'V8',
'clusterAbsZernikeMoment51')
4595 'passesCut(V1 == 1 and V2 >= 0 and V3 >= 0 and V4 >= 0 and V5 >= 0 and V6 >= 0 and V7 >= 0 and V8 >= 0)')
4596 variables.addAlias(
'nbarIDmod',
'conditionalVariableSelector(nbarIDValid == 1, extraInfo(nbarIDFromMVA), constant(-1.0))')
4598 path.add_module(
'MVAExpert', listNames=particleList, extraInfoName=
'nbarIDFromMVA', identifier=
'db_nbarIDECL')
4600 if not decayDescriptor.init(particleList):
4601 raise ValueError(f
"Provided decay string is invalid: {particleList}")
4602 if decayDescriptor.getNDaughters() == 0:
4605 listname = decayDescriptor.getMother().getFullName()
4606 variablesToDaughterExtraInfo(listname, particleList, {
'nbarIDmod':
'nbarID'}, option=2, path=path)
4609def reconstructDecayWithNeutralHadron(decayString, cut, allowGamma=False, allowAnyParticleSource=False, path=None, **kwargs):
4611 Reconstructs decay with a long-lived neutral hadron e.g.
4612 :math:`B^0 \to J/\psi K_L^0`,
4613 :math:`B^0 \to p \bar{n} D^*(2010)^-`.
4615 The calculation is done with IP constraint and mother mass constraint.
4617 The decay string passed in must satisfy the following rules:
4619 - The neutral hadron must be **selected** in the decay string with the
4620 caret (``^``) e.g. ``B0:sig -> J/psi:sig ^K_L0:sig``. (Note the caret
4621 next to the neutral hadron.)
4622 - There can only be **one neutral hadron in a decay**.
4623 - The neutral hadron has to be a direct daughter of its mother.
4625 .. note:: This function forwards its arguments to `reconstructDecay`,
4626 so please check the documentation of `reconstructDecay` for all
4629 @param decayString A decay string following the mentioned rules
4630 @param cut Cut to apply to the particle list
4631 @param allowGamma Whether allow the selected particle to be ``gamma``
4632 @param allowAnyParticleSource Whether allow the selected particle to be from any source.
4633 Should only be used when studying control sample.
4634 @param path The path to put in the module
4637 reconstructDecay(decayString, cut, path=path, **kwargs)
4638 module = register_module(
'NeutralHadron4MomentumCalculator')
4639 module.set_name(
'NeutralHadron4MomentumCalculator_' + decayString)
4640 module.param(
'decayString', decayString)
4641 module.param(
'allowGamma', allowGamma)
4642 module.param(
'allowAnyParticleSource', allowAnyParticleSource)
4643 path.add_module(module)
4646def updateMassHypothesis(particleList, pdg, writeOut=False, path=None):
4648 Module to update the mass hypothesis of a given input particle list with the chosen PDG.
4649 A new particle list is created with updated mass hypothesis.
4650 The allowed mass hypotheses for both input and output are electrons, muons, pions, kaons and protons.
4653 The new particle list is named after the input one, with the additional suffix ``_converted_from_OLDHYPOTHESIS``,
4654 e.g. ``e+:all`` converted to muons becomes ``mu+:all_converted_from_e``.
4656 @param particleList The input particle list name
4657 @param pdg The PDG code for the new mass hypothesis, in [11, 13, 211, 321, 2212]
4658 @param writeOut Whether `RootOutput` module should save the new particle list
4659 @param path Modules are added to this path
4661 mass_updater = register_module(
"ParticleMassHypothesesUpdater")
4662 mass_updater.set_name(
"ParticleMassHypothesesUpdater_" + particleList +
"_to_" + str(pdg))
4663 mass_updater.param(
"particleList", particleList)
4664 mass_updater.param(
"writeOut", writeOut)
4665 mass_updater.param(
"pdgCode", pdg)
4666 path.add_module(mass_updater)
4669func_requiring_analysisGT = [
4670 correctTrackEnergy, scaleTrackMomenta, smearTrackMomenta, oldwritePi0EtaVeto, writePi0EtaVeto, lowEnergyPi0Identification,
4671 getBeamBackgroundProbability, getFakePhotonProbability, tagCurlTracks, applyChargedPidMVA, correctEnergyBias,
4672 addPhotonEfficiencyRatioVariables, addPi0VetoEfficiencySystematics, getNbarIDMVA, getECLKLID]
4673for _
in func_requiring_analysisGT:
4674 _.__doc__ +=
"\n .. note:: This function (optionally) requires a payload stored in the analysis GlobalTag. "\
4675 "Please append or prepend the latest one from `getAnalysisGlobaltag` or `getAnalysisGlobaltagB2BII`.\n"
4678if __name__ ==
'__main__':
4680 pretty_print_module(__name__,
"modularAnalysis")
tuple parse(str cut, verbose=False)
This class provides a set of constants for the framework.
The DecayDescriptor stores information about a decay tree or parts of a decay tree.
Describe one component of the Geometry.
static DBStore & Instance()
Instance of a singleton DBStore.
add_mdst_output(path, mc=True, filename='mdst.root', additionalBranches=[], dataDescription=None)
add_udst_output(path, filename, particleLists=None, additionalBranches=None, dataDescription=None, mc=True)