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
77 if entrySequence
is not None:
78 entrySequence = [entrySequence]
80 inputMdstList([filename], path, environmentType, skipNEvents, entrySequence, parentLevel=parentLevel, **kwargs)
86 environmentType='default',
91 useB2BIIDBCache=True):
93 Loads the specified list of :ref:`mDST <mdst>` (or :ref:`uDST <analysis_udstoutput>`) files with the RootInput module.
95 The correct environment (e.g. magnetic field settings) is determined from
96 ``environmentType``. Options are either: 'default' (for Belle II MC and
97 data: falls back to database), 'Belle': for analysis of converted Belle 1
101 filelist (list(str)): the filename list of files to be loaded
102 path (basf2.Path): modules are added to this path
103 environmentType (str): type of the environment to be loaded (either 'default' or 'Belle')
104 skipNEvents (int): N events of the input files are skipped
105 entrySequences (list(str)): The number sequences (e.g. 23:42,101) defining
106 the entries which are processed for each inputFileName.
107 parentLevel (int): Number of generations of parent files (files used as input when creating a file) to be read
108 useB2BIIDBCache (bool): Loading of local KEKCC database (only to be deactivated in very special cases)
111 roinput = register_module(
'RootInput')
112 roinput.param(
'inputFileNames', filelist)
113 roinput.param(
'skipNEvents', skipNEvents)
114 if entrySequences
is not None:
115 roinput.param(
'entrySequences', entrySequences)
116 roinput.param(
'parentLevel', parentLevel)
118 path.add_module(roinput)
119 path.add_module(
'ProgressBar')
121 if environmentType ==
'Belle':
126 from ROOT
import Belle2
132 setAnalysisConfigParams({
'mcMatchingVersion':
'Belle'}, path)
135 basf2.conditions.metadata_providers = [
"/sw/belle/b2bii/database/conditions/b2bii.sqlite"]
136 basf2.conditions.payload_locations = [
"/sw/belle/b2bii/database/conditions/"]
139def outputMdst(filename, path):
141 Saves mDST (mini-Data Summary Tables) to the output root file.
145 This function is kept for backward-compatibility.
146 Better to use `mdst.add_mdst_output` directly.
154def outputUdst(filename, particleLists=None, includeArrays=None, path=None, dataDescription=None):
156 Save uDST (user-defined Data Summary Tables) = MDST + Particles + ParticleLists
157 The charge-conjugate lists of those given in particleLists are also stored.
158 Additional Store Arrays and Relations to be stored can be specified via includeArrays
162 This does not reduce the amount of Particle objects saved,
163 see `udst.add_skimmed_udst_output` for a function that does.
169 path=path, filename=filename, particleLists=particleLists,
170 additionalBranches=includeArrays, dataDescription=dataDescription)
173def outputIndex(filename, path, includeArrays=None, keepParents=False, mc=True):
175 Write out all particle lists as an index file to be reprocessed using parentLevel flag.
176 Additional branches necessary for file to be read are automatically included.
177 Additional Store Arrays and Relations to be stored can be specified via includeArrays
180 @param str filename the name of the output index file
181 @param str path modules are added to this path
182 @param list(str) includeArrays: datastore arrays/objects to write to the output
183 file in addition to particle lists and related information
184 @param bool keepParents whether the parents of the input event will be saved as the parents of the same event
185 in the output index file. Useful if you are only adding more information to another index file
186 @param bool mc whether the input data is MC or not
189 if includeArrays
is None:
193 onlyPLists = register_module(
'OnlyWriteOutParticleLists')
194 path.add_module(onlyPLists)
199 'ParticlesToMCParticles',
200 'ParticlesToPIDLikelihoods',
201 'ParticleExtraInfoMap',
204 branches = [
'EventMetaData']
205 persistentBranches = [
'FileMetaData']
209 branches += partBranches
210 branches += includeArrays
212 r1 = register_module(
'RootOutput')
213 r1.param(
'outputFileName', filename)
214 r1.param(
'additionalBranchNames', branches)
215 r1.param(
'branchNamesPersistent', persistentBranches)
216 r1.param(
'keepParents', keepParents)
220def setupEventInfo(noEvents, path):
222 Prepare to generate events. This function sets up the EventInfoSetter.
223 You should call this before adding a generator from generators.
224 The experiment and run numbers are set to 0 (run independent generic MC in phase 3).
225 https://xwiki.desy.de/xwiki/rest/p/59192
228 noEvents (int): number of events to be generated
229 path (basf2.Path): modules are added to this path
232 evtnumbers = register_module(
'EventInfoSetter')
233 evtnumbers.param(
'evtNumList', [noEvents])
234 evtnumbers.param(
'runList', [0])
235 evtnumbers.param(
'expList', [0])
236 path.add_module(evtnumbers)
239def loadGearbox(path, silence_warning=False):
241 Loads Gearbox module to the path.
244 Should be used in a job with *cosmic event generation only*
246 Needed for scripts which only generate cosmic events in order to
249 @param path modules are added to this path
250 @param silence_warning stops a verbose warning message if you know you want to use this function
253 if not silence_warning:
254 B2WARNING(
"""You are overwriting the geometry from the database with Gearbox.
255 This is fine if you're generating cosmic events. But in most other cases you probably don't want this.
257 If you're really sure you know what you're doing you can suppress this message with:
259 >>> loadGearbox(silence_warning=True)
263 paramloader = register_module(
'Gearbox')
264 path.add_module(paramloader)
267def printPrimaryMCParticles(path, **kwargs):
269 Prints all primary MCParticles, that is particles from
270 the physics generator and not particles created by the simulation
272 This is equivalent to `printMCParticles(onlyPrimaries=True, path=path) <printMCParticles>` and additional
273 keyword arguments are just forwarded to that function
276 return printMCParticles(onlyPrimaries=
True, path=path, **kwargs)
279def printMCParticles(onlyPrimaries=False, maxLevel=-1, path=None, *,
280 showProperties=False, showMomenta=False, showVertices=False, showStatus=False, suppressPrint=False):
282 Prints all MCParticles or just primary MCParticles up to specified level. -1 means no limit.
284 By default this will print a tree of just the particle names and their pdg
285 codes in the event, for example ::
287 [INFO] Content of MCParticle list
290 ╰── Upsilon(4S) (300553)
292 │ ├── anti-D_0*0 (-10421)
295 │ │ │ │ ├── anti-K0 (-311)
296 │ │ │ │ │ ╰── K_S0 (310)
297 │ │ │ │ │ ├── pi+ (211)
298 │ │ │ │ │ │ ╰╶╶ p+ (2212)
299 │ │ │ │ │ ╰── pi- (-211)
300 │ │ │ │ │ ├╶╶ e- (11)
301 │ │ │ │ │ ├╶╶ n0 (2112)
302 │ │ │ │ │ ├╶╶ n0 (2112)
303 │ │ │ │ │ ╰╶╶ n0 (2112)
304 │ │ │ │ ╰── pi- (-211)
305 │ │ │ │ ├╶╶ anti-nu_mu (-14)
307 │ │ │ │ ├╶╶ nu_mu (14)
308 │ │ │ │ ├╶╶ anti-nu_e (-12)
312 │ │ │ │ ├── gamma (22)
313 │ │ │ │ ╰── gamma (22)
319 │ │ ├╶╶ anti-nu_mu (-14)
327 There's a distinction between primary and secondary particles. Primary
328 particles are the ones created by the physics generator while secondary
329 particles are ones generated by the simulation of the detector interaction.
331 Secondaries are indicated with a dashed line leading to the particle name
332 and if the output is to the terminal they will be printed in red. If
333 ``onlyPrimaries`` is True they will not be included in the tree.
335 On demand, extra information on all the particles can be displayed by
336 enabling any of the ``showProperties``, ``showMomenta``, ``showVertices``
337 and ``showStatus`` flags. Enabling all of them will look like
342 │ mass=0.14 energy=0.445 charge=-1 lifetime=6.36
343 │ p=(0.257, -0.335, 0.0238) |p|=0.423
344 │ production vertex=(0.113, -0.0531, 0.0156), time=0.00589
345 │ status flags=PrimaryParticle, StableInGenerator, StoppedInDetector
349 mass=0.94 energy=0.94 charge=0 lifetime=5.28e+03
350 p=(-0.000238, -0.0127, 0.0116) |p|=0.0172
351 production vertex=(144, 21.9, -1.29), time=39
352 status flags=StoppedInDetector
353 creation process=HadronInelastic
356 The first line of extra information is enabled by ``showProperties``, the
357 second line by ``showMomenta``, the third line by ``showVertices`` and the
358 last two lines by ``showStatus``. Note that all values are given in Belle II
359 standard units, that is GeV, centimeter and nanoseconds.
361 The depth of the tree can be limited with the ``maxLevel`` argument: If it's
362 bigger than zero it will limit the tree to the given number of generations.
363 A visual indicator will be added after each particle which would have
364 additional daughters that are skipped due to this limit. An example event
365 with ``maxLevel=3`` is given below. In this case only the tau neutrino and
366 the pion don't have additional daughters. ::
368 [INFO] Content of MCParticle list
371 ╰── Upsilon(4S) (300553)
373 │ ├── anti-D*0 (-423) → …
382 The same information will be stored in the branch ``__MCDecayString__`` of
383 TTree created by `VariablesToNtuple` or `VariablesToEventBasedTree` module.
384 This branch is automatically created when `PrintMCParticles` modules is called.
385 Printing the information on the log message can be suppressed if ``suppressPrint``
386 is True, while the branch ``__MCDecayString__``. This option helps to reduce the
387 size of the log message.
390 onlyPrimaries (bool): If True show only primary particles, that is particles coming from
391 the generator and not created by the simulation.
392 maxLevel (int): If 0 or less print the whole tree, otherwise stop after n generations
393 showProperties (bool): If True show mass, energy and charge of the particles
394 showMomenta (bool): if True show the momenta of the particles
395 showVertices (bool): if True show production vertex and production time of all particles
396 showStatus (bool): if True show some status information on the particles.
397 For secondary particles this includes creation process.
398 suppressPrint (bool): if True printing the information on the log message is suppressed.
399 Even if True, the branch ``__MCDecayString__`` is created.
402 return path.add_module(
404 onlyPrimaries=onlyPrimaries,
406 showProperties=showProperties,
407 showMomenta=showMomenta,
408 showVertices=showVertices,
409 showStatus=showStatus,
410 suppressPrint=suppressPrint,
414def correctBrems(outputList,
417 maximumAcceptance=3.0,
418 multiplePhotons=False,
419 usePhotonOnlyOnce=True,
423 For each particle in the given ``inputList``, copies it to the ``outputList`` and adds the
424 4-vector of the photon(s) in the ``gammaList`` which has(have) a weighted named relation to
425 the particle's track, set by the ``ECLTrackBremFinder`` module during reconstruction.
428 So far, there haven't been any comprehensive comparisons of the performance of the `BremsFinder` module, which
429 is called in this function, with the `BelleBremRecovery` module, which is called via the `correctBremsBelle`
430 function. If your analysis is very sensitive to the Bremsstrahlung corrections, it is currently advised to use
433 The reason is that studies by the tau WG revealed that in the past the cuts applied by the
434 ``ECLTrackBremFinder`` module were too tight. They were only loosened for proc16 and MC16. New performance
435 studies are needed to verify that now this module outperforms the Belle-like approach.
438 A detailed description of how the weights are set can be found directly at the documentation of the
439 `BremsFinder` module.
441 Please note that a new particle is always generated, with the old particle and -if found- one or more
442 photons as daughters.
444 The ``inputList`` should contain particles with associated tracks. Otherwise, the module will exit with an error.
446 The ``gammaList`` should contain photons. Otherwise, the module will exit with an error.
448 @param outputList The output particle list name containing the corrected particles
449 @param inputList The initial particle list name containing the particles to correct. *It should already exist.*
450 @param gammaList The photon list containing possibly bremsstrahlung photons; *It should already exist.*
451 @param maximumAcceptance Maximum value of the relation weight. Should be a number between [0,3)
452 @param multiplePhotons Whether to use only one photon (the one with the smallest acceptance) or as many as possible
453 @param usePhotonOnlyOnce If true, each brems candidate is used to correct only the track with the smallest relation weight
454 @param writeOut Whether `RootOutput` module should save the created ``outputList``
455 @param path The module is added to this path
460 B2ERROR(
"The BremsFinder can only be run over Belle II data.")
462 bremscorrector = register_module(
'BremsFinder')
463 bremscorrector.set_name(
'bremsCorrector_' + outputList)
464 bremscorrector.param(
'inputList', inputList)
465 bremscorrector.param(
'outputList', outputList)
466 bremscorrector.param(
'gammaList', gammaList)
467 bremscorrector.param(
'maximumAcceptance', maximumAcceptance)
468 bremscorrector.param(
'multiplePhotons', multiplePhotons)
469 bremscorrector.param(
'usePhotonOnlyOnce', usePhotonOnlyOnce)
470 bremscorrector.param(
'writeOut', writeOut)
471 path.add_module(bremscorrector)
474def copyList(outputListName, inputListName, writeOut=False, path=None):
476 Copy all Particle indices from input ParticleList to the output ParticleList.
477 Note that the Particles themselves are not copied. The original and copied
478 ParticleLists will point to the same Particles.
480 @param ouputListName copied ParticleList
481 @param inputListName original ParticleList to be copied
482 @param writeOut whether RootOutput module should save the created ParticleList
483 @param path modules are added to this path
486 copyLists(outputListName, [inputListName], writeOut, path)
489def correctBremsBelle(outputListName,
492 multiplePhotons=True,
494 usePhotonOnlyOnce=False,
498 Run the Belle - like brems finding on the ``inputListName`` of charged particles.
499 Adds all photons in ``gammaListName`` to a copy of the charged particle that are within
503 Studies by the tau WG show that using a rather wide opening angle (up to
504 0.2 rad) and rather low energetic photons results in good correction.
505 However, this should only serve as a starting point for your own studies
506 because the optimal criteria are likely mode-dependent
509 outputListName (str): The output charged particle list containing the corrected charged particles
510 inputListName (str): The initial charged particle list containing the charged particles to correct.
511 gammaListName (str): The gammas list containing possibly radiative gammas, should already exist.
512 multiplePhotons (bool): How many photons should be added to the charged particle? nearest one -> False,
513 add all the photons within the cone -> True
514 angleThreshold (float): The maximum angle in radians between the charged particle and the (radiative)
515 gamma to be accepted.
516 writeOut (bool): whether RootOutput module should save the created ParticleList
517 usePhotonOnlyOnce (bool): If true, a photon is used for correction of the closest charged particle in the inputList.
518 If false, a photon is allowed to be used for correction multiple times (Default).
521 One cannot use a photon twice to reconstruct a composite particle. Thus, for example, if ``e+`` and ``e-`` are corrected
522 with a ``gamma``, the pair of ``e+`` and ``e-`` cannot form a ``J/psi -> e+ e-`` candidate.
524 path (basf2.Path): modules are added to this path
527 fsrcorrector = register_module(
'BelleBremRecovery')
528 fsrcorrector.set_name(
'BelleFSRCorrection_' + outputListName)
529 fsrcorrector.param(
'inputListName', inputListName)
530 fsrcorrector.param(
'outputListName', outputListName)
531 fsrcorrector.param(
'gammaListName', gammaListName)
532 fsrcorrector.param(
'multiplePhotons', multiplePhotons)
533 fsrcorrector.param(
'angleThreshold', angleThreshold)
534 fsrcorrector.param(
'usePhotonOnlyOnce', usePhotonOnlyOnce)
535 fsrcorrector.param(
'writeOut', writeOut)
536 path.add_module(fsrcorrector)
539def copyLists(outputListName, inputListNames, writeOut=False, path=None):
541 Copy all Particle indices from all input ParticleLists to the
542 single output ParticleList.
543 Note that the Particles themselves are not copied.
544 The original and copied ParticleLists will point to the same Particles.
546 Duplicates are removed based on the first-come, first-served principle.
547 Therefore, the order of the input ParticleLists matters.
550 If you want to select the best duplicate based on another criterion, have
551 a look at the function `mergeListsWithBestDuplicate`.
554 Two particles that differ only by the order of their daughters are
555 considered duplicates and one of them will be removed.
557 @param ouputListName copied ParticleList
558 @param inputListName vector of original ParticleLists to be copied
559 @param writeOut whether RootOutput module should save the created ParticleList
560 @param path modules are added to this path
563 pmanipulate = register_module(
'ParticleListManipulator')
564 pmanipulate.set_name(
'PListCopy_' + outputListName)
565 pmanipulate.param(
'outputListName', outputListName)
566 pmanipulate.param(
'inputListNames', inputListNames)
567 pmanipulate.param(
'writeOut', writeOut)
568 path.add_module(pmanipulate)
571def copyParticles(outputListName, inputListName, writeOut=False, path=None):
573 Create copies of Particles given in the input ParticleList and add them to the output ParticleList.
575 The existing relations of the original Particle (or it's (grand-)^n-daughters)
576 are copied as well. Note that only the relation is copied and that the related
577 object is not. Copied particles are therefore related to the *same* object as
580 @param ouputListName new ParticleList filled with copied Particles
581 @param inputListName input ParticleList with original Particles
582 @param writeOut whether RootOutput module should save the created ParticleList
583 @param path modules are added to this path
587 pmanipulate = register_module(
'ParticleListManipulator')
588 pmanipulate.set_name(
'PListCopy_' + outputListName)
589 pmanipulate.param(
'outputListName', outputListName)
590 pmanipulate.param(
'inputListNames', [inputListName])
591 pmanipulate.param(
'writeOut', writeOut)
592 path.add_module(pmanipulate)
595 pcopy = register_module(
'ParticleCopier')
596 pcopy.param(
'inputListNames', [outputListName])
597 path.add_module(pcopy)
600def cutAndCopyLists(outputListName, inputListNames, cut, writeOut=False, path=None):
602 Copy candidates from all lists in ``inputListNames`` to
603 ``outputListName`` if they pass ``cut`` (given selection criteria).
606 Note that the Particles themselves are not copied.
607 The original and copied ParticleLists will point to the same Particles.
610 Require energetic pions safely inside the cdc
612 .. code-block:: python
614 cutAndCopyLists("pi+:energeticPions", ["pi+:good", "pi+:loose"], "[E > 2] and thetaInCDCAcceptance", path=mypath)
617 You must use square braces ``[`` and ``]`` for conditional statements.
620 outputListName (str): the new ParticleList name
621 inputListName (list(str)): list of input ParticleList names
622 cut (str): Candidates that do not pass these selection criteria are removed from the ParticleList
623 writeOut (bool): whether RootOutput module should save the created ParticleList
624 path (basf2.Path): modules are added to this path
627 pmanipulate = register_module(
'ParticleListManipulator')
628 pmanipulate.set_name(
'PListCutAndCopy_' + outputListName)
629 pmanipulate.param(
'outputListName', outputListName)
630 pmanipulate.param(
'inputListNames', inputListNames)
631 pmanipulate.param(
'cut', cut)
632 pmanipulate.param(
'writeOut', writeOut)
633 path.add_module(pmanipulate)
636def cutAndCopyList(outputListName, inputListName, cut, writeOut=False, path=None):
638 Copy candidates from ``inputListName`` to ``outputListName`` if they pass
639 ``cut`` (given selection criteria).
642 Note the Particles themselves are not copied.
643 The original and copied ParticleLists will point to the same Particles.
646 require energetic pions safely inside the cdc
648 .. code-block:: python
650 cutAndCopyList("pi+:energeticPions", "pi+:loose", "[E > 2] and thetaInCDCAcceptance", path=mypath)
653 You must use square braces ``[`` and ``]`` for conditional statements.
656 outputListName (str): the new ParticleList name
657 inputListName (str): input ParticleList name
658 cut (str): Candidates that do not pass these selection criteria are removed from the ParticleList
659 writeOut (bool): whether RootOutput module should save the created ParticleList
660 path (basf2.Path): modules are added to this path
663 cutAndCopyLists(outputListName, [inputListName], cut, writeOut, path)
666def removeTracksForTrackingEfficiencyCalculation(inputListNames, fraction, path=None):
668 Randomly remove tracks from the provided particle lists to estimate the tracking efficiency.
669 Takes care of the duplicates, if any.
672 inputListNames (list(str)): input particle list names
673 fraction (float): fraction of particles to be removed randomly
674 path (basf2.Path): module is added to this path
677 trackingefficiency = register_module(
'TrackingEfficiency')
678 trackingefficiency.param(
'particleLists', inputListNames)
679 trackingefficiency.param(
'frac', fraction)
680 path.add_module(trackingefficiency)
683def scaleTrackMomenta(inputListNames, scale=float(
'nan'), payloadName=
"tracking_MomentumScaling", scalingFactorName=
"central",
686 Scale momenta of the particles according to a scaling factor scale.
687 This scaling factor can either be given as constant number or as the name of the payload which contains
688 the variable scale factors.
689 If the particle list contains composite particles, the momenta of the track-based daughters are scaled.
690 Subsequently, the momentum of the mother particle is updated as well.
693 inputListNames (list(str)): input particle list names
694 scale (float): scaling factor (1.0 -- no scaling). If a valid value is given, it takes precedence over
695 ``payloadName`` and the latter is ignored.
696 payloadName (str): base name of the payload which contains the phase-space dependent scaling factors.
697 The suffix ``_data`` or ``_MC`` is appended automatically depending on whether the module runs on data or MC.
698 Defaults to the standard ``tracking_MomentumScaling`` payload.
699 scalingFactorName (str): name of scaling factor variable in the payload.
700 path (basf2.Path): module is added to this path
705 B2ERROR(
"The tracking momentum scaler can only be run over Belle II data.")
709 if not math.isnan(scale)
and payloadName ==
"tracking_MomentumScaling":
710 B2WARNING(f
"A constant scale value ({scale}) was provided to scaleTrackMomenta: the default "
711 "'tracking_MomentumScaling' payload from the global tag will NOT be used. "
712 "The constant scale is applied instead.")
715 TrackingMomentumScaleFactors = register_module(
'TrackingMomentumScaleFactors')
716 TrackingMomentumScaleFactors.param(
'particleLists', inputListNames)
717 TrackingMomentumScaleFactors.param(
'scale', scale)
718 TrackingMomentumScaleFactors.param(
'payloadName', payloadName)
719 TrackingMomentumScaleFactors.param(
'scalingFactorName', scalingFactorName)
721 path.add_module(TrackingMomentumScaleFactors)
724def correctTrackEnergy(inputListNames, correction=float(
'nan'), payloadName=
"tracking_EnergyLoss", correctionName=
"central",
727 Correct the energy loss of tracks according to a 'correction' value.
728 This correction can either be given as constant number or as the name of the payload which contains
729 the variable corrections.
730 If the particle list contains composite particles, the momenta of the track-based daughters are corrected.
731 Subsequently, the momentum of the mother particle is updated as well.
734 inputListNames (list(str)): input particle list names
735 correction (float): correction value to be subtracted to the particle energy (0.0 -- no correction).
736 If a valid value is given, it takes precedence over ``payloadName`` and the latter is ignored.
737 payloadName (str): base name of the payload which contains the phase-space dependent corrections.
738 The suffix ``_data`` or ``_MC`` is appended automatically depending on whether the module runs on data or MC.
739 Defaults to the standard ``tracking_EnergyLoss`` payload.
740 correctionName (str): name of correction variable in the payload.
741 path (basf2.Path): module is added to this path
746 B2ERROR(
"The tracking energy correction can only be run over Belle II data.")
750 if not math.isnan(correction)
and payloadName ==
"tracking_EnergyLoss":
751 B2WARNING(f
"A constant correction value ({correction}) was provided to correctTrackEnergy: the default "
752 "'tracking_EnergyLoss' payload from the global tag will NOT be used. "
753 "The constant correction is applied instead.")
756 TrackingEnergyLossCorrection = register_module(
'TrackingEnergyLossCorrection')
757 TrackingEnergyLossCorrection.param(
'particleLists', inputListNames)
758 TrackingEnergyLossCorrection.param(
'correction', correction)
759 TrackingEnergyLossCorrection.param(
'payloadName', payloadName)
760 TrackingEnergyLossCorrection.param(
'correctionName', correctionName)
762 path.add_module(TrackingEnergyLossCorrection)
765def smearTrackMomenta(inputListNames, payloadName="", smearingFactorName="smear", path=None):
767 Smear the momenta of the particles according the values read from the given payload.
768 If the particle list contains composite particles, the momenta of the track-based daughters are smeared.
769 Subsequently, the momentum of the mother particle is updated as well.
772 inputListNames (list(str)): input particle list names
773 payloadName (str): name of the payload which contains the smearing values
774 smearingFactorName (str): name of smearing factor variable in the payload.
775 path (basf2.Path): module is added to this path
778 TrackingMomentumScaleFactors = register_module(
'TrackingMomentumScaleFactors')
779 TrackingMomentumScaleFactors.param(
'particleLists', inputListNames)
780 TrackingMomentumScaleFactors.param(
'payloadName', payloadName)
781 TrackingMomentumScaleFactors.param(
'smearingFactorName', smearingFactorName)
783 path.add_module(TrackingMomentumScaleFactors)
786def mergeListsWithBestDuplicate(outputListName,
791 ignoreMotherFlavor=False,
794 Merge input ParticleLists into one output ParticleList. Only the best
795 among duplicates is kept. The lowest or highest value (configurable via
796 preferLowest) of the provided variable determines which duplicate is the
799 @param ouputListName name of merged ParticleList
800 @param inputListName vector of original ParticleLists to be merged
801 @param variable variable to determine best duplicate
802 @param preferLowest whether lowest or highest value of variable should be preferred
803 @param writeOut whether RootOutput module should save the created ParticleList
804 @param ignoreMotherFlavor whether the flavor of the mother particle is ignored when trying to find duplicates
805 @param path modules are added to this path
808 pmanipulate = register_module(
'ParticleListManipulator')
809 pmanipulate.set_name(
'PListMerger_' + outputListName)
810 pmanipulate.param(
'outputListName', outputListName)
811 pmanipulate.param(
'inputListNames', inputListNames)
812 pmanipulate.param(
'variable', variable)
813 pmanipulate.param(
'preferLowest', preferLowest)
814 pmanipulate.param(
'writeOut', writeOut)
815 pmanipulate.param(
'ignoreMotherFlavor', ignoreMotherFlavor)
816 path.add_module(pmanipulate)
819def fillSignalSideParticleList(outputListName, decayString, path):
821 This function should only be used in the ROE path, that is a path
822 that is executed for each ROE object in the DataStore.
824 Example: fillSignalSideParticleList('gamma:sig','B0 -> K*0 ^gamma', roe_path)
826 Function will create a ParticleList with name 'gamma:sig' which will be filled
827 with the existing photon Particle, being the second daughter of the B0 candidate
828 to which the ROE object has to be related.
830 @param ouputListName name of the created ParticleList
831 @param decayString specify Particle to be added to the ParticleList
834 pload = register_module(
'SignalSideParticleListCreator')
835 pload.set_name(
'SSParticleList_' + outputListName)
836 pload.param(
'particleListName', outputListName)
837 pload.param(
'decayString', decayString)
838 path.add_module(pload)
841def fillParticleLists(decayStringsWithCuts, writeOut=False, path=None, enforceFitHypothesis=False,
842 loadPhotonsFromKLM=False):
844 Creates Particles of the desired types from the corresponding ``mdst`` dataobjects,
845 loads them to the ``StoreArray<Particle>`` and fills the ParticleLists.
847 The multiple ParticleLists with their own selection criteria are specified
848 via list tuples (decayString, cut), for example
850 .. code-block:: python
852 kaons = ('K+:mykaons', 'kaonID>0.1')
853 pions = ('pi+:mypions','pionID>0.1')
854 fillParticleLists([kaons, pions], path=mypath)
856 If you are unsure what selection you want, you might like to see the
857 :doc:`StandardParticles` functions.
859 The type of the particles to be loaded is specified via the decayString module parameter.
860 The type of the ``mdst`` dataobject that is used as an input is determined from the type of
861 the particle. The following types of the particles can be loaded:
863 * charged final state particles (input ``mdst`` type = Tracks)
864 - e+, mu+, pi+, K+, p, deuteron (and charge conjugated particles)
866 * neutral final state particles
867 - "gamma" (input ``mdst`` type = ECLCluster)
868 - "K_S0", "Lambda0" (input ``mdst`` type = V0)
869 - "K_L0", "n0" (input ``mdst`` type = KLMCluster or ECLCluster)
872 For "K_S0" and "Lambda0" you must specify the daughter ordering.
874 For example, to load V0s as :math:`\\Lambda^0\\to p^+\\pi^-` decays from V0s:
876 .. code-block:: python
878 v0lambdas = ('Lambda0 -> p+ pi-', '0.9 < M < 1.3')
879 fillParticleLists([kaons, pions, v0lambdas], path=mypath)
882 Gammas can also be loaded from KLMClusters by explicitly setting the
883 parameter ``loadPhotonsFromKLM`` to True. However, this should only be
884 done in selected use-cases and the effect should be studied carefully.
887 For "K_L0" it is now possible to load from ECLClusters, to revert to
888 the old (Belle) behavior, you can require ``'isFromKLM > 0'``.
890 .. code-block:: python
892 klongs = ('K_L0', 'isFromKLM > 0')
893 fillParticleLists([kaons, pions, klongs], path=mypath)
895 * Charged kinks final state particles (input ``mdst`` type = Kink)
898 To reconstruct charged particle kink you must specify the daughter.
900 For example, to load Kinks as :math:`K^- \\to \\pi^-\\pi^0` decays from Kinks:
902 .. code-block:: python
904 kinkKaons = ('K- -> pi-', yourCut)
905 fillParticleLists([kaons, pions, v0lambdas, kinkKaons], path=mypath)
909 decayStringsWithCuts (list): A list of python ntuples of (decayString, cut).
910 The decay string determines the type of Particle
911 and the name of the ParticleList.
912 If the input MDST type is V0 the whole
913 decay chain needs to be specified, so that
914 the user decides and controls the daughters
915 ' order (e.g. ``K_S0 -> pi+ pi-``).
916 If the input MDST type is Kink the decay chain needs to be specified
917 with only one daughter (e.g. ``K- -> pi-``).
918 The cut is the selection criteria
919 to be added to the ParticleList. It can be an empty string.
920 writeOut (bool): whether RootOutput module should save the created ParticleList
921 path (basf2.Path): modules are added to this path
922 enforceFitHypothesis (bool): If true, Particles will be created only for the tracks which have been fitted
923 using a mass hypothesis of the exact type passed to fillParticleLists().
924 If enforceFitHypothesis is False (the default) the next closest fit hypothesis
925 in terms of mass difference will be used if the fit using exact particle
926 type is not available.
927 loadPhotonsFromKLM (bool): If true, photon candidates will be created from KLMClusters as well.
930 pload = register_module(
'ParticleLoader')
931 pload.set_name(
'ParticleLoader_' +
'PLists')
932 pload.param(
'decayStrings', [decayString
for decayString, cut
in decayStringsWithCuts])
933 pload.param(
'writeOut', writeOut)
934 pload.param(
"enforceFitHypothesis", enforceFitHypothesis)
935 path.add_module(pload)
937 from ROOT
import Belle2
939 for decayString, cut
in decayStringsWithCuts:
940 if not decayDescriptor.init(decayString):
941 raise ValueError(
"Invalid decay string")
943 if decayDescriptor.getNDaughters() > 0:
948 if (decayDescriptor.getNDaughters() == 1)
and (decayDescriptor.getMother().getLabel() !=
'kink'):
949 copyList(decayDescriptor.getMother().getFullName(), decayDescriptor.getMother().getName() +
':kink',
951 if (decayDescriptor.getNDaughters() > 1)
and (decayDescriptor.getMother().getLabel() !=
'V0'):
952 copyList(decayDescriptor.getMother().getFullName(), decayDescriptor.getMother().getName() +
':V0', writeOut, path)
953 elif (decayDescriptor.getMother().getLabel() !=
'all' and
954 abs(decayDescriptor.getMother().getPDGCode()) != Belle2.Const.neutron.getPDGCode()):
957 copyList(decayString, decayDescriptor.getMother().getName() +
':all', writeOut, path)
961 applyCuts(decayDescriptor.getMother().getFullName(), cut, path)
963 if decayString.startswith(
"gamma"):
966 if not loadPhotonsFromKLM:
967 applyCuts(decayString,
'isFromECL', path)
970def fillParticleList(decayString, cut, writeOut=False, path=None, enforceFitHypothesis=False,
971 loadPhotonsFromKLM=False):
973 Creates Particles of the desired type from the corresponding ``mdst`` dataobjects,
974 loads them to the StoreArray<Particle> and fills the ParticleList.
977 the :doc:`StandardParticles` functions.
979 The type of the particles to be loaded is specified via the decayString module parameter.
980 The type of the ``mdst`` dataobject that is used as an input is determined from the type of
981 the particle. The following types of the particles can be loaded:
983 * charged final state particles (input ``mdst`` type = Tracks)
984 - e+, mu+, pi+, K+, p, deuteron (and charge conjugated particles)
986 * neutral final state particles
987 - "gamma" (input ``mdst`` type = ECLCluster)
988 - "K_S0", "Lambda0" (input ``mdst`` type = V0)
989 - "K_L0", "n0" (input ``mdst`` type = KLMCluster or ECLCluster)
992 For "K_S0" and "Lambda0" you must specify the daughter ordering.
994 For example, to load V0s as :math:`\\Lambda^0\\to p^+\\pi^-` decays from V0s:
996 .. code-block:: python
998 fillParticleList('Lambda0 -> p+ pi-', '0.9 < M < 1.3', path=mypath)
1001 Gammas can also be loaded from KLMClusters by explicitly setting the
1002 parameter ``loadPhotonsFromKLM`` to True. However, this should only be
1003 done in selected use-cases and the effect should be studied carefully.
1006 For "K_L0" it is now possible to load from ECLClusters, to revert to
1007 the old (Belle) behavior, you can require ``'isFromKLM > 0'``.
1009 .. code-block:: python
1011 fillParticleList('K_L0', 'isFromKLM > 0', path=mypath)
1013 * Charged kinks final state particles (input ``mdst`` type = Kink)
1016 To reconstruct charged particle kink you must specify the daughter.
1018 For example, to load Kinks as :math:`K^- \\to \\pi^-\\pi^0` decays from Kinks:
1020 .. code-block:: python
1022 fillParticleList('K- -> pi-', yourCut, path=mypath)
1026 decayString (str): Type of Particle and determines the name of the ParticleList.
1027 If the input MDST type is V0 the whole decay chain needs to be specified, so that
1028 the user decides and controls the daughters' order (e.g. ``K_S0 -> pi+ pi-``).
1029 If the input MDST type is Kink the decay chain needs to be specified
1030 with only one daughter (e.g. ``K- -> pi-``).
1031 cut (str): Particles need to pass these selection criteria to be added to the ParticleList
1032 writeOut (bool): whether RootOutput module should save the created ParticleList
1033 path (basf2.Path): modules are added to this path
1034 enforceFitHypothesis (bool): If true, Particles will be created only for the tracks which have been fitted
1035 using a mass hypothesis of the exact type passed to fillParticleLists().
1036 If enforceFitHypothesis is False (the default) the next closest fit hypothesis
1037 in terms of mass difference will be used if the fit using exact particle
1038 type is not available.
1039 loadPhotonsFromKLM (bool): If true, photon candidates will be created from KLMClusters as well.
1042 pload = register_module(
'ParticleLoader')
1043 pload.set_name(
'ParticleLoader_' + decayString)
1044 pload.param(
'decayStrings', [decayString])
1045 pload.param(
'writeOut', writeOut)
1046 pload.param(
"enforceFitHypothesis", enforceFitHypothesis)
1047 path.add_module(pload)
1050 from ROOT
import Belle2
1052 if not decayDescriptor.init(decayString):
1053 raise ValueError(
"Invalid decay string")
1054 if decayDescriptor.getNDaughters() > 0:
1059 if (decayDescriptor.getNDaughters() == 1)
and (decayDescriptor.getMother().getLabel() !=
'kink'):
1060 copyList(decayDescriptor.getMother().getFullName(), decayDescriptor.getMother().getName() +
':kink',
1062 if (decayDescriptor.getNDaughters() > 1)
and (decayDescriptor.getMother().getLabel() !=
'V0'):
1063 copyList(decayDescriptor.getMother().getFullName(), decayDescriptor.getMother().getName() +
':V0', writeOut,
1065 elif (decayDescriptor.getMother().getLabel() !=
'all' and
1066 abs(decayDescriptor.getMother().getPDGCode()) != Belle2.Const.neutron.getPDGCode()):
1069 copyList(decayString, decayDescriptor.getMother().getName() +
':all', writeOut, path)
1073 applyCuts(decayDescriptor.getMother().getFullName(), cut, path)
1075 if decayString.startswith(
"gamma"):
1078 if not loadPhotonsFromKLM:
1079 applyCuts(decayString,
'isFromECL', path)
1082def fillParticleListWithTrackHypothesis(decayString,
1086 enforceFitHypothesis=False,
1089 As fillParticleList, but if used for a charged FSP, loads the particle with the requested hypothesis if available
1091 @param decayString specifies type of Particles and determines the name of the ParticleList
1092 @param cut Particles need to pass these selection criteria to be added to the ParticleList
1093 @param hypothesis the PDG code of the desired track hypothesis
1094 @param writeOut whether RootOutput module should save the created ParticleList
1095 @param enforceFitHypothesis If true, Particles will be created only for the tracks which have been fitted
1096 using a mass hypothesis of the exact type passed to fillParticleLists().
1097 If enforceFitHypothesis is False (the default) the next closest fit hypothesis
1098 in terms of mass difference will be used if the fit using exact particle
1099 type is not available.
1100 @param path modules are added to this path
1103 pload = register_module(
'ParticleLoader')
1104 pload.set_name(
'ParticleLoader_' + decayString)
1105 pload.param(
'decayStrings', [decayString])
1106 pload.param(
'trackHypothesis', hypothesis)
1107 pload.param(
'writeOut', writeOut)
1108 pload.param(
"enforceFitHypothesis", enforceFitHypothesis)
1109 path.add_module(pload)
1111 from ROOT
import Belle2
1113 if not decayDescriptor.init(decayString):
1114 raise ValueError(
"Invalid decay string")
1115 if decayDescriptor.getMother().getLabel() !=
'all':
1118 copyList(decayString, decayDescriptor.getMother().getName() +
':all', writeOut, path)
1122 applyCuts(decayString, cut, path)
1125def fillConvertedPhotonsList(decayString, cut, writeOut=False, path=None):
1127 Creates photon Particle object for each e+e- combination in the V0 StoreArray.
1130 You must specify the daughter ordering.
1132 .. code-block:: python
1134 fillConvertedPhotonsList('gamma:converted -> e+ e-', '', path=mypath)
1137 decayString (str): Must be gamma to an e+e- pair. You must specify the daughter ordering.
1138 Will also determine the name of the particleList.
1139 cut (str): Particles need to pass these selection criteria to be added to the ParticleList
1140 writeOut (bool): whether RootOutput module should save the created ParticleList
1141 path (basf2.Path): modules are added to this path
1147 B2ERROR(
'For Belle converted photons are available in the pre-defined list "gamma:v0mdst".')
1149 pload = register_module(
'ParticleLoader')
1150 pload.set_name(
'ParticleLoader_' + decayString)
1151 pload.param(
'decayStrings', [decayString])
1152 pload.param(
'addDaughters',
True)
1153 pload.param(
'writeOut', writeOut)
1154 path.add_module(pload)
1156 from ROOT
import Belle2
1158 if not decayDescriptor.init(decayString):
1159 raise ValueError(
"Invalid decay string")
1160 if decayDescriptor.getMother().getLabel() !=
'V0':
1163 copyList(decayDescriptor.getMother().getFullName(), decayDescriptor.getMother().getName() +
':V0', writeOut, path)
1167 applyCuts(decayDescriptor.getMother().getFullName(), cut, path)
1170def fillParticleListFromROE(decayString,
1173 sourceParticleListName='',
1178 Creates Particle object for each ROE of the desired type found in the
1179 StoreArray<RestOfEvent>, loads them to the StoreArray<Particle>
1180 and fills the ParticleList. If useMissing is True, then the missing
1181 momentum is used instead of ROE.
1183 The type of the particles to be loaded is specified via the decayString module parameter.
1185 @param decayString specifies type of Particles and determines the name of the ParticleList.
1186 Source ROEs can be taken as a daughter list, for example:
1187 'B0:tagFromROE -> B0:signal'
1188 @param cut Particles need to pass these selection criteria to be added to the ParticleList
1189 @param maskName Name of the ROE mask to use
1190 @param sourceParticleListName Use related ROEs to this particle list as a source
1191 @param useMissing Use missing momentum instead of ROE momentum
1192 @param writeOut whether RootOutput module should save the created ParticleList
1193 @param path modules are added to this path
1196 pload = register_module(
'ParticleLoader')
1197 pload.set_name(
'ParticleLoader_' + decayString)
1198 pload.param(
'decayStrings', [decayString])
1199 pload.param(
'writeOut', writeOut)
1200 pload.param(
'roeMaskName', maskName)
1201 pload.param(
'useMissing', useMissing)
1202 pload.param(
'sourceParticleListName', sourceParticleListName)
1203 pload.param(
'useROEs',
True)
1204 path.add_module(pload)
1206 from ROOT
import Belle2
1208 if not decayDescriptor.init(decayString):
1209 raise ValueError(
"Invalid decay string")
1213 applyCuts(decayDescriptor.getMother().getFullName(), cut, path)
1216def fillParticleListFromDummy(decayString,
1219 treatAsInvisible=True,
1223 Creates a ParticleList and fills it with dummy Particles. For self-conjugated Particles one dummy
1224 Particle is created, for Particles that are not self-conjugated one Particle and one anti-Particle is
1225 created. The four-momentum is set to zero.
1227 The type of the particles to be loaded is specified via the decayString module parameter.
1229 @param decayString specifies type of Particles and determines the name of the ParticleList
1230 @param mdstIndex sets the mdst index of Particles
1231 @param covMatrix sets the value of the diagonal covariance matrix of Particles
1232 @param treatAsInvisible whether treeFitter should treat the Particles as invisible
1233 @param writeOut whether RootOutput module should save the created ParticleList
1234 @param path modules are added to this path
1237 pload = register_module(
'ParticleLoader')
1238 pload.set_name(
'ParticleLoader_' + decayString)
1239 pload.param(
'decayStrings', [decayString])
1240 pload.param(
'useDummy',
True)
1241 pload.param(
'dummyMDSTIndex', mdstIndex)
1242 pload.param(
'dummyCovMatrix', covMatrix)
1243 pload.param(
'dummyTreatAsInvisible', treatAsInvisible)
1244 pload.param(
'writeOut', writeOut)
1245 path.add_module(pload)
1248def fillParticleListFromMC(decayString,
1251 skipNonPrimaryDaughters=False,
1254 skipNonPrimary=False,
1257 Creates Particle object for each MCParticle of the desired type found in the StoreArray<MCParticle>,
1258 loads them to the StoreArray<Particle> and fills the ParticleList.
1260 The type of the particles to be loaded is specified via the decayString module parameter.
1262 @param decayString specifies type of Particles and determines the name of the ParticleList
1263 @param cut Particles need to pass these selection criteria to be added to the ParticleList
1264 @param addDaughters adds the bottom part of the decay chain of the particle to the datastore and
1265 sets mother-daughter relations
1266 @param skipNonPrimaryDaughters if true, skip non primary daughters, useful to study final state daughter particles
1267 @param writeOut whether RootOutput module should save the created ParticleList
1268 @param path modules are added to this path
1269 @param skipNonPrimary if true, skip non primary particle
1270 @param skipInitial if true, skip initial particles
1273 pload = register_module(
'ParticleLoader')
1274 pload.set_name(
'ParticleLoader_' + decayString)
1275 pload.param(
'decayStrings', [decayString])
1276 pload.param(
'addDaughters', addDaughters)
1277 pload.param(
'skipNonPrimaryDaughters', skipNonPrimaryDaughters)
1278 pload.param(
'writeOut', writeOut)
1279 pload.param(
'useMCParticles',
True)
1280 pload.param(
'skipNonPrimary', skipNonPrimary)
1281 pload.param(
'skipInitial', skipInitial)
1282 path.add_module(pload)
1284 from ROOT
import Belle2
1286 if not decayDescriptor.init(decayString):
1287 raise ValueError(
"Invalid decay string")
1291 applyCuts(decayString, cut, path)
1294def fillParticleListsFromMC(decayStringsWithCuts,
1296 skipNonPrimaryDaughters=False,
1299 skipNonPrimary=False,
1302 Creates Particle object for each MCParticle of the desired type found in the StoreArray<MCParticle>,
1303 loads them to the StoreArray<Particle> and fills the ParticleLists.
1305 The types of the particles to be loaded are specified via the (decayString, cut) tuples given in a list.
1308 .. code-block:: python
1310 kaons = ('K+:gen', '')
1311 pions = ('pi+:gen', 'pionID>0.1')
1312 fillParticleListsFromMC([kaons, pions], path=mypath)
1315 Daughters of ``Lambda0`` are not primary, but ``Lambda0`` is not final state particle.
1316 Thus, when one reconstructs a particle from ``Lambda0``, that is created with
1317 ``addDaughters=True`` and ``skipNonPrimaryDaughters=True``, the particle always has ``isSignal==0``.
1318 Please set options for ``Lambda0`` to use MC-matching variables properly as follows,
1319 ``addDaughters=True`` and ``skipNonPrimaryDaughters=False``.
1321 @param decayString specifies type of Particles and determines the name of the ParticleList
1322 @param cut Particles need to pass these selection criteria to be added to the ParticleList
1323 @param addDaughters adds the bottom part of the decay chain of the particle to the datastore and
1324 sets mother-daughter relations
1325 @param skipNonPrimaryDaughters if true, skip non primary daughters, useful to study final state daughter particles
1326 @param writeOut whether RootOutput module should save the created ParticleList
1327 @param path modules are added to this path
1328 @param skipNonPrimary if true, skip non primary particle
1329 @param skipInitial if true, skip initial particles
1332 pload = register_module(
'ParticleLoader')
1333 pload.set_name(
'ParticleLoader_' +
'PLists')
1334 pload.param(
'decayStrings', [decayString
for decayString, cut
in decayStringsWithCuts])
1335 pload.param(
'addDaughters', addDaughters)
1336 pload.param(
'skipNonPrimaryDaughters', skipNonPrimaryDaughters)
1337 pload.param(
'writeOut', writeOut)
1338 pload.param(
'useMCParticles',
True)
1339 pload.param(
'skipNonPrimary', skipNonPrimary)
1340 pload.param(
'skipInitial', skipInitial)
1341 path.add_module(pload)
1343 from ROOT
import Belle2
1345 for decayString, cut
in decayStringsWithCuts:
1346 if not decayDescriptor.init(decayString):
1347 raise ValueError(
"Invalid decay string")
1351 applyCuts(decayString, cut, path)
1354def fillParticleListFromChargedCluster(outputParticleList,
1357 useOnlyMostEnergeticECLCluster=True,
1361 Creates the Particle object from ECLCluster and KLMCluster that are being matched with the Track of inputParticleList.
1363 @param outputParticleList The output ParticleList. Only neutral final state particles are supported.
1364 @param inputParticleList The input ParticleList that is required to have the relation to the Track object.
1365 @param cut Particles need to pass these selection criteria to be added to the ParticleList
1366 @param useOnlyMostEnergeticECLCluster If True, only the most energetic ECLCluster among ones that are matched with the Track is
1367 used. If False, all matched ECLClusters are loaded. The default is True. Regardless of
1368 this option, the KLMCluster is loaded.
1369 @param writeOut whether RootOutput module should save the created ParticleList
1370 @param path modules are added to this path
1373 pload = register_module(
'ParticleLoader')
1374 pload.set_name(
'ParticleLoader_' + outputParticleList)
1376 pload.param(
'decayStrings', [outputParticleList])
1377 pload.param(
'sourceParticleListName', inputParticleList)
1378 pload.param(
'writeOut', writeOut)
1379 pload.param(
'loadChargedCluster',
True)
1380 pload.param(
'useOnlyMostEnergeticECLCluster', useOnlyMostEnergeticECLCluster)
1381 path.add_module(pload)
1385 applyCuts(outputParticleList, cut, path)
1388def extractParticlesFromROE(particleLists,
1389 signalSideParticleList=None,
1394 Extract Particle objects that belong to the Rest-Of-Events and fill them into the ParticleLists.
1395 The types of the particles other than those specified by ``particleLists`` are not stored.
1396 If one creates a ROE with ``fillWithMostLikely=True`` via `buildRestOfEvent`, for example,
1397 one should create particleLists for not only ``pi+``, ``gamma``, ``K_L0`` but also other charged final state particles.
1399 When one calls the function in the main path, one has to set the argument ``signalSideParticleList`` and the signal side
1400 ParticleList must have only one candidate.
1402 .. code-block:: python
1404 buildRestOfEvent('B0:sig', fillWithMostLikely=True, path=mypath)
1406 roe_path = create_path()
1407 deadEndPath = create_path()
1408 signalSideParticleFilter('B0:sig', '', roe_path, deadEndPath)
1410 plists = ['%s:in_roe' % ptype for ptype in ['pi+', 'gamma', 'K_L0', 'K+', 'p+', 'e+', 'mu+']]
1411 extractParticlesFromROE(plists, maskName='all', path=roe_path)
1413 # one can analyze these ParticleLists in the roe_path
1415 mypath.for_each('RestOfEvent', 'RestOfEvents', roe_path)
1417 rankByLowest('B0:sig', 'deltaE', numBest=1, path=mypath)
1418 extractParticlesFromROE(plists, signalSideParticleList='B0:sig', maskName='all', path=mypath)
1420 # one can analyze these ParticleLists in the main path
1423 @param particleLists (str or list(str)) Name of output ParticleLists
1424 @param signalSideParticleList (str) Name of signal side ParticleList
1425 @param maskName (str) Name of the ROE mask to be applied on Particles
1426 @param writeOut (bool) whether RootOutput module should save the created ParticleList
1427 @param path (basf2.Path) modules are added to this path
1430 if isinstance(particleLists, str):
1431 particleLists = [particleLists]
1433 pext = register_module(
'ParticleExtractorFromROE')
1434 pext.set_name(
'ParticleExtractorFromROE_' +
'_'.join(particleLists))
1435 pext.param(
'outputListNames', particleLists)
1436 if signalSideParticleList
is not None:
1437 pext.param(
'signalSideParticleListName', signalSideParticleList)
1438 pext.param(
'maskName', maskName)
1439 pext.param(
'writeOut', writeOut)
1440 path.add_module(pext)
1443def applyCuts(list_name, cut, path):
1445 Removes particle candidates from ``list_name`` that do not pass ``cut``
1446 (given selection criteria).
1449 require energetic pions safely inside the cdc
1451 .. code-block:: python
1453 applyCuts("pi+:mypions", "[E > 2] and thetaInCDCAcceptance", path=mypath)
1456 You must use square braces ``[`` and ``]`` for conditional statements.
1459 list_name (str): input ParticleList name
1460 cut (str): Candidates that do not pass these selection criteria are removed from the ParticleList
1461 path (basf2.Path): modules are added to this path
1464 pselect = register_module(
'ParticleSelector')
1465 pselect.set_name(
'ParticleSelector_applyCuts_' + list_name)
1466 pselect.param(
'decayString', list_name)
1467 pselect.param(
'cut', cut)
1468 path.add_module(pselect)
1471def applyEventCuts(cut, path, metavariables=None):
1473 Removes events that do not pass the ``cut`` (given selection criteria).
1476 continuum events (in mc only) with more than 5 tracks
1478 .. code-block:: python
1480 applyEventCuts("[nTracks > 5] and [isContinuumEvent], path=mypath)
1483 Only event-based variables are allowed in this function
1484 and only square brackets ``[`` and ``]`` for conditional statements.
1487 cut (str): Events that do not pass these selection criteria are skipped
1488 path (basf2.Path): modules are added to this path
1489 metavariables (list(str)): List of meta variables to be considered in decomposition of cut
1493 from variables
import variables
1495 def find_vars(t: tuple, var_list: list, meta_list: list) ->
None:
1496 """ Recursive helper function to find variable names """
1497 if not isinstance(t, tuple):
1499 if t[0] == b2parser.B2ExpressionParser.node_types[
'IdentifierNode']:
1502 if t[0] == b2parser.B2ExpressionParser.node_types[
'FunctionNode']:
1503 meta_list.append(list(t[1:]))
1506 if isinstance(i, tuple):
1507 find_vars(i, var_list, meta_list)
1509 def check_variable(var_list: list, metavar_ids: list) ->
None:
1510 for var_string
in var_list:
1512 orig_name = variables.resolveAlias(var_string)
1513 if orig_name != var_string:
1516 find_vars(
b2parser.parse(orig_name), var_list_temp, meta_list_temp)
1518 check_variable(var_list_temp, metavar_ids)
1519 check_meta(meta_list_temp, metavar_ids)
1522 var = variables.getVariable(var_string)
1523 if event_var_id
not in var.description:
1524 B2ERROR(f
'Variable {var_string} is not an event-based variable! "\
1525 "Please check your inputs to the applyEventCuts method!')
1527 def check_meta(meta_list: list, metavar_ids: list) ->
None:
1528 for meta_string_list
in meta_list:
1530 while meta_string_list[0]
in metavar_ids:
1532 meta_string_list.pop(0)
1533 for meta_string
in meta_string_list[0].split(
","):
1534 find_vars(
b2parser.parse(meta_string), var_list_temp, meta_string_list)
1535 if len(meta_string_list) > 0:
1536 meta_string_list.pop(0)
1537 if len(meta_string_list) == 0:
1539 if len(meta_string_list) > 1:
1540 meta_list += meta_string_list[1:]
1541 if isinstance(meta_string_list[0], list):
1542 meta_string_list = [element
for element
in meta_string_list[0]]
1544 check_variable(var_list_temp, metavar_ids)
1546 if len(meta_string_list) == 0:
1548 elif len(meta_string_list) == 1:
1549 var = variables.getVariable(meta_string_list[0])
1551 var = variables.getVariable(meta_string_list[0], meta_string_list[1].split(
","))
1553 if event_var_id
in var.description:
1556 B2ERROR(f
'Variable {var.name} is not an event-based variable! Please check your inputs to the applyEventCuts method!')
1558 event_var_id =
'[Eventbased]'
1559 metavar_ids = [
'formula',
'abs',
1563 'exp',
'log',
'log10',
1565 'isNAN',
'ifNANgiveX']
1567 metavar_ids += metavariables
1571 find_vars(
b2parser.parse(cut), var_list=var_list, meta_list=meta_list)
1573 if len(var_list) == 0
and len(meta_list) == 0:
1574 B2WARNING(f
'Cut string "{cut}" has no variables for applyEventCuts helper function!')
1576 check_variable(var_list, metavar_ids)
1577 check_meta(meta_list, metavar_ids)
1579 eselect = register_module(
'VariableToReturnValue')
1580 eselect.param(
'variable',
'passesEventCut(' + cut +
')')
1581 path.add_module(eselect)
1582 empty_path = create_path()
1583 eselect.if_value(
'<1', empty_path)
1586def reconstructDecay(decayString,
1591 candidate_limit=None,
1592 ignoreIfTooManyCandidates=True,
1593 chargeConjugation=True,
1594 allowChargeViolation=False):
1596 Creates new Particles by making combinations of existing Particles - it reconstructs unstable particles via their specified
1597 decay mode, e.g. in form of a :ref:`DecayString`: :code:`D0 -> K- pi+` or :code:`B+ -> anti-D0 pi+`, ... All possible
1598 combinations are created (particles are used only once per candidate) and combinations that pass the specified selection
1599 criteria are saved to a newly created (mother) ParticleList. By default the charge conjugated decay is reconstructed as well
1600 (meaning that the charge conjugated mother list is created as well) but this can be deactivated.
1602 One can use an ``@``-sign to mark a particle as unspecified for inclusive analyses,
1603 e.g. in a DecayString: :code:`'@Xsd -> K+ pi-'`.
1605 .. seealso:: :ref:`Marker_of_unspecified_particle`
1608 The input ParticleLists are typically ordered according to the upstream reconstruction algorithm.
1609 Therefore, if you combine two or more identical particles in the decay chain you should not expect to see the same
1610 distribution for the daughter kinematics as they may be sorted by geometry, momentum etc.
1612 For example, in the decay :code:`D0 -> pi0 pi0` the momentum distributions of the two ``pi0`` s are not identical.
1613 This can be solved by manually randomising the lists before combining.
1617 * `Particle combiner how does it work? <https://questions.belle2.org/question/4318/particle-combiner-how-does-it-work/>`_
1618 * `Identical particles in decay chain <https://questions.belle2.org/question/5724/identical-particles-in-decay-chain/>`_
1620 @param decayString :ref:`DecayString` specifying what kind of the decay should be reconstructed
1621 (from the DecayString the mother and daughter ParticleLists are determined)
1622 @param cut created (mother) Particles are added to the mother ParticleList if they
1623 pass give cuts (in VariableManager style) and rejected otherwise
1624 @param dmID user specified decay mode identifier
1625 @param writeOut whether RootOutput module should save the created ParticleList
1626 @param path modules are added to this path
1627 @param candidate_limit Maximum amount of candidates to be reconstructed. If
1628 the number of candidates is exceeded a Warning will be
1630 By default, all these candidates will be removed and event will be ignored.
1631 This behaviour can be changed by \'ignoreIfTooManyCandidates\' flag.
1632 If no value is given the amount is limited to a sensible
1633 default. A value <=0 will disable this limit and can
1634 cause huge memory amounts so be careful.
1635 @param ignoreIfTooManyCandidates whether event should be ignored or not if number of reconstructed
1636 candidates reaches limit. If event is ignored, no candidates are reconstructed,
1637 otherwise, number of candidates in candidate_limit is reconstructed.
1638 @param chargeConjugation boolean to decide whether charge conjugated mode should be reconstructed as well (on by default)
1639 @param allowChargeViolation whether the decay string needs to conserve the electric charge
1642 pmake = register_module(
'ParticleCombiner')
1643 pmake.set_name(
'ParticleCombiner_' + decayString)
1644 pmake.param(
'decayString', decayString)
1645 pmake.param(
'cut', cut)
1646 pmake.param(
'decayMode', dmID)
1647 pmake.param(
'writeOut', writeOut)
1648 if candidate_limit
is not None:
1649 pmake.param(
"maximumNumberOfCandidates", candidate_limit)
1650 pmake.param(
"ignoreIfTooManyCandidates", ignoreIfTooManyCandidates)
1651 pmake.param(
'chargeConjugation', chargeConjugation)
1652 pmake.param(
"allowChargeViolation", allowChargeViolation)
1653 path.add_module(pmake)
1656def combineAllParticles(inputParticleLists, outputList, cut='', writeOut=False, path=None):
1658 Creates a new Particle as the combination of all Particles from all
1659 provided inputParticleLists. However, each particle is used only once
1660 (even if duplicates are provided) and the combination has to pass the
1661 specified selection criteria to be saved in the newly created (mother)
1664 @param inputParticleLists List of input particle lists which are combined to the new Particle
1665 @param outputList Name of the particle combination created with this module
1666 @param cut created (mother) Particle is added to the mother ParticleList if it passes
1667 these given cuts (in VariableManager style) and is rejected otherwise
1668 @param writeOut whether RootOutput module should save the created ParticleList
1669 @param path module is added to this path
1672 pmake = register_module(
'AllParticleCombiner')
1673 pmake.set_name(
'AllParticleCombiner_' + outputList)
1674 pmake.param(
'inputListNames', inputParticleLists)
1675 pmake.param(
'outputListName', outputList)
1676 pmake.param(
'cut', cut)
1677 pmake.param(
'writeOut', writeOut)
1678 path.add_module(pmake)
1681def reconstructMissingKlongDecayExpert(decayString,
1688 Creates a list of K_L0's and of B -> K_L0 + X, with X being a fully-reconstructed state.
1689 The K_L0 momentum is determined from kinematic constraints of the two-body B decay into K_L0 and X
1691 @param decayString DecayString specifying what kind of the decay should be reconstructed
1692 (from the DecayString the mother and daughter ParticleLists are determined)
1693 @param cut Particles are added to the K_L0 and B ParticleList if the B candidates
1694 pass the given cuts (in VariableManager style) and rejected otherwise
1695 @param dmID user specified decay mode identifier
1696 @param writeOut whether RootOutput module should save the created ParticleList
1697 @param path modules are added to this path
1698 @param recoList suffix appended to original K_L0 and B ParticleList that identify the newly created K_L0 and B lists
1701 pcalc = register_module(
'KlongMomentumCalculatorExpert')
1702 pcalc.set_name(
'KlongMomentumCalculatorExpert_' + decayString)
1703 pcalc.param(
'decayString', decayString)
1704 pcalc.param(
'writeOut', writeOut)
1705 pcalc.param(
'recoList', recoList)
1706 path.add_module(pcalc)
1708 rmake = register_module(
'KlongDecayReconstructorExpert')
1709 rmake.set_name(
'KlongDecayReconstructorExpert_' + decayString)
1710 rmake.param(
'decayString', decayString)
1711 rmake.param(
'cut', cut)
1712 rmake.param(
'decayMode', dmID)
1713 rmake.param(
'writeOut', writeOut)
1714 rmake.param(
'recoList', recoList)
1715 path.add_module(rmake)
1718def setBeamConstrainedMomentum(particleList, decayStringTarget, decayStringDaughters, path=None):
1720 Replace the four-momentum of the target Particle by p(beam) - p(selected daughters).
1721 The momentum of the mother Particle will not be changed.
1723 @param particleList mother Particlelist
1724 @param decayStringTarget DecayString specifying the target particle whose momentum
1726 @param decayStringDaughters DecayString specifying the daughter particles used to replace
1727 the momentum of the target particle by p(beam)-p(daughters)
1730 mod = register_module(
'ParticleMomentumUpdater')
1731 mod.set_name(
'ParticleMomentumUpdater' + particleList)
1732 mod.param(
'particleList', particleList)
1733 mod.param(
'decayStringTarget', decayStringTarget)
1734 mod.param(
'decayStringDaughters', decayStringDaughters)
1735 path.add_module(mod)
1738def updateKlongKinematicsExpert(particleList,
1742 Calculates and updates the kinematics of B->K_L0 + something else with same method as
1743 `reconstructMissingKlongDecayExpert`. This helps to revert the kinematics after the vertex fitting.
1745 @param particleList input ParticleList of B meson that decays to K_L0 + X
1746 @param writeOut whether RootOutput module should save the ParticleList
1747 @param path modules are added to this path
1750 mod = register_module(
'KlongMomentumUpdaterExpert')
1751 mod.set_name(
'KlongMomentumUpdaterExpert_' + particleList)
1752 mod.param(
'listName', particleList)
1753 mod.param(
'writeOut', writeOut)
1754 path.add_module(mod)
1757def replaceMass(replacerName, particleLists=None, pdgCode=22, path=None):
1759 replaces the mass of the particles inside the given particleLists
1760 with the invariant mass of the particle corresponding to the given pdgCode.
1762 @param particleLists new ParticleList filled with copied Particles
1763 @param pdgCode PDG code for mass reference
1764 @param path modules are added to this path
1767 if particleLists
is None:
1771 pmassupdater = register_module(
'ParticleMassUpdater')
1772 pmassupdater.set_name(
'ParticleMassUpdater_' + replacerName)
1773 pmassupdater.param(
'particleLists', particleLists)
1774 pmassupdater.param(
'pdgCode', pdgCode)
1775 path.add_module(pmassupdater)
1778def reconstructRecoil(decayString,
1783 candidate_limit=None,
1784 allowChargeViolation=False):
1786 Creates new Particles that recoil against the input particles.
1788 For example the decay string M -> D1 D2 D3 will:
1790 - create mother Particle M for each unique combination of D1, D2, D3 Particles
1791 - Particles D1, D2, D3 will be appended as daughters to M
1792 - the 4-momentum of the mother Particle M is given by
1793 p(M) = p(HER) + p(LER) - Sum_i p(Di)
1795 @param decayString DecayString specifying what kind of the decay should be reconstructed
1796 (from the DecayString the mother and daughter ParticleLists are determined)
1797 @param cut created (mother) Particles are added to the mother ParticleList if they
1798 pass give cuts (in VariableManager style) and rejected otherwise
1799 @param dmID user specified decay mode identifier
1800 @param writeOut whether RootOutput module should save the created ParticleList
1801 @param path modules are added to this path
1802 @param candidate_limit Maximum amount of candidates to be reconstructed. If
1803 the number of candidates is exceeded no candidate will be
1804 reconstructed for that event and a Warning will be
1806 If no value is given the amount is limited to a sensible
1807 default. A value <=0 will disable this limit and can
1808 cause huge memory amounts so be careful.
1809 @param allowChargeViolation whether the decay string needs to conserve the electric charge
1812 pmake = register_module(
'ParticleCombiner')
1813 pmake.set_name(
'ParticleCombiner_' + decayString)
1814 pmake.param(
'decayString', decayString)
1815 pmake.param(
'cut', cut)
1816 pmake.param(
'decayMode', dmID)
1817 pmake.param(
'writeOut', writeOut)
1818 pmake.param(
'recoilParticleType', 1)
1819 if candidate_limit
is not None:
1820 pmake.param(
"maximumNumberOfCandidates", candidate_limit)
1821 pmake.param(
'allowChargeViolation', allowChargeViolation)
1822 path.add_module(pmake)
1825def reconstructRecoilDaughter(decayString,
1830 candidate_limit=None,
1831 allowChargeViolation=False):
1833 Creates new Particles that are daughters of the particle reconstructed in the recoil (always assumed to be the first daughter).
1835 For example the decay string M -> D1 D2 D3 will:
1837 - create mother Particle M for each unique combination of D1, D2, D3 Particles
1838 - Particles D1, D2, D3 will be appended as daughters to M
1839 - the 4-momentum of the mother Particle M is given by
1840 p(M) = p(D1) - Sum_i p(Di), where i>1
1842 @param decayString DecayString specifying what kind of the decay should be reconstructed
1843 (from the DecayString the mother and daughter ParticleLists are determined)
1844 @param cut created (mother) Particles are added to the mother ParticleList if they
1845 pass give cuts (in VariableManager style) and rejected otherwise
1846 @param dmID user specified decay mode identifier
1847 @param writeOut whether RootOutput module should save the created ParticleList
1848 @param path modules are added to this path
1849 @param candidate_limit Maximum amount of candidates to be reconstructed. If
1850 the number of candidates is exceeded no candidate will be
1851 reconstructed for that event and a Warning will be
1853 If no value is given the amount is limited to a sensible
1854 default. A value <=0 will disable this limit and can
1855 cause huge memory amounts so be careful.
1856 @param allowChargeViolation whether the decay string needs to conserve the electric charge taking into account that the first
1857 daughter is actually the mother
1860 pmake = register_module(
'ParticleCombiner')
1861 pmake.set_name(
'ParticleCombiner_' + decayString)
1862 pmake.param(
'decayString', decayString)
1863 pmake.param(
'cut', cut)
1864 pmake.param(
'decayMode', dmID)
1865 pmake.param(
'writeOut', writeOut)
1866 pmake.param(
'recoilParticleType', 2)
1867 if candidate_limit
is not None:
1868 pmake.param(
"maximumNumberOfCandidates", candidate_limit)
1869 pmake.param(
'allowChargeViolation', allowChargeViolation)
1870 path.add_module(pmake)
1873def rankByHighest(particleList,
1877 allowMultiRank=False,
1879 overwriteRank=False,
1882 Ranks particles in the input list by the given variable (highest to lowest), and stores an integer rank for each Particle
1883 in an :b2:var:`extraInfo` field ``${variable}_rank`` starting at 1 (best).
1884 The list is also sorted from best to worst candidate.
1885 All particles are ranked together regardless of particle type.
1886 This can be used to perform a best candidate selection by cutting on the corresponding rank value, or by specifying
1887 a non-zero value for 'numBest'.
1890 Extra-info fields can be accessed by the :b2:var:`extraInfo` metavariable.
1891 These variable names can become clunky, so it's probably a good idea to set an alias.
1892 For example if you rank your B candidates by momentum,
1896 rankByHighest("B0:myCandidates", "p", path=mypath)
1897 vm.addAlias("momentumRank", "extraInfo(p_rank)")
1900 @param particleList The input ParticleList
1901 @param variable Variable to order Particles by.
1902 @param numBest If not zero, only the $numBest Particles in particleList with rank <= numBest are kept.
1903 @param outputVariable Name for the variable that will be created which contains the rank, Default is '${variable}_rank'.
1904 @param allowMultiRank If true, candidates with the same value will get the same rank.
1905 @param cut Only candidates passing the cut will be ranked. The others will have rank -1
1906 @param overwriteRank If true, the extraInfo of rank is overwritten when the particle has already the extraInfo.
1907 @param path modules are added to this path
1910 bcs = register_module(
'BestCandidateSelection')
1911 bcs.set_name(
'BestCandidateSelection_' + particleList +
'_' + variable)
1912 bcs.param(
'particleList', particleList)
1913 bcs.param(
'variable', variable)
1914 bcs.param(
'numBest', numBest)
1915 bcs.param(
'outputVariable', outputVariable)
1916 bcs.param(
'allowMultiRank', allowMultiRank)
1917 bcs.param(
'cut', cut)
1918 bcs.param(
'overwriteRank', overwriteRank)
1919 path.add_module(bcs)
1922def rankByLowest(particleList,
1926 allowMultiRank=False,
1928 overwriteRank=False,
1931 Ranks particles in the input list by the given variable (lowest to highest), and stores an integer rank for each Particle
1932 in an :b2:var:`extraInfo` field ``${variable}_rank`` starting at 1 (best).
1933 The list is also sorted from best to worst candidate.
1934 All particles are ranked together regardless of particle type.
1935 This can be used to perform a best candidate selection by cutting on the corresponding rank value, or by specifying
1936 a non-zero value for 'numBest'.
1939 Extra-info fields can be accessed by the :b2:var:`extraInfo` metavariable.
1940 These variable names can become clunky, so it's probably a good idea to set an alias.
1941 For example if you rank your B candidates by :b2:var:`dM`,
1945 rankByLowest("B0:myCandidates", "dM", path=mypath)
1946 vm.addAlias("massDifferenceRank", "extraInfo(dM_rank)")
1949 @param particleList The input ParticleList
1950 @param variable Variable to order Particles by.
1951 @param numBest If not zero, only the $numBest Particles in particleList with rank <= numBest are kept.
1952 @param outputVariable Name for the variable that will be created which contains the rank, Default is '${variable}_rank'.
1953 @param allowMultiRank If true, candidates with the same value will get the same rank.
1954 @param cut Only candidates passing the cut will be ranked. The others will have rank -1
1955 @param overwriteRank If true, the extraInfo of rank is overwritten when the particle has already the extraInfo.
1956 @param path modules are added to this path
1959 bcs = register_module(
'BestCandidateSelection')
1960 bcs.set_name(
'BestCandidateSelection_' + particleList +
'_' + variable)
1961 bcs.param(
'particleList', particleList)
1962 bcs.param(
'variable', variable)
1963 bcs.param(
'numBest', numBest)
1964 bcs.param(
'selectLowest',
True)
1965 bcs.param(
'allowMultiRank', allowMultiRank)
1966 bcs.param(
'outputVariable', outputVariable)
1967 bcs.param(
'cut', cut)
1968 bcs.param(
'overwriteRank', overwriteRank)
1969 path.add_module(bcs)
1972def applyRandomCandidateSelection(particleList, path=None):
1974 If there are multiple candidates in the provided particleList, all but one of them are removed randomly.
1975 This is done on a event-by-event basis.
1977 @param particleList ParticleList for which the random candidate selection should be applied
1978 @param path module is added to this path
1981 rcs = register_module(
'BestCandidateSelection')
1982 rcs.set_name(
'RandomCandidateSelection_' + particleList)
1983 rcs.param(
'particleList', particleList)
1984 rcs.param(
'variable',
'random')
1985 rcs.param(
'selectLowest',
False)
1986 rcs.param(
'allowMultiRank',
False)
1987 rcs.param(
'numBest', 1)
1988 rcs.param(
'cut',
'')
1989 rcs.param(
'outputVariable',
'')
1990 path.add_module(rcs)
1995 Prints the contents of DataStore in the first event (or a specific event number or all events).
1996 Will list all objects and arrays (including size).
1999 The command line tool: ``b2file-size``.
2002 eventNumber (int): Print the datastore only for this event. The default
2003 (-1) prints only the first event, 0 means print for all events (can produce large output)
2004 path (basf2.Path): the PrintCollections module is added to this path
2007 This will print a lot of output if you print it for all events and process many events.
2011 printDS = register_module(
'PrintCollections')
2012 printDS.param(
'printForEvent', eventNumber)
2013 path.add_module(printDS)
2016def printVariableValues(list_name, var_names, path):
2018 Prints out values of specified variables of all Particles included in given ParticleList. For debugging purposes.
2020 @param list_name input ParticleList name
2021 @param var_names vector of variable names to be printed
2022 @param path modules are added to this path
2025 prlist = register_module(
'ParticlePrinter')
2026 prlist.set_name(
'ParticlePrinter_' + list_name)
2027 prlist.param(
'listName', list_name)
2028 prlist.param(
'fullPrint',
False)
2029 prlist.param(
'variables', var_names)
2030 path.add_module(prlist)
2033def printList(list_name, full, path):
2035 Prints the size and executes Particle->print() (if full=True)
2036 method for all Particles in given ParticleList. For debugging purposes.
2038 @param list_name input ParticleList name
2039 @param full execute Particle->print() method for all Particles
2040 @param path modules are added to this path
2043 prlist = register_module(
'ParticlePrinter')
2044 prlist.set_name(
'ParticlePrinter_' + list_name)
2045 prlist.param(
'listName', list_name)
2046 prlist.param(
'fullPrint', full)
2047 path.add_module(prlist)
2050def variablesToNtuple(decayString, variables, treename='variables', filename='ntuple.root', path=None, basketsize=1600,
2051 signalSideParticleList="", filenameSuffix="", useFloat=False, storeEventType=True,
2052 ignoreCommandLineOverride=False):
2054 Creates and fills a flat ntuple with the specified variables from the VariableManager.
2055 If a decayString is provided, then there will be one entry per candidate (for particle in list of candidates).
2056 If an empty decayString is provided, there will be one entry per event (useful for trigger studies, etc).
2059 decayString (str): specifies type of Particles and determines the name of the ParticleList
2060 variables (list(str)): the list of variables (which must be registered in the VariableManager)
2061 treename (str): name of the ntuple tree
2062 filename (str): which is used to store the variables
2063 path (basf2.Path): the basf2 path where the analysis is processed
2064 basketsize (int): size of baskets in the output ntuple in bytes
2065 signalSideParticleList (str): The name of the signal-side ParticleList.
2066 Only valid if the module is called in a for_each loop over the RestOfEvent.
2067 filenameSuffix (str): suffix to be appended to the filename before ``.root``.
2068 useFloat (bool): Use single precision (float) instead of double precision (double)
2069 for floating-point numbers.
2070 storeEventType (bool) : if true, the branch __eventType__ is added for the MC event type information.
2071 The information is available from MC16 on.
2072 ignoreCommandLineOverride (bool) : if true, ignore override of file name via command line argument ``-o``.
2074 .. tip:: The output filename can be overridden using the ``-o`` argument of basf2.
2077 output = register_module(
'VariablesToNtuple')
2078 output.set_name(
'VariablesToNtuple_' + decayString)
2079 output.param(
'particleList', decayString)
2080 output.param(
'variables', variables)
2081 output.param(
'fileName', filename)
2082 output.param(
'treeName', treename)
2083 output.param(
'basketSize', basketsize)
2084 output.param(
'signalSideParticleList', signalSideParticleList)
2085 output.param(
'fileNameSuffix', filenameSuffix)
2086 output.param(
'useFloat', useFloat)
2087 output.param(
'storeEventType', storeEventType)
2088 output.param(
'ignoreCommandLineOverride', ignoreCommandLineOverride)
2089 path.add_module(output)
2095 filename='ntuple.root',
2098 prefixDecayString=False,
2100 ignoreCommandLineOverride=False):
2102 Creates and fills a flat ntuple with the specified variables from the VariableManager
2105 decayString (str): specifies type of Particles and determines the name of the ParticleList
2106 variables (list(tuple))): variables + binning which must be registered in the VariableManager
2107 variables_2d (list(tuple)): pair of variables + binning for each which must be registered in the VariableManager
2108 filename (str): which is used to store the variables
2109 path (basf2.Path): the basf2 path where the analysis is processed
2110 directory (str): directory inside the output file where the histograms should be saved.
2111 Useful if you want to have different histograms in the same file to separate them.
2112 prefixDecayString (bool): If True the decayString will be prepended to the directory name to allow for more
2113 programmatic naming of the structure in the file.
2114 filenameSuffix (str): suffix to be appended to the filename before ``.root``.
2115 ignoreCommandLineOverride (bool) : if true, ignore override of file name via command line argument ``-o``.
2117 .. tip:: The output filename can be overridden using the ``-o`` argument of basf2.
2120 if variables_2d
is None:
2122 output = register_module(
'VariablesToHistogram')
2123 output.set_name(
'VariablesToHistogram_' + decayString)
2124 output.param(
'particleList', decayString)
2125 output.param(
'variables', variables)
2126 output.param(
'variables_2d', variables_2d)
2127 output.param(
'fileName', filename)
2128 output.param(
'fileNameSuffix', filenameSuffix)
2129 output.param(
'ignoreCommandLineOverride', ignoreCommandLineOverride)
2130 if directory
is not None or prefixDecayString:
2131 if directory
is None:
2133 if prefixDecayString:
2134 directory = decayString +
"_" + directory
2135 output.param(
"directory", directory)
2136 path.add_module(output)
2141 For each particle in the input list the selected variables are saved in an extra-info field with the given name.
2142 Can be used when wanting to save variables before modifying them, e.g. when performing vertex fits.
2145 particleList (str): The input ParticleList
2146 variables (dict[str,str]): Dictionary of Variables (key) and extraInfo names (value).
2147 option (int): Option to overwrite an existing extraInfo. Choose among -1, 0, 1, 2.
2148 An existing extra info with the same name will be overwritten if the new
2149 value is lower / will never be overwritten / will be overwritten if the
2150 new value is higher / will always be overwritten (option = -1/0/1/2).
2151 path (basf2.Path): modules are added to this path
2154 mod = register_module(
'VariablesToExtraInfo')
2155 mod.set_name(
'VariablesToExtraInfo_' + particleList)
2156 mod.param(
'particleList', particleList)
2157 mod.param(
'variables', variables)
2158 mod.param(
'overwrite', option)
2159 path.add_module(mod)
2162def variablesToDaughterExtraInfo(particleList, decayString, variables, option=0, path=None):
2164 For each daughter particle specified via decay string the selected variables (estimated for the mother particle)
2165 are saved in an extra-info field with the given name. In other words, the property of mother is saved as extra-info
2166 to specified daughter particle.
2169 particleList (str): The input ParticleList
2170 decayString (str): Decay string that specifies to which daughter the extra info should be appended
2171 variables (dict[str,str]): Dictionary of Variables (key) and extraInfo names (value).
2172 option (int): Option to overwrite an existing extraInfo. Choose among -1, 0, 1, 2.
2173 An existing extra info with the same name will be overwritten if the new
2174 value is lower / will never be overwritten / will be overwritten if the
2175 new value is higher / will always be overwritten (option = -1/0/1/2).
2176 path (basf2.Path): modules are added to this path
2179 mod = register_module(
'VariablesToExtraInfo')
2180 mod.set_name(
'VariablesToDaughterExtraInfo_' + particleList)
2181 mod.param(
'particleList', particleList)
2182 mod.param(
'decayString', decayString)
2183 mod.param(
'variables', variables)
2184 mod.param(
'overwrite', option)
2185 path.add_module(mod)
2188def variablesToEventExtraInfo(particleList, variables, option=0, path=None):
2190 For each particle in the input list the selected variables are saved in an event-extra-info field with the given name,
2191 Can be used to save MC truth information, for example, in a ntuple of reconstructed particles.
2194 When the function is called first time not in the main path but in a sub-path e.g. ``roe_path``,
2195 the eventExtraInfo cannot be accessed from the main path because of the shorter lifetime of the event-extra-info field.
2196 If one wants to call the function in a sub-path, one has to call the function in the main path beforehand.
2199 particleList (str): The input ParticleList
2200 variables (dict[str,str]): Dictionary of Variables (key) and extraInfo names (value).
2201 option (int): Option to overwrite an existing extraInfo. Choose among -1, 0, 1, 2.
2202 An existing extra info with the same name will be overwritten if the new
2203 value is lower / will never be overwritten / will be overwritten if the
2204 new value is higher / will always be overwritten (option = -1/0/1/2).
2205 path (basf2.Path): modules are added to this path
2208 mod = register_module(
'VariablesToEventExtraInfo')
2209 mod.set_name(
'VariablesToEventExtraInfo_' + particleList)
2210 mod.param(
'particleList', particleList)
2211 mod.param(
'variables', variables)
2212 mod.param(
'overwrite', option)
2213 path.add_module(mod)
2216def variableToSignalSideExtraInfo(particleList, varToExtraInfo, path):
2218 Write the value of specified variables estimated for the single particle in the input list (has to contain exactly 1
2219 particle) as an extra info to the particle related to current ROE.
2220 Should be used only in the for_each roe path.
2223 particleList (str): The input ParticleList
2224 varToExtraInfo (dict[str,str]): Dictionary of Variables (key) and extraInfo names (value).
2225 path (basf2.Path): modules are added to this path
2228 mod = register_module(
'SignalSideVariablesToExtraInfo')
2229 mod.set_name(
'SigSideVarToExtraInfo_' + particleList)
2230 mod.param(
'particleListName', particleList)
2231 mod.param(
'variableToExtraInfo', varToExtraInfo)
2232 path.add_module(mod)
2235def signalRegion(particleList, cut, path=None, name="isSignalRegion", blind_data=True):
2237 Define and blind a signal region.
2238 Per default, the defined signal region is cut out if ran on data.
2239 This function will provide a new variable 'isSignalRegion' as default, which is either 0 or 1 depending on the cut
2243 .. code-block:: python
2245 ma.reconstructDecay("B+:sig -> D+ pi0", "Mbc>5.2", path=path)
2246 ma.signalRegion("B+:sig",
2247 "Mbc>5.27 and abs(deltaE)<0.2",
2250 ma.variablesToNtuples("B+:sig", ["isSignalRegion"], path=path)
2253 particleList (str): The input ParticleList
2254 cut (str): Cut string describing the signal region
2255 path (basf2.Path):: Modules are added to this path
2256 name (str): Name of the Signal region in the variable manager
2257 blind_data (bool): Automatically exclude signal region from data
2261 from variables
import variables
2262 mod = register_module(
'VariablesToExtraInfo')
2263 mod.set_name(f
'{name}_' + particleList)
2264 mod.param(
'particleList', particleList)
2265 mod.param(
'variables', {f
"passesCut({cut})": name})
2266 variables.addAlias(name, f
"extraInfo({name})")
2267 path.add_module(mod)
2271 applyCuts(particleList, f
"{name}==0 or isMC==1", path=path)
2274def removeExtraInfo(particleLists=None, removeEventExtraInfo=False, path=None):
2276 Removes the ExtraInfo of the given particleLists. If specified (removeEventExtraInfo = True) also the EventExtraInfo is removed.
2279 if particleLists
is None:
2281 mod = register_module(
'ExtraInfoRemover')
2282 mod.param(
'particleLists', particleLists)
2283 mod.param(
'removeEventExtraInfo', removeEventExtraInfo)
2284 path.add_module(mod)
2287def signalSideParticleFilter(particleList, selection, roe_path, deadEndPath):
2289 Checks if the current ROE object in the for_each roe path (argument roe_path) is related
2290 to the particle from the input ParticleList. Additional selection criteria can be applied.
2291 If ROE is not related to any of the Particles from ParticleList or the Particle doesn't
2292 meet the selection criteria the execution of deadEndPath is started. This path, as the name
2293 suggests should be empty and its purpose is to end the execution of for_each roe path for
2294 the current ROE object.
2296 @param particleList The input ParticleList
2297 @param selection Selection criteria that Particle needs meet in order for for_each ROE path to continue
2298 @param for_each roe path in which this filter is executed
2299 @param deadEndPath empty path that ends execution of or_each roe path for the current ROE object.
2302 mod = register_module(
'SignalSideParticleFilter')
2303 mod.set_name(
'SigSideParticleFilter_' + particleList)
2304 mod.param(
'particleLists', [particleList])
2305 mod.param(
'selection', selection)
2306 roe_path.add_module(mod)
2307 mod.if_false(deadEndPath)
2310def signalSideParticleListsFilter(particleLists, selection, roe_path, deadEndPath):
2312 Checks if the current ROE object in the for_each roe path (argument roe_path) is related
2313 to the particle from the input ParticleList. Additional selection criteria can be applied.
2314 If ROE is not related to any of the Particles from ParticleList or the Particle doesn't
2315 meet the selection criteria the execution of deadEndPath is started. This path, as the name
2316 suggests should be empty and its purpose is to end the execution of for_each roe path for
2317 the current ROE object.
2319 @param particleLists The input ParticleLists
2320 @param selection Selection criteria that Particle needs meet in order for for_each ROE path to continue
2321 @param for_each roe path in which this filter is executed
2322 @param deadEndPath empty path that ends execution of or_each roe path for the current ROE object.
2325 mod = register_module(
'SignalSideParticleFilter')
2326 mod.set_name(
'SigSideParticleFilter_' + particleLists[0])
2327 mod.param(
'particleLists', particleLists)
2328 mod.param(
'selection', selection)
2329 roe_path.add_module(mod)
2330 mod.if_false(deadEndPath)
2339 chargeConjugation=True,
2342 Finds and creates a ``ParticleList`` from given decay string.
2343 ``ParticleList`` of daughters with sub-decay is created.
2345 Only the particles made from MCParticle, which can be loaded by `fillParticleListFromMC`, are accepted as daughters.
2347 Only signal particle, which means :b2:var:`isSignal` is equal to 1, is stored. One can use the decay string grammar
2348 to change the behavior of :b2:var:`isSignal`. One can find detailed information in :ref:`DecayString`.
2351 If one uses same sub-decay twice, same particles are registered to a ``ParticleList``. For example,
2352 ``K_S0:pi0pi0 =direct=> [pi0:gg =direct=> gamma:MC gamma:MC] [pi0:gg =direct=> gamma:MC gamma:MC]``.
2353 One can skip the second sub-decay, ``K_S0:pi0pi0 =direct=> [pi0:gg =direct=> gamma:MC gamma:MC] pi0:gg``.
2356 It is recommended to use only primary particles as daughter particles unless you want to explicitly study the secondary
2357 particles. The behavior of MC-matching for secondary particles from a stable particle decay is not guaranteed.
2358 Please consider to use `fillParticleListFromMC` with ``skipNonPrimary=True`` to load daughter particles.
2359 Moreover, it is recommended to load ``K_S0`` and ``Lambda0`` directly from MCParticle by `fillParticleListFromMC` rather
2360 than reconstructing from two pions or a proton-pion pair, because their direct daughters can be the secondary particle.
2363 @param decayString :ref:`DecayString` specifying what kind of the decay should be reconstructed
2364 (from the DecayString the mother and daughter ParticleLists are determined)
2365 @param cut created (mother) Particles are added to the mother ParticleList if they
2366 pass given cuts (in VariableManager style) and rejected otherwise
2367 isSignal==1 is always required by default.
2368 @param dmID user specified decay mode identifier
2369 @param writeOut whether RootOutput module should save the created ParticleList
2370 @param path modules are added to this path
2371 @param chargeConjugation boolean to decide whether charge conjugated mode should be reconstructed as well (on by default)
2374 pmake = register_module(
'ParticleCombinerFromMC')
2375 pmake.set_name(
'ParticleCombinerFromMC_' + decayString)
2376 pmake.param(
'decayString', decayString)
2377 pmake.param(
'cut', cut)
2378 pmake.param(
'decayMode', dmID)
2379 pmake.param(
'writeOut', writeOut)
2380 pmake.param(
'chargeConjugation', chargeConjugation)
2381 path.add_module(pmake)
2388 appendAllDaughters=False,
2389 skipNonPrimaryDaughters=True,
2393 Finds and creates a ``ParticleList`` for all ``MCParticle`` decays matching a given :ref:`DecayString`.
2394 The decay string is required to describe correctly what you want.
2395 In the case of inclusive decays, you can use :ref:`Grammar_for_custom_MCMatching`
2397 The output particles has only the daughter particles written in the given decay string, if
2398 ``appendAllDaughters=False`` (default). If ``appendAllDaughters=True``, all daughters of the matched MCParticle are
2399 appended in the order defined at the MCParticle level. For example,
2401 .. code-block:: python
2403 findMCDecay('B0:Xee', 'B0 -> e+ e- ... ?gamma', appendAllDaughters=False, path=mypath)
2405 The output ParticleList ``B0:Xee`` will match the inclusive ``B0 -> e+ e-`` decays (but neutrinos are not included),
2406 in both cases of ``appendAllDaughters`` is false and true.
2407 If the ``appendAllDaughters=False`` as above example, the ``B0:Xee`` has only two electrons as daughters.
2408 While, if ``appendAllDaughters=True``, all daughters of the matched MCParticles are appended. When the truth decay mode of
2409 the MCParticle is ``B0 -> [K*0 -> K+ pi-] [J/psi -> e+ e-]``, the first daughter of ``B0:Xee`` is ``K*0`` and ``e+``
2410 will be the first daughter of second daughter of ``B0:Xee``.
2412 The option ``skipNonPrimaryDaughters`` only has an effect if ``appendAllDaughters=True``. If ``skipNonPrimaryDaughters=True``,
2413 all primary daughters are appended but the secondary particles are not.
2416 Daughters of ``Lambda0`` are not primary, but ``Lambda0`` is not a final state particle.
2417 In order for the MCMatching to work properly, the daughters of ``Lambda0`` are appended to
2418 ``Lambda0`` regardless of the value of the option ``skipNonPrimaryDaughters``.
2421 @param list_name The output particle list name
2422 @param decay The decay string which you want
2423 @param writeOut Whether `RootOutput` module should save the created ``outputList``
2424 @param skipNonPrimaryDaughters if true, skip non primary daughters, useful to study final state daughter particles
2425 @param appendAllDaughters if true, not only the daughters described in the decay string but all daughters are appended
2426 @param path modules are added to this path
2429 decayfinder = register_module(
'MCDecayFinder')
2430 decayfinder.set_name(
'MCDecayFinder_' + list_name)
2431 decayfinder.param(
'listName', list_name)
2432 decayfinder.param(
'decayString', decay)
2433 decayfinder.param(
'appendAllDaughters', appendAllDaughters)
2434 decayfinder.param(
'skipNonPrimaryDaughters', skipNonPrimaryDaughters)
2435 decayfinder.param(
'writeOut', writeOut)
2436 path.add_module(decayfinder)
2439def summaryOfLists(particleLists, outputFile=None, path=None):
2441 Prints out Particle statistics at the end of the job: number of events with at
2442 least one candidate, average number of candidates per event, etc.
2443 If an output file name is provided the statistics is also dumped into a json file with that name.
2445 @param particleLists list of input ParticleLists
2446 @param outputFile output file name (not created by default)
2449 particleStats = register_module(
'ParticleStats')
2450 particleStats.param(
'particleLists', particleLists)
2451 if outputFile
is not None:
2452 particleStats.param(
'outputFile', outputFile)
2453 path.add_module(particleStats)
2456def matchMCTruth(list_name, path):
2458 Performs MC matching (sets relation Particle->MCParticle) for
2459 all particles (and its (grand)^N-daughter particles) in the specified
2462 @param list_name name of the input ParticleList
2463 @param path modules are added to this path
2466 mcMatch = register_module(
'MCMatcherParticles')
2467 mcMatch.set_name(
'MCMatch_' + list_name)
2468 mcMatch.param(
'listName', list_name)
2469 path.add_module(mcMatch)
2472def looseMCTruth(list_name, path):
2474 Performs loose MC matching for all particles in the specified
2476 The difference between loose and normal mc matching algorithm is that
2477 the loose algorithm will find the common mother of the majority of daughter
2478 particles while the normal algorithm finds the common mother of all daughters.
2479 The results of loose mc matching algorithm are stored to the following extraInfo
2482 - looseMCMotherPDG: PDG code of most common mother
2483 - looseMCMotherIndex: 1-based StoreArray<MCParticle> index of most common mother
2484 - looseMCWrongDaughterN: number of daughters that don't originate from the most common mother
2485 - looseMCWrongDaughterPDG: PDG code of the daughter that doesn't originate from the most common mother (only if
2486 looseMCWrongDaughterN = 1)
2487 - looseMCWrongDaughterBiB: 1 if the wrong daughter is Beam Induced Background Particle
2489 @param list_name name of the input ParticleList
2490 @param path modules are added to this path
2493 mcMatch = register_module(
'MCMatcherParticles')
2494 mcMatch.set_name(
'LooseMCMatch_' + list_name)
2495 mcMatch.param(
'listName', list_name)
2496 mcMatch.param(
'looseMCMatching',
True)
2497 path.add_module(mcMatch)
2500def matchTagTruth(list_name, path):
2502 Performs tag matching for all particles in the specified ParticleList.
2503 The difference between tag and normal mc matching algorithm is that
2504 a (ccbar) tag (usually defined by ccbarFEI) does not correspond to an actual MC particle.
2505 Instead the tag is meant to capture everything except the signal particle.
2506 Requires that normal MC matching has already been performed and set relations.
2507 Also note that low energy photons with energy < 0.1 GeV and ISR are ignored.
2508 The results of (ccbar) tag matching algorithm are stored to the following extraInfo items:
2509 - ccbarTagSignal: 1st digit is status of signal particle, 2nd digit is Nleft-1, 3rd digit is NextraFSP.
2510 - ccbarTagMCpdg: PDG code of (charm) hadron outside tag (signal side).
2511 - ccbarTagMCpdgMother: PDG code of the mother of the (charm) hadron outside tag (signal side).
2512 - ccbarTagNleft: number of particles (composites have priority) left outisde tag.
2513 - ccbarTagNextraFSP: number of extra FSP particles attached to the tag.
2514 - ccbarTagSignalStatus: status of the targeted signal side particle.
2515 - ccbarTagNwoMC: number of daughters without MC match.
2516 - ccbarTagNwoMCMother: number of daughters without MC mother.
2517 - ccbarTagNnoAllMother: number of daughters without common allmother.
2518 - ccbarTagNmissGamma: number of daughters with missing gamma mc error.
2519 - ccbarTagNmissNeutrino: number of daughters with missing neutrino mc error.
2520 - ccbarTagNdecayInFlight: number of daughters with decay in flight mc error.
2521 - ccbarTagNsevereMCError: number of daughters with severe mc error.
2522 - ccbarTagNmissRecoDaughters: number of daughters with any mc error.
2523 - ccbarTagNleft2ndPDG: PDG of one particle left additionally to the signal particle.
2524 - ccbarTagAllMotherPDG: PDG code of the allmother (Z0 or virtual photon).
2526 @param list_name name of the input ParticleList
2527 @param path modules are added to this path
2530 mcMatch = register_module(
'MCMatcherParticles')
2531 mcMatch.set_name(
'ccbarTagMatch_' + list_name)
2532 mcMatch.param(
'listName', list_name)
2533 mcMatch.param(
'ccbarTagMatching',
True)
2534 path.add_module(mcMatch)
2537def buildRestOfEvent(target_list_name, inputParticlelists=None,
2538 fillWithMostLikely=True,
2539 chargedPIDPriors=None, path=None):
2541 Creates for each Particle in the given ParticleList a RestOfEvent
2542 dataobject and makes basf2 relation between them. User can provide additional
2543 particle lists with a different particle hypothesis like ['K+:good, e+:good'], etc.
2545 @param target_list_name name of the input ParticleList
2546 @param inputParticlelists list of user-defined input particle list names, which serve
2547 as source of particles to build the ROE, the FSP particles from
2548 target_list_name are automatically excluded from the ROE object
2549 @param fillWithMostLikely By default the module uses the most likely particle mass hypothesis for charged particles
2550 based on the PID likelihood. Turn this behavior off if you want to configure your own
2551 input particle lists.
2552 @param chargedPIDPriors The prior PID fractions, that are used to regulate the
2553 amount of certain charged particle species, should be a list of
2554 six floats if not None. The order of particle types is
2555 the following: [e-, mu-, pi-, K-, p+, d+]
2556 @param path modules are added to this path
2559 if inputParticlelists
is None:
2560 inputParticlelists = []
2561 fillParticleList(
'pi+:all',
'', path=path)
2562 if fillWithMostLikely:
2563 from stdCharged
import stdMostLikely
2564 stdMostLikely(chargedPIDPriors,
'_roe', path=path)
2565 inputParticlelists = [f
'{ptype}:mostlikely_roe' for ptype
in [
'K+',
'p+',
'e+',
'mu+']]
2568 fillParticleList(
'gamma:all',
'', path=path)
2569 fillParticleList(
'K_L0:roe_default',
'isFromKLM > 0', path=path)
2570 inputParticlelists += [
'pi+:all',
'gamma:all',
'K_L0:roe_default']
2572 inputParticlelists += [
'pi+:all',
'gamma:mdst']
2573 roeBuilder = register_module(
'RestOfEventBuilder')
2574 roeBuilder.set_name(
'ROEBuilder_' + target_list_name)
2575 roeBuilder.param(
'particleList', target_list_name)
2576 roeBuilder.param(
'particleListsInput', inputParticlelists)
2577 roeBuilder.param(
'mostLikely', fillWithMostLikely)
2578 path.add_module(roeBuilder)
2581def buildNestedRestOfEvent(target_list_name, maskName='all', path=None):
2583 Creates for each Particle in the given ParticleList a RestOfEvent
2584 @param target_list_name name of the input ParticleList
2585 @param mask_name name of the ROEMask to be used
2586 @param path modules are added to this path
2589 roeBuilder = register_module(
'RestOfEventBuilder')
2590 roeBuilder.set_name(
'NestedROEBuilder_' + target_list_name)
2591 roeBuilder.param(
'particleList', target_list_name)
2592 roeBuilder.param(
'nestedROEMask', maskName)
2593 roeBuilder.param(
'createNestedROE',
True)
2594 path.add_module(roeBuilder)
2597def buildRestOfEventFromMC(target_list_name, inputParticlelists=None, path=None):
2599 Creates for each Particle in the given ParticleList a RestOfEvent
2600 @param target_list_name name of the input ParticleList
2601 @param inputParticlelists list of input particle list names, which serve
2602 as a source of particles to build ROE, the FSP particles from
2603 target_list_name are excluded from ROE object
2604 @param path modules are added to this path
2607 if inputParticlelists
is None:
2608 inputParticlelists = []
2609 if (len(inputParticlelists) == 0):
2613 types = [
'gamma',
'e+',
'mu+',
'pi+',
'K+',
'p+',
'K_L0',
2614 'n0',
'nu_e',
'nu_mu',
'nu_tau',
2617 fillParticleListFromMC(f
"{t}:roe_default_gen",
'mcPrimary > 0 and nDaughters == 0',
2618 True,
True, path=path)
2619 inputParticlelists += [f
"{t}:roe_default_gen"]
2620 roeBuilder = register_module(
'RestOfEventBuilder')
2621 roeBuilder.set_name(
'MCROEBuilder_' + target_list_name)
2622 roeBuilder.param(
'particleList', target_list_name)
2623 roeBuilder.param(
'particleListsInput', inputParticlelists)
2624 roeBuilder.param(
'fromMC',
True)
2625 path.add_module(roeBuilder)
2628def appendROEMask(list_name,
2631 eclClusterSelection,
2632 klmClusterSelection='',
2635 Loads the ROE object of a particle and creates a ROE mask with a specific name. It applies
2636 selection criteria for tracks and eclClusters which will be used by variables in ROEVariables.cc.
2638 - append a ROE mask with all tracks in ROE coming from the IP region
2640 .. code-block:: python
2642 appendROEMask('B+:sig', 'IPtracks', '[dr < 2] and [abs(dz) < 5]', path=mypath)
2644 - append a ROE mask with only ECL-based particles that pass as good photon candidates
2646 .. code-block:: python
2648 goodPhotons = 'inCDCAcceptance and clusterErrorTiming < 1e6 and [clusterE1E9 > 0.4 or E > 0.075]'
2649 appendROEMask('B+:sig', 'goodROEGamma', '', goodPhotons, path=mypath)
2652 @param list_name name of the input ParticleList
2653 @param mask_name name of the appended ROEMask
2654 @param trackSelection decay string for the track-based particles in ROE
2655 @param eclClusterSelection decay string for the ECL-based particles in ROE
2656 @param klmClusterSelection decay string for the KLM-based particles in ROE
2657 @param path modules are added to this path
2660 roeMask = register_module(
'RestOfEventInterpreter')
2661 roeMask.set_name(
'RestOfEventInterpreter_' + list_name +
'_' + mask_name)
2662 roeMask.param(
'particleList', list_name)
2663 roeMask.param(
'ROEMasks', [(mask_name, trackSelection, eclClusterSelection, klmClusterSelection)])
2664 path.add_module(roeMask)
2667def appendROEMasks(list_name, mask_tuples, path=None):
2669 Loads the ROE object of a particle and creates a ROE mask with a specific name. It applies
2670 selection criteria for track-, ECL- and KLM-based particles which will be used by ROE variables.
2672 The multiple ROE masks with their own selection criteria are specified
2673 via list of tuples (mask_name, trackParticleSelection, eclParticleSelection, klmParticleSelection) or
2674 (mask_name, trackSelection, eclClusterSelection) in case with fractions.
2676 - Example for two tuples, one with and one without fractions
2678 .. code-block:: python
2680 ipTracks = ('IPtracks', '[dr < 2] and [abs(dz) < 5]', '', '')
2681 goodPhotons = 'inCDCAcceptance and [clusterErrorTiming < 1e6] and [clusterE1E9 > 0.4 or E > 0.075]'
2682 goodROEGamma = ('ROESel', '[dr < 2] and [abs(dz) < 5]', goodPhotons, '')
2683 goodROEKLM = ('IPtracks', '[dr < 2] and [abs(dz) < 5]', '', 'nKLMClusterTrackMatches == 0')
2684 appendROEMasks('B+:sig', [ipTracks, goodROEGamma, goodROEKLM], path=mypath)
2686 @param list_name name of the input ParticleList
2687 @param mask_tuples array of ROEMask list tuples to be appended
2688 @param path modules are added to this path
2691 compatible_masks = []
2692 for mask
in mask_tuples:
2695 compatible_masks += [(*mask,
'')]
2697 compatible_masks += [mask]
2698 roeMask = register_module(
'RestOfEventInterpreter')
2699 roeMask.set_name(
'RestOfEventInterpreter_' + list_name +
'_' +
'MaskList')
2700 roeMask.param(
'particleList', list_name)
2701 roeMask.param(
'ROEMasks', compatible_masks)
2702 path.add_module(roeMask)
2705def updateROEMask(list_name,
2708 eclClusterSelection='',
2709 klmClusterSelection='',
2712 Update an existing ROE mask by applying additional selection cuts for
2713 tracks and/or clusters.
2715 See function `appendROEMask`!
2717 @param list_name name of the input ParticleList
2718 @param mask_name name of the ROEMask to update
2719 @param trackSelection decay string for the track-based particles in ROE
2720 @param eclClusterSelection decay string for the ECL-based particles in ROE
2721 @param klmClusterSelection decay string for the KLM-based particles in ROE
2722 @param path modules are added to this path
2725 roeMask = register_module(
'RestOfEventInterpreter')
2726 roeMask.set_name(
'RestOfEventInterpreter_' + list_name +
'_' + mask_name)
2727 roeMask.param(
'particleList', list_name)
2728 roeMask.param(
'ROEMasks', [(mask_name, trackSelection, eclClusterSelection, klmClusterSelection)])
2729 roeMask.param(
'update',
True)
2730 path.add_module(roeMask)
2733def updateROEMasks(list_name, mask_tuples, path):
2735 Update existing ROE masks by applying additional selection cuts for tracks
2738 The multiple ROE masks with their own selection criteria are specified
2739 via list tuples (mask_name, trackSelection, eclClusterSelection, klmClusterSelection)
2741 See function `appendROEMasks`!
2743 @param list_name name of the input ParticleList
2744 @param mask_tuples array of ROEMask list tuples to be appended
2745 @param path modules are added to this path
2748 compatible_masks = []
2749 for mask
in mask_tuples:
2752 compatible_masks += [(*mask,
'')]
2754 compatible_masks += [mask]
2756 roeMask = register_module(
'RestOfEventInterpreter')
2757 roeMask.set_name(
'RestOfEventInterpreter_' + list_name +
'_' +
'MaskList')
2758 roeMask.param(
'particleList', list_name)
2759 roeMask.param(
'ROEMasks', compatible_masks)
2760 roeMask.param(
'update',
True)
2761 path.add_module(roeMask)
2764def keepInROEMasks(list_name, mask_names, cut_string, path=None):
2766 This function is used to apply particle list specific cuts on one or more ROE masks (track or eclCluster).
2767 With this function one can KEEP the tracks/eclclusters used in particles from provided particle list.
2768 This function should be executed only in the for_each roe path for the current ROE object.
2770 To avoid unnecessary computation, the input particle list should only contain particles from ROE
2771 (use cut 'isInRestOfEvent == 1'). To update the ECLCluster masks, the input particle list should be a photon
2772 particle list (e.g. 'gamma:someLabel'). To update the Track masks, the input particle list should be a charged
2773 pion particle list (e.g. 'pi+:someLabel').
2775 Updating a non-existing mask will create a new one.
2777 - keep only those tracks that were used in provided particle list
2779 .. code-block:: python
2781 keepInROEMasks('pi+:goodTracks', 'mask', '', path=mypath)
2783 - keep only those clusters that were used in provided particle list and pass a cut, apply to several masks
2785 .. code-block:: python
2787 keepInROEMasks('gamma:goodClusters', ['mask1', 'mask2'], 'E > 0.1', path=mypath)
2790 @param list_name name of the input ParticleList
2791 @param mask_names array of ROEMasks to be updated
2792 @param cut_string decay string with which the mask will be updated
2793 @param path modules are added to this path
2796 updateMask = register_module(
'RestOfEventUpdater')
2797 updateMask.set_name(
'RestOfEventUpdater_' + list_name +
'_masks')
2798 updateMask.param(
'particleList', list_name)
2799 updateMask.param(
'updateMasks', mask_names)
2800 updateMask.param(
'cutString', cut_string)
2801 updateMask.param(
'discard',
False)
2802 path.add_module(updateMask)
2805def discardFromROEMasks(list_name, mask_names, cut_string, path=None):
2807 This function is used to apply particle list specific cuts on one or more ROE masks (track or eclCluster).
2808 With this function one can DISCARD the tracks/eclclusters used in particles from provided particle list.
2809 This function should be executed only in the for_each roe path for the current ROE object.
2811 To avoid unnecessary computation, the input particle list should only contain particles from ROE
2812 (use cut 'isInRestOfEvent == 1'). To update the ECLCluster masks, the input particle list should be a photon
2813 particle list (e.g. 'gamma:someLabel'). To update the Track masks, the input particle list should be a charged
2814 pion particle list (e.g. 'pi+:someLabel').
2816 Updating a non-existing mask will create a new one.
2818 - discard tracks that were used in provided particle list
2820 .. code-block:: python
2822 discardFromROEMasks('pi+:badTracks', 'mask', '', path=mypath)
2824 - discard clusters that were used in provided particle list and pass a cut, apply to several masks
2826 .. code-block:: python
2828 discardFromROEMasks('gamma:badClusters', ['mask1', 'mask2'], 'E < 0.1', path=mypath)
2831 @param list_name name of the input ParticleList
2832 @param mask_names array of ROEMasks to be updated
2833 @param cut_string decay string with which the mask will be updated
2834 @param path modules are added to this path
2837 updateMask = register_module(
'RestOfEventUpdater')
2838 updateMask.set_name(
'RestOfEventUpdater_' + list_name +
'_masks')
2839 updateMask.param(
'particleList', list_name)
2840 updateMask.param(
'updateMasks', mask_names)
2841 updateMask.param(
'cutString', cut_string)
2842 updateMask.param(
'discard',
True)
2843 path.add_module(updateMask)
2846def optimizeROEWithV0(list_name, mask_names, cut_string, path=None):
2848 This function is used to apply particle list specific cuts on one or more ROE masks for Tracks.
2849 It is possible to optimize the ROE selection by treating tracks from V0's separately, meaning,
2850 taking V0's 4-momentum into account instead of 4-momenta of tracks. A cut for only specific V0's
2851 passing it can be applied.
2853 The input particle list should be a V0 particle list: K_S0 ('K_S0:someLabel', ''),
2854 Lambda ('Lambda:someLabel', '') or converted photons ('gamma:someLabel').
2856 Updating a non-existing mask will create a new one.
2858 - treat tracks from K_S0 inside mass window separately, replace track momenta with K_S0 momentum
2860 .. code-block:: python
2862 optimizeROEWithV0('K_S0:opt', 'mask', '0.450 < M < 0.550', path=mypath)
2864 @param list_name name of the input ParticleList
2865 @param mask_names array of ROEMasks to be updated
2866 @param cut_string decay string with which the mask will be updated
2867 @param path modules are added to this path
2870 updateMask = register_module(
'RestOfEventUpdater')
2871 updateMask.set_name(
'RestOfEventUpdater_' + list_name +
'_masks')
2872 updateMask.param(
'particleList', list_name)
2873 updateMask.param(
'updateMasks', mask_names)
2874 updateMask.param(
'cutString', cut_string)
2875 path.add_module(updateMask)
2878def updateROEUsingV0Lists(target_particle_list, mask_names, default_cleanup=True, selection_cuts=None,
2879 apply_mass_fit=False, fitter='treefit', path=None):
2881 This function creates V0 particle lists (photons, :math:`K^0_S` and :math:`\\Lambda^0`)
2882 and it uses V0 candidates to update the Rest Of Event, which is associated to the target particle list.
2883 It is possible to apply a standard or customized selection and mass fit to the V0 candidates.
2886 @param target_particle_list name of the input ParticleList
2887 @param mask_names array of ROE masks to be applied
2888 @param default_cleanup if True, predefined cuts will be applied on the V0 lists
2889 @param selection_cuts a single string of selection cuts or tuple of three strings (photon_cuts, K_S0_cuts, Lambda0_cuts),
2890 which will be applied to the V0 lists. These cuts will have a priority over the default ones.
2891 @param apply_mass_fit if True, a mass fit will be applied to the V0 particles
2892 @param fitter string, that represent a fitter choice: "treefit" for TreeFitter and "kfit" for KFit
2893 @param path modules are added to this path
2896 roe_path = create_path()
2897 deadEndPath = create_path()
2898 signalSideParticleFilter(target_particle_list,
'', roe_path, deadEndPath)
2900 if (default_cleanup
and selection_cuts
is None):
2901 B2INFO(
"Using default cleanup in updateROEUsingV0Lists.")
2902 selection_cuts =
'abs(dM) < 0.1 '
2903 selection_cuts +=
'and daughter(0,particleID) > 0.2 and daughter(1,particleID) > 0.2 '
2904 selection_cuts +=
'and daughter(0,thetaInCDCAcceptance) and daughter(1,thetaInCDCAcceptance)'
2905 if (selection_cuts
is None or selection_cuts ==
''):
2906 B2INFO(
"No cleanup in updateROEUsingV0Lists.")
2907 selection_cuts = (
'True',
'True',
'True')
2908 if (isinstance(selection_cuts, str)):
2909 selection_cuts = (selection_cuts, selection_cuts, selection_cuts)
2911 roe_cuts =
'isInRestOfEvent > 0'
2912 fillConvertedPhotonsList(
'gamma:v0_roe -> e+ e-', f
'{selection_cuts[0]} and {roe_cuts}',
2914 fillParticleList(
'K_S0:v0_roe -> pi+ pi-', f
'{selection_cuts[1]} and {roe_cuts}',
2916 fillParticleList(
'Lambda0:v0_roe -> p+ pi-', f
'{selection_cuts[2]} and {roe_cuts}',
2918 fitter = fitter.lower()
2919 if (fitter !=
'treefit' and fitter !=
'kfit'):
2920 B2WARNING(
'Argument "fitter" in updateROEUsingV0Lists has only "treefit" and "kfit" options, '
2921 f
'but "{fitter}" was provided! TreeFitter will be used instead.')
2923 from vertex
import kFit, treeFit
2924 for v0
in [
'gamma:v0_roe',
'K_S0:v0_roe',
'Lambda0:v0_roe']:
2925 if (apply_mass_fit
and fitter ==
'kfit'):
2926 kFit(v0, conf_level=0.0, fit_type=
'massvertex', path=roe_path)
2927 if (apply_mass_fit
and fitter ==
'treefit'):
2928 treeFit(v0, conf_level=0.0, massConstraint=[v0.split(
':')[0]], path=roe_path)
2929 optimizeROEWithV0(v0, mask_names,
'', path=roe_path)
2930 path.for_each(
'RestOfEvent',
'RestOfEvents', roe_path)
2933def printROEInfo(mask_names=None, full_print=False,
2934 unpackComposites=True, path=None):
2936 This function prints out the information for the current ROE, so it should only be used in the for_each path.
2937 It prints out basic ROE object info.
2939 If mask names are provided, specific information for those masks will be printed out.
2941 It is also possible to print out all particles in a given mask if the
2942 'full_print' is set to True.
2944 @param mask_names array of ROEMask names for printing out info
2945 @param unpackComposites if true, replace composite particles by their daughters
2946 @param full_print print out particles in mask
2947 @param path modules are added to this path
2950 if mask_names
is None:
2952 printMask = register_module(
'RestOfEventPrinter')
2953 printMask.set_name(
'RestOfEventPrinter')
2954 printMask.param(
'maskNames', mask_names)
2955 printMask.param(
'fullPrint', full_print)
2956 printMask.param(
'unpackComposites', unpackComposites)
2957 path.add_module(printMask)
2960def buildContinuumSuppression(list_name, roe_mask, ipprofile_fit=False, path=None):
2962 Creates for each Particle in the given ParticleList a ContinuumSuppression
2963 dataobject and makes basf2 relation between them.
2965 :param list_name: name of the input ParticleList
2966 :param roe_mask: name of the ROE mask
2967 :param ipprofile_fit: turn on vertex fit of input tracks with IP profile constraint
2968 :param path: modules are added to this path
2971 qqBuilder = register_module(
'ContinuumSuppressionBuilder')
2972 qqBuilder.set_name(
'QQBuilder_' + list_name)
2973 qqBuilder.param(
'particleList', list_name)
2974 qqBuilder.param(
'ROEMask', roe_mask)
2975 qqBuilder.param(
'performIPProfileFit', ipprofile_fit)
2976 path.add_module(qqBuilder)
2979def removeParticlesNotInLists(lists_to_keep, path):
2981 Removes all Particles that are not in a given list of ParticleLists (or daughters of those).
2982 All relations from/to Particles, daughter indices, and other ParticleLists are fixed.
2984 @param lists_to_keep Keep the Particles and their daughters in these ParticleLists.
2985 @param path modules are added to this path
2988 mod = register_module(
'RemoveParticlesNotInLists')
2989 mod.param(
'particleLists', lists_to_keep)
2990 path.add_module(mod)
2993def inclusiveBtagReconstruction(upsilon_list_name, bsig_list_name, btag_list_name, input_lists_names, path):
2995 Reconstructs Btag from particles in given ParticleLists which do not share any final state particles (mdstSource) with Bsig.
2997 @param upsilon_list_name Name of the ParticleList to be filled with 'Upsilon(4S) -> B:sig anti-B:tag'
2998 @param bsig_list_name Name of the Bsig ParticleList
2999 @param btag_list_name Name of the Bsig ParticleList
3000 @param input_lists_names List of names of the ParticleLists which are used to reconstruct Btag from
3003 btag = register_module(
'InclusiveBtagReconstruction')
3004 btag.set_name(
'InclusiveBtagReconstruction_' + bsig_list_name)
3005 btag.param(
'upsilonListName', upsilon_list_name)
3006 btag.param(
'bsigListName', bsig_list_name)
3007 btag.param(
'btagListName', btag_list_name)
3008 btag.param(
'inputListsNames', input_lists_names)
3009 path.add_module(btag)
3012def selectDaughters(particle_list_name, decay_string, path):
3014 Redefine the Daughters of a particle: select from decayString
3016 @param particle_list_name input particle list
3017 @param decay_string for selecting the Daughters to be preserved
3020 seld = register_module(
'SelectDaughters')
3021 seld.set_name(
'SelectDaughters_' + particle_list_name)
3022 seld.param(
'listName', particle_list_name)
3023 seld.param(
'decayString', decay_string)
3024 path.add_module(seld)
3027def markDuplicate(particleList, prioritiseV0, path):
3029 Call DuplicateVertexMarker to find duplicate particles in a list and
3030 flag the ones that should be kept
3032 @param particleList input particle list
3033 @param prioritiseV0 if true, give V0s a higher priority
3036 markdup = register_module(
'DuplicateVertexMarker')
3037 markdup.param(
'particleList', particleList)
3038 markdup.param(
'prioritiseV0', prioritiseV0)
3039 path.add_module(markdup)
3042PI0ETAVETO_COUNTER = 0
3045def oldwritePi0EtaVeto(
3048 workingDirectory='.',
3049 pi0vetoname='Pi0_Prob',
3050 etavetoname='Eta_Prob',
3056 Give pi0/eta probability for hard photon.
3058 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.
3060 The current default weight files are optimised using MC9.
3061 The input variables are as below. Aliases are set to some variables during training.
3063 * M: pi0/eta candidates Invariant mass
3064 * lowE: soft photon energy in lab frame
3065 * cTheta: soft photon ECL cluster's polar angle
3066 * Zmva: soft photon output of MVA using Zernike moments of the cluster
3067 * minC2Hdist: soft photon distance from eclCluster to nearest point on nearest Helix at the ECL cylindrical radius
3069 If you don't have weight files in your workingDirectory,
3070 these files are downloaded from database to your workingDirectory automatically.
3071 Please refer to analysis/examples/tutorials/B2A306-B02RhoGamma-withPi0EtaVeto.py
3072 about how to use this function.
3075 Please don't use following ParticleList names elsewhere:
3077 ``gamma:HARDPHOTON``, ``pi0:PI0VETO``, ``eta:ETAVETO``,
3078 ``gamma:PI0SOFT + str(PI0ETAVETO_COUNTER)``, ``gamma:ETASOFT + str(PI0ETAVETO_COUNTER)``
3080 Please don't use ``lowE``, ``cTheta``, ``Zmva``, ``minC2Hdist`` as alias elsewhere.
3082 @param particleList The input ParticleList
3083 @param decayString specify Particle to be added to the ParticleList
3084 @param workingDirectory The weight file directory
3085 @param downloadFlag whether download default weight files or not
3086 @param pi0vetoname extraInfo name of pi0 probability
3087 @param etavetoname extraInfo name of eta probability
3088 @param selection Selection criteria that Particle needs meet in order for for_each ROE path to continue
3089 @param path modules are added to this path
3094 B2ERROR(
"The old pi0 / eta veto is not suitable for Belle analyses.")
3099 global PI0ETAVETO_COUNTER
3101 if PI0ETAVETO_COUNTER == 0:
3102 from variables
import variables
3103 variables.addAlias(
'lowE',
'daughter(1,E)')
3104 variables.addAlias(
'cTheta',
'daughter(1,clusterTheta)')
3105 variables.addAlias(
'Zmva',
'daughter(1,clusterZernikeMVA)')
3106 variables.addAlias(
'minC2Tdist',
'daughter(1,minC2TDist)')
3107 variables.addAlias(
'cluNHits',
'daughter(1,clusterNHits)')
3108 variables.addAlias(
'E9E21',
'daughter(1,clusterE9E21)')
3110 PI0ETAVETO_COUNTER = PI0ETAVETO_COUNTER + 1
3112 roe_path = create_path()
3114 deadEndPath = create_path()
3116 signalSideParticleFilter(particleList, selection, roe_path, deadEndPath)
3118 fillSignalSideParticleList(
'gamma:HARDPHOTON', decayString, path=roe_path)
3120 pi0softname =
'gamma:PI0SOFT'
3121 etasoftname =
'gamma:ETASOFT'
3122 softphoton1 = pi0softname + str(PI0ETAVETO_COUNTER)
3123 softphoton2 = etasoftname + str(PI0ETAVETO_COUNTER)
3127 '[clusterReg==1 and E>0.025] or [clusterReg==2 and E>0.02] or [clusterReg==3 and E>0.02]',
3129 applyCuts(softphoton1,
'abs(clusterTiming)<120', path=roe_path)
3132 '[clusterReg==1 and E>0.035] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.03]',
3134 applyCuts(softphoton2,
'abs(clusterTiming)<120', path=roe_path)
3136 reconstructDecay(
'pi0:PI0VETO -> gamma:HARDPHOTON ' + softphoton1,
'', path=roe_path)
3137 reconstructDecay(
'eta:ETAVETO -> gamma:HARDPHOTON ' + softphoton2,
'', path=roe_path)
3139 if not os.path.isdir(workingDirectory):
3140 os.mkdir(workingDirectory)
3141 B2INFO(
'oldwritePi0EtaVeto: ' + workingDirectory +
' has been created as workingDirectory.')
3143 if not os.path.isfile(workingDirectory +
'/pi0veto.root'):
3145 basf2_mva.download(
'Pi0VetoIdentifier', workingDirectory +
'/pi0veto.root')
3146 B2INFO(
'oldwritePi0EtaVeto: pi0veto.root has been downloaded from database to workingDirectory.')
3148 if not os.path.isfile(workingDirectory +
'/etaveto.root'):
3150 basf2_mva.download(
'EtaVetoIdentifier', workingDirectory +
'/etaveto.root')
3151 B2INFO(
'oldwritePi0EtaVeto: etaveto.root has been downloaded from database to workingDirectory.')
3153 roe_path.add_module(
'MVAExpert', listNames=[
'pi0:PI0VETO'], extraInfoName=
'Pi0Veto',
3154 identifier=workingDirectory +
'/pi0veto.root')
3155 roe_path.add_module(
'MVAExpert', listNames=[
'eta:ETAVETO'], extraInfoName=
'EtaVeto',
3156 identifier=workingDirectory +
'/etaveto.root')
3158 rankByHighest(
'pi0:PI0VETO',
'extraInfo(Pi0Veto)', numBest=1, path=roe_path)
3159 rankByHighest(
'eta:ETAVETO',
'extraInfo(EtaVeto)', numBest=1, path=roe_path)
3161 variableToSignalSideExtraInfo(
'pi0:PI0VETO', {
'extraInfo(Pi0Veto)': pi0vetoname}, path=roe_path)
3162 variableToSignalSideExtraInfo(
'eta:ETAVETO', {
'extraInfo(EtaVeto)': etavetoname}, path=roe_path)
3164 path.for_each(
'RestOfEvent',
'RestOfEvents', roe_path)
3170 mode='standardMC16rd',
3174 hardParticle='gamma',
3175 pi0PayloadNameOverride=None,
3176 pi0SoftPhotonCutOverride=None,
3177 etaPayloadNameOverride=None,
3178 etaSoftPhotonCutOverride=None,
3179 requireSoftPhotonIsInROE=False,
3184 Give pi0/eta probability for hard photon.
3186 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.
3187 For MC15rd/MC16rd weight files, the BtoXGamma skim is applied during the MVA training.
3189 The current default weight files are for MC16rd. The weight files for MC15rd/MC12 are still available.
3191 The input variables of the mva training for pi0 veto using MC16rd are:
3193 * M: Invariant mass of pi0 candidates
3194 * cosHelicityAngleMomentum: Cosine of angle between momentum difference of the photons in the pi0 rest frame
3195 and momentum of pi0 in lab frame
3196 * daughter(1,E): soft photon energy in lab frame
3197 * daughter(1,clusterTheta): soft photon ECL cluster's polar angle
3198 * daughter(1,clusterLAT): soft photon lateral energy distribution
3199 * daughter(1,beamBackgroundSuppression): soft photon beam background suppression MVA output
3200 * daughter(1,fakePhotonSuppression): soft photon fake photon suppression MVA output
3202 The input variables of the mva training for eta veto using MC16rd are:
3204 * M: Invariant mass of eta candidates
3205 * cosHelicityAngleMomentum: Cosine of angle between momentum difference of the photons in the eta rest frame
3206 and momentum of eta in lab frame
3207 * daughter(1,E): soft photon energy in lab frame
3208 * daughter(1,clusterTheta): soft photon ECL cluster's polar angle
3209 * daughter(1,clusterLAT): soft photon lateral energy distribution
3210 * daughter(1,clusterNHits): soft photon total crystal weights sum(w_i) with w_i<=1
3211 * daughter(1,clusterE1E9): soft photon ratio between energies of central crystal and inner 3x3 crystals
3212 * daughter(1,clusterE9E21): soft photon ratio of energies in inner 3x3 crystals and 5x5 crystals without corners
3213 * daughter(1,clusterSecondMoment): soft photon second moment
3214 * daughter(1,clusterAbsZernikeMoment40): soft photon Zernike moment 40
3215 * daughter(1,clusterAbsZernikeMoment51): soft photon Zernike moment 51
3216 * daughter(1,beamBackgroundSuppression): soft photon beam background suppression MVA output
3217 * daughter(1,fakePhotonSuppression): soft photon fake photon suppression MVA output
3220 The input variables of the mva training for pi0 veto using MC15rd are:
3222 * M: Invariant mass of pi0 candidates
3223 * cosHelicityAngleMomentum: Cosine of angle between momentum difference of the photons in the pi0 rest frame
3224 and momentum of pi0 in lab frame
3225 * daughter(1,E): soft photon energy in lab frame
3226 * daughter(1,clusterTheta): soft photon ECL cluster's polar angle
3227 * daughter(1,clusterLAT): soft photon lateral energy distribution
3229 The input variables of the mva training for eta veto using MC15rd are:
3231 * M: Invariant mass of eta candidates
3232 * cosHelicityAngleMomentum: Cosine of angle between momentum difference of the photons in the eta rest frame
3233 and momentum of eta in lab frame
3234 * daughter(1,E): soft photon energy in lab frame
3235 * daughter(1,clusterTheta): soft photon ECL cluster's polar angle
3236 * daughter(1,clusterLAT): soft photon lateral energy distribution
3237 * daughter(1,clusterNHits): soft photon total crystal weights sum(w_i) with w_i<=1
3238 * daughter(1,clusterE1E9): soft photon ratio between energies of central crystal and inner 3x3 crystals
3239 * daughter(1,clusterE9E21): soft photon ratio of energies in inner 3x3 crystals and 5x5 crystals without corners
3240 * daughter(1,clusterSecondMoment): soft photon second moment
3241 * daughter(1,clusterAbsZernikeMoment40): soft photon Zernike moment 40
3242 * daughter(1,clusterAbsZernikeMoment51): soft photon Zernike moment 51
3244 The input variables of the mva training using MC12 are:
3246 * M: Invariant mass of pi0/eta candidates
3247 * daughter(1,E): soft photon energy in lab frame
3248 * daughter(1,clusterTheta): soft photon ECL cluster's polar angle
3249 * daughter(1,minC2TDist): soft photon distance from eclCluster to nearest point on nearest Helix at the ECL cylindrical radius
3250 * daughter(1,clusterZernikeMVA): soft photon output of MVA using Zernike moments of the cluster
3251 * daughter(1,clusterNHits): soft photon total crystal weights sum(w_i) with w_i<=1
3252 * daughter(1,clusterE9E21): soft photon ratio of energies in inner 3x3 crystals and 5x5 crystals without corners
3253 * cosHelicityAngleMomentum: Cosine of angle between momentum difference of the photons in the pi0/eta rest frame
3254 and momentum of pi0/eta in lab frame
3256 The following strings are available for mode:
3258 * standard: loose energy cut and no clusterNHits cut are applied to soft photon
3259 * tight: tight energy cut and no clusterNHits cut are applied to soft photon
3260 * cluster: loose energy cut and clusterNHits cut are applied to soft photon
3261 * both: tight energy cut and clusterNHits cut are applied to soft photon
3262 * standardMC15rd: loose energy cut is applied to soft photon and the weight files are trained using MC15rd
3263 * tightMC15rd: tight energy cut is applied to soft photon and the weight files are trained using MC15rd
3264 * standardMC16rd: loose energy cut is applied to soft photon and the weight files are trained using MC16rd
3265 * tightMC16rd: tight energy cut is applied to soft photon and the weight files are trained using MC16rd
3267 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
3268 `pi0Prob`/`etaProb`. Otherwise, it is available as '{Pi0, Eta}ProbOrigin', '{Pi0, Eta}ProbTightEnergyThreshold', '{Pi0,
3269 Eta}ProbLargeClusterSize', '{Pi0, Eta}ProbTightEnergyThresholdAndLargeClusterSize', '{Pi0, Eta}ProbOriginMC15rd', or
3270 '{Pi0, Eta}ProbTightEnergyThresholdMC15rd' for the six modes described above, with the chosen suffix appended. If one would
3271 like to call this veto twice in one script, add suffix in the second time!
3272 The second highest probability of the pi0/eta veto also is stored as an extraInfo, with a prefix of 'second' to the previous
3273 ones, e.g. secondPi0ProbOrigin{suffix}. This can be used to do validation/systematics study.
3276 Please don't use following ParticleList names elsewhere:
3278 ``gamma:HardPhoton``,
3279 ``gamma:Pi0Soft + ListName + '_' + particleList.replace(':', '_')``,
3280 ``gamma:EtaSoft + ListName + '_' + particleList.replace(':', '_')``,
3281 ``pi0:EtaVeto + ListName``,
3282 ``eta:EtaVeto + ListName``
3284 @param particleList the input ParticleList
3285 @param decayString specify Particle to be added to the ParticleList
3286 @param mode choose one mode out of 'standardMC16rd', 'tightMC16rd', 'standardMC15rd', 'tightMC15rd',
3287 'standard', 'tight', 'cluster' and 'both'
3288 @param selection selection criteria that Particle needs meet in order for for_each ROE path to continue
3289 @param path modules are added to this path
3290 @param suffix optional suffix to be appended to the usual extraInfo name
3291 @param hardParticle particle name which is used to calculate the pi0/eta probability (default is gamma)
3292 @param pi0PayloadNameOverride specify the payload name of pi0 veto only if one wants to use non-default one. (default is None)
3293 @param pi0SoftPhotonCutOverride specify the soft photon selection criteria of pi0 veto only if one wants to use non-default one.
3295 @param etaPayloadNameOverride specify the payload name of eta veto only if one wants to use non-default one. (default is None)
3296 @param etaSoftPhotonCutOverride specify the soft photon selection criteria of eta veto only if one wants to use non-default one.
3298 @param requireSoftPhotonIsInROE specify if the soft photons used to build pi0 and eta candidates have to be in the current ROE
3299 or not. Default is False, i.e. all soft photons in the event are used.
3300 @param pi0Selection Selection for the pi0 reconstruction. Default is "".
3301 @param etaSelection Selection for the eta reconstruction. Default is "".
3306 B2ERROR(
"The pi0 / eta veto is not suitable for Belle analyses.")
3308 if (requireSoftPhotonIsInROE):
3309 B2WARNING(
"Requiring the soft photon to being in the ROE was not done for the MVA training. "
3310 "Please check the results carefully.")
3313 if (mode ==
'standardMC15rd' or mode ==
'tightMC15rd'):
3314 if (pi0Selection !=
'[0.03 < M < 0.23]' or etaSelection !=
'[0.25 < M < 0.75]'):
3317 if (pi0Selection !=
'' or etaSelection !=
''):
3321 "Selection criteria for the pi0 or the eta during reconstructDecay differ from those used during the MVA training. "
3322 "You may get NAN value. Please check the results carefully.")
3324 renameSuffix =
False
3326 for module
in path.modules():
3327 if module.type() ==
"SubEvent" and not renameSuffix:
3328 for subpath
in [p.values
for p
in module.available_params()
if p.name ==
"path"]:
3331 for submodule
in subpath.modules():
3332 if f
'{hardParticle}:HardPhoton{suffix}' in submodule.name():
3334 B2WARNING(
"Same extension already used in writePi0EtaVeto, append '_0'")
3338 roe_path = create_path()
3339 deadEndPath = create_path()
3340 signalSideParticleFilter(particleList, selection, roe_path, deadEndPath)
3341 fillSignalSideParticleList(f
'{hardParticle}:HardPhoton{suffix}', decayString, path=roe_path)
3343 dictListName = {
'standard':
'Origin',
3344 'tight':
'TightEnergyThreshold',
3345 'cluster':
'LargeClusterSize',
3346 'both':
'TightEnrgyThresholdAndLargeClusterSize',
3347 'standardMC15rd':
'OriginMC15rd',
3348 'tightMC15rd':
'TightEnergyThresholdMC15rd',
3349 'standardMC16rd':
'OriginMC16rd',
3350 'tightMC16rd':
'TightEnergyThresholdMC16rd'}
3352 dictPi0EnergyCut = {
3353 'standard':
'[[clusterReg==1 and E>0.025] or [clusterReg==2 and E>0.02] or [clusterReg==3 and E>0.02]]',
3354 'tight':
'[[clusterReg==1 and E>0.03] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.04]]',
3355 'cluster':
'[[clusterReg==1 and E>0.025] or [clusterReg==2 and E>0.02] or [clusterReg==3 and E>0.02]]',
3356 'both':
'[[clusterReg==1 and E>0.03] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.04]]',
3357 'standardMC15rd':
'[[clusterReg==1 and E>0.0225] or [clusterReg==2 and E>0.02] or [clusterReg==3 and E>0.02]]',
3358 'tightMC15rd':
'[[clusterReg==1 and E>0.03] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.04]]',
3359 'standardMC16rd':
'[[clusterReg==1 and E>0.0225] or [clusterReg==2 and E>0.02] or [clusterReg==3 and E>0.02]]',
3360 'tightMC16rd':
'[[clusterReg==1 and E>0.03] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.04]]'}
3362 dictEtaEnergyCut = {
3363 'standard':
'[[clusterReg==1 and E>0.035] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.03]]',
3364 'tight':
'[[clusterReg==1 and E>0.06] or [clusterReg==2 and E>0.06] or [clusterReg==3 and E>0.06]]',
3365 'cluster':
'[[clusterReg==1 and E>0.035] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.03]]',
3366 'both':
'[[clusterReg==1 and E>0.06] or [clusterReg==2 and E>0.06] or [clusterReg==3 and E>0.06]]',
3367 'standardMC15rd':
'[[clusterReg==1 and E>0.0225] or [clusterReg==2 and E>0.02] or [clusterReg==3 and E>0.02]]',
3368 'tightMC15rd':
'[[clusterReg==1 and E>0.03] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.04]]',
3369 'standardMC16rd':
'[[clusterReg==1 and E>0.0225] or [clusterReg==2 and E>0.02] or [clusterReg==3 and E>0.02]]',
3370 'tightMC16rd':
'[[clusterReg==1 and E>0.03] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.04]]'}
3372 dictNHitsTimingCut = {
'standard':
'clusterNHits >= 0 and abs(clusterTiming)<clusterErrorTiming',
3373 'tight':
'clusterNHits >= 0 and abs(clusterTiming)<clusterErrorTiming',
3374 'cluster':
'clusterNHits >= 2 and abs(clusterTiming)<clusterErrorTiming',
3375 'both':
'clusterNHits >= 2 and abs(clusterTiming)<clusterErrorTiming',
3376 'standardMC15rd':
'clusterNHits > 1.5 and abs(clusterTiming) < 200',
3377 'tightMC15rd':
'clusterNHits > 1.5 and abs(clusterTiming) < 200',
3378 'standardMC16rd':
'clusterNHits > 1.5 and abs(clusterTiming) < 200',
3379 'tightMC16rd':
'clusterNHits > 1.5 and abs(clusterTiming) < 200'}
3381 dictPi0PayloadName = {
'standard':
'Pi0VetoIdentifierStandard',
3382 'tight':
'Pi0VetoIdentifierWithHigherEnergyThreshold',
3383 'cluster':
'Pi0VetoIdentifierWithLargerClusterSize',
3384 'both':
'Pi0VetoIdentifierWithHigherEnergyThresholdAndLargerClusterSize',
3385 'standardMC15rd':
'Pi0VetoIdentifierStandardMC15rd',
3386 'tightMC15rd':
'Pi0VetoIdentifierWithHigherEnergyThresholdMC15rd',
3387 'standardMC16rd':
'Pi0VetoIdentifierStandardMC16rd',
3388 'tightMC16rd':
'Pi0VetoIdentifierWithHigherEnergyThresholdMC16rd'}
3390 dictEtaPayloadName = {
'standard':
'EtaVetoIdentifierStandard',
3391 'tight':
'EtaVetoIdentifierWithHigherEnergyThreshold',
3392 'cluster':
'EtaVetoIdentifierWithLargerClusterSize',
3393 'both':
'EtaVetoIdentifierWithHigherEnergyThresholdAndLargerClusterSize',
3394 'standardMC15rd':
'EtaVetoIdentifierStandardMC15rd',
3395 'tightMC15rd':
'EtaVetoIdentifierWithHigherEnergyThresholdMC15rd',
3396 'standardMC16rd':
'EtaVetoIdentifierStandardMC16rd',
3397 'tightMC16rd':
'EtaVetoIdentifierWithHigherEnergyThresholdMC16rd'}
3399 dictPi0ExtraInfoName = {
'standard':
'Pi0ProbOrigin',
3400 'tight':
'Pi0ProbTightEnergyThreshold',
3401 'cluster':
'Pi0ProbLargeClusterSize',
3402 'both':
'Pi0ProbTightEnergyThresholdAndLargeClusterSize',
3403 'standardMC15rd':
'Pi0ProbOriginMC15rd',
3404 'tightMC15rd':
'Pi0ProbTightEnergyThresholdMC15rd',
3405 'standardMC16rd':
'Pi0ProbOriginMC16rd',
3406 'tightMC16rd':
'Pi0ProbTightEnergyThresholdMC16rd'}
3408 dictEtaExtraInfoName = {
'standard':
'EtaProbOrigin',
3409 'tight':
'EtaProbTightEnergyThreshold',
3410 'cluster':
'EtaProbLargeClusterSize',
3411 'both':
'EtaProbTightEnergyThresholdAndLargeClusterSize',
3412 'standardMC15rd':
'EtaProbOriginMC15rd',
3413 'tightMC15rd':
'EtaProbTightEnergyThresholdMC15rd',
3414 'standardMC16rd':
'EtaProbOriginMC16rd',
3415 'tightMC16rd':
'EtaProbTightEnergyThresholdMC16rd'}
3417 ListName = dictListName[mode]
3418 Pi0EnergyCut = dictPi0EnergyCut[mode]
3419 EtaEnergyCut = dictEtaEnergyCut[mode]
3420 NHitsTimingCut = dictNHitsTimingCut[mode]
3421 Pi0PayloadName = dictPi0PayloadName[mode]
3422 EtaPayloadName = dictEtaPayloadName[mode]
3423 Pi0ExtraInfoName = dictPi0ExtraInfoName[mode]
3424 EtaExtraInfoName = dictEtaExtraInfoName[mode]
3427 if pi0PayloadNameOverride
is not None:
3428 Pi0PayloadName = pi0PayloadNameOverride
3429 B2WARNING(
"You're using personal weight files, be careful. ")
3430 if pi0SoftPhotonCutOverride
is None:
3431 Pi0SoftPhotonCut = Pi0EnergyCut +
' and ' + NHitsTimingCut
3433 Pi0SoftPhotonCut = pi0SoftPhotonCutOverride
3434 B2WARNING(
"You're applying personal cuts on the soft photon candidates, be careful. ")
3436 if requireSoftPhotonIsInROE:
3437 Pi0SoftPhotonCut +=
' and isInRestOfEvent==1'
3440 pi0soft = f
'gamma:Pi0Soft{suffix}' + ListName +
'_' + particleList.replace(
':',
'_')
3442 fillParticleList(pi0soft, Pi0SoftPhotonCut, path=roe_path)
3444 if 'MC16rd' in mode:
3445 getBeamBackgroundProbability(pi0soft, weight=
"MC16rd", path=roe_path)
3446 getFakePhotonProbability(pi0soft, weight=
"MC16rd", path=roe_path)
3448 reconstructDecay(
'pi0:Pi0Veto' + ListName + suffix + f
' -> {hardParticle}:HardPhoton{suffix} ' + pi0soft, pi0Selection,
3449 allowChargeViolation=
True, path=roe_path)
3451 roe_path.add_module(
'MVAExpert', listNames=[
'pi0:Pi0Veto' + ListName + suffix],
3452 extraInfoName=Pi0ExtraInfoName, identifier=Pi0PayloadName)
3455 'pi0:Pi0Veto' + ListName + suffix,
3456 'extraInfo(' + Pi0ExtraInfoName +
')',
3458 outputVariable=
"Pi0VetoRank",
3460 cutAndCopyList(outputListName=
'pi0:Pi0VetoFirst' + ListName + suffix,
3461 inputListName=
'pi0:Pi0Veto' + ListName + suffix,
3462 cut=
'extraInfo(Pi0VetoRank)==1',
3464 variableToSignalSideExtraInfo(
'pi0:Pi0VetoFirst' + ListName + suffix,
3465 {
'extraInfo(' + Pi0ExtraInfoName +
')': Pi0ExtraInfoName + suffix}, path=roe_path)
3466 variableToSignalSideExtraInfo(
'pi0:Pi0VetoFirst' + ListName + suffix,
3467 {
'daughter(1,E)':
'SoftGammaEinPi0' + suffix}, path=roe_path)
3469 cutAndCopyList(outputListName=
'pi0:Pi0VetoSecond' + ListName + suffix,
3470 inputListName=
'pi0:Pi0Veto' + ListName + suffix,
3471 cut=
'extraInfo(Pi0VetoRank)==2',
3473 variableToSignalSideExtraInfo(
'pi0:Pi0VetoSecond' + ListName + suffix,
3474 {
'extraInfo(' + Pi0ExtraInfoName +
')':
'second' + Pi0ExtraInfoName + suffix}, path=roe_path)
3475 variableToSignalSideExtraInfo(
'pi0:Pi0VetoSecond' + ListName + suffix,
3476 {
'daughter(1,E)':
'secondSoftGammaEinPi0' + suffix}, path=roe_path)
3479 if etaPayloadNameOverride
is not None:
3480 EtaPayloadName = etaPayloadNameOverride
3481 B2WARNING(
"You're using personal weight files, be careful. ")
3482 if etaSoftPhotonCutOverride
is None:
3483 EtaSoftPhotonCut = EtaEnergyCut +
' and ' + NHitsTimingCut
3485 EtaSoftPhotonCut = etaSoftPhotonCutOverride
3486 B2WARNING(
"You're applying personal cuts on the soft photon candidates, be careful. ")
3488 if requireSoftPhotonIsInROE:
3489 EtaSoftPhotonCut +=
' and isInRestOfEvent==1'
3491 etasoft = f
'gamma:EtaSoft{suffix}' + ListName +
'_' + particleList.replace(
':',
'_')
3492 fillParticleList(etasoft, EtaSoftPhotonCut, path=roe_path)
3494 if 'MC16rd' in mode:
3495 getBeamBackgroundProbability(etasoft, weight=
"MC16rd", path=roe_path)
3496 getFakePhotonProbability(etasoft, weight=
"MC16rd", path=roe_path)
3497 reconstructDecay(
'eta:EtaVeto' + ListName + suffix + f
' -> {hardParticle}:HardPhoton{suffix} ' + etasoft, etaSelection,
3498 allowChargeViolation=
True, path=roe_path)
3499 roe_path.add_module(
'MVAExpert', listNames=[
'eta:EtaVeto' + ListName + suffix],
3500 extraInfoName=EtaExtraInfoName, identifier=EtaPayloadName)
3502 'eta:EtaVeto' + ListName + suffix,
3503 'extraInfo(' + EtaExtraInfoName +
')',
3505 outputVariable=
"EtaVetoRank",
3507 cutAndCopyList(outputListName=
'eta:EtaVetoFirst' + ListName + suffix,
3508 inputListName=
'eta:EtaVeto' + ListName + suffix,
3509 cut=
'extraInfo(EtaVetoRank)==1',
3511 variableToSignalSideExtraInfo(
'eta:EtaVetoFirst' + ListName + suffix,
3512 {
'extraInfo(' + EtaExtraInfoName +
')': EtaExtraInfoName + suffix}, path=roe_path)
3513 variableToSignalSideExtraInfo(
'eta:EtaVetoFirst' + ListName + suffix,
3514 {
'daughter(1,E)':
'SoftGammaEinEta' + suffix}, path=roe_path)
3515 cutAndCopyList(outputListName=
'eta:EtaVetoSecond' + ListName + suffix,
3516 inputListName=
'eta:EtaVeto' + ListName + suffix,
3517 cut=
'extraInfo(EtaVetoRank)==2',
3519 variableToSignalSideExtraInfo(
'eta:EtaVetoSecond' + ListName + suffix,
3520 {
'extraInfo(' + EtaExtraInfoName +
')':
'second' + EtaExtraInfoName + suffix}, path=roe_path)
3521 variableToSignalSideExtraInfo(
'eta:EtaVetoSecond' + ListName + suffix,
3522 {
'daughter(1,E)':
'secondSoftGammaEinEta' + suffix}, path=roe_path)
3524 path.for_each(
'RestOfEvent',
'RestOfEvents', roe_path)
3527def lowEnergyPi0Identification(pi0List, gammaList, payloadNameSuffix,
3530 Calculate low-energy pi0 identification.
3531 The result is stored as ExtraInfo ``lowEnergyPi0Identification`` for
3535 pi0List (str): Pi0 list.
3537 gammaList (str): Gamma list. First, an energy cut E > 0.2 is applied to the photons from this list.
3538 Then, all possible combinations with a pi0 daughter photon are formed except the one
3539 corresponding to the reconstructed pi0.
3540 The maximum low-energy pi0 veto value is calculated for such photon pairs
3541 and used as one of the input variables for the identification classifier.
3543 payloadNameSuffix (str): Payload name suffix. The weight payloads are stored in the analysis global
3544 tag and have the following names:\n
3545 * ``'LowEnergyPi0Veto' + payloadNameSuffix``
3546 * ``'LowEnergyPi0Identification' + payloadNameSuffix``\n
3547 The possible suffixes are:\n
3548 * ``'Belle1'`` for Belle data.
3549 * ``'Belle2Release5'`` for Belle II release 5 data (MC14, proc12, buckets 16 - 25).
3550 * ``'Belle2Release6'`` for Belle II release 6 data (MC15, proc13, buckets 26 - 36).
3552 path (basf2.Path): Module path.
3556 gammaListVeto = f
'{gammaList}_pi0veto'
3557 cutAndCopyList(gammaListVeto, gammaList,
'E > 0.2', path=path)
3559 payload_name =
'LowEnergyPi0Veto' + payloadNameSuffix
3560 path.add_module(
'LowEnergyPi0VetoExpert', identifier=payload_name,
3561 VetoPi0Daughters=
True, GammaListName=gammaListVeto,
3563 payload_name =
'LowEnergyPi0Identification' + payloadNameSuffix
3564 path.add_module(
'LowEnergyPi0IdentificationExpert',
3565 identifier=payload_name, Pi0ListName=pi0List,
3569def getNeutralHadronGeomMatches(
3573 efficiencyCorrectionKl=0.83,
3574 efficiencyCorrectionNeutrons=1.0,
3577 For an ECL-based list, assign the mcdistanceKL and mcdistanceNeutron variables that correspond
3578 to the distance to the closest MC KL and neutron, respectively.
3579 @param particleLists the input ParticleLists, must be ECL-based lists (e.g. photons)
3580 @param addKL (default True) add distance to MC KL
3581 @param addNeutrons (default False) add distance to MC neutrons
3582 @param efficiencyCorrectionKl (default 0.83) apply overall efficiency correction
3583 @param efficiencyCorrectionNeutrons (default 1.0) apply overall efficiency correction
3584 @param path modules are added to this path
3586 from ROOT
import Belle2
3591 "NeutralHadronMatcher",
3592 particleLists=particleLists,
3593 mcPDGcode=Const.Klong.getPDGCode(),
3594 efficiencyCorrection=efficiencyCorrectionKl)
3597 "NeutralHadronMatcher",
3598 particleLists=particleLists,
3599 mcPDGcode=Const.neutron.getPDGCode(),
3600 efficiencyCorrection=efficiencyCorrectionNeutrons)
3603def getBeamBackgroundProbability(particleList, weight, path=None):
3605 Assign a probability to each ECL cluster as being signal like (1) compared to beam background like (0)
3606 @param particleList the input ParticleList, must be a photon list
3607 @param weight type of weight file to use
3608 @param path modules are added to this path
3613 B2WARNING(
"weight type must be 'Belle' for b2bii.")
3615 path.add_module(
'MVAExpert',
3616 listNames=particleList,
3617 extraInfoName=
'beamBackgroundSuppression',
3618 identifier=f
'BeamBackgroundMVA_{weight}')
3621def getFakePhotonProbability(particleList, weight, path=None):
3623 Assign a probability to each ECL cluster as being signal like (1) compared to fake photon like (0)
3624 @param particleList the input ParticleList, must be a photon list
3625 @param weight type of weight file to use
3626 @param path modules are added to this path
3631 B2WARNING(
"weight type must be 'Belle' for b2bii.")
3633 path.add_module(
'MVAExpert',
3634 listNames=particleList,
3635 extraInfoName=
'fakePhotonSuppression',
3636 identifier=f
'FakePhotonMVA_{weight}')
3639def buildEventKinematics(inputListNames=None, default_cleanup=True, custom_cuts=None,
3640 chargedPIDPriors=None, fillWithMostLikely=False, path=None):
3642 Calculates the global kinematics of the event (visible energy, missing momentum, missing mass...)
3643 using ParticleLists provided. If no ParticleList is provided, default ParticleLists are used
3644 (all track and all hits in ECL without associated track).
3646 The visible energy missing values are
3647 stored in a EventKinematics dataobject.
3649 @param inputListNames list of ParticleLists used to calculate the global event kinematics.
3650 If the list is empty, default ParticleLists pi+:evtkin and gamma:evtkin are filled.
3651 @param fillWithMostLikely if True, the module uses the most likely particle mass hypothesis for charged particles
3652 according to the PID likelihood and the option inputListNames will be ignored.
3653 @param chargedPIDPriors The prior PID fractions, that are used to regulate
3654 amount of certain charged particle species, should be a list of
3655 six floats if not None. The order of particle types is
3656 the following: [e-, mu-, pi-, K-, p+, d+]
3657 @param default_cleanup if True and either inputListNames empty or fillWithMostLikely True, default clean up cuts are applied
3658 @param custom_cuts tuple of selection cut strings of form (trackCuts, photonCuts), default is None,
3659 which would result in a standard predefined selection cuts
3660 @param path modules are added to this path
3663 if inputListNames
is None:
3665 trackCuts =
'pt > 0.1'
3666 trackCuts +=
' and thetaInCDCAcceptance'
3667 trackCuts +=
' and abs(dz) < 3'
3668 trackCuts +=
' and dr < 0.5'
3670 gammaCuts =
'E > 0.05'
3671 gammaCuts +=
' and thetaInCDCAcceptance'
3673 gammaCuts +=
' and abs(clusterTiming) < 200'
3674 if (custom_cuts
is not None):
3675 trackCuts, gammaCuts = custom_cuts
3677 if fillWithMostLikely:
3678 from stdCharged
import stdMostLikely
3679 stdMostLikely(chargedPIDPriors,
'_evtkin', path=path)
3680 inputListNames = [f
'{ptype}:mostlikely_evtkin' for ptype
in [
'K+',
'p+',
'e+',
'mu+',
'pi+']]
3682 copyList(
'gamma:evtkin',
'gamma:mdst', path=path)
3684 fillParticleList(
'gamma:evtkin',
'', path=path)
3685 inputListNames += [
'gamma:evtkin']
3687 B2INFO(
"Using default cleanup in EventKinematics module.")
3688 for ptype
in [
'K+',
'p+',
'e+',
'mu+',
'pi+']:
3689 applyCuts(f
'{ptype}:mostlikely_evtkin', trackCuts, path=path)
3690 applyCuts(
'gamma:evtkin', gammaCuts, path=path)
3692 B2INFO(
"No cleanup in EventKinematics module.")
3693 if not inputListNames:
3694 B2INFO(
"Creating particle lists pi+:evtkin and gamma:evtkin to get the global kinematics of the event.")
3695 fillParticleList(
'pi+:evtkin',
'', path=path)
3697 copyList(
'gamma:evtkin',
'gamma:mdst', path=path)
3699 fillParticleList(
'gamma:evtkin',
'', path=path)
3700 particleLists = [
'pi+:evtkin',
'gamma:evtkin']
3702 if (custom_cuts
is not None):
3703 B2INFO(
"Using default cleanup in EventKinematics module.")
3704 applyCuts(
'pi+:evtkin', trackCuts, path=path)
3705 applyCuts(
'gamma:evtkin', gammaCuts, path=path)
3707 B2INFO(
"No cleanup in EventKinematics module.")
3709 particleLists = inputListNames
3711 eventKinematicsModule = register_module(
'EventKinematics')
3712 eventKinematicsModule.set_name(
'EventKinematics_reco')
3713 eventKinematicsModule.param(
'particleLists', particleLists)
3714 path.add_module(eventKinematicsModule)
3717def buildEventKinematicsFromMC(inputListNames=None, selectionCut='', path=None):
3719 Calculates the global kinematics of the event (visible energy, missing momentum, missing mass...)
3720 using generated particles. If no ParticleList is provided, default generated ParticleLists are used.
3722 @param inputListNames list of ParticleLists used to calculate the global event kinematics.
3723 If the list is empty, default ParticleLists are filled.
3724 @param selectionCut optional selection cuts
3725 @param path Path to append the eventKinematics module to.
3728 if inputListNames
is None:
3730 if (len(inputListNames) == 0):
3734 types = [
'gamma',
'e+',
'mu+',
'pi+',
'K+',
'p+',
3737 fillParticleListFromMC(f
"{t}:evtkin_default_gen",
'mcPrimary > 0 and nDaughters == 0',
3738 True,
True, path=path)
3739 if (selectionCut !=
''):
3740 applyCuts(f
"{t}:evtkin_default_gen", selectionCut, path=path)
3741 inputListNames += [f
"{t}:evtkin_default_gen"]
3743 eventKinematicsModule = register_module(
'EventKinematics')
3744 eventKinematicsModule.set_name(
'EventKinematics_gen')
3745 eventKinematicsModule.param(
'particleLists', inputListNames)
3746 eventKinematicsModule.param(
'usingMC',
True)
3747 path.add_module(eventKinematicsModule)
3750def buildEventShape(inputListNames=None,
3751 default_cleanup=True,
3757 harmonicMoments=True,
3761 checkForDuplicates=False,
3764 Calculates the event-level shape quantities (thrust, sphericity, Fox-Wolfram moments...)
3765 using the particles in the lists provided by the user. If no particle list is provided,
3766 the function will internally create a list of good tracks and a list of good photons
3767 with (optionally) minimal quality cuts.
3770 The results of the calculation are then stored into the EventShapeContainer dataobject,
3771 and are accessible using the variables of the EventShape group.
3773 The user can switch the calculation of certain quantities on or off to save computing
3774 time. By default the calculation of the high-order moments (5-8) is turned off.
3775 Switching off an option will make the corresponding variables not available.
3778 The user can provide as many particle lists as needed, using also composite particles.
3779 In these cases, it is recommended to activate the checkForDuplicates flag since it
3780 will eliminate duplicates, e.g., if the same track is provided multiple times
3781 (either with different mass hypothesis or once as an independent particle and once
3782 as daughter of a composite particle). The first occurrence will be used in the
3783 calculations so the order in which the particle lists are given as well as within
3784 the particle lists matters.
3786 @param inputListNames List of ParticleLists used to calculate the
3787 event shape variables. If the list is empty the default
3788 particleLists pi+:evtshape and gamma:evtshape are filled.
3789 @param default_cleanup If True, applies standard cuts on pt and cosTheta when
3790 defining the internal lists. This option is ignored if the
3791 particleLists are provided by the user.
3792 @param custom_cuts tuple of selection cut strings of form (trackCuts, photonCuts), default is None,
3793 which would result in a standard predefined selection cuts
3794 @param path Path to append the eventShape modules to.
3795 @param thrust Enables the calculation of thrust-related quantities (CLEO
3796 cones, Harmonic moments, jets).
3797 @param collisionAxis Enables the calculation of the quantities related to the
3799 @param foxWolfram Enables the calculation of the Fox-Wolfram moments.
3800 @param harmonicMoments Enables the calculation of the Harmonic moments with respect
3801 to both the thrust axis and, if collisionAxis = True, the collision axis.
3802 @param allMoments If True, calculates also the FW and harmonic moments from order
3803 5 to 8 instead of the low-order ones only.
3804 @param cleoCones Enables the calculation of the CLEO cones with respect to both the thrust
3805 axis and, if collisionAxis = True, the collision axis.
3806 @param jets Enables the calculation of the hemisphere momenta and masses.
3807 Requires thrust = True.
3808 @param sphericity Enables the calculation of the sphericity-related quantities.
3809 @param checkForDuplicates Perform a check for duplicate particles before adding them. Regardless of the value of this option,
3810 it is recommended to consider sanitizing the lists you are passing to the function since this will
3811 speed up the processing.
3815 if inputListNames
is None:
3817 trackCuts =
'pt > 0.1'
3818 trackCuts +=
' and thetaInCDCAcceptance'
3819 trackCuts +=
' and abs(dz) < 3.0'
3820 trackCuts +=
' and dr < 0.5'
3822 gammaCuts =
'E > 0.05'
3823 gammaCuts +=
' and thetaInCDCAcceptance'
3825 gammaCuts +=
' and abs(clusterTiming) < 200'
3826 if (custom_cuts
is not None):
3827 trackCuts, gammaCuts = custom_cuts
3829 if not inputListNames:
3830 B2INFO(
"Creating particle lists pi+:evtshape and gamma:evtshape to get the event shape variables.")
3831 fillParticleList(
'pi+:evtshape',
'', path=path)
3833 copyList(
'gamma:evtshape',
'gamma:mdst', path=path)
3839 particleLists = [
'pi+:evtshape',
'gamma:evtshape']
3842 if (custom_cuts
is not None):
3843 B2INFO(
"Applying standard cuts")
3844 applyCuts(
'pi+:evtshape', trackCuts, path=path)
3846 applyCuts(
'gamma:evtshape', gammaCuts, path=path)
3848 B2WARNING(
"Creating the default lists with no cleanup.")
3850 particleLists = inputListNames
3852 eventShapeModule = register_module(
'EventShapeCalculator')
3853 eventShapeModule.set_name(
'EventShape')
3854 eventShapeModule.param(
'particleListNames', particleLists)
3855 eventShapeModule.param(
'enableAllMoments', allMoments)
3856 eventShapeModule.param(
'enableCleoCones', cleoCones)
3857 eventShapeModule.param(
'enableCollisionAxis', collisionAxis)
3858 eventShapeModule.param(
'enableFoxWolfram', foxWolfram)
3859 eventShapeModule.param(
'enableJets', jets)
3860 eventShapeModule.param(
'enableHarmonicMoments', harmonicMoments)
3861 eventShapeModule.param(
'enableSphericity', sphericity)
3862 eventShapeModule.param(
'enableThrust', thrust)
3863 eventShapeModule.param(
'checkForDuplicates', checkForDuplicates)
3865 path.add_module(eventShapeModule)
3868def labelTauPairMC(printDecayInfo=False, path=None, TauolaBelle=False, mapping_minus=None, mapping_plus=None):
3870 Search tau leptons into the MC information of the event. If confirms it's a generated tau pair decay,
3871 labels the decay generated of the positive and negative leptons using the ID of KKMC tau decay table.
3873 @param printDecayInfo: If true, prints ID and prong of each tau lepton in the event.
3874 @param path: module is added to this path
3875 @param TauolaBelle: if False, TauDecayMode is set. If True, TauDecayMarker is set.
3876 @param mapping_minus: if None, the map is the default one, else the path for the map is given by the user for tau-
3877 @param mapping_plus: if None, the map is the default one, else the path for the map is given by the user for tau+
3880 from basf2
import find_file
3886 m_printmode =
'default'
3888 if mapping_minus
is None:
3889 mp_file_minus = find_file(
'data/analysis/modules/TauDecayMode/map_tauminus.txt')
3891 mp_file_minus = mapping_minus
3893 if mapping_plus
is None:
3894 mp_file_plus = find_file(
'data/analysis/modules/TauDecayMode/map_tauplus.txt')
3896 mp_file_plus = mapping_plus
3898 path.add_module(
'TauDecayMode', printmode=m_printmode, file_minus=mp_file_minus, file_plus=mp_file_plus)
3901 tauDecayMarker = register_module(
'TauDecayMarker')
3902 tauDecayMarker.set_name(
'TauDecayMarker_')
3904 path.add_module(tauDecayMarker, printDecayInfo=printDecayInfo)
3907def tagCurlTracks(particleLists,
3917 The cut selector is not calibrated with Belle II data and should not be used without extensive study.
3919 Identifies curl tracks and tags them with extraInfo(isCurl=1) for later removal.
3920 For Belle data with a `b2bii` analysis the available cut based selection is described in `BN1079`_.
3922 .. _BN1079: https://belle.kek.jp/secured/belle_note/gn1079/bn1079.pdf
3925 The module loops over all particles in a given list with a transverse momentum below the pre-selection **ptCut**
3926 and assigns them to bundles based on the response of the chosen **selector** and the required minimum response set by the
3927 **responseCut**. Once all particles are assigned they are ranked by 25dr^2+dz^2. All but the lowest are tagged
3928 with extraInfo(isCurl=1) to allow for later removal by cutting the list or removing these from ROE as
3932 @param particleLists: list of particle lists to check for curls.
3933 @param mcTruth: bool flag to additionally assign particles with extraInfo(isTruthCurl) and
3934 extraInfo(truthBundleSize). To calculate these particles are assigned to bundles by their
3935 genParticleIndex then ranked and tagged as normal.
3936 @param responseCut: float min classifier response that considers two tracks to come from the same particle.
3937 If set to ``-1`` a cut value optimised to maximise the accuracy on a BBbar sample is used.
3938 Note 'cut' selector is binary 0/1.
3939 @param selectorType: string name of selector to use. The available options are 'cut' and 'mva'.
3940 It is strongly recommended to used the 'mva' selection. The 'cut' selection
3941 is based on BN1079 and is only calibrated for Belle data.
3943 @param ptCut: Pre-selection cut on transverse momentum. Only tracks below that are considered as curler candidates.
3945 @param expert_train: flag to set training mode if selector has a training mode (mva).
3946 @param expert_filename: set file name of produced training ntuple (mva).
3947 @param path: module is added to this path.
3953 if (
not isinstance(particleLists, list)):
3954 particleLists = [particleLists]
3956 curlTagger = register_module(
'CurlTagger')
3957 curlTagger.set_name(
'CurlTagger_')
3958 curlTagger.param(
'particleLists', particleLists)
3959 curlTagger.param(
'belle', belle)
3960 curlTagger.param(
'mcTruth', mcTruth)
3961 curlTagger.param(
'responseCut', responseCut)
3962 if abs(responseCut + 1) < 1e-9:
3963 curlTagger.param(
'usePayloadCut',
True)
3965 curlTagger.param(
'usePayloadCut',
False)
3967 curlTagger.param(
'selectorType', selectorType)
3968 curlTagger.param(
'ptCut', ptCut)
3969 curlTagger.param(
'train', expert_train)
3970 curlTagger.param(
'trainFilename', expert_filename)
3972 path.add_module(curlTagger)
3975def applyChargedPidMVA(particleLists, path, trainingMode, chargeIndependent=False, binaryHypoPDGCodes=(0, 0)):
3977 Use an MVA to perform particle identification for charged stable particles, using the `ChargedPidMVA` module.
3979 The module decorates Particle objects in the input ParticleList(s) with variables
3980 containing the appropriate MVA score, which can be used to select candidates by placing a cut on it.
3983 The MVA algorithm used is a gradient boosted decision tree (**TMVA 4.3.0**, **ROOT 6.20/04**).
3985 The module can perform either 'binary' PID between input S, B particle mass hypotheses according to the following scheme:
3987 * e (11) vs. pi (211)
3988 * mu (13) vs. pi (211)
3989 * pi (211) vs. K (321)
3990 * K (321) vs. pi (211)
3992 , or 'global' PID, namely "one-vs-others" separation. The latter exploits an MVA algorithm trained in multi-class mode,
3993 and it's the default behaviour. Currently, the multi-class training separates the following standard charged hypotheses:
3995 - e (11), mu (13), pi (211), K (321)
3998 In order to run the `ChargedPidMVA` and ensure the most up-to-date MVA training weights are applied,
3999 it is necessary to append the latest analysis global tag (GT) to the steering script.
4002 particleLists (list(str)): the input list of DecayStrings, where each selected (^) daughter should correspond to a
4003 standard charged ParticleList, e.g. ``['Lambda0:sig -> ^p+ ^pi-', 'J/psi:sig -> ^mu+ ^mu-']``.
4004 One can also directly pass a list of standard charged ParticleLists,
4005 e.g. ``['e+:my_electrons', 'pi+:my_pions']``.
4006 Note that charge-conjugated ParticleLists will automatically be included.
4007 path (basf2.Path): the module is added to this path.
4008 trainingMode (``Belle2.ChargedPidMVAWeights.ChargedPidMVATrainingMode``): enum identifier of the training mode.
4009 Needed to pick up the correct payload from the DB. Available choices:
4011 * c_Classification=0
4013 * c_ECL_Classification=2
4014 * c_ECL_Multiclass=3
4015 * c_PSD_Classification=4
4016 * c_PSD_Multiclass=5
4017 * c_ECL_PSD_Classification=6
4018 * c_ECL_PSD_Multiclass=7
4020 chargeIndependent (bool, ``optional``): use a BDT trained on a sample of inclusively charged particles.
4021 binaryHypoPDGCodes (tuple(int, int), ``optional``): the pdgIds of the signal, background mass hypothesis.
4022 Required only for binary PID mode.
4027 B2ERROR(
"Charged PID via MVA is not available for Belle data.")
4029 from ROOT
import Belle2
4031 TrainingMode = Belle2.ChargedPidMVAWeights.ChargedPidMVATrainingMode
4034 plSet = set(particleLists)
4038 TrainingMode.c_Classification:
4039 {
"mode":
"Classification",
"detector":
"ALL"},
4040 TrainingMode.c_Multiclass:
4041 {
"mode":
"Multiclass",
"detector":
"ALL"},
4042 TrainingMode.c_ECL_Classification:
4043 {
"mode":
"ECL_Classification",
"detector":
"ECL"},
4044 TrainingMode.c_ECL_Multiclass:
4045 {
"mode":
"ECL_Multiclass",
"detector":
"ECL"},
4046 TrainingMode.c_PSD_Classification:
4047 {
"mode":
"PSD_Classification",
"detector":
"ALL"},
4048 TrainingMode.c_PSD_Multiclass:
4049 {
"mode":
"PSD_Multiclass",
"detector":
"ALL"},
4050 TrainingMode.c_ECL_PSD_Classification:
4051 {
"mode":
"ECL_PSD_Classification",
"detector":
"ECL"},
4052 TrainingMode.c_ECL_PSD_Multiclass:
4053 {
"mode":
"ECL_PSD_Multiclass",
"detector":
"ECL"},
4056 if payloadNames.get(trainingMode)
is None:
4057 B2FATAL(
"The chosen training mode integer identifier:\n", trainingMode,
4058 "\nis not supported. Please choose among the following:\n",
4059 "\n".join(f
"{key}:{val.get('mode')}" for key, val
in sorted(payloadNames.items())))
4061 mode = payloadNames.get(trainingMode).get(
"mode")
4062 detector = payloadNames.get(trainingMode).get(
"detector")
4064 payloadName = f
"ChargedPidMVAWeights_{mode}"
4069 Const.electron.getPDGCode():
4070 {
"pName":
"e",
"pFullName":
"electron",
"pNameBkg":
"pi",
"pdgIdBkg": Const.pion.getPDGCode()},
4071 Const.muon.getPDGCode():
4072 {
"pName":
"mu",
"pFullName":
"muon",
"pNameBkg":
"pi",
"pdgIdBkg": Const.pion.getPDGCode()},
4073 Const.pion.getPDGCode():
4074 {
"pName":
"pi",
"pFullName":
"pion",
"pNameBkg":
"K",
"pdgIdBkg": Const.kaon.getPDGCode()},
4075 Const.kaon.getPDGCode():
4076 {
"pName":
"K",
"pFullName":
"kaon",
"pNameBkg":
"pi",
"pdgIdBkg": Const.pion.getPDGCode()},
4077 Const.proton.getPDGCode():
4078 {
"pName":
"p",
"pFullName":
"proton",
"pNameBkg":
"pi",
"pdgIdBkg": Const.pion.getPDGCode()},
4079 Const.deuteron.getPDGCode():
4080 {
"pName":
"d",
"pFullName":
"deuteron",
"pNameBkg":
"pi",
"pdgIdBkg": Const.pion.getPDGCode()},
4083 if binaryHypoPDGCodes == (0, 0):
4086 chargedpid = register_module(
"ChargedPidMVAMulticlass")
4087 chargedpid.set_name(f
"ChargedPidMVAMulticlass_{mode}")
4094 binaryOpts = [(pdgIdSig, info[
"pdgIdBkg"])
for pdgIdSig, info
in stdChargedMap.items()]
4096 if binaryHypoPDGCodes
not in binaryOpts:
4097 B2FATAL(
"No charged pid MVA was trained to separate ", binaryHypoPDGCodes[0],
" vs. ", binaryHypoPDGCodes[1],
4098 ". Please choose among the following pairs:\n",
4099 "\n".join(f
"{opt[0]} vs. {opt[1]}" for opt
in binaryOpts))
4103 if not decayDescriptor.init(name):
4104 raise ValueError(f
"Invalid particle list {name} in applyChargedPidMVA!")
4105 msg = f
"Input ParticleList: {name}"
4106 pdgs = [abs(decayDescriptor.getMother().getPDGCode())]
4107 daughter_pdgs = decayDescriptor.getSelectionPDGCodes()
4108 if len(daughter_pdgs) > 0:
4109 pdgs = daughter_pdgs
4110 for idaughter, pdg
in enumerate(pdgs):
4111 if abs(pdg)
not in binaryHypoPDGCodes:
4113 msg = f
"Selected daughter {idaughter} in ParticleList: {name}"
4115 f
"{msg} (PDG={pdg}) is neither signal ({binaryHypoPDGCodes[0]}) nor background ({binaryHypoPDGCodes[1]}).")
4117 chargedpid = register_module(
"ChargedPidMVA")
4118 chargedpid.set_name(f
"ChargedPidMVA_{binaryHypoPDGCodes[0]}_vs_{binaryHypoPDGCodes[1]}_{mode}")
4119 chargedpid.param(
"sigHypoPDGCode", binaryHypoPDGCodes[0])
4120 chargedpid.param(
"bkgHypoPDGCode", binaryHypoPDGCodes[1])
4122 chargedpid.param(
"particleLists", list(plSet))
4123 chargedpid.param(
"payloadName", payloadName)
4124 chargedpid.param(
"chargeIndependent", chargeIndependent)
4127 if detector ==
"ECL":
4128 chargedpid.param(
"useECLOnlyTraining",
True)
4130 path.add_module(chargedpid)
4133def calculateTrackIsolation(
4137 reference_list_name=None,
4138 vars_for_nearest_part=[],
4139 highest_prob_mass_for_ext=True,
4140 exclude_pid_det_weights=False):
4142 Given an input decay string, compute variables that quantify track helix-based isolation of the charged
4143 stable particles in the input decay chain.
4146 An "isolation score" can be defined using the distance
4147 of each particle to its closest neighbour, defined as the segment connecting the two
4148 extrapolated track helices intersection points on a given cylindrical surface.
4149 The distance variables defined in the `VariableManager` is named `minET2ETDist`,
4150 the isolation scores are named `minET2ETIsoScore`, `minET2ETIsoScoreAsWeightedAvg`.
4152 The definition of distance and the number of distances that are calculated per sub-detector is based on
4153 the following recipe:
4155 * **CDC**: as the segmentation is very coarse along :math:`z`,
4156 the distance is defined as the cord length on the :math:`(\\rho=R, \\phi)` plane.
4157 A total of 9 distances are calculated: the cylindrical surfaces are defined at radiuses
4158 that correspond to the positions of the 9 CDC wire superlayers: :math:`R_{i}^{\\mathrm{CDC}}~(i \\in \\{0,...,8\\})`.
4160 * **TOP**: as there is no segmentation along :math:`z`,
4161 the distance is defined as the cord length on the :math:`(\\rho=R, \\phi)` plane.
4162 Only one distance at the TOP entry radius :math:`R_{0}^{\\mathrm{TOP}}` is calculated.
4164 * **ARICH**: as there is no segmentation along :math:`z`,
4165 the distance is defined as the distance on the :math:`(\\rho=R, \\phi)` plane at fixed :math:`z=Z`.
4166 Only one distance at the ARICH photon detector entry coordinate :math:`Z_{0}^{\\mathrm{ARICH}}` is calculated.
4168 * **ECL**: the distance is defined on the :math:`(\\rho=R, \\phi, z)` surface in the barrel,
4169 on the :math:`(\\rho, \\phi, z=Z)` surface in the endcaps.
4170 Two distances are calculated: one at the ECL entry surface :math:`R_{0}^{\\mathrm{ECL}}` (barrel),
4171 :math:`Z_{0}^{\\mathrm{ECL}}` (endcaps), and one at :math:`R_{1}^{\\mathrm{ECL}}` (barrel),
4172 :math:`Z_{1}^{\\mathrm{ECL}}` (endcaps), corresponding roughly to the mid-point
4173 of the longitudinal size of the crystals.
4175 * **KLM**: the distance is defined on the :math:`(\\rho=R, \\phi, z)` surface in the barrel,
4176 on the :math:`(\\rho, \\phi, z=Z)` surface in the endcaps.
4177 Only one distance at the KLM first strip entry surface :math:`R_{0}^{\\mathrm{KLM}}` (barrel),
4178 :math:`Z_{0}^{\\mathrm{KLM}}` (endcaps) is calculated.
4181 decay_string (str): name of the input decay string with selected charged stable daughters,
4182 for example: ``Lambda0:merged -> ^p+ ^pi-``.
4183 Alternatively, it can be a particle list for charged stable particles
4184 as defined in ``Const::chargedStableSet``, for example: ``mu+:all``.
4185 The charge-conjugate particle list will be also processed automatically.
4186 path (basf2.Path): path to which module(s) will be added.
4187 *detectors: detectors for which track isolation variables will be calculated.
4188 Choose among: ``{'CDC', 'TOP', 'ARICH', 'ECL', 'KLM'}``.
4189 reference_list_name (Optional[str]): name of the input charged stable particle list for the reference tracks.
4190 By default, the ``:all`` ParticleList of the same type
4191 of the selected particle in ``decay_string`` is used.
4192 The charge-conjugate particle list will be also processed automatically.
4193 vars_for_nearest_part (Optional[list(str)]): a list of variables to calculate for the nearest particle in the reference
4194 list at each detector surface. It uses the metavariable `minET2ETDistVar`.
4195 If unset, only the distances to the nearest neighbour
4196 per detector are calculated.
4197 highest_prob_mass_for_hex (Optional[bool]): if this option is set to True (default), the helix extrapolation
4198 for the particles will use the track fit result for the most
4199 probable mass hypothesis, namely, the one that gives the highest
4200 chi2Prob of the fit. Otherwise, it uses the mass hypothesis that
4201 corresponds to the particle lists PDG.
4202 exclude_pid_det_weights (Optional[bool]): if this option is set to False (default), the isolation score
4203 calculation will take into account the weight that each detector has on the PID
4204 for the particle species of interest.
4207 dict(int, list(str)): a dictionary mapping the PDG of each reference particle list to its isolation variables.
4212 from ROOT
import Belle2, TDatabasePDG
4215 if not decayDescriptor.init(decay_string):
4216 B2FATAL(f
"Invalid particle list {decay_string} in calculateTrackIsolation!")
4217 no_reference_list_name =
not reference_list_name
4220 "CDC": list(range(9)),
4226 if any(d
not in det_and_layers
for d
in detectors):
4228 "Your input detector list: ",
4230 " contains an invalid choice. Please select among: ",
4232 det_and_layers.keys()))
4237 processed_decay_strings = []
4238 if select_symbol
in decay_string:
4239 splitted_ds = decay_string.split(select_symbol)
4240 for i
in range(decay_string.count(select_symbol)):
4241 tmp = list(splitted_ds)
4242 tmp.insert(i+1, select_symbol)
4243 processed_decay_strings += [
''.join(tmp)]
4245 processed_decay_strings += [decay_string]
4247 reference_lists_to_vars = {}
4249 for processed_dec
in processed_decay_strings:
4250 if no_reference_list_name:
4251 decayDescriptor.init(processed_dec)
4252 selected_daughter_pdgs = decayDescriptor.getSelectionPDGCodes()
4253 if len(selected_daughter_pdgs) > 0:
4254 reference_list_name = f
'{TDatabasePDG.Instance().GetParticle(abs(selected_daughter_pdgs[-1])).GetName()}:all'
4256 reference_list_name = f
'{processed_dec.split(":")[0]}:all'
4260 trackiso = path.add_module(
"TrackIsoCalculator",
4261 decayString=processed_dec,
4262 detectorNames=list(detectors),
4263 particleListReference=reference_list_name,
4264 useHighestProbMassForExt=highest_prob_mass_for_ext,
4265 excludePIDDetWeights=exclude_pid_det_weights)
4266 trackiso.set_name(f
"TrackIsoCalculator_{'_'.join(detectors)}_{processed_dec}_VS_{reference_list_name}")
4272 f
"minET2ETDist({d}, {d_layer}, {reference_list_name}, {int(highest_prob_mass_for_ext)})"
4273 for d
in detectors
for d_layer
in det_and_layers[d]]
4276 f
"minET2ETIsoScore({reference_list_name}, {int(highest_prob_mass_for_ext)}, {', '.join(detectors)})",
4277 f
"minET2ETIsoScoreAsWeightedAvg({reference_list_name}, {int(highest_prob_mass_for_ext)}, {', '.join(detectors)})",
4280 if vars_for_nearest_part:
4281 trackiso_vars.extend(
4283 f
"minET2ETDistVar({d}, {d_layer}, {reference_list_name}, {v})"
4284 for d
in detectors
for d_layer
in det_and_layers[d]
for v
in vars_for_nearest_part
4286 trackiso_vars.sort()
4288 reference_lists_to_vars[ref_pdg] = trackiso_vars
4290 return reference_lists_to_vars
4293def calculateDistance(list_name, decay_string, mode='vertextrack', path=None):
4295 Calculates distance between two vertices, distance of closest approach between a vertex and a track,\
4296 distance of closest approach between a vertex and btube. For track, this calculation ignores track curvature,\
4297 it's negligible for small distances.The user should use extraInfo(CalculatedDistance)\
4298 to get it. A full example steering file is at analysis/tests/test_DistanceCalculator.py
4301 .. code-block:: python
4303 from modularAnalysis import calculateDistance
4304 calculateDistance('list_name', 'decay_string', "mode", path=user_path)
4306 @param list_name name of the input ParticleList
4307 @param decay_string select particles between the distance of closest approach will be calculated
4308 @param mode Specifies how the distance is calculated
4309 vertextrack: calculate the distance of closest approach between a track and a\
4310 vertex, taking the first candidate as vertex, default
4311 trackvertex: calculate the distance of closest approach between a track and a\
4312 vertex, taking the first candidate as track
4313 2tracks: calculates the distance of closest approach between two tracks
4314 2vertices: calculates the distance between two vertices
4315 vertexbtube: calculates the distance of closest approach between a vertex and btube
4316 trackbtube: calculates the distance of closest approach between a track and btube
4317 @param path modules are added to this path
4321 dist_mod = register_module(
'DistanceCalculator')
4323 dist_mod.set_name(
'DistanceCalculator_' + list_name)
4324 dist_mod.param(
'listName', list_name)
4325 dist_mod.param(
'decayString', decay_string)
4326 dist_mod.param(
'mode', mode)
4327 path.add_module(dist_mod)
4330def addInclusiveDstarReconstruction(decayString, slowPionCut, DstarCut, path):
4332 Adds the InclusiveDstarReconstruction module to the given path.
4333 This module creates a D* particle list by estimating the D* four momenta
4334 from slow pions, specified by a given cut. The D* energy is approximated
4335 as E(D*) = m(D*)/(m(D*) - m(D)) * E(pi). The absolute value of the D*
4336 momentum is calculated using the D* PDG mass and the direction is collinear
4337 to the slow pion direction. The charge of the given pion list has to be consistent
4340 @param decayString Decay string, must be of form ``D* -> pi``
4341 @param slowPionCut Cut applied to the input pion list to identify slow pions
4342 @param DstarCut Cut applied to the output D* list
4343 @param path the module is added to this path
4346 incl_dstar = register_module(
"InclusiveDstarReconstruction")
4347 incl_dstar.param(
"decayString", decayString)
4348 incl_dstar.param(
"slowPionCut", slowPionCut)
4349 incl_dstar.param(
"DstarCut", DstarCut)
4350 path.add_module(incl_dstar)
4353def scaleError(outputListName, inputListName,
4354 scaleFactors=[1.149631, 1.085547, 1.151704, 1.096434, 1.086659],
4355 scaleFactorsNoPXD=[1.149631, 1.085547, 1.151704, 1.096434, 1.086659],
4356 d0Resolution=[0.00115328, 0.00134704],
4357 z0Resolution=[0.00124327, 0.0013272],
4362 This module creates a new charged particle list.
4363 The helix errors of the new particles are scaled by constant factors.
4364 Two sets of five scale factors are defined for tracks with and without a PXD hit.
4365 The scale factors are in order of (d0, phi0, omega, z0, tanlambda).
4366 For tracks with a PXD hit, in order to avoid severe underestimation of d0 and z0 errors,
4367 lower limits (best resolution) can be set in a momentum-dependent form.
4368 This module is supposed to be used only for TDCPV analysis and for low-momentum (0-3 GeV/c) tracks in BBbar events.
4369 Details will be documented in a Belle II note, BELLE2-NOTE-PH-2021-038.
4371 @param inputListName Name of input charged particle list to be scaled
4372 @param outputListName Name of output charged particle list with scaled error
4373 @param scaleFactors List of five constants to be multiplied to each of helix errors (for tracks with a PXD hit)
4374 @param scaleFactorsNoPXD List of five constants to be multiplied to each of helix errors (for tracks without a PXD hit)
4375 @param d0Resolution List of two parameters, (a [cm], b [cm/(GeV/c)]),
4376 defining d0 best resolution as sqrt{ a**2 + (b / (p*beta*sinTheta**1.5))**2 }
4377 @param z0Resolution List of two parameters, (a [cm], b [cm/(GeV/c)]),
4378 defining z0 best resolution as sqrt{ a**2 + (b / (p*beta*sinTheta**2.5))**2 }
4379 @param d0MomThr d0 best resolution is kept constant below this momentum
4380 @param z0MomThr z0 best resolution is kept constant below this momentum
4384 scale_error = register_module(
"HelixErrorScaler")
4385 scale_error.set_name(
'ScaleError_' + inputListName)
4386 scale_error.param(
'inputListName', inputListName)
4387 scale_error.param(
'outputListName', outputListName)
4388 scale_error.param(
'scaleFactors_PXD', scaleFactors)
4389 scale_error.param(
'scaleFactors_noPXD', scaleFactorsNoPXD)
4390 scale_error.param(
'd0ResolutionParameters', d0Resolution)
4391 scale_error.param(
'z0ResolutionParameters', z0Resolution)
4392 scale_error.param(
'd0MomentumThreshold', d0MomThr)
4393 scale_error.param(
'z0MomentumThreshold', z0MomThr)
4394 path.add_module(scale_error)
4397def estimateAndAttachTrackFitResult(inputListName, path=None):
4399 Create a TrackFitResult from the momentum of the Particle assuming it originates from the IP and make a relation between them.
4400 The covariance, detector hit information, and fit-related information (pValue, NDF) are assigned meaningless values. The input
4401 Particles must not have already Track or TrackFitResult and thus are supposed to be composite particles, recoil, dummy
4402 particles, and so on.
4405 .. warning:: Since the source type is not overwritten as Track, not all track-related variables are guaranteed to be available.
4408 @param inputListName Name of input ParticleList
4411 estimator = register_module(
"TrackFitResultEstimator")
4412 estimator.set_name(
"trackFitResultEstimator_" + inputListName)
4413 estimator.param(
"inputListName", inputListName)
4414 path.add_module(estimator)
4417def correctEnergyBias(inputListNames, tableName, path=None):
4419 Scale energy of the particles according to the scaling factor.
4420 If the particle list contains composite particles, the energy of the daughters are scaled.
4421 Subsequently, the energy of the mother particle is updated as well.
4424 inputListNames (list(str)): input particle list names
4425 tableName : stored in localdb and created using ParticleWeightingLookUpCreator
4426 path (basf2.Path): module is added to this path
4431 B2ERROR(
"The energy bias cannot be corrected with this tool for Belle data.")
4433 correctenergybias = register_module(
'EnergyBiasCorrection')
4434 correctenergybias.param(
'particleLists', inputListNames)
4435 correctenergybias.param(
'tableName', tableName)
4436 path.add_module(correctenergybias)
4439def twoBodyISRPhotonCorrector(outputListName, inputListName, massiveParticle, path=None):
4441 Sets photon kinematics to corrected values in two body decays with an ISR photon
4442 and a massive particle. The original photon kinematics are kept in the input
4443 particleList and can be accessed using the originalParticle() metavariable on the
4446 @param ouputListName new ParticleList filled with copied Particles
4447 @param inputListName input ParticleList with original Particles
4448 @param massiveParticle name or PDG code of massive particle participating in the two
4449 body decay with the ISR photon
4450 @param path modules are added to this path
4454 photon_energy_correction = register_module(
'TwoBodyISRPhotonCorrector')
4455 photon_energy_correction.set_name(
'TwoBodyISRPhotonCorrector_' + outputListName)
4456 photon_energy_correction.param(
'outputGammaList', outputListName)
4457 photon_energy_correction.param(
'inputGammaList', inputListName)
4460 if isinstance(massiveParticle, int):
4461 photon_energy_correction.param(
'massiveParticlePDGCode', massiveParticle)
4463 from ROOT
import Belle2
4465 if not decayDescriptor.init(massiveParticle):
4466 raise ValueError(
"TwoBodyISRPhotonCorrector: value of massiveParticle must be" +
4467 " an int or valid decay string.")
4468 pdgCode = decayDescriptor.getMother().getPDGCode()
4469 photon_energy_correction.param(
'massiveParticlePDGCode', pdgCode)
4471 path.add_module(photon_energy_correction)
4474def addPhotonEfficiencyRatioVariables(inputListNames, tableName, path=None):
4476 Add photon Data/MC detection efficiency ratio weights to the specified particle list
4479 inputListNames (list(str)): input particle list names
4480 tableName : taken from database with appropriate name
4481 path (basf2.Path): module is added to this path
4486 B2ERROR(
"For Belle data the photon data/MC detection efficiency ratio is not available with this tool.")
4488 photon_efficiency_correction = register_module(
'PhotonEfficiencySystematics')
4489 photon_efficiency_correction.param(
'particleLists', inputListNames)
4490 photon_efficiency_correction.param(
'tableName', tableName)
4491 path.add_module(photon_efficiency_correction)
4494def addPi0VetoEfficiencySystematics(particleList, decayString, tableName, threshold, mode='standard', suffix='', path=None):
4496 Add pi0 veto Data/MC efficiency ratio weights to the specified particle list
4498 @param particleList the input ParticleList
4499 @param decayString specify hard photon to be performed pi0 veto (e.g. 'B+:sig -> rho+:sig ^gamma:hard')
4500 @param tableName table name corresponding to payload version (e.g. 'Pi0VetoEfficiencySystematics_Mar2022')
4501 @param threshold pi0 veto threshold (0.10, 0.11, ..., 0.99)
4502 @param mode choose one mode (same as writePi0EtaVeto) out of 'standard', 'tight', 'cluster' and 'both'
4503 @param suffix optional suffix to be appended to the usual extraInfo name
4504 @param path the module is added to this path
4506 The following extraInfo are available related with the given particleList:
4508 * Pi0VetoEfficiencySystematics_{mode}{suffix}_data_MC_ratio : weight of Data/MC for the veto efficiency
4509 * Pi0VetoEfficiencySystematics_{mode}{suffix}_data_MC_uncertainty_stat : the statistical uncertainty of the weight
4510 * Pi0VetoEfficiencySystematics_{mode}{suffix}_data_MC_uncertainty_sys : the systematic uncertainty of the weight
4511 * Pi0VetoEfficiencySystematics_{mode}{suffix}_data_MC_uncertainty_total : the total uncertainty of the weight
4512 * Pi0VetoEfficiencySystematics_{mode}{suffix}_threshold : threshold of the pi0 veto
4517 B2ERROR(
"For Belle data the pi0 veto data/MC efficiency ratio weights are not available via this tool.")
4519 pi0veto_efficiency_correction = register_module(
'Pi0VetoEfficiencySystematics')
4520 pi0veto_efficiency_correction.param(
'particleLists', particleList)
4521 pi0veto_efficiency_correction.param(
'decayString', decayString)
4522 pi0veto_efficiency_correction.param(
'tableName', tableName)
4523 pi0veto_efficiency_correction.param(
'threshold', threshold)
4524 pi0veto_efficiency_correction.param(
'mode', mode)
4525 pi0veto_efficiency_correction.param(
'suffix', suffix)
4526 path.add_module(pi0veto_efficiency_correction)
4529def getAnalysisGlobaltag(timeout=180) -> str:
4531 Returns a string containing the name of the latest and recommended analysis globaltag.
4534 timeout: Seconds to wait for b2conditionsdb-recommend
4539 B2ERROR(
"The getAnalysisGlobaltag() function cannot be used for Belle data.")
4544 tags = subprocess.check_output(
4545 [
'b2conditionsdb-recommend',
'--oneline'],
4547 ).decode(
'UTF-8').rstrip().split(
' ')
4550 if tag.startswith(
'analysis_tools'):
4554 except subprocess.TimeoutExpired
as te:
4555 B2FATAL(f
'A {te} exception was raised during the call of getAnalysisGlobaltag(). '
4556 'The function took too much time to retrieve the requested information '
4557 'from the versioning repository.\n'
4558 'Please try to re-run your job. In case of persistent failures, there may '
4559 'be issues with the DESY collaborative services, so please contact the experts.')
4560 except subprocess.CalledProcessError
as ce:
4561 B2FATAL(f
'A {ce} exception was raised during the call of getAnalysisGlobaltag(). '
4562 'Please try to re-run your job. In case of persistent failures, please contact '
4566def getAnalysisGlobaltagB2BII() -> str:
4568 Get recommended global tag for B2BII analysis.
4573 B2ERROR(
'The getAnalysisGlobaltagB2BII() function cannot be used for Belle II data.')
4574 from versioning
import recommended_b2bii_analysis_global_tag
4575 return recommended_b2bii_analysis_global_tag()
4578def getECLKLID(particleList: str, variable=
'ECLKLID', path=
None):
4580 The function calculates the PID value for Klongs that are constructed from ECL cluster.
4582 @param particleList the input ParticleList
4583 @param variable the variable name for Klong ID
4584 @param path modules are added to this path
4590 B2ERROR(
"The ECL variables based Klong Identification is only available for Belle II data.")
4592 from variables
import variables
4593 path.add_module(
'MVAExpert', listNames=particleList, extraInfoName=
'ECLKLID', identifier=
'ECLKLID')
4595 variables.addAlias(variable,
'conditionalVariableSelector(isFromECL and PDG==130, extraInfo(ECLKLID), constant(NaN))')
4598def getNbarIDMVA(particleList: str, path=
None):
4600 This function can give a score to predict if it is a anti-n0.
4601 It is not used to predict n0.
4602 Currently, this can be used only for ECL cluster.
4603 output will be stored in extraInfo(nbarID); -1 means MVA invalid
4605 @param particleList The input ParticleList name or a decay string which contains a full mother particle list name.
4606 Only one selected daughter is supported.
4607 @param path modules are added to this path
4610 from ROOT
import Belle2
4613 B2ERROR(
"The MVA-based anti-neutron PID is only available for Belle II data.")
4615 from variables
import variables
4617 variables.addAlias(
'V1',
'clusterHasPulseShapeDiscrimination')
4618 variables.addAlias(
'V2',
'clusterE')
4619 variables.addAlias(
'V3',
'clusterLAT')
4620 variables.addAlias(
'V4',
'clusterE1E9')
4621 variables.addAlias(
'V5',
'clusterE9E21')
4622 variables.addAlias(
'V6',
'clusterZernikeMVA')
4623 variables.addAlias(
'V7',
'clusterAbsZernikeMoment40')
4624 variables.addAlias(
'V8',
'clusterAbsZernikeMoment51')
4628 'passesCut(V1 == 1 and V2 >= 0 and V3 >= 0 and V4 >= 0 and V5 >= 0 and V6 >= 0 and V7 >= 0 and V8 >= 0)')
4629 variables.addAlias(
'nbarIDmod',
'conditionalVariableSelector(nbarIDValid == 1, extraInfo(nbarIDFromMVA), constant(-1.0))')
4631 path.add_module(
'MVAExpert', listNames=particleList, extraInfoName=
'nbarIDFromMVA', identifier=
'db_nbarIDECL')
4633 if not decayDescriptor.init(particleList):
4634 raise ValueError(f
"Provided decay string is invalid: {particleList}")
4635 if decayDescriptor.getNDaughters() == 0:
4638 listname = decayDescriptor.getMother().getFullName()
4639 variablesToDaughterExtraInfo(listname, particleList, {
'nbarIDmod':
'nbarID'}, option=2, path=path)
4642def reconstructDecayWithNeutralHadron(decayString, cut, allowGamma=False, allowAnyParticleSource=False, path=None, **kwargs):
4644 Reconstructs decay with a long-lived neutral hadron e.g.
4645 :math:`B^0 \to J/\psi K_L^0`,
4646 :math:`B^0 \to p \bar{n} D^*(2010)^-`.
4648 The calculation is done with IP constraint and mother mass constraint.
4650 The decay string passed in must satisfy the following rules:
4652 - The neutral hadron must be **selected** in the decay string with the
4653 caret (``^``) e.g. ``B0:sig -> J/psi:sig ^K_L0:sig``. (Note the caret
4654 next to the neutral hadron.)
4655 - There can only be **one neutral hadron in a decay**.
4656 - The neutral hadron has to be a direct daughter of its mother.
4658 .. note:: This function forwards its arguments to `reconstructDecay`,
4659 so please check the documentation of `reconstructDecay` for all
4662 @param decayString A decay string following the mentioned rules
4663 @param cut Cut to apply to the particle list
4664 @param allowGamma Whether allow the selected particle to be ``gamma``
4665 @param allowAnyParticleSource Whether allow the selected particle to be from any source.
4666 Should only be used when studying control sample.
4667 @param path The path to put in the module
4670 reconstructDecay(decayString, cut, path=path, **kwargs)
4671 module = register_module(
'NeutralHadron4MomentumCalculator')
4672 module.set_name(
'NeutralHadron4MomentumCalculator_' + decayString)
4673 module.param(
'decayString', decayString)
4674 module.param(
'allowGamma', allowGamma)
4675 module.param(
'allowAnyParticleSource', allowAnyParticleSource)
4676 path.add_module(module)
4679def updateMassHypothesis(particleList, pdg, writeOut=False, path=None):
4681 Module to update the mass hypothesis of a given input particle list with the chosen PDG.
4682 A new particle list is created with updated mass hypothesis.
4683 The allowed mass hypotheses for both input and output are electrons, muons, pions, kaons and protons.
4686 The new particle list is named after the input one, with the additional suffix ``_converted_from_OLDHYPOTHESIS``,
4687 e.g. ``e+:all`` converted to muons becomes ``mu+:all_converted_from_e``.
4689 @param particleList The input particle list name
4690 @param pdg The PDG code for the new mass hypothesis, in [11, 13, 211, 321, 2212]
4691 @param writeOut Whether `RootOutput` module should save the new particle list
4692 @param path Modules are added to this path
4694 mass_updater = register_module(
"ParticleMassHypothesesUpdater")
4695 mass_updater.set_name(
"ParticleMassHypothesesUpdater_" + particleList +
"_to_" + str(pdg))
4696 mass_updater.param(
"particleList", particleList)
4697 mass_updater.param(
"writeOut", writeOut)
4698 mass_updater.param(
"pdgCode", pdg)
4699 path.add_module(mass_updater)
4702func_requiring_analysisGT = [
4703 correctTrackEnergy, scaleTrackMomenta, smearTrackMomenta, oldwritePi0EtaVeto, writePi0EtaVeto, lowEnergyPi0Identification,
4704 getBeamBackgroundProbability, getFakePhotonProbability, tagCurlTracks, applyChargedPidMVA, correctEnergyBias,
4705 addPhotonEfficiencyRatioVariables, addPi0VetoEfficiencySystematics, getNbarIDMVA, getECLKLID]
4706for _
in func_requiring_analysisGT:
4707 _.__doc__ +=
"\n .. note:: This function (optionally) requires a payload stored in the analysis GlobalTag. "\
4708 "Please append or prepend the latest one from `getAnalysisGlobaltag` or `getAnalysisGlobaltagB2BII`.\n"
4711if __name__ ==
'__main__':
4713 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)