12This module defines wrapper functions around the analysis modules.
16from basf2
import register_module, create_path
17from basf2
import B2INFO, B2WARNING, B2ERROR, B2FATAL
22def setAnalysisConfigParams(configParametersAndValues, path):
24 Sets analysis configuration parameters.
28 - 'tupleStyle':
'Default' (default)
or 'Laconic'
30 - defines the style of the branch name
in the ntuple
32 -
'mcMatchingVersion': Specifies what version of mc matching algorithm
is going to be used:
34 -
'Belle' - analysis of Belle MC
35 -
'BelleII' (default) - all other cases
37 @param configParametersAndValues dictionary of parameters
and their values of the form {param1: value, param2: value, ...)
38 @param modules are added to this path
41 conf = register_module('AnalysisConfiguration')
43 allParameters = [
'tupleStyle',
'mcMatchingVersion']
45 keys = configParametersAndValues.keys()
47 if key
not in allParameters:
48 allParametersString =
', '.join(allParameters)
49 B2ERROR(
'Invalid analysis configuration parameter: ' + key +
'.\n'
50 'Please use one of the following: ' + allParametersString)
52 for param
in allParameters:
53 if param
in configParametersAndValues:
54 conf.param(param, configParametersAndValues.get(param))
59def inputMdst(filename, path, environmentType='default', skipNEvents=0, entrySequence=None, *, parentLevel=0, **kwargs):
61 Loads the specified :ref:`mDST <mdst>` (or :ref:`uDST <analysis_udstoutput>`) file
with the RootInput module.
63 The correct environment (e.g. magnetic field settings)
is determined
from
64 ``environmentType``. Options are either:
'default' (
for Belle II MC
and
65 data: falls back to database),
'Belle':
for analysis of converted Belle 1
69 filename (str): the name of the file to be loaded
70 path (basf2.Path): modules are added to this path
71 environmentType (str): type of the environment to be loaded (either
'default' or 'Belle')
72 skipNEvents (int): N events of the input file are skipped
73 entrySequence (str): The number sequences (e.g. 23:42,101) defining the entries which are processed.
74 parentLevel (int): Number of generations of parent files (files used
as input when creating a file) to be read
78 if filename ==
'default':
80We have simplified the arguments to inputMdst! If you are running on Belle II
81data or MC, you don't have to use "default" any more.
83 inputMdst("default",
"/your/input/file.root", path=mypath)
85 inputMdst(
"/your/input/file.root", path=mypath)
87 elif filename ==
"Belle":
89We have reordered the arguments to inputMdst! If you are running on Belle 1
90data or MC, you need to specify the 'environmentType'.
92 inputMdst("Belle",
"/your/input/file.root", path=mypath)
94 inputMdst(
"/your/input/file.root", path=mypath, environmentType=
'Belle')
96 elif filename
in [f
"MC{i}" for i
in range(5, 10)]:
97 B2FATAL(f
"We no longer support the MC version {filename}. Sorry.")
99 if entrySequence
is not None:
100 entrySequence = [entrySequence]
102 inputMdstList([filename], path, environmentType, skipNEvents, entrySequence, parentLevel=parentLevel, **kwargs)
108 environmentType='default',
113 useB2BIIDBCache=True):
115 Loads the specified list of :ref:`mDST <mdst>` (or :ref:`uDST <analysis_udstoutput>`) files
with the RootInput module.
117 The correct environment (e.g. magnetic field settings)
is determined
from
118 ``environmentType``. Options are either:
'default' (
for Belle II MC
and
119 data: falls back to database),
'Belle':
for analysis of converted Belle 1
123 filelist (list(str)): the filename list of files to be loaded
124 path (basf2.Path): modules are added to this path
125 environmentType (str): type of the environment to be loaded (either
'default' or 'Belle')
126 skipNEvents (int): N events of the input files are skipped
127 entrySequences (list(str)): The number sequences (e.g. 23:42,101) defining
128 the entries which are processed
for each inputFileName.
129 parentLevel (int): Number of generations of parent files (files used
as input when creating a file) to be read
130 useB2BIIDBCache (bool): Loading of local KEKCC database (only to be deactivated
in very special cases)
134 if filelist ==
'default':
136We have simplified the arguments to inputMdstList! If you are running on
137Belle II data or MC, you don't have to use "default" any more.
139 inputMdstList("default", list_of_your_files, path=mypath)
141 inputMdstList(list_of_your_files, path=mypath)
143 elif filelist ==
"Belle":
145We have reordered the arguments to inputMdstList! If you are running on
146Belle 1 data or MC, you need to specify the 'environmentType'.
148 inputMdstList("Belle", list_of_your_files, path=mypath)
150 inputMdstList(list_of_your_files, path=mypath, environmentType=
'Belle')
152 elif filelist
in [f
"MC{i}" for i
in range(5, 10)]:
153 B2FATAL(f
"We no longer support the MC version {filelist}. Sorry.")
155 roinput = register_module(
'RootInput')
156 roinput.param(
'inputFileNames', filelist)
157 roinput.param(
'skipNEvents', skipNEvents)
158 if entrySequences
is not None:
159 roinput.param(
'entrySequences', entrySequences)
160 roinput.param(
'parentLevel', parentLevel)
162 path.add_module(roinput)
163 path.add_module(
'ProgressBar')
165 if environmentType ==
'Belle':
170 from ROOT
import Belle2
176 setAnalysisConfigParams({
'mcMatchingVersion':
'Belle'}, path)
179 basf2.conditions.metadata_providers = [
"/sw/belle/b2bii/database/conditions/b2bii.sqlite"]
180 basf2.conditions.payload_locations = [
"/sw/belle/b2bii/database/conditions/"]
183def outputMdst(filename, path):
185 Saves mDST (mini-Data Summary Tables) to the output root file.
189 This function is kept
for backward-compatibility.
190 Better to use `mdst.add_mdst_output` directly.
198def outputUdst(filename, particleLists=None, includeArrays=None, path=None, dataDescription=None):
200 Save uDST (user-defined Data Summary Tables) = MDST + Particles + ParticleLists
201 The charge-conjugate lists of those given in particleLists are also stored.
202 Additional Store Arrays
and Relations to be stored can be specified via includeArrays
206 This does
not reduce the amount of Particle objects saved,
207 see `udst.add_skimmed_udst_output`
for a function that does.
213 path=path, filename=filename, particleLists=particleLists,
214 additionalBranches=includeArrays, dataDescription=dataDescription)
217def outputIndex(filename, path, includeArrays=None, keepParents=False, mc=True):
219 Write out all particle lists as an index file to be reprocessed using parentLevel flag.
220 Additional branches necessary
for file to be read are automatically included.
221 Additional Store Arrays
and Relations to be stored can be specified via includeArrays
224 @param str filename the name of the output index file
225 @param str path modules are added to this path
226 @param list(str) includeArrays: datastore arrays/objects to write to the output
227 file
in addition to particle lists
and related information
228 @param bool keepParents whether the parents of the input event will be saved
as the parents of the same event
229 in the output index file. Useful
if you are only adding more information to another index file
230 @param bool mc whether the input data
is MC
or not
233 if includeArrays
is None:
237 onlyPLists = register_module(
'OnlyWriteOutParticleLists')
238 path.add_module(onlyPLists)
243 'ParticlesToMCParticles',
244 'ParticlesToPIDLikelihoods',
245 'ParticleExtraInfoMap',
248 branches = [
'EventMetaData']
249 persistentBranches = [
'FileMetaData']
253 branches += partBranches
254 branches += includeArrays
256 r1 = register_module(
'RootOutput')
257 r1.param(
'outputFileName', filename)
258 r1.param(
'additionalBranchNames', branches)
259 r1.param(
'branchNamesPersistent', persistentBranches)
260 r1.param(
'keepParents', keepParents)
264def setupEventInfo(noEvents, path):
266 Prepare to generate events. This function sets up the EventInfoSetter.
267 You should call this before adding a generator from generators.
268 The experiment
and run numbers are set to 0 (run independent generic MC
in phase 3).
269 https://xwiki.desy.de/xwiki/rest/p/59192
272 noEvents (int): number of events to be generated
273 path (basf2.Path): modules are added to this path
276 evtnumbers = register_module('EventInfoSetter')
277 evtnumbers.param(
'evtNumList', [noEvents])
278 evtnumbers.param(
'runList', [0])
279 evtnumbers.param(
'expList', [0])
280 path.add_module(evtnumbers)
283def loadGearbox(path, silence_warning=False):
285 Loads Gearbox module to the path.
288 Should be used in a job
with *cosmic event generation only*
290 Needed
for scripts which only generate cosmic events
in order to
293 @param path modules are added to this path
294 @param silence_warning stops a verbose warning message
if you know you want to use this function
297 if not silence_warning:
298 B2WARNING(
"""You are overwriting the geometry from the database with Gearbox.
299 This is fine
if you
're generating cosmic events. But in most other cases you probably don't want this.
301 If you
're really sure you know what you're doing you can suppress this message
with:
303 >>> loadGearbox(silence_warning=
True)
307 paramloader = register_module('Gearbox')
308 path.add_module(paramloader)
311def printPrimaryMCParticles(path, **kwargs):
313 Prints all primary MCParticles, that is particles
from
314 the physics generator
and not particles created by the simulation
316 This
is equivalent to `printMCParticles(onlyPrimaries=
True, path=path) <printMCParticles>`
and additional
317 keyword arguments are just forwarded to that function
320 return printMCParticles(onlyPrimaries=
True, path=path, **kwargs)
323def printMCParticles(onlyPrimaries=False, maxLevel=-1, path=None, *,
324 showProperties=False, showMomenta=False, showVertices=False, showStatus=False, suppressPrint=False):
326 Prints all MCParticles or just primary MCParticles up to specified level. -1 means no limit.
328 By default this will
print a tree of just the particle names
and their pdg
329 codes
in the event,
for example ::
331 [INFO] Content of MCParticle list
334 ╰── Upsilon(4S) (300553)
336 │ ├── anti-D_0*0 (-10421)
337 │ │ ├── D- (-411)
338 │ │ │ ├── K*- (-323)
339 │ │ │ │ ├── anti-K0 (-311)
340 │ │ │ │ │ ╰── K_S0 (310)
341 │ │ │ │ │ ├── pi+ (211)
342 │ │ │ │ │ │ ╰╶╶ p+ (2212)
343 │ │ │ │ │ ╰── pi- (-211)
344 │ │ │ │ │ ├╶╶ e- (11)
345 │ │ │ │ │ ├╶╶ n0 (2112)
346 │ │ │ │ │ ├╶╶ n0 (2112)
347 │ │ │ │ │ ╰╶╶ n0 (2112)
348 │ │ │ │ ╰── pi- (-211)
349 │ │ │ │ ├╶╶ anti-nu_mu (-14)
350 │ │ │ │ ╰╶╶ mu- (13)
351 │ │ │ │ ├╶╶ nu_mu (14)
352 │ │ │ │ ├╶╶ anti-nu_e (-12)
353 │ │ │ │ ╰╶╶ e- (11)
354 │ │ │ ╰── K_S0 (310)
355 │ │ │ ├── pi0 (111)
356 │ │ │ │ ├── gamma (22)
357 │ │ │ │ ╰── gamma (22)
358 │ │ │ ╰── pi0 (111)
359 │ │ │ ├── gamma (22)
360 │ │ │ ╰── gamma (22)
361 │ │ ╰── pi+ (211)
362 │ ├── mu+ (-13)
363 │ │ ├╶╶ anti-nu_mu (-14)
364 │ │ ├╶╶ nu_e (12)
365 │ │ ╰╶╶ e+ (-11)
366 │ ├── nu_mu (14)
367 │ ╰── gamma (22)
371 There
's a distinction between primary and secondary particles. Primary particles are the ones created by the physics generator while secondary
372 particles are ones generated by the simulation of the detector interaction.
374 Secondaries are indicated
with a dashed line leading to the particle name
375 and if the output
is to the terminal they will be printed
in red. If
376 ``onlyPrimaries``
is True they will
not be included
in the tree.
378 On demand, extra information on all the particles can be displayed by
379 enabling any of the ``showProperties``, ``showMomenta``, ``showVertices``
380 and ``showStatus`` flags. Enabling all of them will look like
385 │ mass=0.14 energy=0.445 charge=-1 lifetime=6.36
386 │ p=(0.257, -0.335, 0.0238) |p|=0.423
387 │ production vertex=(0.113, -0.0531, 0.0156), time=0.00589
388 │ status flags=PrimaryParticle, StableInGenerator, StoppedInDetector
392 mass=0.94 energy=0.94 charge=0 lifetime=5.28e+03
393 p=(-0.000238, -0.0127, 0.0116) |p|=0.0172
394 production vertex=(144, 21.9, -1.29), time=39
395 status flags=StoppedInDetector
396 creation process=HadronInelastic
399 The first line of extra information
is enabled by ``showProperties``, the
400 second line by ``showMomenta``, the third line by ``showVertices``
and the
401 last two lines by ``showStatus``. Note that all values are given
in Belle II
402 standard units, that
is GeV, centimeter
and nanoseconds.
404 The depth of the tree can be limited
with the ``maxLevel`` argument: If it
's
405 bigger than zero it will limit the tree to the given number of generations.
406 A visual indicator will be added after each particle which would have
407 additional daughters that are skipped due to this limit. An example event
408 with ``maxLevel=3``
is given below. In this case only the tau neutrino
and
409 the pion don
't have additional daughters. ::
411 [INFO] Content of MCParticle list
414 ╰── Upsilon(4S) (300553)
416 │ ├── anti-D*0 (-423) → …
417 │ ├── tau+ (-15) → …
418 │ ╰── nu_tau (16)
420 ├── D*0 (423) → …
421 ├── K*- (-323) → …
422 ├── K*+ (323) → …
425 The same information will be stored in the branch ``__MCDecayString__`` of
426 TTree created by `VariablesToNtuple`
or `VariablesToEventBasedTree` module.
427 This branch
is automatically created when `PrintMCParticles` modules
is called.
428 Printing the information on the log message can be suppressed
if ``suppressPrint``
429 is True,
while the branch ``__MCDecayString__``. This option helps to reduce the
430 size of the log message.
433 onlyPrimaries (bool): If
True show only primary particles, that
is particles coming
from
434 the generator
and not created by the simulation.
435 maxLevel (int): If 0
or less
print the whole tree, otherwise stop after n generations
436 showProperties (bool): If
True show mass, energy
and charge of the particles
437 showMomenta (bool):
if True show the momenta of the particles
438 showVertices (bool):
if True show production vertex
and production time of all particles
439 showStatus (bool):
if True show some status information on the particles.
440 For secondary particles this includes creation process.
441 suppressPrint (bool):
if True printing the information on the log message
is suppressed.
442 Even
if True, the branch ``__MCDecayString__``
is created.
445 return path.add_module(
447 onlyPrimaries=onlyPrimaries,
449 showProperties=showProperties,
450 showMomenta=showMomenta,
451 showVertices=showVertices,
452 showStatus=showStatus,
453 suppressPrint=suppressPrint,
457def correctBrems(outputList,
460 maximumAcceptance=3.0,
461 multiplePhotons=False,
462 usePhotonOnlyOnce=True,
466 For each particle in the given ``inputList``, copies it to the ``outputList``
and adds the
467 4-vector of the photon(s)
in the ``gammaList`` which has(have) a weighted named relation to
468 the particle
's track, set by the ``ECLTrackBremFinder`` module during reconstruction.
471 This can only work if the mdst file contains the *Bremsstrahlung* named relation. Official MC samples
472 up to
and including MC12
and proc9 **do
not** contain this. Newer production campaigns (
from proc10
and MC13) do.
473 However, studies by the tau WG revealed that the cuts applied by the ``ECLTrackBremFinder`` module are too tight.
474 These will be loosened but this will only have effect
with proc13
and MC15.
475 If your analysis
is very sensitive to the Bremsstrahlung corrections, it
is advised to use `correctBremsBelle`.
478 A detailed description of how the weights are set can be found directly at the documentation of the
479 `BremsFinder` module.
481 Please note that a new particle
is always generated,
with the old particle
and -
if found- one
or more
482 photons
as daughters.
484 The ``inputList`` should contain particles
with associated tracks. Otherwise, the module will exit
with an error.
486 The ``gammaList`` should contain photons. Otherwise, the module will exit
with an error.
488 @param outputList The output particle list name containing the corrected particles
489 @param inputList The initial particle list name containing the particles to correct. *It should already exist.*
490 @param gammaList The photon list containing possibly bremsstrahlung photons; *It should already exist.*
491 @param maximumAcceptance Maximum value of the relation weight. Should be a number between [0,3)
492 @param multiplePhotons Whether to use only one photon (the one
with the smallest acceptance)
or as many
as possible
493 @param usePhotonOnlyOnce If true, each brems candidate
is used to correct only the track
with the smallest relation weight
494 @param writeOut Whether `RootOutput` module should save the created ``outputList``
495 @param path The module
is added to this path
500 B2ERROR(
"The BremsFinder can only be run over Belle II data.")
502 bremscorrector = register_module(
'BremsFinder')
503 bremscorrector.set_name(
'bremsCorrector_' + outputList)
504 bremscorrector.param(
'inputList', inputList)
505 bremscorrector.param(
'outputList', outputList)
506 bremscorrector.param(
'gammaList', gammaList)
507 bremscorrector.param(
'maximumAcceptance', maximumAcceptance)
508 bremscorrector.param(
'multiplePhotons', multiplePhotons)
509 bremscorrector.param(
'usePhotonOnlyOnce', usePhotonOnlyOnce)
510 bremscorrector.param(
'writeOut', writeOut)
511 path.add_module(bremscorrector)
514def copyList(outputListName, inputListName, writeOut=False, path=None):
516 Copy all Particle indices from input ParticleList to the output ParticleList.
517 Note that the Particles themselves are
not copied. The original
and copied
518 ParticleLists will point to the same Particles.
520 @param ouputListName copied ParticleList
521 @param inputListName original ParticleList to be copied
522 @param writeOut whether RootOutput module should save the created ParticleList
523 @param path modules are added to this path
526 copyLists(outputListName, [inputListName], writeOut, path)
529def correctBremsBelle(outputListName,
532 multiplePhotons=True,
534 usePhotonOnlyOnce=False,
538 Run the Belle - like brems finding on the ``inputListName`` of charged particles.
539 Adds all photons in ``gammaListName`` to a copy of the charged particle that are within
543 Studies by the tau WG show that using a rather wide opening angle (up to
544 0.2 rad)
and rather low energetic photons results
in good correction.
545 However, this should only serve
as a starting point
for your own studies
546 because the optimal criteria are likely mode-dependent
549 outputListName (str): The output charged particle list containing the corrected charged particles
550 inputListName (str): The initial charged particle list containing the charged particles to correct.
551 gammaListName (str): The gammas list containing possibly radiative gammas, should already exist.
552 multiplePhotons (bool): How many photons should be added to the charged particle? nearest one ->
False,
553 add all the photons within the cone ->
True
554 angleThreshold (float): The maximum angle
in radians between the charged particle
and the (radiative)
555 gamma to be accepted.
556 writeOut (bool): whether RootOutput module should save the created ParticleList
557 usePhotonOnlyOnce (bool): If true, a photon
is used
for correction of the closest charged particle
in the inputList.
558 If false, a photon
is allowed to be used
for correction multiple times (Default).
561 One cannot use a photon twice to reconstruct a composite particle. Thus,
for example,
if ``e+``
and ``e-`` are corrected
562 with a ``gamma``, the pair of ``e+``
and ``e-`` cannot form a ``J/psi -> e+ e-`` candidate.
564 path (basf2.Path): modules are added to this path
567 fsrcorrector = register_module('BelleBremRecovery')
568 fsrcorrector.set_name(
'BelleFSRCorrection_' + outputListName)
569 fsrcorrector.param(
'inputListName', inputListName)
570 fsrcorrector.param(
'outputListName', outputListName)
571 fsrcorrector.param(
'gammaListName', gammaListName)
572 fsrcorrector.param(
'multiplePhotons', multiplePhotons)
573 fsrcorrector.param(
'angleThreshold', angleThreshold)
574 fsrcorrector.param(
'usePhotonOnlyOnce', usePhotonOnlyOnce)
575 fsrcorrector.param(
'writeOut', writeOut)
576 path.add_module(fsrcorrector)
579def copyLists(outputListName, inputListNames, writeOut=False, path=None):
581 Copy all Particle indices from all input ParticleLists to the
582 single output ParticleList.
583 Note that the Particles themselves are
not copied.
584 The original
and copied ParticleLists will point to the same Particles.
586 Duplicates are removed based on the first-come, first-served principle.
587 Therefore, the order of the input ParticleLists matters.
590 If you want to select the best duplicate based on another criterion, have
591 a look at the function `mergeListsWithBestDuplicate`.
594 Two particles that differ only by the order of their daughters are
595 considered duplicates
and one of them will be removed.
597 @param ouputListName copied ParticleList
598 @param inputListName vector of original ParticleLists to be copied
599 @param writeOut whether RootOutput module should save the created ParticleList
600 @param path modules are added to this path
603 pmanipulate = register_module('ParticleListManipulator')
604 pmanipulate.set_name(
'PListCopy_' + outputListName)
605 pmanipulate.param(
'outputListName', outputListName)
606 pmanipulate.param(
'inputListNames', inputListNames)
607 pmanipulate.param(
'writeOut', writeOut)
608 path.add_module(pmanipulate)
611def copyParticles(outputListName, inputListName, writeOut=False, path=None):
613 Create copies of Particles given in the input ParticleList
and add them to the output ParticleList.
615 The existing relations of the original Particle (
or it
's (grand-)^n-daughters)
616 are copied as well. Note that only the relation
is copied
and that the related
617 object
is not. Copied particles are therefore related to the *same* object
as
620 @param ouputListName new ParticleList filled
with copied Particles
621 @param inputListName input ParticleList
with original Particles
622 @param writeOut whether RootOutput module should save the created ParticleList
623 @param path modules are added to this path
627 pmanipulate = register_module(
'ParticleListManipulator')
628 pmanipulate.set_name(
'PListCopy_' + outputListName)
629 pmanipulate.param(
'outputListName', outputListName)
630 pmanipulate.param(
'inputListNames', [inputListName])
631 pmanipulate.param(
'writeOut', writeOut)
632 path.add_module(pmanipulate)
635 pcopy = register_module(
'ParticleCopier')
636 pcopy.param(
'inputListNames', [outputListName])
637 path.add_module(pcopy)
640def cutAndCopyLists(outputListName, inputListNames, cut, writeOut=False, path=None):
642 Copy candidates from all lists
in ``inputListNames`` to
643 ``outputListName``
if they
pass ``cut`` (given selection criteria).
646 Note that the Particles themselves are
not copied.
647 The original
and copied ParticleLists will point to the same Particles.
650 Require energetic pions safely inside the cdc
652 .. code-block:: python
654 cutAndCopyLists(
"pi+:energeticPions", [
"pi+:good",
"pi+:loose"],
"[E > 2] and thetaInCDCAcceptance", path=mypath)
657 You must use square braces ``[``
and ``]``
for conditional statements.
660 outputListName (str): the new ParticleList name
661 inputListName (list(str)): list of input ParticleList names
662 cut (str): Candidates that do
not pass these selection criteria are removed
from the ParticleList
663 writeOut (bool): whether RootOutput module should save the created ParticleList
664 path (basf2.Path): modules are added to this path
667 pmanipulate = register_module('ParticleListManipulator')
668 pmanipulate.set_name(
'PListCutAndCopy_' + outputListName)
669 pmanipulate.param(
'outputListName', outputListName)
670 pmanipulate.param(
'inputListNames', inputListNames)
671 pmanipulate.param(
'cut', cut)
672 pmanipulate.param(
'writeOut', writeOut)
673 path.add_module(pmanipulate)
676def cutAndCopyList(outputListName, inputListName, cut, writeOut=False, path=None):
678 Copy candidates from ``inputListName`` to ``outputListName``
if they
pass
679 ``cut`` (given selection criteria).
682 Note the Particles themselves are
not copied.
683 The original
and copied ParticleLists will point to the same Particles.
686 require energetic pions safely inside the cdc
688 .. code-block:: python
690 cutAndCopyList(
"pi+:energeticPions",
"pi+:loose",
"[E > 2] and thetaInCDCAcceptance", path=mypath)
693 You must use square braces ``[``
and ``]``
for conditional statements.
696 outputListName (str): the new ParticleList name
697 inputListName (str): input ParticleList name
698 cut (str): Candidates that do
not pass these selection criteria are removed
from the ParticleList
699 writeOut (bool): whether RootOutput module should save the created ParticleList
700 path (basf2.Path): modules are added to this path
703 cutAndCopyLists(outputListName, [inputListName], cut, writeOut, path)
706def removeTracksForTrackingEfficiencyCalculation(inputListNames, fraction, path=None):
708 Randomly remove tracks from the provided particle lists to estimate the tracking efficiency.
709 Takes care of the duplicates,
if any.
712 inputListNames (list(str)): input particle list names
713 fraction (float): fraction of particles to be removed randomly
714 path (basf2.Path): module
is added to this path
717 trackingefficiency = register_module('TrackingEfficiency')
718 trackingefficiency.param(
'particleLists', inputListNames)
719 trackingefficiency.param(
'frac', fraction)
720 path.add_module(trackingefficiency)
723def scaleTrackMomenta(inputListNames, scale=float(
'nan'), payloadName=
"", scalingFactorName=
"SF", path=
None):
725 Scale momenta of the particles according to a scaling factor scale.
726 This scaling factor can either be given as constant number
or as the name of the payload which contains
727 the variable scale factors.
728 If the particle list contains composite particles, the momenta of the track-based daughters are scaled.
729 Subsequently, the momentum of the mother particle
is updated
as well.
732 inputListNames (list(str)): input particle list names
733 scale (float): scaling factor (1.0 -- no scaling)
734 payloadName (str): name of the payload which contains the phase-space dependent scaling factors
735 scalingFactorName (str): name of scaling factor variable
in the payload.
736 path (basf2.Path): module
is added to this path
741 B2ERROR(
"The tracking momentum scaler can only be run over Belle II data.")
743 TrackingMomentumScaleFactors = register_module(
'TrackingMomentumScaleFactors')
744 TrackingMomentumScaleFactors.param(
'particleLists', inputListNames)
745 TrackingMomentumScaleFactors.param(
'scale', scale)
746 TrackingMomentumScaleFactors.param(
'payloadName', payloadName)
747 TrackingMomentumScaleFactors.param(
'scalingFactorName', scalingFactorName)
749 path.add_module(TrackingMomentumScaleFactors)
752def correctTrackEnergy(inputListNames, correction=float(
'nan'), payloadName=
"", correctionName=
"SF", path=
None):
754 Correct the energy loss of tracks according to a 'correction' value.
755 This correction can either be given
as constant number
or as the name of the payload which contains
756 the variable corrections.
757 If the particle list contains composite particles, the momenta of the track-based daughters are corrected.
758 Subsequently, the momentum of the mother particle
is updated
as well.
761 inputListNames (list(str)): input particle list names
762 correction (float): correction value to be subtracted to the particle energy (0.0 -- no correction)
763 payloadName (str): name of the payload which contains the phase-space dependent scaling factors
764 correctionName (str): name of correction variable
in the payload.
765 path (basf2.Path): module
is added to this path
770 B2ERROR(
"The tracking energy correction can only be run over Belle II data.")
772 TrackingEnergyLossCorrection = register_module(
'TrackingEnergyLossCorrection')
773 TrackingEnergyLossCorrection.param(
'particleLists', inputListNames)
774 TrackingEnergyLossCorrection.param(
'correction', correction)
775 TrackingEnergyLossCorrection.param(
'payloadName', payloadName)
776 TrackingEnergyLossCorrection.param(
'correctionName', correctionName)
778 path.add_module(TrackingEnergyLossCorrection)
781def smearTrackMomenta(inputListNames, payloadName="", smearingFactorName="smear", path=None):
783 Smear the momenta of the particles according the values read from the given payload.
784 If the particle list contains composite particles, the momenta of the track-based daughters are smeared.
785 Subsequently, the momentum of the mother particle
is updated
as well.
788 inputListNames (list(str)): input particle list names
789 payloadName (str): name of the payload which contains the smearing values
790 smearingFactorName (str): name of smearing factor variable
in the payload.
791 path (basf2.Path): module
is added to this path
794 TrackingMomentumScaleFactors = register_module('TrackingMomentumScaleFactors')
795 TrackingMomentumScaleFactors.param(
'particleLists', inputListNames)
796 TrackingMomentumScaleFactors.param(
'payloadName', payloadName)
797 TrackingMomentumScaleFactors.param(
'smearingFactorName', smearingFactorName)
799 path.add_module(TrackingMomentumScaleFactors)
802def mergeListsWithBestDuplicate(outputListName,
807 ignoreMotherFlavor=False,
810 Merge input ParticleLists into one output ParticleList. Only the best
811 among duplicates is kept. The lowest
or highest value (configurable via
812 preferLowest) of the provided variable determines which duplicate
is the
815 @param ouputListName name of merged ParticleList
816 @param inputListName vector of original ParticleLists to be merged
817 @param variable variable to determine best duplicate
818 @param preferLowest whether lowest
or highest value of variable should be preferred
819 @param writeOut whether RootOutput module should save the created ParticleList
820 @param ignoreMotherFlavor whether the flavor of the mother particle
is ignored when trying to find duplicates
821 @param path modules are added to this path
824 pmanipulate = register_module('ParticleListManipulator')
825 pmanipulate.set_name(
'PListMerger_' + outputListName)
826 pmanipulate.param(
'outputListName', outputListName)
827 pmanipulate.param(
'inputListNames', inputListNames)
828 pmanipulate.param(
'variable', variable)
829 pmanipulate.param(
'preferLowest', preferLowest)
830 pmanipulate.param(
'writeOut', writeOut)
831 pmanipulate.param(
'ignoreMotherFlavor', ignoreMotherFlavor)
832 path.add_module(pmanipulate)
835def fillSignalSideParticleList(outputListName, decayString, path):
837 This function should only be used in the ROE path, that
is a path
838 that
is executed
for each ROE object
in the DataStore.
840 Example: fillSignalSideParticleList(
'gamma:sig',
'B0 -> K*0 ^gamma', roe_path)
842 Function will create a ParticleList
with name
'gamma:sig' which will be filled
843 with the existing photon Particle, being the second daughter of the B0 candidate
844 to which the ROE object has to be related.
846 @param ouputListName name of the created ParticleList
847 @param decayString specify Particle to be added to the ParticleList
850 pload = register_module('SignalSideParticleListCreator')
851 pload.set_name(
'SSParticleList_' + outputListName)
852 pload.param(
'particleListName', outputListName)
853 pload.param(
'decayString', decayString)
854 path.add_module(pload)
857def fillParticleLists(decayStringsWithCuts, writeOut=False, path=None, enforceFitHypothesis=False,
858 loadPhotonsFromKLM=False):
860 Creates Particles of the desired types from the corresponding ``mdst`` dataobjects,
861 loads them to the ``StoreArray<Particle>``
and fills the ParticleLists.
863 The multiple ParticleLists
with their own selection criteria are specified
864 via list tuples (decayString, cut),
for example
866 .. code-block:: python
868 kaons = (
'K+:mykaons',
'kaonID>0.1')
869 pions = (
'pi+:mypions',
'pionID>0.1')
870 fillParticleLists([kaons, pions], path=mypath)
872 If you are unsure what selection you want, you might like to see the
873 :doc:`StandardParticles` functions.
875 The type of the particles to be loaded
is specified via the decayString module parameter.
876 The type of the ``mdst`` dataobject that
is used
as an input
is determined
from the type of
877 the particle. The following types of the particles can be loaded:
879 * charged final state particles (input ``mdst`` type = Tracks)
880 - e+, mu+, pi+, K+, p, deuteron (
and charge conjugated particles)
882 * neutral final state particles
883 -
"gamma" (input ``mdst`` type = ECLCluster)
884 -
"K_S0",
"Lambda0" (input ``mdst`` type = V0)
885 -
"K_L0",
"n0" (input ``mdst`` type = KLMCluster
or ECLCluster)
888 For
"K_S0" and "Lambda0" you must specify the daughter ordering.
890 For example, to load V0s
as :math:`\\Lambda^0\\to p^+\\pi^-` decays
from V0s:
892 .. code-block:: python
894 v0lambdas = (
'Lambda0 -> p+ pi-',
'0.9 < M < 1.3')
895 fillParticleLists([kaons, pions, v0lambdas], path=mypath)
898 Gammas can also be loaded
from KLMClusters by explicitly setting the
899 parameter ``loadPhotonsFromKLM`` to
True. However, this should only be
900 done
in selected use-cases
and the effect should be studied carefully.
903 For
"K_L0" it
is now possible to load
from ECLClusters, to revert to
904 the old (Belle) behavior, you can require ``
'isFromKLM > 0'``.
906 .. code-block:: python
908 klongs = (
'K_L0',
'isFromKLM > 0')
909 fillParticleLists([kaons, pions, klongs], path=mypath)
911 * Charged kinks final state particles (input ``mdst`` type = Kink)
914 To reconstruct charged particle kink you must specify the daughter.
916 For example, to load Kinks
as :math:`K^- \\to \\pi^-\\pi^0` decays
from Kinks:
918 .. code-block:: python
920 kinkKaons = (
'K- -> pi-', yourCut)
921 fillParticleLists([kaons, pions, v0lambdas, kinkKaons], path=mypath)
925 decayStringsWithCuts (list): A list of python ntuples of (decayString, cut).
926 The decay string determines the type of Particle
927 and the name of the ParticleList.
928 If the input MDST type
is V0 the whole
929 decay chain needs to be specified, so that
930 the user decides
and controls the daughters
931 ' order (e.g. ``K_S0 -> pi+ pi-``).
932 If the input MDST type is Kink the decay chain needs to be specified
933 with only one daughter (e.g. ``K- -> pi-``).
934 The cut
is the selection criteria
935 to be added to the ParticleList. It can be an empty string.
936 writeOut (bool): whether RootOutput module should save the created ParticleList
937 path (basf2.Path): modules are added to this path
938 enforceFitHypothesis (bool): If true, Particles will be created only
for the tracks which have been fitted
939 using a mass hypothesis of the exact type passed to fillParticleLists().
940 If enforceFitHypothesis
is False (the default) the next closest fit hypothesis
941 in terms of mass difference will be used
if the fit using exact particle
942 type
is not available.
943 loadPhotonsFromKLM (bool): If true, photon candidates will be created
from KLMClusters
as well.
946 pload = register_module('ParticleLoader')
947 pload.set_name(
'ParticleLoader_' +
'PLists')
948 pload.param(
'decayStrings', [decayString
for decayString, cut
in decayStringsWithCuts])
949 pload.param(
'writeOut', writeOut)
950 pload.param(
"enforceFitHypothesis", enforceFitHypothesis)
951 path.add_module(pload)
953 from ROOT
import Belle2
955 for decayString, cut
in decayStringsWithCuts:
956 if not decayDescriptor.init(decayString):
957 raise ValueError(
"Invalid decay string")
959 if decayDescriptor.getNDaughters() > 0:
964 if (decayDescriptor.getNDaughters() == 1)
and (decayDescriptor.getMother().getLabel() !=
'kink'):
965 copyList(decayDescriptor.getMother().getFullName(), decayDescriptor.getMother().getName() +
':kink',
967 if (decayDescriptor.getNDaughters() > 1)
and (decayDescriptor.getMother().getLabel() !=
'V0'):
968 copyList(decayDescriptor.getMother().getFullName(), decayDescriptor.getMother().getName() +
':V0', writeOut, path)
969 elif (decayDescriptor.getMother().getLabel() !=
'all' and
970 abs(decayDescriptor.getMother().getPDGCode()) != Belle2.Const.neutron.getPDGCode()):
973 copyList(decayString, decayDescriptor.getMother().getName() +
':all', writeOut, path)
977 applyCuts(decayDescriptor.getMother().getFullName(), cut, path)
979 if decayString.startswith(
"gamma"):
982 if not loadPhotonsFromKLM:
983 applyCuts(decayString,
'isFromECL', path)
986def fillParticleList(decayString, cut, writeOut=False, path=None, enforceFitHypothesis=False,
987 loadPhotonsFromKLM=False):
989 Creates Particles of the desired type from the corresponding ``mdst`` dataobjects,
990 loads them to the StoreArray<Particle>
and fills the ParticleList.
993 the :doc:`StandardParticles` functions.
995 The type of the particles to be loaded
is specified via the decayString module parameter.
996 The type of the ``mdst`` dataobject that
is used
as an input
is determined
from the type of
997 the particle. The following types of the particles can be loaded:
999 * charged final state particles (input ``mdst`` type = Tracks)
1000 - e+, mu+, pi+, K+, p, deuteron (
and charge conjugated particles)
1002 * neutral final state particles
1003 -
"gamma" (input ``mdst`` type = ECLCluster)
1004 -
"K_S0",
"Lambda0" (input ``mdst`` type = V0)
1005 -
"K_L0",
"n0" (input ``mdst`` type = KLMCluster
or ECLCluster)
1008 For
"K_S0" and "Lambda0" you must specify the daughter ordering.
1010 For example, to load V0s
as :math:`\\Lambda^0\\to p^+\\pi^-` decays
from V0s:
1012 .. code-block:: python
1014 fillParticleList(
'Lambda0 -> p+ pi-',
'0.9 < M < 1.3', path=mypath)
1017 Gammas can also be loaded
from KLMClusters by explicitly setting the
1018 parameter ``loadPhotonsFromKLM`` to
True. However, this should only be
1019 done
in selected use-cases
and the effect should be studied carefully.
1022 For
"K_L0" it
is now possible to load
from ECLClusters, to revert to
1023 the old (Belle) behavior, you can require ``
'isFromKLM > 0'``.
1025 .. code-block:: python
1027 fillParticleList(
'K_L0',
'isFromKLM > 0', path=mypath)
1029 * Charged kinks final state particles (input ``mdst`` type = Kink)
1032 To reconstruct charged particle kink you must specify the daughter.
1034 For example, to load Kinks
as :math:`K^- \\to \\pi^-\\pi^0` decays
from Kinks:
1036 .. code-block:: python
1038 fillParticleList(
'K- -> pi-', yourCut, path=mypath)
1042 decayString (str): Type of Particle
and determines the name of the ParticleList.
1043 If the input MDST type
is V0 the whole decay chain needs to be specified, so that
1044 the user decides
and controls the daughters
' order (e.g. ``K_S0 -> pi+ pi-``).
1045 If the input MDST type is Kink the decay chain needs to be specified
1046 with only one daughter (e.g. ``K- -> pi-``).
1047 cut (str): Particles need to
pass these selection criteria to be added to the ParticleList
1048 writeOut (bool): whether RootOutput module should save the created ParticleList
1049 path (basf2.Path): modules are added to this path
1050 enforceFitHypothesis (bool): If true, Particles will be created only
for the tracks which have been fitted
1051 using a mass hypothesis of the exact type passed to fillParticleLists().
1052 If enforceFitHypothesis
is False (the default) the next closest fit hypothesis
1053 in terms of mass difference will be used
if the fit using exact particle
1054 type
is not available.
1055 loadPhotonsFromKLM (bool): If true, photon candidates will be created
from KLMClusters
as well.
1058 pload = register_module('ParticleLoader')
1059 pload.set_name(
'ParticleLoader_' + decayString)
1060 pload.param(
'decayStrings', [decayString])
1061 pload.param(
'writeOut', writeOut)
1062 pload.param(
"enforceFitHypothesis", enforceFitHypothesis)
1063 path.add_module(pload)
1066 from ROOT
import Belle2
1068 if not decayDescriptor.init(decayString):
1069 raise ValueError(
"Invalid decay string")
1070 if decayDescriptor.getNDaughters() > 0:
1075 if (decayDescriptor.getNDaughters() == 1)
and (decayDescriptor.getMother().getLabel() !=
'kink'):
1076 copyList(decayDescriptor.getMother().getFullName(), decayDescriptor.getMother().getName() +
':kink',
1078 if (decayDescriptor.getNDaughters() > 1)
and (decayDescriptor.getMother().getLabel() !=
'V0'):
1079 copyList(decayDescriptor.getMother().getFullName(), decayDescriptor.getMother().getName() +
':V0', writeOut,
1081 elif (decayDescriptor.getMother().getLabel() !=
'all' and
1082 abs(decayDescriptor.getMother().getPDGCode()) != Belle2.Const.neutron.getPDGCode()):
1085 copyList(decayString, decayDescriptor.getMother().getName() +
':all', writeOut, path)
1089 applyCuts(decayDescriptor.getMother().getFullName(), cut, path)
1091 if decayString.startswith(
"gamma"):
1094 if not loadPhotonsFromKLM:
1095 applyCuts(decayString,
'isFromECL', path)
1098def fillParticleListWithTrackHypothesis(decayString,
1102 enforceFitHypothesis=False,
1105 As fillParticleList, but if used
for a charged FSP, loads the particle
with the requested hypothesis
if available
1107 @param decayString specifies type of Particles
and determines the name of the ParticleList
1108 @param cut Particles need to
pass these selection criteria to be added to the ParticleList
1109 @param hypothesis the PDG code of the desired track hypothesis
1110 @param writeOut whether RootOutput module should save the created ParticleList
1111 @param enforceFitHypothesis If true, Particles will be created only
for the tracks which have been fitted
1112 using a mass hypothesis of the exact type passed to fillParticleLists().
1113 If enforceFitHypothesis
is False (the default) the next closest fit hypothesis
1114 in terms of mass difference will be used
if the fit using exact particle
1115 type
is not available.
1116 @param path modules are added to this path
1119 pload = register_module('ParticleLoader')
1120 pload.set_name(
'ParticleLoader_' + decayString)
1121 pload.param(
'decayStrings', [decayString])
1122 pload.param(
'trackHypothesis', hypothesis)
1123 pload.param(
'writeOut', writeOut)
1124 pload.param(
"enforceFitHypothesis", enforceFitHypothesis)
1125 path.add_module(pload)
1127 from ROOT
import Belle2
1129 if not decayDescriptor.init(decayString):
1130 raise ValueError(
"Invalid decay string")
1131 if decayDescriptor.getMother().getLabel() !=
'all':
1134 copyList(decayString, decayDescriptor.getMother().getName() +
':all', writeOut, path)
1138 applyCuts(decayString, cut, path)
1141def fillConvertedPhotonsList(decayString, cut, writeOut=False, path=None):
1143 Creates photon Particle object for each e+e- combination
in the V0 StoreArray.
1146 You must specify the daughter ordering.
1148 .. code-block:: python
1150 fillConvertedPhotonsList(
'gamma:converted -> e+ e-',
'', path=mypath)
1153 decayString (str): Must be gamma to an e+e- pair. You must specify the daughter ordering.
1154 Will also determine the name of the particleList.
1155 cut (str): Particles need to
pass these selection criteria to be added to the ParticleList
1156 writeOut (bool): whether RootOutput module should save the created ParticleList
1157 path (basf2.Path): modules are added to this path
1163 B2ERROR(
'For Belle converted photons are available in the pre-defined list "gamma:v0mdst".')
1165 pload = register_module(
'ParticleLoader')
1166 pload.set_name(
'ParticleLoader_' + decayString)
1167 pload.param(
'decayStrings', [decayString])
1168 pload.param(
'addDaughters',
True)
1169 pload.param(
'writeOut', writeOut)
1170 path.add_module(pload)
1172 from ROOT
import Belle2
1174 if not decayDescriptor.init(decayString):
1175 raise ValueError(
"Invalid decay string")
1176 if decayDescriptor.getMother().getLabel() !=
'V0':
1179 copyList(decayDescriptor.getMother().getFullName(), decayDescriptor.getMother().getName() +
':V0', writeOut, path)
1183 applyCuts(decayDescriptor.getMother().getFullName(), cut, path)
1186def fillParticleListFromROE(decayString,
1189 sourceParticleListName='',
1194 Creates Particle object for each ROE of the desired type found
in the
1195 StoreArray<RestOfEvent>, loads them to the StoreArray<Particle>
1196 and fills the ParticleList. If useMissing
is True, then the missing
1197 momentum
is used instead of ROE.
1199 The type of the particles to be loaded
is specified via the decayString module parameter.
1201 @param decayString specifies type of Particles
and determines the name of the ParticleList.
1202 Source ROEs can be taken
as a daughter list,
for example:
1203 'B0:tagFromROE -> B0:signal'
1204 @param cut Particles need to
pass these selection criteria to be added to the ParticleList
1205 @param maskName Name of the ROE mask to use
1206 @param sourceParticleListName Use related ROEs to this particle list
as a source
1207 @param useMissing Use missing momentum instead of ROE momentum
1208 @param writeOut whether RootOutput module should save the created ParticleList
1209 @param path modules are added to this path
1212 pload = register_module('ParticleLoader')
1213 pload.set_name(
'ParticleLoader_' + decayString)
1214 pload.param(
'decayStrings', [decayString])
1215 pload.param(
'writeOut', writeOut)
1216 pload.param(
'roeMaskName', maskName)
1217 pload.param(
'useMissing', useMissing)
1218 pload.param(
'sourceParticleListName', sourceParticleListName)
1219 pload.param(
'useROEs',
True)
1220 path.add_module(pload)
1222 from ROOT
import Belle2
1224 if not decayDescriptor.init(decayString):
1225 raise ValueError(
"Invalid decay string")
1229 applyCuts(decayDescriptor.getMother().getFullName(), cut, path)
1232def fillParticleListFromDummy(decayString,
1235 treatAsInvisible=True,
1239 Creates a ParticleList and fills it
with dummy Particles. For self-conjugated Particles one dummy
1240 Particle
is created,
for Particles that are
not self-conjugated one Particle
and one anti-Particle
is
1241 created. The four-momentum
is set to zero.
1243 The type of the particles to be loaded
is specified via the decayString module parameter.
1245 @param decayString specifies type of Particles
and determines the name of the ParticleList
1246 @param mdstIndex sets the mdst index of Particles
1247 @param covMatrix sets the value of the diagonal covariance matrix of Particles
1248 @param treatAsInvisible whether treeFitter should treat the Particles
as invisible
1249 @param writeOut whether RootOutput module should save the created ParticleList
1250 @param path modules are added to this path
1253 pload = register_module('ParticleLoader')
1254 pload.set_name(
'ParticleLoader_' + decayString)
1255 pload.param(
'decayStrings', [decayString])
1256 pload.param(
'useDummy',
True)
1257 pload.param(
'dummyMDSTIndex', mdstIndex)
1258 pload.param(
'dummyCovMatrix', covMatrix)
1259 pload.param(
'dummyTreatAsInvisible', treatAsInvisible)
1260 pload.param(
'writeOut', writeOut)
1261 path.add_module(pload)
1264def fillParticleListFromMC(decayString,
1267 skipNonPrimaryDaughters=False,
1270 skipNonPrimary=False,
1273 Creates Particle object for each MCParticle of the desired type found
in the StoreArray<MCParticle>,
1274 loads them to the StoreArray<Particle>
and fills the ParticleList.
1276 The type of the particles to be loaded
is specified via the decayString module parameter.
1278 @param decayString specifies type of Particles
and determines the name of the ParticleList
1279 @param cut Particles need to
pass these selection criteria to be added to the ParticleList
1280 @param addDaughters adds the bottom part of the decay chain of the particle to the datastore
and
1281 sets mother-daughter relations
1282 @param skipNonPrimaryDaughters
if true, skip non primary daughters, useful to study final state daughter particles
1283 @param writeOut whether RootOutput module should save the created ParticleList
1284 @param path modules are added to this path
1285 @param skipNonPrimary
if true, skip non primary particle
1286 @param skipInitial
if true, skip initial particles
1289 pload = register_module('ParticleLoader')
1290 pload.set_name(
'ParticleLoader_' + decayString)
1291 pload.param(
'decayStrings', [decayString])
1292 pload.param(
'addDaughters', addDaughters)
1293 pload.param(
'skipNonPrimaryDaughters', skipNonPrimaryDaughters)
1294 pload.param(
'writeOut', writeOut)
1295 pload.param(
'useMCParticles',
True)
1296 pload.param(
'skipNonPrimary', skipNonPrimary)
1297 pload.param(
'skipInitial', skipInitial)
1298 path.add_module(pload)
1300 from ROOT
import Belle2
1302 if not decayDescriptor.init(decayString):
1303 raise ValueError(
"Invalid decay string")
1307 applyCuts(decayString, cut, path)
1310def fillParticleListsFromMC(decayStringsWithCuts,
1312 skipNonPrimaryDaughters=False,
1315 skipNonPrimary=False,
1318 Creates Particle object for each MCParticle of the desired type found
in the StoreArray<MCParticle>,
1319 loads them to the StoreArray<Particle>
and fills the ParticleLists.
1321 The types of the particles to be loaded are specified via the (decayString, cut) tuples given
in a list.
1324 .. code-block:: python
1326 kaons = (
'K+:gen',
'')
1327 pions = (
'pi+:gen',
'pionID>0.1')
1328 fillParticleListsFromMC([kaons, pions], path=mypath)
1331 Daughters of ``Lambda0`` are
not primary, but ``Lambda0``
is not final state particle.
1332 Thus, when one reconstructs a particle
from ``Lambda0``, that
is created
with
1333 ``addDaughters=
True``
and ``skipNonPrimaryDaughters=
True``, the particle always has ``isSignal==0``.
1334 Please set options
for ``Lambda0`` to use MC-matching variables properly
as follows,
1335 ``addDaughters=
True``
and ``skipNonPrimaryDaughters=
False``.
1337 @param decayString specifies type of Particles
and determines the name of the ParticleList
1338 @param cut Particles need to
pass these selection criteria to be added to the ParticleList
1339 @param addDaughters adds the bottom part of the decay chain of the particle to the datastore
and
1340 sets mother-daughter relations
1341 @param skipNonPrimaryDaughters
if true, skip non primary daughters, useful to study final state daughter particles
1342 @param writeOut whether RootOutput module should save the created ParticleList
1343 @param path modules are added to this path
1344 @param skipNonPrimary
if true, skip non primary particle
1345 @param skipInitial
if true, skip initial particles
1348 pload = register_module('ParticleLoader')
1349 pload.set_name(
'ParticleLoader_' +
'PLists')
1350 pload.param(
'decayStrings', [decayString
for decayString, cut
in decayStringsWithCuts])
1351 pload.param(
'addDaughters', addDaughters)
1352 pload.param(
'skipNonPrimaryDaughters', skipNonPrimaryDaughters)
1353 pload.param(
'writeOut', writeOut)
1354 pload.param(
'useMCParticles',
True)
1355 pload.param(
'skipNonPrimary', skipNonPrimary)
1356 pload.param(
'skipInitial', skipInitial)
1357 path.add_module(pload)
1359 from ROOT
import Belle2
1361 for decayString, cut
in decayStringsWithCuts:
1362 if not decayDescriptor.init(decayString):
1363 raise ValueError(
"Invalid decay string")
1367 applyCuts(decayString, cut, path)
1370def fillParticleListFromChargedCluster(outputParticleList,
1373 useOnlyMostEnergeticECLCluster=True,
1377 Creates the Particle object from ECLCluster
and KLMCluster that are being matched
with the Track of inputParticleList.
1379 @param outputParticleList The output ParticleList. Only neutral final state particles are supported.
1380 @param inputParticleList The input ParticleList that
is required to have the relation to the Track object.
1381 @param cut Particles need to
pass these selection criteria to be added to the ParticleList
1382 @param useOnlyMostEnergeticECLCluster If
True, only the most energetic ECLCluster among ones that are matched
with the Track
is
1383 used. If
False, all matched ECLClusters are loaded. The default
is True. Regardless of
1384 this option, the KLMCluster
is loaded.
1385 @param writeOut whether RootOutput module should save the created ParticleList
1386 @param path modules are added to this path
1389 pload = register_module('ParticleLoader')
1390 pload.set_name(
'ParticleLoader_' + outputParticleList)
1392 pload.param(
'decayStrings', [outputParticleList])
1393 pload.param(
'sourceParticleListName', inputParticleList)
1394 pload.param(
'writeOut', writeOut)
1395 pload.param(
'loadChargedCluster',
True)
1396 pload.param(
'useOnlyMostEnergeticECLCluster', useOnlyMostEnergeticECLCluster)
1397 path.add_module(pload)
1401 applyCuts(outputParticleList, cut, path)
1404def extractParticlesFromROE(particleLists,
1405 signalSideParticleList=None,
1410 Extract Particle objects that belong to the Rest-Of-Events and fill them into the ParticleLists.
1411 The types of the particles other than those specified by ``particleLists`` are
not stored.
1412 If one creates a ROE
with ``fillWithMostLikely=
True`` via `buildRestOfEvent`,
for example,
1413 one should create particleLists
for not only ``pi+``, ``gamma``, ``K_L0`` but also other charged final state particles.
1415 When one calls the function
in the main path, one has to set the argument ``signalSideParticleList``
and the signal side
1416 ParticleList must have only one candidate.
1418 .. code-block:: python
1420 buildRestOfEvent(
'B0:sig', fillWithMostLikely=
True, path=mypath)
1422 roe_path = create_path()
1423 deadEndPath = create_path()
1424 signalSideParticleFilter(
'B0:sig',
'', roe_path, deadEndPath)
1426 plists = [
'%s:in_roe' % ptype
for ptype
in [
'pi+',
'gamma',
'K_L0',
'K+',
'p+',
'e+',
'mu+']]
1427 extractParticlesFromROE(plists, maskName=
'all', path=roe_path)
1431 mypath.for_each(
'RestOfEvent',
'RestOfEvents', roe_path)
1433 rankByLowest(
'B0:sig',
'deltaE', numBest=1, path=mypath)
1434 extractParticlesFromROE(plists, signalSideParticleList=
'B0:sig', maskName=
'all', path=mypath)
1439 @param particleLists (str
or list(str)) Name of output ParticleLists
1440 @param signalSideParticleList (str) Name of signal side ParticleList
1441 @param maskName (str) Name of the ROE mask to be applied on Particles
1442 @param writeOut (bool) whether RootOutput module should save the created ParticleList
1443 @param path (basf2.Path) modules are added to this path
1446 if isinstance(particleLists, str):
1447 particleLists = [particleLists]
1449 pext = register_module(
'ParticleExtractorFromROE')
1450 pext.set_name(
'ParticleExtractorFromROE_' +
'_'.join(particleLists))
1451 pext.param(
'outputListNames', particleLists)
1452 if signalSideParticleList
is not None:
1453 pext.param(
'signalSideParticleListName', signalSideParticleList)
1454 pext.param(
'maskName', maskName)
1455 pext.param(
'writeOut', writeOut)
1456 path.add_module(pext)
1459def applyCuts(list_name, cut, path):
1461 Removes particle candidates from ``list_name`` that do
not pass ``cut``
1462 (given selection criteria).
1465 require energetic pions safely inside the cdc
1467 .. code-block:: python
1469 applyCuts(
"pi+:mypions",
"[E > 2] and thetaInCDCAcceptance", path=mypath)
1472 You must use square braces ``[``
and ``]``
for conditional statements.
1475 list_name (str): input ParticleList name
1476 cut (str): Candidates that do
not pass these selection criteria are removed
from the ParticleList
1477 path (basf2.Path): modules are added to this path
1480 pselect = register_module('ParticleSelector')
1481 pselect.set_name(
'ParticleSelector_applyCuts_' + list_name)
1482 pselect.param(
'decayString', list_name)
1483 pselect.param(
'cut', cut)
1484 path.add_module(pselect)
1487def applyEventCuts(cut, path, metavariables=None):
1489 Removes events that do not pass the ``cut`` (given selection criteria).
1492 continuum events (
in mc only)
with more than 5 tracks
1494 .. code-block:: python
1496 applyEventCuts(
"[nTracks > 5] and [isContinuumEvent], path=mypath)
1499 Only event-based variables are allowed in this function
1500 and only square brackets ``[``
and ``]``
for conditional statements.
1503 cut (str): Events that do
not pass these selection criteria are skipped
1504 path (basf2.Path): modules are added to this path
1505 metavariables (list(str)): List of meta variables to be considered
in decomposition of cut
1509 from variables
import variables
1511 def find_vars(t: tuple, var_list: list, meta_list: list) ->
None:
1512 """ Recursive helper function to find variable names """
1513 if not isinstance(t, tuple):
1515 if t[0] == b2parser.B2ExpressionParser.node_types[
'IdentifierNode']:
1518 if t[0] == b2parser.B2ExpressionParser.node_types[
'FunctionNode']:
1519 meta_list.append(list(t[1:]))
1522 if isinstance(i, tuple):
1523 find_vars(i, var_list, meta_list)
1525 def check_variable(var_list: list, metavar_ids: list) ->
None:
1526 for var_string
in var_list:
1528 orig_name = variables.resolveAlias(var_string)
1529 if orig_name != var_string:
1532 find_vars(
b2parser.parse(orig_name), var_list_temp, meta_list_temp)
1534 check_variable(var_list_temp, metavar_ids)
1535 check_meta(meta_list_temp, metavar_ids)
1538 var = variables.getVariable(var_string)
1539 if event_var_id
not in var.description:
1540 B2ERROR(f
'Variable {var_string} is not an event-based variable! "\
1541 "Please check your inputs to the applyEventCuts method!')
1543 def check_meta(meta_list: list, metavar_ids: list) ->
None:
1544 for meta_string_list
in meta_list:
1546 while meta_string_list[0]
in metavar_ids:
1548 meta_string_list.pop(0)
1549 for meta_string
in meta_string_list[0].split(
","):
1550 find_vars(
b2parser.parse(meta_string), var_list_temp, meta_string_list)
1551 if len(meta_string_list) > 0:
1552 meta_string_list.pop(0)
1553 if len(meta_string_list) == 0:
1555 if len(meta_string_list) > 1:
1556 meta_list += meta_string_list[1:]
1557 if isinstance(meta_string_list[0], list):
1558 meta_string_list = [element
for element
in meta_string_list[0]]
1560 check_variable(var_list_temp, metavar_ids)
1562 if len(meta_string_list) == 0:
1564 elif len(meta_string_list) == 1:
1565 var = variables.getVariable(meta_string_list[0])
1567 var = variables.getVariable(meta_string_list[0], meta_string_list[1].split(
","))
1569 if event_var_id
in var.description:
1572 B2ERROR(f
'Variable {var.name} is not an event-based variable! Please check your inputs to the applyEventCuts method!')
1574 event_var_id =
'[Eventbased]'
1575 metavar_ids = [
'formula',
'abs',
1579 'exp',
'log',
'log10',
1581 'isNAN',
'ifNANgiveX']
1583 metavar_ids += metavariables
1587 find_vars(
b2parser.parse(cut), var_list=var_list, meta_list=meta_list)
1589 if len(var_list) == 0
and len(meta_list) == 0:
1590 B2WARNING(f
'Cut string "{cut}" has no variables for applyEventCuts helper function!')
1592 check_variable(var_list, metavar_ids)
1593 check_meta(meta_list, metavar_ids)
1595 eselect = register_module(
'VariableToReturnValue')
1596 eselect.param(
'variable',
'passesEventCut(' + cut +
')')
1597 path.add_module(eselect)
1598 empty_path = create_path()
1599 eselect.if_value(
'<1', empty_path)
1602def reconstructDecay(decayString,
1607 candidate_limit=None,
1608 ignoreIfTooManyCandidates=True,
1609 chargeConjugation=True,
1610 allowChargeViolation=False):
1612 Creates new Particles by making combinations of existing Particles - it reconstructs unstable particles via their specified
1613 decay mode, e.g. in form of a :ref:`DecayString`: :code:`D0 -> K- pi+`
or :code:`B+ -> anti-D0 pi+`, ... All possible
1614 combinations are created (particles are used only once per candidate)
and combinations that
pass the specified selection
1615 criteria are saved to a newly created (mother) ParticleList. By default the charge conjugated decay
is reconstructed
as well
1616 (meaning that the charge conjugated mother list
is created
as well) but this can be deactivated.
1618 One can use an ``@``-sign to mark a particle
as unspecified
for inclusive analyses,
1619 e.g.
in a DecayString: :code:`
'@Xsd -> K+ pi-'`.
1621 .. seealso:: :ref:`Marker_of_unspecified_particle`
1624 The input ParticleLists are typically ordered according to the upstream reconstruction algorithm.
1625 Therefore,
if you combine two
or more identical particles
in the decay chain you should
not expect to see the same
1626 distribution
for the daughter kinematics
as they may be sorted by geometry, momentum etc.
1628 For example,
in the decay :code:`D0 -> pi0 pi0` the momentum distributions of the two ``pi0`` s are
not identical.
1629 This can be solved by manually randomising the lists before combining.
1633 * `Particle combiner how does it work? <https://questions.belle2.org/question/4318/particle-combiner-how-does-it-work/>`_
1634 * `Identical particles
in decay chain <https://questions.belle2.org/question/5724/identical-particles-
in-decay-chain/>`_
1636 @param decayString :ref:`DecayString` specifying what kind of the decay should be reconstructed
1637 (
from the DecayString the mother
and daughter ParticleLists are determined)
1638 @param cut created (mother) Particles are added to the mother ParticleList
if they
1639 pass give cuts (
in VariableManager style)
and rejected otherwise
1640 @param dmID user specified decay mode identifier
1641 @param writeOut whether RootOutput module should save the created ParticleList
1642 @param path modules are added to this path
1643 @param candidate_limit Maximum amount of candidates to be reconstructed. If
1644 the number of candidates
is exceeded a Warning will be
1646 By default, all these candidates will be removed
and event will be ignored.
1647 This behaviour can be changed by \
'ignoreIfTooManyCandidates\' flag.
1648 If no value is given the amount
is limited to a sensible
1649 default. A value <=0 will disable this limit
and can
1650 cause huge memory amounts so be careful.
1651 @param ignoreIfTooManyCandidates whether event should be ignored
or not if number of reconstructed
1652 candidates reaches limit. If event
is ignored, no candidates are reconstructed,
1653 otherwise, number of candidates
in candidate_limit
is reconstructed.
1654 @param chargeConjugation boolean to decide whether charge conjugated mode should be reconstructed
as well (on by default)
1655 @param allowChargeViolation whether the decay string needs to conserve the electric charge
1658 pmake = register_module('ParticleCombiner')
1659 pmake.set_name(
'ParticleCombiner_' + decayString)
1660 pmake.param(
'decayString', decayString)
1661 pmake.param(
'cut', cut)
1662 pmake.param(
'decayMode', dmID)
1663 pmake.param(
'writeOut', writeOut)
1664 if candidate_limit
is not None:
1665 pmake.param(
"maximumNumberOfCandidates", candidate_limit)
1666 pmake.param(
"ignoreIfTooManyCandidates", ignoreIfTooManyCandidates)
1667 pmake.param(
'chargeConjugation', chargeConjugation)
1668 pmake.param(
"allowChargeViolation", allowChargeViolation)
1669 path.add_module(pmake)
1672def combineAllParticles(inputParticleLists, outputList, cut='', writeOut=False, path=None):
1674 Creates a new Particle as the combination of all Particles
from all
1675 provided inputParticleLists. However, each particle
is used only once
1676 (even
if duplicates are provided)
and the combination has to
pass the
1677 specified selection criteria to be saved
in the newly created (mother)
1680 @param inputParticleLists List of input particle lists which are combined to the new Particle
1681 @param outputList Name of the particle combination created
with this module
1682 @param cut created (mother) Particle
is added to the mother ParticleList
if it passes
1683 these given cuts (
in VariableManager style)
and is rejected otherwise
1684 @param writeOut whether RootOutput module should save the created ParticleList
1685 @param path module
is added to this path
1688 pmake = register_module('AllParticleCombiner')
1689 pmake.set_name(
'AllParticleCombiner_' + outputList)
1690 pmake.param(
'inputListNames', inputParticleLists)
1691 pmake.param(
'outputListName', outputList)
1692 pmake.param(
'cut', cut)
1693 pmake.param(
'writeOut', writeOut)
1694 path.add_module(pmake)
1697def reconstructMissingKlongDecayExpert(decayString,
1704 Creates a list of K_L0's and of B -> K_L0 + X, with X being a fully-reconstructed state.
1705 The K_L0 momentum is determined
from kinematic constraints of the two-body B decay into K_L0
and X
1707 @param decayString DecayString specifying what kind of the decay should be reconstructed
1708 (
from the DecayString the mother
and daughter ParticleLists are determined)
1709 @param cut Particles are added to the K_L0
and B ParticleList
if the B candidates
1710 pass the given cuts (
in VariableManager style)
and rejected otherwise
1711 @param dmID user specified decay mode identifier
1712 @param writeOut whether RootOutput module should save the created ParticleList
1713 @param path modules are added to this path
1714 @param recoList suffix appended to original K_L0
and B ParticleList that identify the newly created K_L0
and B lists
1717 pcalc = register_module('KlongMomentumCalculatorExpert')
1718 pcalc.set_name(
'KlongMomentumCalculatorExpert_' + decayString)
1719 pcalc.param(
'decayString', decayString)
1720 pcalc.param(
'writeOut', writeOut)
1721 pcalc.param(
'recoList', recoList)
1722 path.add_module(pcalc)
1724 rmake = register_module(
'KlongDecayReconstructorExpert')
1725 rmake.set_name(
'KlongDecayReconstructorExpert_' + decayString)
1726 rmake.param(
'decayString', decayString)
1727 rmake.param(
'cut', cut)
1728 rmake.param(
'decayMode', dmID)
1729 rmake.param(
'writeOut', writeOut)
1730 rmake.param(
'recoList', recoList)
1731 path.add_module(rmake)
1734def setBeamConstrainedMomentum(particleList, decayStringTarget, decayStringDaughters, path=None):
1736 Replace the four-momentum of the target Particle by p(beam) - p(selected daughters).
1737 The momentum of the mother Particle will not be changed.
1739 @param particleList mother Particlelist
1740 @param decayStringTarget DecayString specifying the target particle whose momentum
1742 @param decayStringDaughters DecayString specifying the daughter particles used to replace
1743 the momentum of the target particle by p(beam)-p(daughters)
1746 mod = register_module('ParticleMomentumUpdater')
1747 mod.set_name(
'ParticleMomentumUpdater' + particleList)
1748 mod.param(
'particleList', particleList)
1749 mod.param(
'decayStringTarget', decayStringTarget)
1750 mod.param(
'decayStringDaughters', decayStringDaughters)
1751 path.add_module(mod)
1754def updateKlongKinematicsExpert(particleList,
1758 Calculates and updates the kinematics of B->K_L0 + something
else with same method
as
1759 `reconstructMissingKlongDecayExpert`. This helps to revert the kinematics after the vertex fitting.
1761 @param particleList input ParticleList of B meson that decays to K_L0 + X
1762 @param writeOut whether RootOutput module should save the ParticleList
1763 @param path modules are added to this path
1766 mod = register_module('KlongMomentumUpdaterExpert')
1767 mod.set_name(
'KlongMomentumUpdaterExpert_' + particleList)
1768 mod.param(
'listName', particleList)
1769 mod.param(
'writeOut', writeOut)
1770 path.add_module(mod)
1773def replaceMass(replacerName, particleLists=None, pdgCode=22, path=None):
1775 replaces the mass of the particles inside the given particleLists
1776 with the invariant mass of the particle corresponding to the given pdgCode.
1778 @param particleLists new ParticleList filled
with copied Particles
1779 @param pdgCode PDG code
for mass reference
1780 @param path modules are added to this path
1783 if particleLists
is None:
1787 pmassupdater = register_module(
'ParticleMassUpdater')
1788 pmassupdater.set_name(
'ParticleMassUpdater_' + replacerName)
1789 pmassupdater.param(
'particleLists', particleLists)
1790 pmassupdater.param(
'pdgCode', pdgCode)
1791 path.add_module(pmassupdater)
1794def reconstructRecoil(decayString,
1799 candidate_limit=None,
1800 allowChargeViolation=False):
1802 Creates new Particles that recoil against the input particles.
1804 For example the decay string M -> D1 D2 D3 will:
1805 - create mother Particle M for each unique combination of D1, D2, D3 Particles
1806 - Particles D1, D2, D3 will be appended
as daughters to M
1807 - the 4-momentum of the mother Particle M
is given by
1808 p(M) = p(HER) + p(LER) - Sum_i p(Di)
1810 @param decayString DecayString specifying what kind of the decay should be reconstructed
1811 (
from the DecayString the mother
and daughter ParticleLists are determined)
1812 @param cut created (mother) Particles are added to the mother ParticleList
if they
1813 pass give cuts (
in VariableManager style)
and rejected otherwise
1814 @param dmID user specified decay mode identifier
1815 @param writeOut whether RootOutput module should save the created ParticleList
1816 @param path modules are added to this path
1817 @param candidate_limit Maximum amount of candidates to be reconstructed. If
1818 the number of candidates
is exceeded no candidate will be
1819 reconstructed
for that event
and a Warning will be
1821 If no value
is given the amount
is limited to a sensible
1822 default. A value <=0 will disable this limit
and can
1823 cause huge memory amounts so be careful.
1824 @param allowChargeViolation whether the decay string needs to conserve the electric charge
1827 pmake = register_module('ParticleCombiner')
1828 pmake.set_name(
'ParticleCombiner_' + decayString)
1829 pmake.param(
'decayString', decayString)
1830 pmake.param(
'cut', cut)
1831 pmake.param(
'decayMode', dmID)
1832 pmake.param(
'writeOut', writeOut)
1833 pmake.param(
'recoilParticleType', 1)
1834 if candidate_limit
is not None:
1835 pmake.param(
"maximumNumberOfCandidates", candidate_limit)
1836 pmake.param(
'allowChargeViolation', allowChargeViolation)
1837 path.add_module(pmake)
1840def reconstructRecoilDaughter(decayString,
1845 candidate_limit=None,
1846 allowChargeViolation=False):
1848 Creates new Particles that are daughters of the particle reconstructed in the recoil (always assumed to be the first daughter).
1850 For example the decay string M -> D1 D2 D3 will:
1851 - create mother Particle M
for each unique combination of D1, D2, D3 Particles
1852 - Particles D1, D2, D3 will be appended
as daughters to M
1853 - the 4-momentum of the mother Particle M
is given by
1854 p(M) = p(D1) - Sum_i p(Di), where i>1
1856 @param decayString DecayString specifying what kind of the decay should be reconstructed
1857 (
from the DecayString the mother
and daughter ParticleLists are determined)
1858 @param cut created (mother) Particles are added to the mother ParticleList
if they
1859 pass give cuts (
in VariableManager style)
and rejected otherwise
1860 @param dmID user specified decay mode identifier
1861 @param writeOut whether RootOutput module should save the created ParticleList
1862 @param path modules are added to this path
1863 @param candidate_limit Maximum amount of candidates to be reconstructed. If
1864 the number of candidates
is exceeded no candidate will be
1865 reconstructed
for that event
and a Warning will be
1867 If no value
is given the amount
is limited to a sensible
1868 default. A value <=0 will disable this limit
and can
1869 cause huge memory amounts so be careful.
1870 @param allowChargeViolation whether the decay string needs to conserve the electric charge taking into account that the first
1871 daughter
is actually the mother
1874 pmake = register_module('ParticleCombiner')
1875 pmake.set_name(
'ParticleCombiner_' + decayString)
1876 pmake.param(
'decayString', decayString)
1877 pmake.param(
'cut', cut)
1878 pmake.param(
'decayMode', dmID)
1879 pmake.param(
'writeOut', writeOut)
1880 pmake.param(
'recoilParticleType', 2)
1881 if candidate_limit
is not None:
1882 pmake.param(
"maximumNumberOfCandidates", candidate_limit)
1883 pmake.param(
'allowChargeViolation', allowChargeViolation)
1884 path.add_module(pmake)
1887def rankByHighest(particleList,
1891 allowMultiRank=False,
1893 overwriteRank=False,
1896 Ranks particles in the input list by the given variable (highest to lowest),
and stores an integer rank
for each Particle
1897 in an :b2:var:`extraInfo` field ``${variable}_rank`` starting at 1 (best).
1898 The list
is also sorted
from best to worst candidate
1899 (each charge, e.g. B+/B-, separately).
1900 This can be used to perform a best candidate selection by cutting on the corresponding rank value,
or by specifying
1901 a non-zero value
for 'numBest'.
1904 Extra-info fields can be accessed by the :b2:var:`extraInfo` metavariable.
1905 These variable names can become clunky, so it
's probably a good idea to set an alias.
1906 For example if you rank your B candidates by momentum,
1910 rankByHighest(
"B0:myCandidates",
"p", path=mypath)
1911 vm.addAlias(
"momentumRank",
"extraInfo(p_rank)")
1914 @param particleList The input ParticleList
1915 @param variable Variable to order Particles by.
1916 @param numBest If
not zero, only the $numBest Particles
in particleList
with rank <= numBest are kept.
1917 @param outputVariable Name
for the variable that will be created which contains the rank, Default
is '${variable}_rank'.
1918 @param allowMultiRank If true, candidates
with the same value will get the same rank.
1919 @param cut Only candidates passing the cut will be ranked. The others will have rank -1
1920 @param overwriteRank If true, the extraInfo of rank
is overwritten when the particle has already the extraInfo.
1921 @param path modules are added to this path
1924 bcs = register_module('BestCandidateSelection')
1925 bcs.set_name(
'BestCandidateSelection_' + particleList +
'_' + variable)
1926 bcs.param(
'particleList', particleList)
1927 bcs.param(
'variable', variable)
1928 bcs.param(
'numBest', numBest)
1929 bcs.param(
'outputVariable', outputVariable)
1930 bcs.param(
'allowMultiRank', allowMultiRank)
1931 bcs.param(
'cut', cut)
1932 bcs.param(
'overwriteRank', overwriteRank)
1933 path.add_module(bcs)
1936def rankByLowest(particleList,
1940 allowMultiRank=False,
1942 overwriteRank=False,
1945 Ranks particles in the input list by the given variable (lowest to highest),
and stores an integer rank
for each Particle
1946 in an :b2:var:`extraInfo` field ``${variable}_rank`` starting at 1 (best).
1947 The list
is also sorted
from best to worst candidate
1948 (each charge, e.g. B+/B-, separately).
1949 This can be used to perform a best candidate selection by cutting on the corresponding rank value,
or by specifying
1950 a non-zero value
for 'numBest'.
1953 Extra-info fields can be accessed by the :b2:var:`extraInfo` metavariable.
1954 These variable names can become clunky, so it
's probably a good idea to set an alias.
1955 For example if you rank your B candidates by :b2:var:`dM`,
1959 rankByLowest(
"B0:myCandidates",
"dM", path=mypath)
1960 vm.addAlias(
"massDifferenceRank",
"extraInfo(dM_rank)")
1963 @param particleList The input ParticleList
1964 @param variable Variable to order Particles by.
1965 @param numBest If
not zero, only the $numBest Particles
in particleList
with rank <= numBest are kept.
1966 @param outputVariable Name
for the variable that will be created which contains the rank, Default
is '${variable}_rank'.
1967 @param allowMultiRank If true, candidates
with the same value will get the same rank.
1968 @param cut Only candidates passing the cut will be ranked. The others will have rank -1
1969 @param overwriteRank If true, the extraInfo of rank
is overwritten when the particle has already the extraInfo.
1970 @param path modules are added to this path
1973 bcs = register_module('BestCandidateSelection')
1974 bcs.set_name(
'BestCandidateSelection_' + particleList +
'_' + variable)
1975 bcs.param(
'particleList', particleList)
1976 bcs.param(
'variable', variable)
1977 bcs.param(
'numBest', numBest)
1978 bcs.param(
'selectLowest',
True)
1979 bcs.param(
'allowMultiRank', allowMultiRank)
1980 bcs.param(
'outputVariable', outputVariable)
1981 bcs.param(
'cut', cut)
1982 bcs.param(
'overwriteRank', overwriteRank)
1983 path.add_module(bcs)
1986def applyRandomCandidateSelection(particleList, path=None):
1988 If there are multiple candidates in the provided particleList, all but one of them are removed randomly.
1989 This
is done on a event-by-event basis.
1991 @param particleList ParticleList
for which the random candidate selection should be applied
1992 @param path module
is added to this path
1995 rcs = register_module('BestCandidateSelection')
1996 rcs.set_name(
'RandomCandidateSelection_' + particleList)
1997 rcs.param(
'particleList', particleList)
1998 rcs.param(
'variable',
'random')
1999 rcs.param(
'selectLowest',
False)
2000 rcs.param(
'allowMultiRank',
False)
2001 rcs.param(
'numBest', 1)
2002 rcs.param(
'cut',
'')
2003 rcs.param(
'outputVariable',
'')
2004 path.add_module(rcs)
2009 Prints the contents of DataStore in the first event (
or a specific event number
or all events).
2010 Will list all objects
and arrays (including size).
2013 The command line tool: ``b2file-size``.
2016 eventNumber (int): Print the datastore only
for this event. The default
2017 (-1) prints only the first event, 0 means
print for all events (can produce large output)
2018 path (basf2.Path): the PrintCollections module
is added to this path
2021 This will
print a lot of output
if you
print it
for all events
and process many events.
2025 printDS = register_module('PrintCollections')
2026 printDS.param(
'printForEvent', eventNumber)
2027 path.add_module(printDS)
2030def printVariableValues(list_name, var_names, path):
2032 Prints out values of specified variables of all Particles included in given ParticleList. For debugging purposes.
2034 @param list_name input ParticleList name
2035 @param var_names vector of variable names to be printed
2036 @param path modules are added to this path
2039 prlist = register_module('ParticlePrinter')
2040 prlist.set_name(
'ParticlePrinter_' + list_name)
2041 prlist.param(
'listName', list_name)
2042 prlist.param(
'fullPrint',
False)
2043 prlist.param(
'variables', var_names)
2044 path.add_module(prlist)
2047def printList(list_name, full, path):
2049 Prints the size and executes Particle->print() (
if full=
True)
2050 method
for all Particles
in given ParticleList. For debugging purposes.
2052 @param list_name input ParticleList name
2053 @param full execute Particle->print() method
for all Particles
2054 @param path modules are added to this path
2057 prlist = register_module('ParticlePrinter')
2058 prlist.set_name(
'ParticlePrinter_' + list_name)
2059 prlist.param(
'listName', list_name)
2060 prlist.param(
'fullPrint', full)
2061 path.add_module(prlist)
2064def variablesToNtuple(decayString, variables, treename='variables', filename='ntuple.root', path=None, basketsize=1600,
2065 signalSideParticleList="", filenameSuffix="", useFloat=False, storeEventType=True,
2066 ignoreCommandLineOverride=False):
2068 Creates and fills a flat ntuple
with the specified variables
from the VariableManager.
2069 If a decayString
is provided, then there will be one entry per candidate (
for particle
in list of candidates).
2070 If an empty decayString
is provided, there will be one entry per event (useful
for trigger studies, etc).
2073 decayString (str): specifies type of Particles
and determines the name of the ParticleList
2074 variables (list(str)): the list of variables (which must be registered
in the VariableManager)
2075 treename (str): name of the ntuple tree
2076 filename (str): which
is used to store the variables
2077 path (basf2.Path): the basf2 path where the analysis
is processed
2078 basketsize (int): size of baskets
in the output ntuple
in bytes
2079 signalSideParticleList (str): The name of the signal-side ParticleList.
2080 Only valid
if the module
is called
in a for_each loop over the RestOfEvent.
2081 filenameSuffix (str): suffix to be appended to the filename before ``.root``.
2082 useFloat (bool): Use single precision (float) instead of double precision (double)
2083 for floating-point numbers.
2084 storeEventType (bool) :
if true, the branch __eventType__
is added
for the MC event type information.
2085 The information
is available
from MC16 on.
2086 ignoreCommandLineOverride (bool) :
if true, ignore override of file name via command line argument ``-o``.
2088 .. tip:: The output filename can be overridden using the ``-o`` argument of basf2.
2091 output = register_module('VariablesToNtuple')
2092 output.set_name(
'VariablesToNtuple_' + decayString)
2093 output.param(
'particleList', decayString)
2094 output.param(
'variables', variables)
2095 output.param(
'fileName', filename)
2096 output.param(
'treeName', treename)
2097 output.param(
'basketSize', basketsize)
2098 output.param(
'signalSideParticleList', signalSideParticleList)
2099 output.param(
'fileNameSuffix', filenameSuffix)
2100 output.param(
'useFloat', useFloat)
2101 output.param(
'storeEventType', storeEventType)
2102 output.param(
'ignoreCommandLineOverride', ignoreCommandLineOverride)
2103 path.add_module(output)
2109 filename='ntuple.root',
2112 prefixDecayString=False,
2114 ignoreCommandLineOverride=False):
2116 Creates and fills a flat ntuple
with the specified variables
from the VariableManager
2119 decayString (str): specifies type of Particles
and determines the name of the ParticleList
2120 variables (list(tuple))): variables + binning which must be registered
in the VariableManager
2121 variables_2d (list(tuple)): pair of variables + binning
for each which must be registered
in the VariableManager
2122 filename (str): which
is used to store the variables
2123 path (basf2.Path): the basf2 path where the analysis
is processed
2124 directory (str): directory inside the output file where the histograms should be saved.
2125 Useful
if you want to have different histograms
in the same file to separate them.
2126 prefixDecayString (bool): If
True the decayString will be prepended to the directory name to allow
for more
2127 programmatic naming of the structure
in the file.
2128 filenameSuffix (str): suffix to be appended to the filename before ``.root``.
2129 ignoreCommandLineOverride (bool) :
if true, ignore override of file name via command line argument ``-o``.
2131 .. tip:: The output filename can be overridden using the ``-o`` argument of basf2.
2134 if variables_2d
is None:
2136 output = register_module(
'VariablesToHistogram')
2137 output.set_name(
'VariablesToHistogram_' + decayString)
2138 output.param(
'particleList', decayString)
2139 output.param(
'variables', variables)
2140 output.param(
'variables_2d', variables_2d)
2141 output.param(
'fileName', filename)
2142 output.param(
'fileNameSuffix', filenameSuffix)
2143 output.param(
'ignoreCommandLineOverride', ignoreCommandLineOverride)
2144 if directory
is not None or prefixDecayString:
2145 if directory
is None:
2147 if prefixDecayString:
2148 directory = decayString +
"_" + directory
2149 output.param(
"directory", directory)
2150 path.add_module(output)
2155 For each particle in the input list the selected variables are saved
in an extra-info field
with the given name.
2156 Can be used when wanting to save variables before modifying them, e.g. when performing vertex fits.
2159 particleList (str): The input ParticleList
2160 variables (dict[str,str]): Dictionary of Variables (key)
and extraInfo names (value).
2161 option (int): Option to overwrite an existing extraInfo. Choose among -1, 0, 1, 2.
2162 An existing extra info
with the same name will be overwritten
if the new
2163 value
is lower / will never be overwritten / will be overwritten
if the
2164 new value
is higher / will always be overwritten (option = -1/0/1/2).
2165 path (basf2.Path): modules are added to this path
2168 mod = register_module('VariablesToExtraInfo')
2169 mod.set_name(
'VariablesToExtraInfo_' + particleList)
2170 mod.param(
'particleList', particleList)
2171 mod.param(
'variables', variables)
2172 mod.param(
'overwrite', option)
2173 path.add_module(mod)
2176def variablesToDaughterExtraInfo(particleList, decayString, variables, option=0, path=None):
2178 For each daughter particle specified via decay string the selected variables (estimated for the mother particle)
2179 are saved
in an extra-info field
with the given name. In other words, the property of mother
is saved
as extra-info
2180 to specified daughter particle.
2183 particleList (str): The input ParticleList
2184 decayString (str): Decay string that specifies to which daughter the extra info should be appended
2185 variables (dict[str,str]): Dictionary of Variables (key)
and extraInfo names (value).
2186 option (int): Option to overwrite an existing extraInfo. Choose among -1, 0, 1, 2.
2187 An existing extra info
with the same name will be overwritten
if the new
2188 value
is lower / will never be overwritten / will be overwritten
if the
2189 new value
is higher / will always be overwritten (option = -1/0/1/2).
2190 path (basf2.Path): modules are added to this path
2193 mod = register_module('VariablesToExtraInfo')
2194 mod.set_name(
'VariablesToDaughterExtraInfo_' + particleList)
2195 mod.param(
'particleList', particleList)
2196 mod.param(
'decayString', decayString)
2197 mod.param(
'variables', variables)
2198 mod.param(
'overwrite', option)
2199 path.add_module(mod)
2202def variablesToEventExtraInfo(particleList, variables, option=0, path=None):
2204 For each particle in the input list the selected variables are saved
in an event-extra-info field
with the given name,
2205 Can be used to save MC truth information,
for example,
in a ntuple of reconstructed particles.
2208 When the function
is called first time
not in the main path but
in a sub-path e.g. ``roe_path``,
2209 the eventExtraInfo cannot be accessed
from the main path because of the shorter lifetime of the event-extra-info field.
2210 If one wants to call the function
in a sub-path, one has to call the function
in the main path beforehand.
2213 particleList (str): The input ParticleList
2214 variables (dict[str,str]): Dictionary of Variables (key)
and extraInfo names (value).
2215 option (int): Option to overwrite an existing extraInfo. Choose among -1, 0, 1, 2.
2216 An existing extra info
with the same name will be overwritten
if the new
2217 value
is lower / will never be overwritten / will be overwritten
if the
2218 new value
is higher / will always be overwritten (option = -1/0/1/2).
2219 path (basf2.Path): modules are added to this path
2222 mod = register_module('VariablesToEventExtraInfo')
2223 mod.set_name(
'VariablesToEventExtraInfo_' + particleList)
2224 mod.param(
'particleList', particleList)
2225 mod.param(
'variables', variables)
2226 mod.param(
'overwrite', option)
2227 path.add_module(mod)
2230def variableToSignalSideExtraInfo(particleList, varToExtraInfo, path):
2232 Write the value of specified variables estimated for the single particle
in the input list (has to contain exactly 1
2233 particle)
as an extra info to the particle related to current ROE.
2234 Should be used only
in the for_each roe path.
2237 particleList (str): The input ParticleList
2238 varToExtraInfo (dict[str,str]): Dictionary of Variables (key)
and extraInfo names (value).
2239 path (basf2.Path): modules are added to this path
2242 mod = register_module('SignalSideVariablesToExtraInfo')
2243 mod.set_name(
'SigSideVarToExtraInfo_' + particleList)
2244 mod.param(
'particleListName', particleList)
2245 mod.param(
'variableToExtraInfo', varToExtraInfo)
2246 path.add_module(mod)
2249def signalRegion(particleList, cut, path=None, name="isSignalRegion", blind_data=True):
2251 Define and blind a signal region.
2252 Per default, the defined signal region
is cut out
if ran on data.
2253 This function will provide a new variable
'isSignalRegion' as default, which
is either 0
or 1 depending on the cut
2257 .. code-block:: python
2259 ma.reconstructDecay(
"B+:sig -> D+ pi0",
"Mbc>5.2", path=path)
2260 ma.signalRegion(
"B+:sig",
2261 "Mbc>5.27 and abs(deltaE)<0.2",
2264 ma.variablesToNtuples(
"B+:sig", [
"isSignalRegion"], path=path)
2267 particleList (str): The input ParticleList
2268 cut (str): Cut string describing the signal region
2269 path (basf2.Path):: Modules are added to this path
2270 name (str): Name of the Signal region
in the variable manager
2271 blind_data (bool): Automatically exclude signal region
from data
2275 from variables
import variables
2276 mod = register_module(
'VariablesToExtraInfo')
2277 mod.set_name(f
'{name}_' + particleList)
2278 mod.param(
'particleList', particleList)
2279 mod.param(
'variables', {f
"passesCut({cut})": name})
2280 variables.addAlias(name, f
"extraInfo({name})")
2281 path.add_module(mod)
2285 applyCuts(particleList, f
"{name}==0 or isMC==1", path=path)
2288def removeExtraInfo(particleLists=None, removeEventExtraInfo=False, path=None):
2290 Removes the ExtraInfo of the given particleLists. If specified (removeEventExtraInfo = True) also the EventExtraInfo
is removed.
2293 if particleLists
is None:
2295 mod = register_module(
'ExtraInfoRemover')
2296 mod.param(
'particleLists', particleLists)
2297 mod.param(
'removeEventExtraInfo', removeEventExtraInfo)
2298 path.add_module(mod)
2301def signalSideParticleFilter(particleList, selection, roe_path, deadEndPath):
2303 Checks if the current ROE object
in the for_each roe path (argument roe_path)
is related
2304 to the particle
from the input ParticleList. Additional selection criteria can be applied.
2305 If ROE
is not related to any of the Particles
from ParticleList
or the Particle doesn
't
2306 meet the selection criteria the execution of deadEndPath is started. This path,
as the name
2307 suggests should be empty
and its purpose
is to end the execution of for_each roe path
for
2308 the current ROE object.
2310 @param particleList The input ParticleList
2311 @param selection Selection criteria that Particle needs meet
in order
for for_each ROE path to
continue
2312 @param for_each roe path
in which this filter
is executed
2313 @param deadEndPath empty path that ends execution of or_each roe path
for the current ROE object.
2316 mod = register_module('SignalSideParticleFilter')
2317 mod.set_name(
'SigSideParticleFilter_' + particleList)
2318 mod.param(
'particleLists', [particleList])
2319 mod.param(
'selection', selection)
2320 roe_path.add_module(mod)
2321 mod.if_false(deadEndPath)
2324def signalSideParticleListsFilter(particleLists, selection, roe_path, deadEndPath):
2326 Checks if the current ROE object
in the for_each roe path (argument roe_path)
is related
2327 to the particle
from the input ParticleList. Additional selection criteria can be applied.
2328 If ROE
is not related to any of the Particles
from ParticleList
or the Particle doesn
't
2329 meet the selection criteria the execution of deadEndPath is started. This path,
as the name
2330 suggests should be empty
and its purpose
is to end the execution of for_each roe path
for
2331 the current ROE object.
2333 @param particleLists The input ParticleLists
2334 @param selection Selection criteria that Particle needs meet
in order
for for_each ROE path to
continue
2335 @param for_each roe path
in which this filter
is executed
2336 @param deadEndPath empty path that ends execution of or_each roe path
for the current ROE object.
2339 mod = register_module('SignalSideParticleFilter')
2340 mod.set_name(
'SigSideParticleFilter_' + particleLists[0])
2341 mod.param(
'particleLists', particleLists)
2342 mod.param(
'selection', selection)
2343 roe_path.add_module(mod)
2344 mod.if_false(deadEndPath)
2353 chargeConjugation=True,
2356 Finds and creates a ``ParticleList``
from given decay string.
2357 ``ParticleList`` of daughters
with sub-decay
is created.
2359 Only the particles made
from MCParticle, which can be loaded by `fillParticleListFromMC`, are accepted
as daughters.
2361 Only signal particle, which means :b2:var:`isSignal`
is equal to 1,
is stored. One can use the decay string grammar
2362 to change the behavior of :b2:var:`isSignal`. One can find detailed information
in :ref:`DecayString`.
2365 If one uses same sub-decay twice, same particles are registered to a ``ParticleList``. For example,
2366 ``K_S0:pi0pi0 =direct=> [pi0:gg =direct=> gamma:MC gamma:MC] [pi0:gg =direct=> gamma:MC gamma:MC]``.
2367 One can skip the second sub-decay, ``K_S0:pi0pi0 =direct=> [pi0:gg =direct=> gamma:MC gamma:MC] pi0:gg``.
2370 It
is recommended to use only primary particles
as daughter particles unless you want to explicitly study the secondary
2371 particles. The behavior of MC-matching
for secondary particles
from a stable particle decay
is not guaranteed.
2372 Please consider to use `fillParticleListFromMC`
with ``skipNonPrimary=
True`` to load daughter particles.
2373 Moreover, it
is recommended to load ``K_S0``
and ``Lambda0`` directly
from MCParticle by `fillParticleListFromMC` rather
2374 than reconstructing
from two pions
or a proton-pion pair, because their direct daughters can be the secondary particle.
2377 @param decayString :ref:`DecayString` specifying what kind of the decay should be reconstructed
2378 (
from the DecayString the mother
and daughter ParticleLists are determined)
2379 @param cut created (mother) Particles are added to the mother ParticleList
if they
2380 pass given cuts (
in VariableManager style)
and rejected otherwise
2381 isSignal==1
is always required by default.
2382 @param dmID user specified decay mode identifier
2383 @param writeOut whether RootOutput module should save the created ParticleList
2384 @param path modules are added to this path
2385 @param chargeConjugation boolean to decide whether charge conjugated mode should be reconstructed
as well (on by default)
2388 pmake = register_module('ParticleCombinerFromMC')
2389 pmake.set_name(
'ParticleCombinerFromMC_' + decayString)
2390 pmake.param(
'decayString', decayString)
2391 pmake.param(
'cut', cut)
2392 pmake.param(
'decayMode', dmID)
2393 pmake.param(
'writeOut', writeOut)
2394 pmake.param(
'chargeConjugation', chargeConjugation)
2395 path.add_module(pmake)
2402 appendAllDaughters=False,
2403 skipNonPrimaryDaughters=True,
2407 Finds and creates a ``ParticleList``
for all ``MCParticle`` decays matching a given :ref:`DecayString`.
2408 The decay string
is required to describe correctly what you want.
2409 In the case of inclusive decays, you can use :ref:`Grammar_for_custom_MCMatching`
2411 The output particles has only the daughter particles written
in the given decay string,
if
2412 ``appendAllDaughters=
False`` (default). If ``appendAllDaughters=
True``, all daughters of the matched MCParticle are
2413 appended
in the order defined at the MCParticle level. For example,
2415 .. code-block:: python
2417 findMCDecay(
'B0:Xee',
'B0 -> e+ e- ... ?gamma', appendAllDaughters=
False, path=mypath)
2419 The output ParticleList ``B0:Xee`` will match the inclusive ``B0 -> e+ e-`` decays (but neutrinos are
not included),
2420 in both cases of ``appendAllDaughters``
is false
and true.
2421 If the ``appendAllDaughters=
False``
as above example, the ``B0:Xee`` has only two electrons
as daughters.
2422 While,
if ``appendAllDaughters=
True``, all daughters of the matched MCParticles are appended. When the truth decay mode of
2423 the MCParticle
is ``B0 -> [K*0 -> K+ pi-] [J/psi -> e+ e-]``, the first daughter of ``B0:Xee``
is ``K*0``
and ``e+``
2424 will be the first daughter of second daughter of ``B0:Xee``.
2426 The option ``skipNonPrimaryDaughters`` only has an effect
if ``appendAllDaughters=
True``. If ``skipNonPrimaryDaughters=
True``,
2427 all primary daughters are appended but the secondary particles are
not.
2430 Daughters of ``Lambda0`` are
not primary, but ``Lambda0``
is not a final state particle.
2431 In order
for the MCMatching to work properly, the daughters of ``Lambda0`` are appended to
2432 ``Lambda0`` regardless of the value of the option ``skipNonPrimaryDaughters``.
2435 @param list_name The output particle list name
2436 @param decay The decay string which you want
2437 @param writeOut Whether `RootOutput` module should save the created ``outputList``
2438 @param skipNonPrimaryDaughters
if true, skip non primary daughters, useful to study final state daughter particles
2439 @param appendAllDaughters
if true,
not only the daughters described
in the decay string but all daughters are appended
2440 @param path modules are added to this path
2443 decayfinder = register_module('MCDecayFinder')
2444 decayfinder.set_name(
'MCDecayFinder_' + list_name)
2445 decayfinder.param(
'listName', list_name)
2446 decayfinder.param(
'decayString', decay)
2447 decayfinder.param(
'appendAllDaughters', appendAllDaughters)
2448 decayfinder.param(
'skipNonPrimaryDaughters', skipNonPrimaryDaughters)
2449 decayfinder.param(
'writeOut', writeOut)
2450 path.add_module(decayfinder)
2453def summaryOfLists(particleLists, outputFile=None, path=None):
2455 Prints out Particle statistics at the end of the job: number of events with at
2456 least one candidate, average number of candidates per event, etc.
2457 If an output file name
is provided the statistics
is also dumped into a json file
with that name.
2459 @param particleLists list of input ParticleLists
2460 @param outputFile output file name (
not created by default)
2463 particleStats = register_module('ParticleStats')
2464 particleStats.param(
'particleLists', particleLists)
2465 if outputFile
is not None:
2466 particleStats.param(
'outputFile', outputFile)
2467 path.add_module(particleStats)
2470def matchMCTruth(list_name, path):
2472 Performs MC matching (sets relation Particle->MCParticle) for
2473 all particles (
and its (grand)^N-daughter particles)
in the specified
2476 @param list_name name of the input ParticleList
2477 @param path modules are added to this path
2480 mcMatch = register_module('MCMatcherParticles')
2481 mcMatch.set_name(
'MCMatch_' + list_name)
2482 mcMatch.param(
'listName', list_name)
2483 path.add_module(mcMatch)
2486def looseMCTruth(list_name, path):
2488 Performs loose MC matching for all particles
in the specified
2490 The difference between loose
and normal mc matching algorithm
is that
2491 the loose algorithm will find the common mother of the majority of daughter
2492 particles
while the normal algorithm finds the common mother of all daughters.
2493 The results of loose mc matching algorithm are stored to the following extraInfo
2496 - looseMCMotherPDG: PDG code of most common mother
2497 - looseMCMotherIndex: 1-based StoreArray<MCParticle> index of most common mother
2498 - looseMCWrongDaughterN: number of daughters that don
't originate from the most common mother
2499 - looseMCWrongDaughterPDG: PDG code of the daughter that doesn't originate from the most common mother (only if
2500 looseMCWrongDaughterN = 1)
2501 - looseMCWrongDaughterBiB: 1 if the wrong daughter
is Beam Induced Background Particle
2503 @param list_name name of the input ParticleList
2504 @param path modules are added to this path
2507 mcMatch = register_module('MCMatcherParticles')
2508 mcMatch.set_name(
'LooseMCMatch_' + list_name)
2509 mcMatch.param(
'listName', list_name)
2510 mcMatch.param(
'looseMCMatching',
True)
2511 path.add_module(mcMatch)
2514def buildRestOfEvent(target_list_name, inputParticlelists=None,
2515 fillWithMostLikely=True,
2516 chargedPIDPriors=None, path=None):
2518 Creates for each Particle
in the given ParticleList a RestOfEvent
2519 dataobject
and makes basf2 relation between them. User can provide additional
2520 particle lists
with a different particle hypothesis like [
'K+:good, e+:good'], etc.
2522 @param target_list_name name of the input ParticleList
2523 @param inputParticlelists list of user-defined input particle list names, which serve
2524 as source of particles to build the ROE, the FSP particles
from
2525 target_list_name are automatically excluded
from the ROE object
2526 @param fillWithMostLikely By default the module uses the most likely particle mass hypothesis
for charged particles
2527 based on the PID likelihood. Turn this behavior off
if you want to configure your own
2528 input particle lists.
2529 @param chargedPIDPriors The prior PID fractions, that are used to regulate the
2530 amount of certain charged particle species, should be a list of
2531 six floats
if not None. The order of particle types
is
2532 the following: [e-, mu-, pi-, K-, p+, d+]
2533 @param path modules are added to this path
2536 if inputParticlelists
is None:
2537 inputParticlelists = []
2538 fillParticleList(
'pi+:all',
'', path=path)
2539 if fillWithMostLikely:
2540 from stdCharged
import stdMostLikely
2541 stdMostLikely(chargedPIDPriors,
'_roe', path=path)
2542 inputParticlelists = [f
'{ptype}:mostlikely_roe' for ptype
in [
'K+',
'p+',
'e+',
'mu+']]
2545 fillParticleList(
'gamma:all',
'', path=path)
2546 fillParticleList(
'K_L0:roe_default',
'isFromKLM > 0', path=path)
2547 inputParticlelists += [
'pi+:all',
'gamma:all',
'K_L0:roe_default']
2549 inputParticlelists += [
'pi+:all',
'gamma:mdst']
2550 roeBuilder = register_module(
'RestOfEventBuilder')
2551 roeBuilder.set_name(
'ROEBuilder_' + target_list_name)
2552 roeBuilder.param(
'particleList', target_list_name)
2553 roeBuilder.param(
'particleListsInput', inputParticlelists)
2554 roeBuilder.param(
'mostLikely', fillWithMostLikely)
2555 path.add_module(roeBuilder)
2558def buildNestedRestOfEvent(target_list_name, maskName='all', path=None):
2560 Creates for each Particle
in the given ParticleList a RestOfEvent
2561 @param target_list_name name of the input ParticleList
2562 @param mask_name name of the ROEMask to be used
2563 @param path modules are added to this path
2566 roeBuilder = register_module('RestOfEventBuilder')
2567 roeBuilder.set_name(
'NestedROEBuilder_' + target_list_name)
2568 roeBuilder.param(
'particleList', target_list_name)
2569 roeBuilder.param(
'nestedROEMask', maskName)
2570 roeBuilder.param(
'createNestedROE',
True)
2571 path.add_module(roeBuilder)
2574def buildRestOfEventFromMC(target_list_name, inputParticlelists=None, path=None):
2576 Creates for each Particle
in the given ParticleList a RestOfEvent
2577 @param target_list_name name of the input ParticleList
2578 @param inputParticlelists list of input particle list names, which serve
2579 as a source of particles to build ROE, the FSP particles
from
2580 target_list_name are excluded
from ROE object
2581 @param path modules are added to this path
2584 if inputParticlelists
is None:
2585 inputParticlelists = []
2586 if (len(inputParticlelists) == 0):
2590 types = [
'gamma',
'e+',
'mu+',
'pi+',
'K+',
'p+',
'K_L0',
2591 'n0',
'nu_e',
'nu_mu',
'nu_tau',
2594 fillParticleListFromMC(f
"{t}:roe_default_gen",
'mcPrimary > 0 and nDaughters == 0',
2595 True,
True, path=path)
2596 inputParticlelists += [f
"{t}:roe_default_gen"]
2597 roeBuilder = register_module(
'RestOfEventBuilder')
2598 roeBuilder.set_name(
'MCROEBuilder_' + target_list_name)
2599 roeBuilder.param(
'particleList', target_list_name)
2600 roeBuilder.param(
'particleListsInput', inputParticlelists)
2601 roeBuilder.param(
'fromMC',
True)
2602 path.add_module(roeBuilder)
2605def appendROEMask(list_name,
2608 eclClusterSelection,
2609 klmClusterSelection='',
2612 Loads the ROE object of a particle and creates a ROE mask
with a specific name. It applies
2613 selection criteria
for tracks
and eclClusters which will be used by variables
in ROEVariables.cc.
2615 - append a ROE mask
with all tracks
in ROE coming
from the IP region
2617 .. code-block:: python
2619 appendROEMask(
'B+:sig',
'IPtracks',
'[dr < 2] and [abs(dz) < 5]', path=mypath)
2621 - append a ROE mask
with only ECL-based particles that
pass as good photon candidates
2623 .. code-block:: python
2625 goodPhotons =
'inCDCAcceptance and clusterErrorTiming < 1e6 and [clusterE1E9 > 0.4 or E > 0.075]'
2626 appendROEMask(
'B+:sig',
'goodROEGamma',
'', goodPhotons, path=mypath)
2629 @param list_name name of the input ParticleList
2630 @param mask_name name of the appended ROEMask
2631 @param trackSelection decay string
for the track-based particles
in ROE
2632 @param eclClusterSelection decay string
for the ECL-based particles
in ROE
2633 @param klmClusterSelection decay string
for the KLM-based particles
in ROE
2634 @param path modules are added to this path
2637 roeMask = register_module('RestOfEventInterpreter')
2638 roeMask.set_name(
'RestOfEventInterpreter_' + list_name +
'_' + mask_name)
2639 roeMask.param(
'particleList', list_name)
2640 roeMask.param(
'ROEMasks', [(mask_name, trackSelection, eclClusterSelection, klmClusterSelection)])
2641 path.add_module(roeMask)
2644def appendROEMasks(list_name, mask_tuples, path=None):
2646 Loads the ROE object of a particle and creates a ROE mask
with a specific name. It applies
2647 selection criteria
for track-, ECL-
and KLM-based particles which will be used by ROE variables.
2649 The multiple ROE masks
with their own selection criteria are specified
2650 via list of tuples (mask_name, trackParticleSelection, eclParticleSelection, klmParticleSelection)
or
2651 (mask_name, trackSelection, eclClusterSelection)
in case
with fractions.
2653 - Example
for two tuples, one
with and one without fractions
2655 .. code-block:: python
2657 ipTracks = (
'IPtracks',
'[dr < 2] and [abs(dz) < 5]',
'',
'')
2658 goodPhotons =
'inCDCAcceptance and [clusterErrorTiming < 1e6] and [clusterE1E9 > 0.4 or E > 0.075]'
2659 goodROEGamma = (
'ROESel',
'[dr < 2] and [abs(dz) < 5]', goodPhotons,
'')
2660 goodROEKLM = (
'IPtracks',
'[dr < 2] and [abs(dz) < 5]',
'',
'nKLMClusterTrackMatches == 0')
2661 appendROEMasks(
'B+:sig', [ipTracks, goodROEGamma, goodROEKLM], path=mypath)
2663 @param list_name name of the input ParticleList
2664 @param mask_tuples array of ROEMask list tuples to be appended
2665 @param path modules are added to this path
2668 compatible_masks = []
2669 for mask
in mask_tuples:
2672 compatible_masks += [(*mask,
'')]
2674 compatible_masks += [mask]
2675 roeMask = register_module(
'RestOfEventInterpreter')
2676 roeMask.set_name(
'RestOfEventInterpreter_' + list_name +
'_' +
'MaskList')
2677 roeMask.param(
'particleList', list_name)
2678 roeMask.param(
'ROEMasks', compatible_masks)
2679 path.add_module(roeMask)
2682def updateROEMask(list_name,
2685 eclClusterSelection='',
2686 klmClusterSelection='',
2689 Update an existing ROE mask by applying additional selection cuts for
2690 tracks
and/
or clusters.
2692 See function `appendROEMask`!
2694 @param list_name name of the input ParticleList
2695 @param mask_name name of the ROEMask to update
2696 @param trackSelection decay string
for the track-based particles
in ROE
2697 @param eclClusterSelection decay string
for the ECL-based particles
in ROE
2698 @param klmClusterSelection decay string
for the KLM-based particles
in ROE
2699 @param path modules are added to this path
2702 roeMask = register_module('RestOfEventInterpreter')
2703 roeMask.set_name(
'RestOfEventInterpreter_' + list_name +
'_' + mask_name)
2704 roeMask.param(
'particleList', list_name)
2705 roeMask.param(
'ROEMasks', [(mask_name, trackSelection, eclClusterSelection, klmClusterSelection)])
2706 roeMask.param(
'update',
True)
2707 path.add_module(roeMask)
2710def updateROEMasks(list_name, mask_tuples, path):
2712 Update existing ROE masks by applying additional selection cuts for tracks
2715 The multiple ROE masks
with their own selection criteria are specified
2716 via list tuples (mask_name, trackSelection, eclClusterSelection, klmClusterSelection)
2718 See function `appendROEMasks`!
2720 @param list_name name of the input ParticleList
2721 @param mask_tuples array of ROEMask list tuples to be appended
2722 @param path modules are added to this path
2725 compatible_masks = []
2726 for mask
in mask_tuples:
2729 compatible_masks += [(*mask,
'')]
2731 compatible_masks += [mask]
2733 roeMask = register_module(
'RestOfEventInterpreter')
2734 roeMask.set_name(
'RestOfEventInterpreter_' + list_name +
'_' +
'MaskList')
2735 roeMask.param(
'particleList', list_name)
2736 roeMask.param(
'ROEMasks', compatible_masks)
2737 roeMask.param(
'update',
True)
2738 path.add_module(roeMask)
2741def keepInROEMasks(list_name, mask_names, cut_string, path=None):
2743 This function is used to apply particle list specific cuts on one
or more ROE masks (track
or eclCluster).
2744 With this function one can KEEP the tracks/eclclusters used
in particles
from provided particle list.
2745 This function should be executed only
in the for_each roe path
for the current ROE object.
2747 To avoid unnecessary computation, the input particle list should only contain particles
from ROE
2748 (use cut
'isInRestOfEvent == 1'). To update the ECLCluster masks, the input particle list should be a photon
2749 particle list (e.g.
'gamma:someLabel'). To update the Track masks, the input particle list should be a charged
2750 pion particle list (e.g.
'pi+:someLabel').
2752 Updating a non-existing mask will create a new one.
2754 - keep only those tracks that were used
in provided particle list
2756 .. code-block:: python
2758 keepInROEMasks(
'pi+:goodTracks',
'mask',
'', path=mypath)
2760 - keep only those clusters that were used
in provided particle list
and pass a cut, apply to several masks
2762 .. code-block:: python
2764 keepInROEMasks(
'gamma:goodClusters', [
'mask1',
'mask2'],
'E > 0.1', path=mypath)
2767 @param list_name name of the input ParticleList
2768 @param mask_names array of ROEMasks to be updated
2769 @param cut_string decay string
with which the mask will be updated
2770 @param path modules are added to this path
2773 updateMask = register_module('RestOfEventUpdater')
2774 updateMask.set_name(
'RestOfEventUpdater_' + list_name +
'_masks')
2775 updateMask.param(
'particleList', list_name)
2776 updateMask.param(
'updateMasks', mask_names)
2777 updateMask.param(
'cutString', cut_string)
2778 updateMask.param(
'discard',
False)
2779 path.add_module(updateMask)
2782def discardFromROEMasks(list_name, mask_names, cut_string, path=None):
2784 This function is used to apply particle list specific cuts on one
or more ROE masks (track
or eclCluster).
2785 With this function one can DISCARD the tracks/eclclusters used
in particles
from provided particle list.
2786 This function should be executed only
in the for_each roe path
for the current ROE object.
2788 To avoid unnecessary computation, the input particle list should only contain particles
from ROE
2789 (use cut
'isInRestOfEvent == 1'). To update the ECLCluster masks, the input particle list should be a photon
2790 particle list (e.g.
'gamma:someLabel'). To update the Track masks, the input particle list should be a charged
2791 pion particle list (e.g.
'pi+:someLabel').
2793 Updating a non-existing mask will create a new one.
2795 - discard tracks that were used
in provided particle list
2797 .. code-block:: python
2799 discardFromROEMasks(
'pi+:badTracks',
'mask',
'', path=mypath)
2801 - discard clusters that were used
in provided particle list
and pass a cut, apply to several masks
2803 .. code-block:: python
2805 discardFromROEMasks(
'gamma:badClusters', [
'mask1',
'mask2'],
'E < 0.1', path=mypath)
2808 @param list_name name of the input ParticleList
2809 @param mask_names array of ROEMasks to be updated
2810 @param cut_string decay string
with which the mask will be updated
2811 @param path modules are added to this path
2814 updateMask = register_module('RestOfEventUpdater')
2815 updateMask.set_name(
'RestOfEventUpdater_' + list_name +
'_masks')
2816 updateMask.param(
'particleList', list_name)
2817 updateMask.param(
'updateMasks', mask_names)
2818 updateMask.param(
'cutString', cut_string)
2819 updateMask.param(
'discard',
True)
2820 path.add_module(updateMask)
2823def optimizeROEWithV0(list_name, mask_names, cut_string, path=None):
2825 This function is used to apply particle list specific cuts on one
or more ROE masks
for Tracks.
2826 It
is possible to optimize the ROE selection by treating tracks
from V0
's separately, meaning,
2827 taking V0's 4-momentum into account instead of 4-momenta of tracks. A cut for only specific V0's
2828 passing it can be applied.
2830 The input particle list should be a V0 particle list: K_S0 (
'K_S0:someLabel',
''),
2831 Lambda (
'Lambda:someLabel',
'')
or converted photons (
'gamma:someLabel').
2833 Updating a non-existing mask will create a new one.
2835 - treat tracks
from K_S0 inside mass window separately, replace track momenta
with K_S0 momentum
2837 .. code-block:: python
2839 optimizeROEWithV0(
'K_S0:opt',
'mask',
'0.450 < M < 0.550', path=mypath)
2841 @param list_name name of the input ParticleList
2842 @param mask_names array of ROEMasks to be updated
2843 @param cut_string decay string
with which the mask will be updated
2844 @param path modules are added to this path
2847 updateMask = register_module('RestOfEventUpdater')
2848 updateMask.set_name(
'RestOfEventUpdater_' + list_name +
'_masks')
2849 updateMask.param(
'particleList', list_name)
2850 updateMask.param(
'updateMasks', mask_names)
2851 updateMask.param(
'cutString', cut_string)
2852 path.add_module(updateMask)
2855def updateROEUsingV0Lists(target_particle_list, mask_names, default_cleanup=True, selection_cuts=None,
2856 apply_mass_fit=False, fitter='treefit', path=None):
2858 This function creates V0 particle lists (photons, :math:`K^0_S` and :math:`\\Lambda^0`)
2859 and it uses V0 candidates to update the Rest Of Event, which
is associated to the target particle list.
2860 It
is possible to apply a standard
or customized selection
and mass fit to the V0 candidates.
2863 @param target_particle_list name of the input ParticleList
2864 @param mask_names array of ROE masks to be applied
2865 @param default_cleanup
if True, predefined cuts will be applied on the V0 lists
2866 @param selection_cuts a single string of selection cuts
or tuple of three strings (photon_cuts, K_S0_cuts, Lambda0_cuts),
2867 which will be applied to the V0 lists. These cuts will have a priority over the default ones.
2868 @param apply_mass_fit
if True, a mass fit will be applied to the V0 particles
2869 @param fitter string, that represent a fitter choice:
"treefit" for TreeFitter
and "kfit" for KFit
2870 @param path modules are added to this path
2873 roe_path = create_path()
2874 deadEndPath = create_path()
2875 signalSideParticleFilter(target_particle_list, '', roe_path, deadEndPath)
2877 if (default_cleanup
and selection_cuts
is None):
2878 B2INFO(
"Using default cleanup in updateROEUsingV0Lists.")
2879 selection_cuts =
'abs(dM) < 0.1 '
2880 selection_cuts +=
'and daughter(0,particleID) > 0.2 and daughter(1,particleID) > 0.2 '
2881 selection_cuts +=
'and daughter(0,thetaInCDCAcceptance) and daughter(1,thetaInCDCAcceptance)'
2882 if (selection_cuts
is None or selection_cuts ==
''):
2883 B2INFO(
"No cleanup in updateROEUsingV0Lists.")
2884 selection_cuts = (
'True',
'True',
'True')
2885 if (isinstance(selection_cuts, str)):
2886 selection_cuts = (selection_cuts, selection_cuts, selection_cuts)
2888 roe_cuts =
'isInRestOfEvent > 0'
2889 fillConvertedPhotonsList(
'gamma:v0_roe -> e+ e-', f
'{selection_cuts[0]} and {roe_cuts}',
2891 fillParticleList(
'K_S0:v0_roe -> pi+ pi-', f
'{selection_cuts[1]} and {roe_cuts}',
2893 fillParticleList(
'Lambda0:v0_roe -> p+ pi-', f
'{selection_cuts[2]} and {roe_cuts}',
2895 fitter = fitter.lower()
2896 if (fitter !=
'treefit' and fitter !=
'kfit'):
2897 B2WARNING(
'Argument "fitter" in updateROEUsingV0Lists has only "treefit" and "kfit" options, '
2898 f
'but "{fitter}" was provided! TreeFitter will be used instead.')
2900 from vertex
import kFit, treeFit
2901 for v0
in [
'gamma:v0_roe',
'K_S0:v0_roe',
'Lambda0:v0_roe']:
2902 if (apply_mass_fit
and fitter ==
'kfit'):
2903 kFit(v0, conf_level=0.0, fit_type=
'massvertex', path=roe_path)
2904 if (apply_mass_fit
and fitter ==
'treefit'):
2905 treeFit(v0, conf_level=0.0, massConstraint=[v0.split(
':')[0]], path=roe_path)
2906 optimizeROEWithV0(v0, mask_names,
'', path=roe_path)
2907 path.for_each(
'RestOfEvent',
'RestOfEvents', roe_path)
2910def printROEInfo(mask_names=None, full_print=False,
2911 unpackComposites=True, path=None):
2913 This function prints out the information for the current ROE, so it should only be used
in the for_each path.
2914 It prints out basic ROE object info.
2916 If mask names are provided, specific information
for those masks will be printed out.
2918 It
is also possible to
print out all particles
in a given mask
if the
2919 'full_print' is set to
True.
2921 @param mask_names array of ROEMask names
for printing out info
2922 @param unpackComposites
if true, replace composite particles by their daughters
2923 @param full_print
print out particles
in mask
2924 @param path modules are added to this path
2927 if mask_names
is None:
2929 printMask = register_module(
'RestOfEventPrinter')
2930 printMask.set_name(
'RestOfEventPrinter')
2931 printMask.param(
'maskNames', mask_names)
2932 printMask.param(
'fullPrint', full_print)
2933 printMask.param(
'unpackComposites', unpackComposites)
2934 path.add_module(printMask)
2937def buildContinuumSuppression(list_name, roe_mask, path):
2939 Creates for each Particle
in the given ParticleList a ContinuumSuppression
2940 dataobject
and makes basf2 relation between them.
2942 :param list_name: name of the input ParticleList
2943 :param roe_mask: name of the ROE mask
2944 :param path: modules are added to this path
2947 qqBuilder = register_module('ContinuumSuppressionBuilder')
2948 qqBuilder.set_name(
'QQBuilder_' + list_name)
2949 qqBuilder.param(
'particleList', list_name)
2950 qqBuilder.param(
'ROEMask', roe_mask)
2951 path.add_module(qqBuilder)
2956 Removes all Particles that are not in a given list of ParticleLists (
or daughters of those).
2957 All relations
from/to Particles, daughter indices,
and other ParticleLists are fixed.
2959 @param lists_to_keep Keep the Particles
and their daughters
in these ParticleLists.
2960 @param path modules are added to this path
2963 mod = register_module('RemoveParticlesNotInLists')
2964 mod.param(
'particleLists', lists_to_keep)
2965 path.add_module(mod)
2968def inclusiveBtagReconstruction(upsilon_list_name, bsig_list_name, btag_list_name, input_lists_names, path):
2970 Reconstructs Btag from particles
in given ParticleLists which do
not share any final state particles (mdstSource)
with Bsig.
2972 @param upsilon_list_name Name of the ParticleList to be filled
with 'Upsilon(4S) -> B:sig anti-B:tag'
2973 @param bsig_list_name Name of the Bsig ParticleList
2974 @param btag_list_name Name of the Bsig ParticleList
2975 @param input_lists_names List of names of the ParticleLists which are used to reconstruct Btag
from
2978 btag = register_module('InclusiveBtagReconstruction')
2979 btag.set_name(
'InclusiveBtagReconstruction_' + bsig_list_name)
2980 btag.param(
'upsilonListName', upsilon_list_name)
2981 btag.param(
'bsigListName', bsig_list_name)
2982 btag.param(
'btagListName', btag_list_name)
2983 btag.param(
'inputListsNames', input_lists_names)
2984 path.add_module(btag)
2987def selectDaughters(particle_list_name, decay_string, path):
2989 Redefine the Daughters of a particle: select from decayString
2991 @param particle_list_name input particle list
2992 @param decay_string
for selecting the Daughters to be preserved
2995 seld = register_module('SelectDaughters')
2996 seld.set_name(
'SelectDaughters_' + particle_list_name)
2997 seld.param(
'listName', particle_list_name)
2998 seld.param(
'decayString', decay_string)
2999 path.add_module(seld)
3002def markDuplicate(particleList, prioritiseV0, path):
3004 Call DuplicateVertexMarker to find duplicate particles in a list
and
3005 flag the ones that should be kept
3007 @param particleList input particle list
3008 @param prioritiseV0
if true, give V0s a higher priority
3011 markdup = register_module('DuplicateVertexMarker')
3012 markdup.param(
'particleList', particleList)
3013 markdup.param(
'prioritiseV0', prioritiseV0)
3014 path.add_module(markdup)
3017PI0ETAVETO_COUNTER = 0
3020def oldwritePi0EtaVeto(
3023 workingDirectory='.',
3024 pi0vetoname='Pi0_Prob',
3025 etavetoname='Eta_Prob',
3031 Give pi0/eta probability for hard photon.
3033 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.
3035 The current default weight files are optimised using MC9.
3036 The input variables are
as below. Aliases are set to some variables during training.
3038 * M: pi0/eta candidates Invariant mass
3039 * lowE: soft photon energy
in lab frame
3040 * cTheta: soft photon ECL cluster
's polar angle
3041 * Zmva: soft photon output of MVA using Zernike moments of the cluster
3042 * minC2Hdist: soft photon distance from eclCluster to nearest point on nearest Helix at the ECL cylindrical radius
3044 If you don
't have weight files in your workingDirectory,
3045 these files are downloaded from database to your workingDirectory automatically.
3046 Please refer to analysis/examples/tutorials/B2A306-B02RhoGamma-withPi0EtaVeto.py
3047 about how to use this function.
3050 Please don
't use following ParticleList names elsewhere:
3052 ``gamma:HARDPHOTON``, ``pi0:PI0VETO``, ``eta:ETAVETO``,
3053 ``gamma:PI0SOFT + str(PI0ETAVETO_COUNTER)``, ``gamma:ETASOFT + str(PI0ETAVETO_COUNTER)``
3055 Please don't use ``lowE``, ``cTheta``, ``Zmva``, ``minC2Hdist`` as alias elsewhere.
3057 @param particleList The input ParticleList
3058 @param decayString specify Particle to be added to the ParticleList
3059 @param workingDirectory The weight file directory
3060 @param downloadFlag whether download default weight files
or not
3061 @param pi0vetoname extraInfo name of pi0 probability
3062 @param etavetoname extraInfo name of eta probability
3063 @param selection Selection criteria that Particle needs meet
in order
for for_each ROE path to
continue
3064 @param path modules are added to this path
3069 B2ERROR(
"The old pi0 / eta veto is not suitable for Belle analyses.")
3074 global PI0ETAVETO_COUNTER
3076 if PI0ETAVETO_COUNTER == 0:
3077 from variables
import variables
3078 variables.addAlias(
'lowE',
'daughter(1,E)')
3079 variables.addAlias(
'cTheta',
'daughter(1,clusterTheta)')
3080 variables.addAlias(
'Zmva',
'daughter(1,clusterZernikeMVA)')
3081 variables.addAlias(
'minC2Tdist',
'daughter(1,minC2TDist)')
3082 variables.addAlias(
'cluNHits',
'daughter(1,clusterNHits)')
3083 variables.addAlias(
'E9E21',
'daughter(1,clusterE9E21)')
3085 PI0ETAVETO_COUNTER = PI0ETAVETO_COUNTER + 1
3087 roe_path = create_path()
3089 deadEndPath = create_path()
3091 signalSideParticleFilter(particleList, selection, roe_path, deadEndPath)
3093 fillSignalSideParticleList(
'gamma:HARDPHOTON', decayString, path=roe_path)
3095 pi0softname =
'gamma:PI0SOFT'
3096 etasoftname =
'gamma:ETASOFT'
3097 softphoton1 = pi0softname + str(PI0ETAVETO_COUNTER)
3098 softphoton2 = etasoftname + str(PI0ETAVETO_COUNTER)
3102 '[clusterReg==1 and E>0.025] or [clusterReg==2 and E>0.02] or [clusterReg==3 and E>0.02]',
3104 applyCuts(softphoton1,
'abs(clusterTiming)<120', path=roe_path)
3107 '[clusterReg==1 and E>0.035] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.03]',
3109 applyCuts(softphoton2,
'abs(clusterTiming)<120', path=roe_path)
3111 reconstructDecay(
'pi0:PI0VETO -> gamma:HARDPHOTON ' + softphoton1,
'', path=roe_path)
3112 reconstructDecay(
'eta:ETAVETO -> gamma:HARDPHOTON ' + softphoton2,
'', path=roe_path)
3114 if not os.path.isdir(workingDirectory):
3115 os.mkdir(workingDirectory)
3116 B2INFO(
'oldwritePi0EtaVeto: ' + workingDirectory +
' has been created as workingDirectory.')
3118 if not os.path.isfile(workingDirectory +
'/pi0veto.root'):
3120 basf2_mva.download(
'Pi0VetoIdentifier', workingDirectory +
'/pi0veto.root')
3121 B2INFO(
'oldwritePi0EtaVeto: pi0veto.root has been downloaded from database to workingDirectory.')
3123 if not os.path.isfile(workingDirectory +
'/etaveto.root'):
3125 basf2_mva.download(
'EtaVetoIdentifier', workingDirectory +
'/etaveto.root')
3126 B2INFO(
'oldwritePi0EtaVeto: etaveto.root has been downloaded from database to workingDirectory.')
3128 roe_path.add_module(
'MVAExpert', listNames=[
'pi0:PI0VETO'], extraInfoName=
'Pi0Veto',
3129 identifier=workingDirectory +
'/pi0veto.root')
3130 roe_path.add_module(
'MVAExpert', listNames=[
'eta:ETAVETO'], extraInfoName=
'EtaVeto',
3131 identifier=workingDirectory +
'/etaveto.root')
3133 rankByHighest(
'pi0:PI0VETO',
'extraInfo(Pi0Veto)', numBest=1, path=roe_path)
3134 rankByHighest(
'eta:ETAVETO',
'extraInfo(EtaVeto)', numBest=1, path=roe_path)
3136 variableToSignalSideExtraInfo(
'pi0:PI0VETO', {
'extraInfo(Pi0Veto)': pi0vetoname}, path=roe_path)
3137 variableToSignalSideExtraInfo(
'eta:ETAVETO', {
'extraInfo(EtaVeto)': etavetoname}, path=roe_path)
3139 path.for_each(
'RestOfEvent',
'RestOfEvents', roe_path)
3145 mode='standardMC15rd',
3149 hardParticle='gamma',
3150 pi0PayloadNameOverride=None,
3151 pi0SoftPhotonCutOverride=None,
3152 etaPayloadNameOverride=None,
3153 etaSoftPhotonCutOverride=None,
3154 requireSoftPhotonIsInROE=False,
3155 pi0Selection='[0.03 < M < 0.23]',
3156 etaSelection='[0.25 < M < 0.75]'
3159 Give pi0/eta probability for hard photon.
3161 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.
3162 For MC15rd weight files, the BtoXGamma skim
is applied during the MVA training.
3164 The current default weight files are optimised using MC15rd. The weight files
for MC12 (last version) are still available.
3166 The input variables of the mva training
for pi0 veto using MC15rd are:
3168 * M: Invariant mass of pi0 candidates
3169 * cosHelicityAngleMomentum: Cosine of angle between momentum difference of the photons
in the pi0 rest frame
3170 and momentum of pi0
in lab frame
3171 * daughter(1,E): soft photon energy
in lab frame
3172 * daughter(1,clusterTheta): soft photon ECL cluster
's polar angle
3173 * daughter(1,clusterLAT): soft photon lateral energy distribution
3175 The input variables of the mva training for eta veto using MC15rd are:
3177 * M: Invariant mass of eta candidates
3178 * cosHelicityAngleMomentum: Cosine of angle between momentum difference of the photons
in the eta rest frame
3179 and momentum of eta
in lab frame
3180 * daughter(1,E): soft photon energy
in lab frame
3181 * daughter(1,clusterTheta): soft photon ECL cluster
's polar angle
3182 * daughter(1,clusterLAT): soft photon lateral energy distribution
3183 * daughter(1,clusterNHits): soft photon total crystal weights sum(w_i) with w_i<=1
3184 * daughter(1,clusterE1E9): soft photon ratio between energies of central crystal
and inner 3x3 crystals
3185 * daughter(1,clusterE9E21): soft photon ratio of energies
in inner 3x3 crystals
and 5x5 crystals without corners
3186 * daughter(1,clusterSecondMoment): soft photon second moment
3187 * daughter(1,clusterAbsZernikeMoment40): soft photon Zernike moment 40
3188 * daughter(1,clusterAbsZernikeMoment51): soft photon Zernike moment 51
3190 The input variables of the mva training using MC12 are:
3192 * M: Invariant mass of pi0/eta candidates
3193 * daughter(1,E): soft photon energy
in lab frame
3194 * daughter(1,clusterTheta): soft photon ECL cluster
's polar angle
3195 * daughter(1,minC2TDist): soft photon distance from eclCluster to nearest point on nearest Helix at the ECL cylindrical radius
3196 * daughter(1,clusterZernikeMVA): soft photon output of MVA using Zernike moments of the cluster
3197 * daughter(1,clusterNHits): soft photon total crystal weights sum(w_i)
with w_i<=1
3198 * daughter(1,clusterE9E21): soft photon ratio of energies
in inner 3x3 crystals
and 5x5 crystals without corners
3199 * cosHelicityAngleMomentum: Cosine of angle between momentum difference of the photons
in the pi0/eta rest frame
3200 and momentum of pi0/eta
in lab frame
3202 The following strings are available
for mode:
3204 * standard: loose energy cut
and no clusterNHits cut are applied to soft photon
3205 * tight: tight energy cut
and no clusterNHits cut are applied to soft photon
3206 * cluster: loose energy cut
and clusterNHits cut are applied to soft photon
3207 * both: tight energy cut
and clusterNHits cut are applied to soft photon
3208 * standardMC15rd: loose energy cut
is applied to soft photon
and the weight files are trained using MC15rd
3209 * tightMC15rd: tight energy cut
is applied to soft photon
and the weight files are trained using MC15rd
3211 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
3212 `pi0Prob`/`etaProb`. Otherwise, it
is available
as '{Pi0, Eta}ProbOrigin',
'{Pi0, Eta}ProbTightEnergyThreshold',
'{Pi0,
3213 Eta}ProbLargeClusterSize', '{Pi0, Eta}ProbTightEnergyThresholdAndLargeClusterSize
', '{Pi0, Eta}ProbOriginMC15rd
', or
3214 '{Pi0, Eta}ProbTightEnergyThresholdMC15rd' for the six modes described above,
with the chosen suffix appended. If one would
3215 like to call this veto twice
in one script, add suffix
in the second time!
3216 The second highest probability of the pi0/eta veto also
is stored
as an extraInfo,
with a prefix of
'second' to the previous
3217 ones, e.g. secondPi0ProbOrigin{suffix}. This can be used to do validation/systematics study.
3220 Please don
't use following ParticleList names elsewhere:
3222 ``gamma:HardPhoton``,
3223 ``gamma:Pi0Soft + ListName + '_' + particleList.replace(
':',
'_')``,
3224 ``gamma:EtaSoft + ListName +
'_' + particleList.replace(
':',
'_')``,
3225 ``pi0:EtaVeto + ListName``,
3226 ``eta:EtaVeto + ListName``
3228 @param particleList the input ParticleList
3229 @param decayString specify Particle to be added to the ParticleList
3230 @param mode choose one mode out of
'standardMC15rd',
'tightMC15rd',
'standard',
'tight',
'cluster' and 'both'
3231 @param selection selection criteria that Particle needs meet
in order
for for_each ROE path to
continue
3232 @param path modules are added to this path
3233 @param suffix optional suffix to be appended to the usual extraInfo name
3234 @param hardParticle particle name which
is used to calculate the pi0/eta probability (default
is gamma)
3235 @param pi0PayloadNameOverride specify the payload name of pi0 veto only
if one wants to use non-default one. (default
is None)
3236 @param pi0SoftPhotonCutOverride specify the soft photon selection criteria of pi0 veto only
if one wants to use non-default one.
3238 @param etaPayloadNameOverride specify the payload name of eta veto only
if one wants to use non-default one. (default
is None)
3239 @param etaSoftPhotonCutOverride specify the soft photon selection criteria of eta veto only
if one wants to use non-default one.
3241 @param requireSoftPhotonIsInROE specify
if the soft photons used to build pi0
and eta candidates have to be
in the current ROE
3242 or not. Default
is False, i.e. all soft photons
in the event are used.
3243 @param pi0Selection Selection
for the pi0 reconstruction. Default
is '(0.03 < M < 0.23)'.
3244 @param etaSelection Selection
for the eta reconstruction. Default
is '(0.25 < M < 0.75)'.
3249 B2ERROR(
"The pi0 / eta veto is not suitable for Belle analyses.")
3251 if (requireSoftPhotonIsInROE):
3252 B2WARNING(
"Requiring the soft photon to being in the ROE was not done for the MVA training. "
3253 "Please check the results carefully.")
3254 if (mode ==
'standardMC15rd' or mode ==
'tightMC15rd'):
3255 if (pi0Selection !=
'[0.03 < M < 0.23]' or etaSelection !=
'[0.25 < M < 0.75]'):
3257 "Personal selection criteria for the pi0 or the eta during reconstructDecay were not used during the MVA training. "
3258 "Please check the results carefully.")
3260 if (pi0Selection !=
'' or etaSelection !=
''):
3262 "Personal selection criteria for the pi0 or the eta during reconstructDecay were not used during the MVA training. "
3263 "Please check the results carefully.")
3265 renameSuffix =
False
3267 for module
in path.modules():
3268 if module.type() ==
"SubEvent" and not renameSuffix:
3269 for subpath
in [p.values
for p
in module.available_params()
if p.name ==
"path"]:
3272 for submodule
in subpath.modules():
3273 if f
'{hardParticle}:HardPhoton{suffix}' in submodule.name():
3275 B2WARNING(
"Same extension already used in writePi0EtaVeto, append '_0'")
3279 roe_path = create_path()
3280 deadEndPath = create_path()
3281 signalSideParticleFilter(particleList, selection, roe_path, deadEndPath)
3282 fillSignalSideParticleList(f
'{hardParticle}:HardPhoton{suffix}', decayString, path=roe_path)
3284 dictListName = {
'standard':
'Origin',
3285 'tight':
'TightEnergyThreshold',
3286 'cluster':
'LargeClusterSize',
3287 'both':
'TightEnrgyThresholdAndLargeClusterSize',
3288 'standardMC15rd':
'OriginMC15rd',
3289 'tightMC15rd':
'TightEnergyThresholdMC15rd'}
3291 dictPi0EnergyCut = {
3292 'standard':
'[[clusterReg==1 and E>0.025] or [clusterReg==2 and E>0.02] or [clusterReg==3 and E>0.02]]',
3293 'tight':
'[[clusterReg==1 and E>0.03] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.04]]',
3294 'cluster':
'[[clusterReg==1 and E>0.025] or [clusterReg==2 and E>0.02] or [clusterReg==3 and E>0.02]]',
3295 'both':
'[[clusterReg==1 and E>0.03] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.04]]',
3296 'standardMC15rd':
'[[clusterReg==1 and E>0.0225] or [clusterReg==2 and E>0.02] or [clusterReg==3 and E>0.02]]',
3297 'tightMC15rd':
'[[clusterReg==1 and E>0.03] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.04]]'}
3299 dictEtaEnergyCut = {
3300 'standard':
'[[clusterReg==1 and E>0.035] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.03]]',
3301 'tight':
'[[clusterReg==1 and E>0.06] or [clusterReg==2 and E>0.06] or [clusterReg==3 and E>0.06]]',
3302 'cluster':
'[[clusterReg==1 and E>0.035] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.03]]',
3303 'both':
'[[clusterReg==1 and E>0.06] or [clusterReg==2 and E>0.06] or [clusterReg==3 and E>0.06]]',
3304 'standardMC15rd':
'[[clusterReg==1 and E>0.0225] or [clusterReg==2 and E>0.02] or [clusterReg==3 and E>0.02]]',
3305 'tightMC15rd':
'[[clusterReg==1 and E>0.03] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.04]]'}
3307 dictNHitsTimingCut = {
'standard':
'clusterNHits >= 0 and abs(clusterTiming)<clusterErrorTiming',
3308 'tight':
'clusterNHits >= 0 and abs(clusterTiming)<clusterErrorTiming',
3309 'cluster':
'clusterNHits >= 2 and abs(clusterTiming)<clusterErrorTiming',
3310 'both':
'clusterNHits >= 2 and abs(clusterTiming)<clusterErrorTiming',
3311 'standardMC15rd':
'clusterNHits > 1.5 and abs(clusterTiming) < 200',
3312 'tightMC15rd':
'clusterNHits > 1.5 and abs(clusterTiming) < 200'}
3314 dictPi0PayloadName = {
'standard':
'Pi0VetoIdentifierStandard',
3315 'tight':
'Pi0VetoIdentifierWithHigherEnergyThreshold',
3316 'cluster':
'Pi0VetoIdentifierWithLargerClusterSize',
3317 'both':
'Pi0VetoIdentifierWithHigherEnergyThresholdAndLargerClusterSize',
3318 'standardMC15rd':
'Pi0VetoIdentifierStandardMC15rd',
3319 'tightMC15rd':
'Pi0VetoIdentifierWithHigherEnergyThresholdMC15rd'}
3321 dictEtaPayloadName = {
'standard':
'EtaVetoIdentifierStandard',
3322 'tight':
'EtaVetoIdentifierWithHigherEnergyThreshold',
3323 'cluster':
'EtaVetoIdentifierWithLargerClusterSize',
3324 'both':
'EtaVetoIdentifierWithHigherEnergyThresholdAndLargerClusterSize',
3325 'standardMC15rd':
'EtaVetoIdentifierStandardMC15rd',
3326 'tightMC15rd':
'EtaVetoIdentifierWithHigherEnergyThresholdMC15rd'}
3328 dictPi0ExtraInfoName = {
'standard':
'Pi0ProbOrigin',
3329 'tight':
'Pi0ProbTightEnergyThreshold',
3330 'cluster':
'Pi0ProbLargeClusterSize',
3331 'both':
'Pi0ProbTightEnergyThresholdAndLargeClusterSize',
3332 'standardMC15rd':
'Pi0ProbOriginMC15rd',
3333 'tightMC15rd':
'Pi0ProbTightEnergyThresholdMC15rd'}
3335 dictEtaExtraInfoName = {
'standard':
'EtaProbOrigin',
3336 'tight':
'EtaProbTightEnergyThreshold',
3337 'cluster':
'EtaProbLargeClusterSize',
3338 'both':
'EtaProbTightEnergyThresholdAndLargeClusterSize',
3339 'standardMC15rd':
'EtaProbOriginMC15rd',
3340 'tightMC15rd':
'EtaProbTightEnergyThresholdMC15rd'}
3342 ListName = dictListName[mode]
3343 Pi0EnergyCut = dictPi0EnergyCut[mode]
3344 EtaEnergyCut = dictEtaEnergyCut[mode]
3345 NHitsTimingCut = dictNHitsTimingCut[mode]
3346 Pi0PayloadName = dictPi0PayloadName[mode]
3347 EtaPayloadName = dictEtaPayloadName[mode]
3348 Pi0ExtraInfoName = dictPi0ExtraInfoName[mode]
3349 EtaExtraInfoName = dictEtaExtraInfoName[mode]
3352 if pi0PayloadNameOverride
is not None:
3353 Pi0PayloadName = pi0PayloadNameOverride
3354 B2WARNING(
"You're using personal weight files, be careful. ")
3355 if pi0SoftPhotonCutOverride
is None:
3356 Pi0SoftPhotonCut = Pi0EnergyCut +
' and ' + NHitsTimingCut
3358 Pi0SoftPhotonCut = pi0SoftPhotonCutOverride
3359 B2WARNING(
"You're applying personal cuts on the soft photon candidates, be careful. ")
3361 if requireSoftPhotonIsInROE:
3362 Pi0SoftPhotonCut +=
' and isInRestOfEvent==1'
3365 pi0soft = f
'gamma:Pi0Soft{suffix}' + ListName +
'_' + particleList.replace(
':',
'_')
3367 fillParticleList(pi0soft, Pi0SoftPhotonCut, path=roe_path)
3369 reconstructDecay(
'pi0:Pi0Veto' + ListName + suffix + f
' -> {hardParticle}:HardPhoton{suffix} ' + pi0soft, pi0Selection,
3370 allowChargeViolation=
True, path=roe_path)
3372 roe_path.add_module(
'MVAExpert', listNames=[
'pi0:Pi0Veto' + ListName + suffix],
3373 extraInfoName=Pi0ExtraInfoName, identifier=Pi0PayloadName)
3376 'pi0:Pi0Veto' + ListName + suffix,
3377 'extraInfo(' + Pi0ExtraInfoName +
')',
3379 outputVariable=
"Pi0VetoRank",
3381 cutAndCopyList(outputListName=
'pi0:Pi0VetoFirst' + ListName + suffix,
3382 inputListName=
'pi0:Pi0Veto' + ListName + suffix,
3383 cut=
'extraInfo(Pi0VetoRank)==1',
3385 variableToSignalSideExtraInfo(
'pi0:Pi0VetoFirst' + ListName + suffix,
3386 {
'extraInfo(' + Pi0ExtraInfoName +
')': Pi0ExtraInfoName + suffix}, path=roe_path)
3388 cutAndCopyList(outputListName=
'pi0:Pi0VetoSecond' + ListName + suffix,
3389 inputListName=
'pi0:Pi0Veto' + ListName + suffix,
3390 cut=
'extraInfo(Pi0VetoRank)==2',
3392 variableToSignalSideExtraInfo(
'pi0:Pi0VetoSecond' + ListName + suffix,
3393 {
'extraInfo(' + Pi0ExtraInfoName +
')':
'second' + Pi0ExtraInfoName + suffix}, path=roe_path)
3396 if etaPayloadNameOverride
is not None:
3397 EtaPayloadName = etaPayloadNameOverride
3398 B2WARNING(
"You're using personal weight files, be careful. ")
3399 if etaSoftPhotonCutOverride
is None:
3400 EtaSoftPhotonCut = EtaEnergyCut +
' and ' + NHitsTimingCut
3402 EtaSoftPhotonCut = etaSoftPhotonCutOverride
3403 B2WARNING(
"You're applying personal cuts on the soft photon candidates, be careful. ")
3405 if requireSoftPhotonIsInROE:
3406 EtaSoftPhotonCut +=
' and isInRestOfEvent==1'
3408 etasoft = f
'gamma:EtaSoft{suffix}' + ListName +
'_' + particleList.replace(
':',
'_')
3409 fillParticleList(etasoft, EtaSoftPhotonCut, path=roe_path)
3410 reconstructDecay(
'eta:EtaVeto' + ListName + suffix + f
' -> {hardParticle}:HardPhoton{suffix} ' + etasoft, etaSelection,
3411 allowChargeViolation=
True, path=roe_path)
3412 roe_path.add_module(
'MVAExpert', listNames=[
'eta:EtaVeto' + ListName + suffix],
3413 extraInfoName=EtaExtraInfoName, identifier=EtaPayloadName)
3415 'eta:EtaVeto' + ListName + suffix,
3416 'extraInfo(' + EtaExtraInfoName +
')',
3418 outputVariable=
"EtaVetoRank",
3420 cutAndCopyList(outputListName=
'eta:EtaVetoFirst' + ListName + suffix,
3421 inputListName=
'eta:EtaVeto' + ListName + suffix,
3422 cut=
'extraInfo(EtaVetoRank)==1',
3424 variableToSignalSideExtraInfo(
'eta:EtaVetoFirst' + ListName + suffix,
3425 {
'extraInfo(' + EtaExtraInfoName +
')': EtaExtraInfoName + suffix}, path=roe_path)
3426 cutAndCopyList(outputListName=
'eta:EtaVetoSecond' + ListName + suffix,
3427 inputListName=
'eta:EtaVeto' + ListName + suffix,
3428 cut=
'extraInfo(EtaVetoRank)==2',
3430 variableToSignalSideExtraInfo(
'eta:EtaVetoSecond' + ListName + suffix,
3431 {
'extraInfo(' + EtaExtraInfoName +
')':
'second' + EtaExtraInfoName + suffix}, path=roe_path)
3433 path.for_each(
'RestOfEvent',
'RestOfEvents', roe_path)
3436def lowEnergyPi0Identification(pi0List, gammaList, payloadNameSuffix,
3439 Calculate low-energy pi0 identification.
3440 The result is stored
as ExtraInfo ``lowEnergyPi0Identification``
for
3444 pi0List (str): Pi0 list.
3446 gammaList (str): Gamma list. First, an energy cut E > 0.2
is applied to the photons
from this list.
3447 Then, all possible combinations
with a pi0 daughter photon are formed
except the one
3448 corresponding to the reconstructed pi0.
3449 The maximum low-energy pi0 veto value
is calculated
for such photon pairs
3450 and used
as one of the input variables
for the identification classifier.
3452 payloadNameSuffix (str): Payload name suffix. The weight payloads are stored
in the analysis
global
3453 tag
and have the following names:\n
3454 * ``
'LowEnergyPi0Veto' + payloadNameSuffix``
3455 * ``
'LowEnergyPi0Identification' + payloadNameSuffix``\n
3456 The possible suffixes are:\n
3457 * ``
'Belle1'``
for Belle data.
3458 * ``
'Belle2Release5'``
for Belle II release 5 data (MC14, proc12, buckets 16 - 25).
3459 * ``
'Belle2Release6'``
for Belle II release 6 data (MC15, proc13, buckets 26 - 36).
3461 path (basf2.Path): Module path.
3465 gammaListVeto = f
'{gammaList}_pi0veto'
3466 cutAndCopyList(gammaListVeto, gammaList,
'E > 0.2', path=path)
3468 payload_name =
'LowEnergyPi0Veto' + payloadNameSuffix
3469 path.add_module(
'LowEnergyPi0VetoExpert', identifier=payload_name,
3470 VetoPi0Daughters=
True, GammaListName=gammaListVeto,
3472 payload_name =
'LowEnergyPi0Identification' + payloadNameSuffix
3473 path.add_module(
'LowEnergyPi0IdentificationExpert',
3474 identifier=payload_name, Pi0ListName=pi0List,
3478def getNeutralHadronGeomMatches(
3482 efficiencyCorrectionKl=0.83,
3483 efficiencyCorrectionNeutrons=1.0,
3486 For an ECL-based list, assign the mcdistanceKL and mcdistanceNeutron variables that correspond
3487 to the distance to the closest MC KL
and neutron, respectively.
3488 @param particleLists the input ParticleLists, must be ECL-based lists (e.g. photons)
3489 @param addKL (default
True) add distance to MC KL
3490 @param addNeutrons (default
False) add distance to MC neutrons
3491 @param efficiencyCorrectionKl (default 0.83) apply overall efficiency correction
3492 @param efficiencyCorrectionNeutrons (default 1.0) apply overall efficiency correction
3493 @param path modules are added to this path
3495 from ROOT
import Belle2
3500 "NeutralHadronMatcher",
3501 particleLists=particleLists,
3502 mcPDGcode=Const.Klong.getPDGCode(),
3503 efficiencyCorrection=efficiencyCorrectionKl)
3506 "NeutralHadronMatcher",
3507 particleLists=particleLists,
3508 mcPDGcode=Const.neutron.getPDGCode(),
3509 efficiencyCorrection=efficiencyCorrectionNeutrons)
3512def getBeamBackgroundProbability(particleList, weight, path=None):
3514 Assign a probability to each ECL cluster as being signal like (1) compared to beam background like (0)
3515 @param particleList the input ParticleList, must be a photon list
3516 @param weight type of weight file to use
3517 @param path modules are added to this path
3522 B2WARNING(
"weight type must be 'Belle' for b2bii.")
3524 path.add_module(
'MVAExpert',
3525 listNames=particleList,
3526 extraInfoName=
'beamBackgroundSuppression',
3527 identifier=f
'BeamBackgroundMVA_{weight}')
3530def getFakePhotonProbability(particleList, weight, path=None):
3532 Assign a probability to each ECL cluster as being signal like (1) compared to fake photon like (0)
3533 @param particleList the input ParticleList, must be a photon list
3534 @param weight type of weight file to use
3535 @param path modules are added to this path
3540 B2WARNING(
"weight type must be 'Belle' for b2bii.")
3542 path.add_module(
'MVAExpert',
3543 listNames=particleList,
3544 extraInfoName=
'fakePhotonSuppression',
3545 identifier=f
'FakePhotonMVA_{weight}')
3548def buildEventKinematics(inputListNames=None, default_cleanup=True, custom_cuts=None,
3549 chargedPIDPriors=None, fillWithMostLikely=False, path=None):
3551 Calculates the global kinematics of the event (visible energy, missing momentum, missing mass...)
3552 using ParticleLists provided. If no ParticleList
is provided, default ParticleLists are used
3553 (all track
and all hits
in ECL without associated track).
3555 The visible energy missing values are
3556 stored
in a EventKinematics dataobject.
3558 @param inputListNames list of ParticleLists used to calculate the
global event kinematics.
3559 If the list
is empty, default ParticleLists pi+:evtkin
and gamma:evtkin are filled.
3560 @param fillWithMostLikely
if True, the module uses the most likely particle mass hypothesis
for charged particles
3561 according to the PID likelihood
and the option inputListNames will be ignored.
3562 @param chargedPIDPriors The prior PID fractions, that are used to regulate
3563 amount of certain charged particle species, should be a list of
3564 six floats
if not None. The order of particle types
is
3565 the following: [e-, mu-, pi-, K-, p+, d+]
3566 @param default_cleanup
if True and either inputListNames empty
or fillWithMostLikely
True, default clean up cuts are applied
3567 @param custom_cuts tuple of selection cut strings of form (trackCuts, photonCuts), default
is None,
3568 which would result
in a standard predefined selection cuts
3569 @param path modules are added to this path
3572 if inputListNames
is None:
3574 trackCuts =
'pt > 0.1'
3575 trackCuts +=
' and thetaInCDCAcceptance'
3576 trackCuts +=
' and abs(dz) < 3'
3577 trackCuts +=
' and dr < 0.5'
3579 gammaCuts =
'E > 0.05'
3580 gammaCuts +=
' and thetaInCDCAcceptance'
3582 gammaCuts +=
' and abs(clusterTiming) < 200'
3583 if (custom_cuts
is not None):
3584 trackCuts, gammaCuts = custom_cuts
3586 if fillWithMostLikely:
3587 from stdCharged
import stdMostLikely
3588 stdMostLikely(chargedPIDPriors,
'_evtkin', path=path)
3589 inputListNames = [f
'{ptype}:mostlikely_evtkin' for ptype
in [
'K+',
'p+',
'e+',
'mu+',
'pi+']]
3591 copyList(
'gamma:evtkin',
'gamma:mdst', path=path)
3593 fillParticleList(
'gamma:evtkin',
'', path=path)
3594 inputListNames += [
'gamma:evtkin']
3596 B2INFO(
"Using default cleanup in EventKinematics module.")
3597 for ptype
in [
'K+',
'p+',
'e+',
'mu+',
'pi+']:
3598 applyCuts(f
'{ptype}:mostlikely_evtkin', trackCuts, path=path)
3599 applyCuts(
'gamma:evtkin', gammaCuts, path=path)
3601 B2INFO(
"No cleanup in EventKinematics module.")
3602 if not inputListNames:
3603 B2INFO(
"Creating particle lists pi+:evtkin and gamma:evtkin to get the global kinematics of the event.")
3604 fillParticleList(
'pi+:evtkin',
'', path=path)
3606 copyList(
'gamma:evtkin',
'gamma:mdst', path=path)
3608 fillParticleList(
'gamma:evtkin',
'', path=path)
3609 particleLists = [
'pi+:evtkin',
'gamma:evtkin']
3611 if (custom_cuts
is not None):
3612 B2INFO(
"Using default cleanup in EventKinematics module.")
3613 applyCuts(
'pi+:evtkin', trackCuts, path=path)
3614 applyCuts(
'gamma:evtkin', gammaCuts, path=path)
3616 B2INFO(
"No cleanup in EventKinematics module.")
3618 particleLists = inputListNames
3620 eventKinematicsModule = register_module(
'EventKinematics')
3621 eventKinematicsModule.set_name(
'EventKinematics_reco')
3622 eventKinematicsModule.param(
'particleLists', particleLists)
3623 path.add_module(eventKinematicsModule)
3626def buildEventKinematicsFromMC(inputListNames=None, selectionCut='', path=None):
3628 Calculates the global kinematics of the event (visible energy, missing momentum, missing mass...)
3629 using generated particles. If no ParticleList
is provided, default generated ParticleLists are used.
3631 @param inputListNames list of ParticleLists used to calculate the
global event kinematics.
3632 If the list
is empty, default ParticleLists are filled.
3633 @param selectionCut optional selection cuts
3634 @param path Path to append the eventKinematics module to.
3637 if inputListNames
is None:
3639 if (len(inputListNames) == 0):
3643 types = [
'gamma',
'e+',
'mu+',
'pi+',
'K+',
'p+',
3646 fillParticleListFromMC(f
"{t}:evtkin_default_gen",
'mcPrimary > 0 and nDaughters == 0',
3647 True,
True, path=path)
3648 if (selectionCut !=
''):
3649 applyCuts(f
"{t}:evtkin_default_gen", selectionCut, path=path)
3650 inputListNames += [f
"{t}:evtkin_default_gen"]
3652 eventKinematicsModule = register_module(
'EventKinematics')
3653 eventKinematicsModule.set_name(
'EventKinematics_gen')
3654 eventKinematicsModule.param(
'particleLists', inputListNames)
3655 eventKinematicsModule.param(
'usingMC',
True)
3656 path.add_module(eventKinematicsModule)
3659def buildEventShape(inputListNames=None,
3660 default_cleanup=True,
3666 harmonicMoments=True,
3670 checkForDuplicates=False,
3673 Calculates the event-level shape quantities (thrust, sphericity, Fox-Wolfram moments...)
3674 using the particles in the lists provided by the user. If no particle list
is provided,
3675 the function will internally create a list of good tracks
and a list of good photons
3676 with (optionally) minimal quality cuts.
3679 The results of the calculation are then stored into the EventShapeContainer dataobject,
3680 and are accessible using the variables of the EventShape group.
3682 The user can switch the calculation of certain quantities on
or off to save computing
3683 time. By default the calculation of the high-order moments (5-8)
is turned off.
3684 Switching off an option will make the corresponding variables
not available.
3687 The user can provide
as many particle lists
as needed, using also composite particles.
3688 In these cases, it
is recommended to activate the checkForDuplicates flag since it
3689 will eliminate duplicates, e.g.,
if the same track
is provided multiple times
3690 (either
with different mass hypothesis
or once
as an independent particle
and once
3691 as daughter of a composite particle). The first occurrence will be used
in the
3692 calculations so the order
in which the particle lists are given
as well
as within
3693 the particle lists matters.
3695 @param inputListNames List of ParticleLists used to calculate the
3696 event shape variables. If the list
is empty the default
3697 particleLists pi+:evtshape
and gamma:evtshape are filled.
3698 @param default_cleanup If
True, applies standard cuts on pt
and cosTheta when
3699 defining the internal lists. This option
is ignored
if the
3700 particleLists are provided by the user.
3701 @param custom_cuts tuple of selection cut strings of form (trackCuts, photonCuts), default
is None,
3702 which would result
in a standard predefined selection cuts
3703 @param path Path to append the eventShape modules to.
3704 @param thrust Enables the calculation of thrust-related quantities (CLEO
3705 cones, Harmonic moments, jets).
3706 @param collisionAxis Enables the calculation of the quantities related to the
3708 @param foxWolfram Enables the calculation of the Fox-Wolfram moments.
3709 @param harmonicMoments Enables the calculation of the Harmonic moments
with respect
3710 to both the thrust axis
and,
if collisionAxis =
True, the collision axis.
3711 @param allMoments If
True, calculates also the FW
and harmonic moments
from order
3712 5 to 8 instead of the low-order ones only.
3713 @param cleoCones Enables the calculation of the CLEO cones
with respect to both the thrust
3714 axis
and,
if collisionAxis =
True, the collision axis.
3715 @param jets Enables the calculation of the hemisphere momenta
and masses.
3716 Requires thrust =
True.
3717 @param sphericity Enables the calculation of the sphericity-related quantities.
3718 @param checkForDuplicates Perform a check
for duplicate particles before adding them. Regardless of the value of this option,
3719 it
is recommended to consider sanitizing the lists you are passing to the function since this will
3720 speed up the processing.
3724 if inputListNames
is None:
3726 trackCuts =
'pt > 0.1'
3727 trackCuts +=
' and thetaInCDCAcceptance'
3728 trackCuts +=
' and abs(dz) < 3.0'
3729 trackCuts +=
' and dr < 0.5'
3731 gammaCuts =
'E > 0.05'
3732 gammaCuts +=
' and thetaInCDCAcceptance'
3734 gammaCuts +=
' and abs(clusterTiming) < 200'
3735 if (custom_cuts
is not None):
3736 trackCuts, gammaCuts = custom_cuts
3738 if not inputListNames:
3739 B2INFO(
"Creating particle lists pi+:evtshape and gamma:evtshape to get the event shape variables.")
3740 fillParticleList(
'pi+:evtshape',
'', path=path)
3742 copyList(
'gamma:evtshape',
'gamma:mdst', path=path)
3748 particleLists = [
'pi+:evtshape',
'gamma:evtshape']
3751 if (custom_cuts
is not None):
3752 B2INFO(
"Applying standard cuts")
3753 applyCuts(
'pi+:evtshape', trackCuts, path=path)
3755 applyCuts(
'gamma:evtshape', gammaCuts, path=path)
3757 B2WARNING(
"Creating the default lists with no cleanup.")
3759 particleLists = inputListNames
3761 eventShapeModule = register_module(
'EventShapeCalculator')
3762 eventShapeModule.set_name(
'EventShape')
3763 eventShapeModule.param(
'particleListNames', particleLists)
3764 eventShapeModule.param(
'enableAllMoments', allMoments)
3765 eventShapeModule.param(
'enableCleoCones', cleoCones)
3766 eventShapeModule.param(
'enableCollisionAxis', collisionAxis)
3767 eventShapeModule.param(
'enableFoxWolfram', foxWolfram)
3768 eventShapeModule.param(
'enableJets', jets)
3769 eventShapeModule.param(
'enableHarmonicMoments', harmonicMoments)
3770 eventShapeModule.param(
'enableSphericity', sphericity)
3771 eventShapeModule.param(
'enableThrust', thrust)
3772 eventShapeModule.param(
'checkForDuplicates', checkForDuplicates)
3774 path.add_module(eventShapeModule)
3777def labelTauPairMC(printDecayInfo=False, path=None, TauolaBelle=False, mapping_minus=None, mapping_plus=None):
3779 Search tau leptons into the MC information of the event. If confirms it's a generated tau pair decay,
3780 labels the decay generated of the positive and negative leptons using the ID of KKMC tau decay table.
3782 @param printDecayInfo: If true, prints ID
and prong of each tau lepton
in the event.
3783 @param path: module
is added to this path
3784 @param TauolaBelle:
if False, TauDecayMode
is set. If
True, TauDecayMarker
is set.
3785 @param mapping_minus:
if None, the map
is the default one,
else the path
for the map
is given by the user
for tau-
3786 @param mapping_plus:
if None, the map
is the default one,
else the path
for the map
is given by the user
for tau+
3789 from basf2
import find_file
3795 m_printmode =
'default'
3797 if mapping_minus
is None:
3798 mp_file_minus = find_file(
'data/analysis/modules/TauDecayMode/map_tauminus.txt')
3800 mp_file_minus = mapping_minus
3802 if mapping_plus
is None:
3803 mp_file_plus = find_file(
'data/analysis/modules/TauDecayMode/map_tauplus.txt')
3805 mp_file_plus = mapping_plus
3807 path.add_module(
'TauDecayMode', printmode=m_printmode, file_minus=mp_file_minus, file_plus=mp_file_plus)
3810 tauDecayMarker = register_module(
'TauDecayMarker')
3811 tauDecayMarker.set_name(
'TauDecayMarker_')
3813 path.add_module(tauDecayMarker, printDecayInfo=printDecayInfo)
3816def tagCurlTracks(particleLists,
3826 The cut selector is not calibrated
with Belle II data
and should
not be used without extensive study.
3828 Identifies curl tracks
and tags them
with extraInfo(isCurl=1)
for later removal.
3829 For Belle data
with a `b2bii` analysis the available cut based selection
is described
in `BN1079`_.
3831 .. _BN1079: https://belle.kek.jp/secured/belle_note/gn1079/bn1079.pdf
3834 The module loops over all particles
in a given list
with a transverse momentum below the pre-selection **ptCut**
3835 and assigns them to bundles based on the response of the chosen **selector**
and the required minimum response set by the
3836 **responseCut**. Once all particles are assigned they are ranked by 25dr^2+dz^2. All but the lowest are tagged
3837 with extraInfo(isCurl=1) to allow
for later removal by cutting the list
or removing these
from ROE
as
3841 @param particleLists: list of particle lists to check
for curls.
3842 @param mcTruth: bool flag to additionally assign particles
with extraInfo(isTruthCurl)
and
3843 extraInfo(truthBundleSize). To calculate these particles are assigned to bundles by their
3844 genParticleIndex then ranked
and tagged
as normal.
3845 @param responseCut: float min classifier response that considers two tracks to come
from the same particle.
3846 If set to ``-1`` a cut value optimised to maximise the accuracy on a BBbar sample
is used.
3847 Note
'cut' selector
is binary 0/1.
3848 @param selectorType: string name of selector to use. The available options are
'cut' and 'mva'.
3849 It
is strongly recommended to used the
'mva' selection. The
'cut' selection
3850 is based on BN1079
and is only calibrated
for Belle data.
3852 @param ptCut: Pre-selection cut on transverse momentum. Only tracks below that are considered
as curler candidates.
3854 @param expert_train: flag to set training mode
if selector has a training mode (mva).
3855 @param expert_filename: set file name of produced training ntuple (mva).
3856 @param path: module
is added to this path.
3862 if (
not isinstance(particleLists, list)):
3863 particleLists = [particleLists]
3865 curlTagger = register_module(
'CurlTagger')
3866 curlTagger.set_name(
'CurlTagger_')
3867 curlTagger.param(
'particleLists', particleLists)
3868 curlTagger.param(
'belle', belle)
3869 curlTagger.param(
'mcTruth', mcTruth)
3870 curlTagger.param(
'responseCut', responseCut)
3871 if abs(responseCut + 1) < 1e-9:
3872 curlTagger.param(
'usePayloadCut',
True)
3874 curlTagger.param(
'usePayloadCut',
False)
3876 curlTagger.param(
'selectorType', selectorType)
3877 curlTagger.param(
'ptCut', ptCut)
3878 curlTagger.param(
'train', expert_train)
3879 curlTagger.param(
'trainFilename', expert_filename)
3881 path.add_module(curlTagger)
3884def applyChargedPidMVA(particleLists, path, trainingMode, chargeIndependent=False, binaryHypoPDGCodes=(0, 0)):
3886 Use an MVA to perform particle identification for charged stable particles, using the `ChargedPidMVA` module.
3888 The module decorates Particle objects
in the input ParticleList(s)
with variables
3889 containing the appropriate MVA score, which can be used to select candidates by placing a cut on it.
3892 The MVA algorithm used
is a gradient boosted decision tree (**TMVA 4.3.0**, **ROOT 6.20/04**).
3894 The module can perform either
'binary' PID between input S, B particle mass hypotheses according to the following scheme:
3896 * e (11) vs. pi (211)
3897 * mu (13) vs. pi (211)
3898 * pi (211) vs. K (321)
3899 * K (321) vs. pi (211)
3901 ,
or 'global' PID, namely
"one-vs-others" separation. The latter exploits an MVA algorithm trained
in multi-
class mode,
3902 and it
's the default behaviour. Currently, the multi-class training separates the following standard charged hypotheses:
3904 - e (11), mu (13), pi (211), K (321)
3907 In order to run the `ChargedPidMVA` and ensure the most up-to-date MVA training weights are applied,
3908 it
is necessary to append the latest analysis
global tag (GT) to the steering script.
3911 particleLists (list(str)): the input list of DecayStrings, where each selected (^) daughter should correspond to a
3912 standard charged ParticleList, e.g. ``[
'Lambda0:sig -> ^p+ ^pi-',
'J/psi:sig -> ^mu+ ^mu-']``.
3913 One can also directly
pass a list of standard charged ParticleLists,
3914 e.g. ``[
'e+:my_electrons',
'pi+:my_pions']``.
3915 Note that charge-conjugated ParticleLists will automatically be included.
3916 path (basf2.Path): the module
is added to this path.
3917 trainingMode (``Belle2.ChargedPidMVAWeights.ChargedPidMVATrainingMode``): enum identifier of the training mode.
3918 Needed to pick up the correct payload
from the DB. Available choices:
3920 * c_Classification=0
3922 * c_ECL_Classification=2
3923 * c_ECL_Multiclass=3
3924 * c_PSD_Classification=4
3925 * c_PSD_Multiclass=5
3926 * c_ECL_PSD_Classification=6
3927 * c_ECL_PSD_Multiclass=7
3929 chargeIndependent (bool, ``optional``): use a BDT trained on a sample of inclusively charged particles.
3930 binaryHypoPDGCodes (tuple(int, int), ``optional``): the pdgIds of the signal, background mass hypothesis.
3931 Required only
for binary PID mode.
3936 B2ERROR(
"Charged PID via MVA is not available for Belle data.")
3938 from ROOT
import Belle2
3940 TrainingMode = Belle2.ChargedPidMVAWeights.ChargedPidMVATrainingMode
3943 plSet = set(particleLists)
3947 TrainingMode.c_Classification:
3948 {
"mode":
"Classification",
"detector":
"ALL"},
3949 TrainingMode.c_Multiclass:
3950 {
"mode":
"Multiclass",
"detector":
"ALL"},
3951 TrainingMode.c_ECL_Classification:
3952 {
"mode":
"ECL_Classification",
"detector":
"ECL"},
3953 TrainingMode.c_ECL_Multiclass:
3954 {
"mode":
"ECL_Multiclass",
"detector":
"ECL"},
3955 TrainingMode.c_PSD_Classification:
3956 {
"mode":
"PSD_Classification",
"detector":
"ALL"},
3957 TrainingMode.c_PSD_Multiclass:
3958 {
"mode":
"PSD_Multiclass",
"detector":
"ALL"},
3959 TrainingMode.c_ECL_PSD_Classification:
3960 {
"mode":
"ECL_PSD_Classification",
"detector":
"ECL"},
3961 TrainingMode.c_ECL_PSD_Multiclass:
3962 {
"mode":
"ECL_PSD_Multiclass",
"detector":
"ECL"},
3965 if payloadNames.get(trainingMode)
is None:
3966 B2FATAL(
"The chosen training mode integer identifier:\n", trainingMode,
3967 "\nis not supported. Please choose among the following:\n",
3968 "\n".join(f
"{key}:{val.get('mode')}" for key, val
in sorted(payloadNames.items())))
3970 mode = payloadNames.get(trainingMode).get(
"mode")
3971 detector = payloadNames.get(trainingMode).get(
"detector")
3973 payloadName = f
"ChargedPidMVAWeights_{mode}"
3978 Const.electron.getPDGCode():
3979 {
"pName":
"e",
"pFullName":
"electron",
"pNameBkg":
"pi",
"pdgIdBkg": Const.pion.getPDGCode()},
3980 Const.muon.getPDGCode():
3981 {
"pName":
"mu",
"pFullName":
"muon",
"pNameBkg":
"pi",
"pdgIdBkg": Const.pion.getPDGCode()},
3982 Const.pion.getPDGCode():
3983 {
"pName":
"pi",
"pFullName":
"pion",
"pNameBkg":
"K",
"pdgIdBkg": Const.kaon.getPDGCode()},
3984 Const.kaon.getPDGCode():
3985 {
"pName":
"K",
"pFullName":
"kaon",
"pNameBkg":
"pi",
"pdgIdBkg": Const.pion.getPDGCode()},
3986 Const.proton.getPDGCode():
3987 {
"pName":
"p",
"pFullName":
"proton",
"pNameBkg":
"pi",
"pdgIdBkg": Const.pion.getPDGCode()},
3988 Const.deuteron.getPDGCode():
3989 {
"pName":
"d",
"pFullName":
"deuteron",
"pNameBkg":
"pi",
"pdgIdBkg": Const.pion.getPDGCode()},
3992 if binaryHypoPDGCodes == (0, 0):
3995 chargedpid = register_module(
"ChargedPidMVAMulticlass")
3996 chargedpid.set_name(f
"ChargedPidMVAMulticlass_{mode}")
4003 binaryOpts = [(pdgIdSig, info[
"pdgIdBkg"])
for pdgIdSig, info
in stdChargedMap.items()]
4005 if binaryHypoPDGCodes
not in binaryOpts:
4006 B2FATAL(
"No charged pid MVA was trained to separate ", binaryHypoPDGCodes[0],
" vs. ", binaryHypoPDGCodes[1],
4007 ". Please choose among the following pairs:\n",
4008 "\n".join(f
"{opt[0]} vs. {opt[1]}" for opt
in binaryOpts))
4012 if not decayDescriptor.init(name):
4013 raise ValueError(f
"Invalid particle list {name} in applyChargedPidMVA!")
4014 msg = f
"Input ParticleList: {name}"
4015 pdgs = [abs(decayDescriptor.getMother().getPDGCode())]
4016 daughter_pdgs = decayDescriptor.getSelectionPDGCodes()
4017 if len(daughter_pdgs) > 0:
4018 pdgs = daughter_pdgs
4019 for idaughter, pdg
in enumerate(pdgs):
4020 if abs(pdg)
not in binaryHypoPDGCodes:
4022 msg = f
"Selected daughter {idaughter} in ParticleList: {name}"
4024 f
"{msg} (PDG={pdg}) is neither signal ({binaryHypoPDGCodes[0]}) nor background ({binaryHypoPDGCodes[1]}).")
4026 chargedpid = register_module(
"ChargedPidMVA")
4027 chargedpid.set_name(f
"ChargedPidMVA_{binaryHypoPDGCodes[0]}_vs_{binaryHypoPDGCodes[1]}_{mode}")
4028 chargedpid.param(
"sigHypoPDGCode", binaryHypoPDGCodes[0])
4029 chargedpid.param(
"bkgHypoPDGCode", binaryHypoPDGCodes[1])
4031 chargedpid.param(
"particleLists", list(plSet))
4032 chargedpid.param(
"payloadName", payloadName)
4033 chargedpid.param(
"chargeIndependent", chargeIndependent)
4036 if detector ==
"ECL":
4037 chargedpid.param(
"useECLOnlyTraining",
True)
4039 path.add_module(chargedpid)
4042def calculateTrackIsolation(
4046 reference_list_name=None,
4047 vars_for_nearest_part=[],
4048 highest_prob_mass_for_ext=True,
4049 exclude_pid_det_weights=False):
4051 Given an input decay string, compute variables that quantify track helix-based isolation of the charged
4052 stable particles in the input decay chain.
4055 An
"isolation score" can be defined using the distance
4056 of each particle to its closest neighbour, defined
as the segment connecting the two
4057 extrapolated track helices intersection points on a given cylindrical surface.
4058 The distance variables defined
in the `VariableManager`
is named `minET2ETDist`,
4059 the isolation scores are named `minET2ETIsoScore`, `minET2ETIsoScoreAsWeightedAvg`.
4061 The definition of distance
and the number of distances that are calculated per sub-detector
is based on
4062 the following recipe:
4064 * **CDC**:
as the segmentation
is very coarse along :math:`z`,
4065 the distance
is defined
as the cord length on the :math:`(\\rho=R, \\phi)` plane.
4066 A total of 9 distances are calculated: the cylindrical surfaces are defined at radiuses
4067 that correspond to the positions of the 9 CDC wire superlayers: :math:`R_{i}^{\\mathrm{CDC}}~(i \\
in \\{0,...,8\\})`.
4069 * **TOP**:
as there
is no segmentation along :math:`z`,
4070 the distance
is defined
as the cord length on the :math:`(\\rho=R, \\phi)` plane.
4071 Only one distance at the TOP entry radius :math:`R_{0}^{\\mathrm{TOP}}`
is calculated.
4073 * **ARICH**:
as there
is no segmentation along :math:`z`,
4074 the distance
is defined
as the distance on the :math:`(\\rho=R, \\phi)` plane at fixed :math:`z=Z`.
4075 Only one distance at the ARICH photon detector entry coordinate :math:`Z_{0}^{\\mathrm{ARICH}}`
is calculated.
4077 * **ECL**: the distance
is defined on the :math:`(\\rho=R, \\phi, z)` surface
in the barrel,
4078 on the :math:`(\\rho, \\phi, z=Z)` surface
in the endcaps.
4079 Two distances are calculated: one at the ECL entry surface :math:`R_{0}^{\\mathrm{ECL}}` (barrel),
4080 :math:`Z_{0}^{\\mathrm{ECL}}` (endcaps),
and one at :math:`R_{1}^{\\mathrm{ECL}}` (barrel),
4081 :math:`Z_{1}^{\\mathrm{ECL}}` (endcaps), corresponding roughly to the mid-point
4082 of the longitudinal size of the crystals.
4084 * **KLM**: the distance
is defined on the :math:`(\\rho=R, \\phi, z)` surface
in the barrel,
4085 on the :math:`(\\rho, \\phi, z=Z)` surface
in the endcaps.
4086 Only one distance at the KLM first strip entry surface :math:`R_{0}^{\\mathrm{KLM}}` (barrel),
4087 :math:`Z_{0}^{\\mathrm{KLM}}` (endcaps)
is calculated.
4090 decay_string (str): name of the input decay string
with selected charged stable daughters,
4091 for example: ``Lambda0:merged -> ^p+ ^pi-``.
4092 Alternatively, it can be a particle list
for charged stable particles
4093 as defined
in ``Const::chargedStableSet``,
for example: ``mu+:all``.
4094 The charge-conjugate particle list will be also processed automatically.
4095 path (basf2.Path): path to which module(s) will be added.
4096 *detectors: detectors
for which track isolation variables will be calculated.
4097 Choose among: ``{
'CDC',
'TOP',
'ARICH',
'ECL',
'KLM'}``.
4098 reference_list_name (Optional[str]): name of the input charged stable particle list
for the reference tracks.
4099 By default, the ``:all`` ParticleList of the same type
4100 of the selected particle
in ``decay_string``
is used.
4101 The charge-conjugate particle list will be also processed automatically.
4102 vars_for_nearest_part (Optional[list(str)]): a list of variables to calculate
for the nearest particle
in the reference
4103 list at each detector surface. It uses the metavariable `minET2ETDistVar`.
4104 If unset, only the distances to the nearest neighbour
4105 per detector are calculated.
4106 highest_prob_mass_for_hex (Optional[bool]):
if this option
is set to
True (default), the helix extrapolation
4107 for the particles will use the track fit result
for the most
4108 probable mass hypothesis, namely, the one that gives the highest
4109 chi2Prob of the fit. Otherwise, it uses the mass hypothesis that
4110 corresponds to the particle lists PDG.
4111 exclude_pid_det_weights (Optional[bool]):
if this option
is set to
False (default), the isolation score
4112 calculation will take into account the weight that each detector has on the PID
4113 for the particle species of interest.
4116 dict(int, list(str)): a dictionary mapping the PDG of each reference particle list to its isolation variables.
4121 from ROOT
import Belle2, TDatabasePDG
4124 if not decayDescriptor.init(decay_string):
4125 B2FATAL(f
"Invalid particle list {decay_string} in calculateTrackIsolation!")
4126 no_reference_list_name =
not reference_list_name
4129 "CDC": list(range(9)),
4135 if any(d
not in det_and_layers
for d
in detectors):
4137 "Your input detector list: ",
4139 " contains an invalid choice. Please select among: ",
4141 det_and_layers.keys()))
4146 processed_decay_strings = []
4147 if select_symbol
in decay_string:
4148 splitted_ds = decay_string.split(select_symbol)
4149 for i
in range(decay_string.count(select_symbol)):
4150 tmp = list(splitted_ds)
4151 tmp.insert(i+1, select_symbol)
4152 processed_decay_strings += [
''.join(tmp)]
4154 processed_decay_strings += [decay_string]
4156 reference_lists_to_vars = {}
4158 for processed_dec
in processed_decay_strings:
4159 if no_reference_list_name:
4160 decayDescriptor.init(processed_dec)
4161 selected_daughter_pdgs = decayDescriptor.getSelectionPDGCodes()
4162 if len(selected_daughter_pdgs) > 0:
4163 reference_list_name = f
'{TDatabasePDG.Instance().GetParticle(abs(selected_daughter_pdgs[-1])).GetName()}:all'
4165 reference_list_name = f
'{processed_dec.split(":")[0]}:all'
4169 trackiso = path.add_module(
"TrackIsoCalculator",
4170 decayString=processed_dec,
4171 detectorNames=list(detectors),
4172 particleListReference=reference_list_name,
4173 useHighestProbMassForExt=highest_prob_mass_for_ext,
4174 excludePIDDetWeights=exclude_pid_det_weights)
4175 trackiso.set_name(f
"TrackIsoCalculator_{'_'.join(detectors)}_{processed_dec}_VS_{reference_list_name}")
4181 f
"minET2ETDist({d}, {d_layer}, {reference_list_name}, {int(highest_prob_mass_for_ext)})"
4182 for d
in detectors
for d_layer
in det_and_layers[d]]
4185 f
"minET2ETIsoScore({reference_list_name}, {int(highest_prob_mass_for_ext)}, {', '.join(detectors)})",
4186 f
"minET2ETIsoScoreAsWeightedAvg({reference_list_name}, {int(highest_prob_mass_for_ext)}, {', '.join(detectors)})",
4189 if vars_for_nearest_part:
4190 trackiso_vars.extend(
4192 f
"minET2ETDistVar({d}, {d_layer}, {reference_list_name}, {v})"
4193 for d
in detectors
for d_layer
in det_and_layers[d]
for v
in vars_for_nearest_part
4195 trackiso_vars.sort()
4197 reference_lists_to_vars[ref_pdg] = trackiso_vars
4199 return reference_lists_to_vars
4202def calculateDistance(list_name, decay_string, mode='vertextrack', path=None):
4204 Calculates distance between two vertices, distance of closest approach between a vertex and a track,\
4205 distance of closest approach between a vertex
and btube. For track, this calculation ignores track curvature,\
4206 it
's negligible for small distances.The user should use extraInfo(CalculatedDistance)\
4207 to get it. A full example steering file is at analysis/tests/test_DistanceCalculator.py
4210 .. code-block:: python
4212 from modularAnalysis
import calculateDistance
4213 calculateDistance(
'list_name',
'decay_string',
"mode", path=user_path)
4215 @param list_name name of the input ParticleList
4216 @param decay_string select particles between the distance of closest approach will be calculated
4217 @param mode Specifies how the distance
is calculated
4218 vertextrack: calculate the distance of closest approach between a track
and a\
4219 vertex, taking the first candidate
as vertex, default
4220 trackvertex: calculate the distance of closest approach between a track
and a\
4221 vertex, taking the first candidate
as track
4222 2tracks: calculates the distance of closest approach between two tracks
4223 2vertices: calculates the distance between two vertices
4224 vertexbtube: calculates the distance of closest approach between a vertex
and btube
4225 trackbtube: calculates the distance of closest approach between a track
and btube
4226 @param path modules are added to this path
4230 dist_mod = register_module('DistanceCalculator')
4232 dist_mod.set_name(
'DistanceCalculator_' + list_name)
4233 dist_mod.param(
'listName', list_name)
4234 dist_mod.param(
'decayString', decay_string)
4235 dist_mod.param(
'mode', mode)
4236 path.add_module(dist_mod)
4239def addInclusiveDstarReconstruction(decayString, slowPionCut, DstarCut, path):
4241 Adds the InclusiveDstarReconstruction module to the given path.
4242 This module creates a D* particle list by estimating the D* four momenta
4243 from slow pions, specified by a given cut. The D* energy
is approximated
4244 as E(D*) = m(D*)/(m(D*) - m(D)) * E(pi). The absolute value of the D*
4245 momentum
is calculated using the D* PDG mass
and the direction
is collinear
4246 to the slow pion direction. The charge of the given pion list has to be consistent
4249 @param decayString Decay string, must be of form ``D* -> pi``
4250 @param slowPionCut Cut applied to the input pion list to identify slow pions
4251 @param DstarCut Cut applied to the output D* list
4252 @param path the module
is added to this path
4255 incl_dstar = register_module("InclusiveDstarReconstruction")
4256 incl_dstar.param(
"decayString", decayString)
4257 incl_dstar.param(
"slowPionCut", slowPionCut)
4258 incl_dstar.param(
"DstarCut", DstarCut)
4259 path.add_module(incl_dstar)
4262def scaleError(outputListName, inputListName,
4263 scaleFactors=[1.149631, 1.085547, 1.151704, 1.096434, 1.086659],
4264 scaleFactorsNoPXD=[1.149631, 1.085547, 1.151704, 1.096434, 1.086659],
4265 d0Resolution=[0.00115328, 0.00134704],
4266 z0Resolution=[0.00124327, 0.0013272],
4271 This module creates a new charged particle list.
4272 The helix errors of the new particles are scaled by constant factors.
4273 Two sets of five scale factors are defined for tracks
with and without a PXD hit.
4274 The scale factors are
in order of (d0, phi0, omega, z0, tanlambda).
4275 For tracks
with a PXD hit,
in order to avoid severe underestimation of d0
and z0 errors,
4276 lower limits (best resolution) can be set
in a momentum-dependent form.
4277 This module
is supposed to be used only
for TDCPV analysis
and for low-momentum (0-3 GeV/c) tracks
in BBbar events.
4278 Details will be documented
in a Belle II note, BELLE2-NOTE-PH-2021-038.
4280 @param inputListName Name of input charged particle list to be scaled
4281 @param outputListName Name of output charged particle list
with scaled error
4282 @param scaleFactors List of five constants to be multiplied to each of helix errors (
for tracks
with a PXD hit)
4283 @param scaleFactorsNoPXD List of five constants to be multiplied to each of helix errors (
for tracks without a PXD hit)
4284 @param d0Resolution List of two parameters, (a [cm], b [cm/(GeV/c)]),
4285 defining d0 best resolution
as sqrt{ a**2 + (b / (p*beta*sinTheta**1.5))**2 }
4286 @param z0Resolution List of two parameters, (a [cm], b [cm/(GeV/c)]),
4287 defining z0 best resolution
as sqrt{ a**2 + (b / (p*beta*sinTheta**2.5))**2 }
4288 @param d0MomThr d0 best resolution
is kept constant below this momentum
4289 @param z0MomThr z0 best resolution
is kept constant below this momentum
4293 scale_error = register_module("HelixErrorScaler")
4294 scale_error.set_name(
'ScaleError_' + inputListName)
4295 scale_error.param(
'inputListName', inputListName)
4296 scale_error.param(
'outputListName', outputListName)
4297 scale_error.param(
'scaleFactors_PXD', scaleFactors)
4298 scale_error.param(
'scaleFactors_noPXD', scaleFactorsNoPXD)
4299 scale_error.param(
'd0ResolutionParameters', d0Resolution)
4300 scale_error.param(
'z0ResolutionParameters', z0Resolution)
4301 scale_error.param(
'd0MomentumThreshold', d0MomThr)
4302 scale_error.param(
'z0MomentumThreshold', z0MomThr)
4303 path.add_module(scale_error)
4306def estimateAndAttachTrackFitResult(inputListName, path=None):
4308 Create a TrackFitResult from the momentum of the Particle assuming it originates
from the IP
and make a relation between them.
4309 The covariance, detector hit information,
and fit-related information (pValue, NDF) are assigned meaningless values. The input
4310 Particles must
not have already Track
or TrackFitResult
and thus are supposed to be composite particles, recoil, dummy
4311 particles,
and so on.
4314 .. warning:: Since the source type
is not overwritten
as Track,
not all track-related variables are guaranteed to be available.
4317 @param inputListName Name of input ParticleList
4320 estimator = register_module("TrackFitResultEstimator")
4321 estimator.set_name(
"trackFitResultEstimator_" + inputListName)
4322 estimator.param(
"inputListName", inputListName)
4323 path.add_module(estimator)
4326def correctEnergyBias(inputListNames, tableName, path=None):
4328 Scale energy of the particles according to the scaling factor.
4329 If the particle list contains composite particles, the energy of the daughters are scaled.
4330 Subsequently, the energy of the mother particle is updated
as well.
4333 inputListNames (list(str)): input particle list names
4334 tableName : stored
in localdb
and created using ParticleWeightingLookUpCreator
4335 path (basf2.Path): module
is added to this path
4340 B2ERROR(
"The energy bias cannot be corrected with this tool for Belle data.")
4342 correctenergybias = register_module(
'EnergyBiasCorrection')
4343 correctenergybias.param(
'particleLists', inputListNames)
4344 correctenergybias.param(
'tableName', tableName)
4345 path.add_module(correctenergybias)
4348def twoBodyISRPhotonCorrector(outputListName, inputListName, massiveParticle, path=None):
4350 Sets photon kinematics to corrected values in two body decays
with an ISR photon
4351 and a massive particle. The original photon kinematics are kept
in the input
4352 particleList
and can be accessed using the originalParticle() metavariable on the
4355 @param ouputListName new ParticleList filled
with copied Particles
4356 @param inputListName input ParticleList
with original Particles
4357 @param massiveParticle name
or PDG code of massive particle participating
in the two
4358 body decay
with the ISR photon
4359 @param path modules are added to this path
4363 photon_energy_correction = register_module(
'TwoBodyISRPhotonCorrector')
4364 photon_energy_correction.set_name(
'TwoBodyISRPhotonCorrector_' + outputListName)
4365 photon_energy_correction.param(
'outputGammaList', outputListName)
4366 photon_energy_correction.param(
'inputGammaList', inputListName)
4369 if isinstance(massiveParticle, int):
4370 photon_energy_correction.param(
'massiveParticlePDGCode', massiveParticle)
4372 from ROOT
import Belle2
4374 if not decayDescriptor.init(massiveParticle):
4375 raise ValueError(
"TwoBodyISRPhotonCorrector: value of massiveParticle must be" +
4376 " an int or valid decay string.")
4377 pdgCode = decayDescriptor.getMother().getPDGCode()
4378 photon_energy_correction.param(
'massiveParticlePDGCode', pdgCode)
4380 path.add_module(photon_energy_correction)
4383def addPhotonEfficiencyRatioVariables(inputListNames, tableName, path=None):
4385 Add photon Data/MC detection efficiency ratio weights to the specified particle list
4388 inputListNames (list(str)): input particle list names
4389 tableName : taken from database
with appropriate name
4390 path (basf2.Path): module
is added to this path
4395 B2ERROR(
"For Belle data the photon data/MC detection efficiency ratio is not available with this tool.")
4397 photon_efficiency_correction = register_module(
'PhotonEfficiencySystematics')
4398 photon_efficiency_correction.param(
'particleLists', inputListNames)
4399 photon_efficiency_correction.param(
'tableName', tableName)
4400 path.add_module(photon_efficiency_correction)
4403def addPi0VetoEfficiencySystematics(particleList, decayString, tableName, threshold, mode='standard', suffix='', path=None):
4405 Add pi0 veto Data/MC efficiency ratio weights to the specified particle list
4407 @param particleList the input ParticleList
4408 @param decayString specify hard photon to be performed pi0 veto (e.g.
'B+:sig -> rho+:sig ^gamma:hard')
4409 @param tableName table name corresponding to payload version (e.g.
'Pi0VetoEfficiencySystematics_Mar2022')
4410 @param threshold pi0 veto threshold (0.10, 0.11, ..., 0.99)
4411 @param mode choose one mode (same
as writePi0EtaVeto) out of
'standard',
'tight',
'cluster' and 'both'
4412 @param suffix optional suffix to be appended to the usual extraInfo name
4413 @param path the module
is added to this path
4415 The following extraInfo are available related
with the given particleList:
4417 * Pi0VetoEfficiencySystematics_{mode}{suffix}_data_MC_ratio : weight of Data/MC
for the veto efficiency
4418 * Pi0VetoEfficiencySystematics_{mode}{suffix}_data_MC_uncertainty_stat : the statistical uncertainty of the weight
4419 * Pi0VetoEfficiencySystematics_{mode}{suffix}_data_MC_uncertainty_sys : the systematic uncertainty of the weight
4420 * Pi0VetoEfficiencySystematics_{mode}{suffix}_data_MC_uncertainty_total : the total uncertainty of the weight
4421 * Pi0VetoEfficiencySystematics_{mode}{suffix}_threshold : threshold of the pi0 veto
4426 B2ERROR(
"For Belle data the pi0 veto data/MC efficiency ratio weights are not available via this tool.")
4428 pi0veto_efficiency_correction = register_module(
'Pi0VetoEfficiencySystematics')
4429 pi0veto_efficiency_correction.param(
'particleLists', particleList)
4430 pi0veto_efficiency_correction.param(
'decayString', decayString)
4431 pi0veto_efficiency_correction.param(
'tableName', tableName)
4432 pi0veto_efficiency_correction.param(
'threshold', threshold)
4433 pi0veto_efficiency_correction.param(
'mode', mode)
4434 pi0veto_efficiency_correction.param(
'suffix', suffix)
4435 path.add_module(pi0veto_efficiency_correction)
4438def getAnalysisGlobaltag(timeout=180) -> str:
4440 Returns a string containing the name of the latest and recommended analysis globaltag.
4443 timeout: Seconds to wait
for b2conditionsdb-recommend
4448 B2ERROR(
"The getAnalysisGlobaltag() function cannot be used for Belle data.")
4453 tags = subprocess.check_output(
4454 [
'b2conditionsdb-recommend',
'--oneline'],
4456 ).decode(
'UTF-8').rstrip().split(
' ')
4459 if tag.startswith(
'analysis_tools'):
4463 except subprocess.TimeoutExpired
as te:
4464 B2FATAL(f
'A {te} exception was raised during the call of getAnalysisGlobaltag(). '
4465 'The function took too much time to retrieve the requested information '
4466 'from the versioning repository.\n'
4467 'Please try to re-run your job. In case of persistent failures, there may '
4468 'be issues with the DESY collaborative services, so please contact the experts.')
4469 except subprocess.CalledProcessError
as ce:
4470 B2FATAL(f
'A {ce} exception was raised during the call of getAnalysisGlobaltag(). '
4471 'Please try to re-run your job. In case of persistent failures, please contact '
4475def getAnalysisGlobaltagB2BII() -> str:
4477 Get recommended global tag
for B2BII analysis.
4482 B2ERROR(
'The getAnalysisGlobaltagB2BII() function cannot be used for Belle II data.')
4483 from versioning
import recommended_b2bii_analysis_global_tag
4484 return recommended_b2bii_analysis_global_tag()
4487def getECLKLID(particleList: str, variable=
'ECLKLID', path=
None):
4489 The function calculates the PID value for Klongs that are constructed
from ECL cluster.
4491 @param particleList the input ParticleList
4492 @param variable the variable name
for Klong ID
4493 @param path modules are added to this path
4499 B2ERROR(
"The ECL variables based Klong Identification is only available for Belle II data.")
4501 from variables
import variables
4502 path.add_module(
'MVAExpert', listNames=particleList, extraInfoName=
'ECLKLID', identifier=
'ECLKLID')
4504 variables.addAlias(variable,
'conditionalVariableSelector(isFromECL and PDG==130, extraInfo(ECLKLID), constant(NaN))')
4507def getNbarIDMVA(particleList: str, path=
None):
4509 This function can give a score to predict if it
is a anti-n0.
4510 It
is not used to predict n0.
4511 Currently, this can be used only
for ECL cluster.
4512 output will be stored
in extraInfo(nbarID); -1 means MVA invalid
4514 @param particleList The input ParticleList name
or a decay string which contains a full mother particle list name.
4515 Only one selected daughter
is supported.
4516 @param path modules are added to this path
4519 from ROOT
import Belle2
4522 B2ERROR(
"The MVA-based anti-neutron PID is only available for Belle II data.")
4524 from variables
import variables
4526 variables.addAlias(
'V1',
'clusterHasPulseShapeDiscrimination')
4527 variables.addAlias(
'V2',
'clusterE')
4528 variables.addAlias(
'V3',
'clusterLAT')
4529 variables.addAlias(
'V4',
'clusterE1E9')
4530 variables.addAlias(
'V5',
'clusterE9E21')
4531 variables.addAlias(
'V6',
'clusterZernikeMVA')
4532 variables.addAlias(
'V7',
'clusterAbsZernikeMoment40')
4533 variables.addAlias(
'V8',
'clusterAbsZernikeMoment51')
4537 'passesCut(V1 == 1 and V2 >= 0 and V3 >= 0 and V4 >= 0 and V5 >= 0 and V6 >= 0 and V7 >= 0 and V8 >= 0)')
4538 variables.addAlias(
'nbarIDmod',
'conditionalVariableSelector(nbarIDValid == 1, extraInfo(nbarIDFromMVA), constant(-1.0))')
4540 path.add_module(
'MVAExpert', listNames=particleList, extraInfoName=
'nbarIDFromMVA', identifier=
'db_nbarIDECL')
4542 if not decayDescriptor.init(particleList):
4543 raise ValueError(f
"Provided decay string is invalid: {particleList}")
4544 if decayDescriptor.getNDaughters() == 0:
4547 listname = decayDescriptor.getMother().getFullName()
4548 variablesToDaughterExtraInfo(listname, particleList, {
'nbarIDmod':
'nbarID'}, option=2, path=path)
4551def reconstructDecayWithNeutralHadron(decayString, cut, allowGamma=False, allowAnyParticleSource=False, path=None, **kwargs):
4553 Reconstructs decay with a long-lived neutral hadron e.g.
4554 :math:`B^0 \to J/\psi K_L^0`,
4555 :math:`B^0 \to p \bar{n} D^*(2010)^-`.
4557 The calculation
is done
with IP constraint
and mother mass constraint.
4559 The decay string passed
in must satisfy the following rules:
4561 - The neutral hadron must be **selected**
in the decay string
with the
4562 caret (``^``) e.g. ``B0:sig -> J/psi:sig ^K_L0:sig``. (Note the caret
4563 next to the neutral hadron.)
4564 - There can only be **one neutral hadron
in a decay**.
4565 - The neutral hadron has to be a direct daughter of its mother.
4567 .. note:: This function forwards its arguments to `reconstructDecay`,
4568 so please check the documentation of `reconstructDecay`
for all
4571 @param decayString A decay string following the mentioned rules
4572 @param cut Cut to apply to the particle list
4573 @param allowGamma Whether allow the selected particle to be ``gamma``
4574 @param allowAnyParticleSource Whether allow the selected particle to be
from any source.
4575 Should only be used when studying control sample.
4576 @param path The path to put
in the module
4579 reconstructDecay(decayString, cut, path=path, **kwargs)
4580 module = register_module('NeutralHadron4MomentumCalculator')
4581 module.set_name(
'NeutralHadron4MomentumCalculator_' + decayString)
4582 module.param(
'decayString', decayString)
4583 module.param(
'allowGamma', allowGamma)
4584 module.param(
'allowAnyParticleSource', allowAnyParticleSource)
4585 path.add_module(module)
4588def updateMassHypothesis(particleList, pdg, writeOut=False, path=None):
4590 Module to update the mass hypothesis of a given input particle list with the chosen PDG.
4591 A new particle list
is created
with updated mass hypothesis.
4592 The allowed mass hypotheses
for both input
and output are electrons, muons, pions, kaons
and protons.
4595 The new particle list
is named after the input one,
with the additional suffix ``_converted_from_OLDHYPOTHESIS``,
4596 e.g. ``e+:all`` converted to muons becomes ``mu+:all_converted_from_e``.
4598 @param particleList The input particle list name
4599 @param pdg The PDG code
for the new mass hypothesis,
in [11, 13, 211, 321, 2212]
4600 @param writeOut Whether `RootOutput` module should save the new particle list
4601 @param path Modules are added to this path
4603 mass_updater = register_module("ParticleMassHypothesesUpdater")
4604 mass_updater.set_name(
"ParticleMassHypothesesUpdater_" + particleList +
"_to_" + str(pdg))
4605 mass_updater.param(
"particleList", particleList)
4606 mass_updater.param(
"writeOut", writeOut)
4607 mass_updater.param(
"pdgCode", pdg)
4608 path.add_module(mass_updater)
4611func_requiring_analysisGT = [
4612 correctTrackEnergy, scaleTrackMomenta, smearTrackMomenta, oldwritePi0EtaVeto, writePi0EtaVeto, lowEnergyPi0Identification,
4613 getBeamBackgroundProbability, getFakePhotonProbability, tagCurlTracks, applyChargedPidMVA, correctEnergyBias,
4614 addPhotonEfficiencyRatioVariables, addPi0VetoEfficiencySystematics, getNbarIDMVA, getECLKLID]
4615for _
in func_requiring_analysisGT:
4616 _.__doc__ +=
"\n .. note:: This function (optionally) requires a payload stored in the analysis GlobalTag. "\
4617 "Please append or prepend the latest one from `getAnalysisGlobaltag` or `getAnalysisGlobaltagB2BII`.\n"
4620if __name__ ==
'__main__':
4622 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.
def add_mdst_output(path, mc=True, filename='mdst.root', additionalBranches=[], dataDescription=None)
def add_udst_output(path, filename, particleLists=None, additionalBranches=None, dataDescription=None, mc=True)