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://confluence.desy.de/display/BI/Experiment+numbering
272 noEvents (int): number of events to be generated
273 path (basf2.Path): modules are added to this path
276 evtnumbers = register_module('EventInfoSetter')
277 evtnumbers.param(
'evtNumList', [noEvents])
278 evtnumbers.param(
'runList', [0])
279 evtnumbers.param(
'expList', [0])
280 path.add_module(evtnumbers)
283def loadGearbox(path, silence_warning=False):
285 Loads Gearbox module to the path.
288 Should be used in a job
with *cosmic event generation only*
290 Needed
for scripts which only generate cosmic events
in order to
293 @param path modules are added to this path
294 @param silence_warning stops a verbose warning message
if you know you want to use this function
297 if not silence_warning:
298 B2WARNING(
"""You are overwriting the geometry from the database with Gearbox.
299 This is fine
if you
're generating cosmic events. But in most other cases you probably don't want this.
301 If you
're really sure you know what you're doing you can suppress this message
with:
303 >>> loadGearbox(silence_warning=
True)
307 paramloader = register_module('Gearbox')
308 path.add_module(paramloader)
311def printPrimaryMCParticles(path, **kwargs):
313 Prints all primary MCParticles, that is particles
from
314 the physics generator
and not particles created by the simulation
316 This
is equivalent to `printMCParticles(onlyPrimaries=
True, path=path) <printMCParticles>`
and additional
317 keyword arguments are just forwarded to that function
320 return printMCParticles(onlyPrimaries=
True, path=path, **kwargs)
323def printMCParticles(onlyPrimaries=False, maxLevel=-1, path=None, *,
324 showProperties=False, showMomenta=False, showVertices=False, showStatus=False, suppressPrint=False):
326 Prints all MCParticles or just primary MCParticles up to specified level. -1 means no limit.
328 By default this will
print a tree of just the particle names
and their pdg
329 codes
in the event,
for example ::
331 [INFO] Content of MCParticle list
334 ╰── Upsilon(4S) (300553)
336 │ ├── anti-D_0*0 (-10421)
339 │ │ │ │ ├── anti-K0 (-311)
340 │ │ │ │ │ ╰── K_S0 (310)
341 │ │ │ │ │ ├── pi+ (211)
342 │ │ │ │ │ │ ╰╶╶ p+ (2212)
343 │ │ │ │ │ ╰── pi- (-211)
344 │ │ │ │ │ ├╶╶ e- (11)
345 │ │ │ │ │ ├╶╶ n0 (2112)
346 │ │ │ │ │ ├╶╶ n0 (2112)
347 │ │ │ │ │ ╰╶╶ n0 (2112)
348 │ │ │ │ ╰── pi- (-211)
349 │ │ │ │ ├╶╶ anti-nu_mu (-14)
351 │ │ │ │ ├╶╶ nu_mu (14)
352 │ │ │ │ ├╶╶ anti-nu_e (-12)
356 │ │ │ │ ├── gamma (22)
357 │ │ │ │ ╰── gamma (22)
363 │ │ ├╶╶ anti-nu_mu (-14)
371 There
's a distinction between primary and secondary particles. Primary 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) → …
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" (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)
913 decayStringsWithCuts (list): A list of python ntuples of (decayString, cut).
914 The decay string determines the type of Particle
915 and the name of the ParticleList.
916 If the input MDST type
is V0 the whole
917 decay chain needs to be specified, so that
918 the user decides
and controls the daughters
919 ' order (e.g. ``K_S0 -> pi+ pi-``)
920 The cut is the selection criteria
921 to be added to the ParticleList. It can be an empty string.
922 writeOut (bool): whether RootOutput module should save the created ParticleList
923 path (basf2.Path): modules are added to this path
924 enforceFitHypothesis (bool): If true, Particles will be created only
for the tracks which have been fitted
925 using a mass hypothesis of the exact type passed to fillParticleLists().
926 If enforceFitHypothesis
is False (the default) the next closest fit hypothesis
927 in terms of mass difference will be used
if the fit using exact particle
928 type
is not available.
929 loadPhotonsFromKLM (bool): If true, photon candidates will be created
from KLMClusters
as well.
932 pload = register_module('ParticleLoader')
933 pload.set_name(
'ParticleLoader_' +
'PLists')
934 pload.param(
'decayStrings', [decayString
for decayString, cut
in decayStringsWithCuts])
935 pload.param(
'writeOut', writeOut)
936 pload.param(
"enforceFitHypothesis", enforceFitHypothesis)
937 path.add_module(pload)
939 from ROOT
import Belle2
941 for decayString, cut
in decayStringsWithCuts:
942 if not decayDescriptor.init(decayString):
943 raise ValueError(
"Invalid decay string")
945 if decayDescriptor.getNDaughters() > 0:
949 if decayDescriptor.getMother().getLabel() !=
'V0':
950 copyList(decayDescriptor.getMother().getFullName(), decayDescriptor.getMother().getName() +
':V0', writeOut, path)
951 elif decayDescriptor.getMother().getLabel() !=
'all':
954 copyList(decayString, decayDescriptor.getMother().getName() +
':all', writeOut, path)
958 applyCuts(decayDescriptor.getMother().getFullName(), cut, path)
960 if decayString.startswith(
"gamma"):
963 if not loadPhotonsFromKLM:
964 applyCuts(decayString,
'isFromECL', path)
967def fillParticleList(decayString, cut, writeOut=False, path=None, enforceFitHypothesis=False,
968 loadPhotonsFromKLM=False):
970 Creates Particles of the desired type from the corresponding ``mdst`` dataobjects,
971 loads them to the StoreArray<Particle>
and fills the ParticleList.
974 the :doc:`StandardParticles` functions.
976 The type of the particles to be loaded
is specified via the decayString module parameter.
977 The type of the ``mdst`` dataobject that
is used
as an input
is determined
from the type of
978 the particle. The following types of the particles can be loaded:
980 * charged final state particles (input ``mdst`` type = Tracks)
981 - e+, mu+, pi+, K+, p, deuteron (
and charge conjugated particles)
983 * neutral final state particles
984 -
"gamma" (input ``mdst`` type = ECLCluster)
985 -
"K_S0",
"Lambda0" (input ``mdst`` type = V0)
986 -
"K_L0" (input ``mdst`` type = KLMCluster
or ECLCluster)
989 For
"K_S0" and "Lambda0" you must specify the daughter ordering.
991 For example, to load V0s
as :math:`\\Lambda^0\\to p^+\\pi^-` decays
from V0s:
993 .. code-block:: python
995 fillParticleList(
'Lambda0 -> p+ pi-',
'0.9 < M < 1.3', path=mypath)
998 Gammas can also be loaded
from KLMClusters by explicitly setting the
999 parameter ``loadPhotonsFromKLM`` to
True. However, this should only be
1000 done
in selected use-cases
and the effect should be studied carefully.
1003 For
"K_L0" it
is now possible to load
from ECLClusters, to revert to
1004 the old (Belle) behavior, you can require ``
'isFromKLM > 0'``.
1006 .. code-block:: python
1008 fillParticleList(
'K_L0',
'isFromKLM > 0', path=mypath)
1011 decayString (str): Type of Particle
and determines the name of the ParticleList.
1012 If the input MDST type
is V0 the whole decay chain needs to be specified, so that
1013 the user decides
and controls the daughters
' order (e.g. ``K_S0 -> pi+ pi-``)
1014 cut (str): Particles need to pass these selection criteria to be added to the ParticleList
1015 writeOut (bool): whether RootOutput module should save the created ParticleList
1016 path (basf2.Path): modules are added to this path
1017 enforceFitHypothesis (bool): If true, Particles will be created only
for the tracks which have been fitted
1018 using a mass hypothesis of the exact type passed to fillParticleLists().
1019 If enforceFitHypothesis
is False (the default) the next closest fit hypothesis
1020 in terms of mass difference will be used
if the fit using exact particle
1021 type
is not available.
1022 loadPhotonsFromKLM (bool): If true, photon candidates will be created
from KLMClusters
as well.
1025 pload = register_module('ParticleLoader')
1026 pload.set_name(
'ParticleLoader_' + decayString)
1027 pload.param(
'decayStrings', [decayString])
1028 pload.param(
'writeOut', writeOut)
1029 pload.param(
"enforceFitHypothesis", enforceFitHypothesis)
1030 path.add_module(pload)
1033 from ROOT
import Belle2
1035 if not decayDescriptor.init(decayString):
1036 raise ValueError(
"Invalid decay string")
1037 if decayDescriptor.getNDaughters() > 0:
1041 if decayDescriptor.getMother().getLabel() !=
'V0':
1042 copyList(decayDescriptor.getMother().getFullName(), decayDescriptor.getMother().getName() +
':V0', writeOut, path)
1043 elif decayDescriptor.getMother().getLabel() !=
'all':
1046 copyList(decayString, decayDescriptor.getMother().getName() +
':all', writeOut, path)
1050 applyCuts(decayDescriptor.getMother().getFullName(), cut, path)
1052 if decayString.startswith(
"gamma"):
1055 if not loadPhotonsFromKLM:
1056 applyCuts(decayString,
'isFromECL', path)
1059def fillParticleListWithTrackHypothesis(decayString,
1063 enforceFitHypothesis=False,
1066 As fillParticleList, but if used
for a charged FSP, loads the particle
with the requested hypothesis
if available
1068 @param decayString specifies type of Particles
and determines the name of the ParticleList
1069 @param cut Particles need to
pass these selection criteria to be added to the ParticleList
1070 @param hypothesis the PDG code of the desired track hypothesis
1071 @param writeOut whether RootOutput module should save the created ParticleList
1072 @param enforceFitHypothesis If true, Particles will be created only
for the tracks which have been fitted
1073 using a mass hypothesis of the exact type passed to fillParticleLists().
1074 If enforceFitHypothesis
is False (the default) the next closest fit hypothesis
1075 in terms of mass difference will be used
if the fit using exact particle
1076 type
is not available.
1077 @param path modules are added to this path
1080 pload = register_module('ParticleLoader')
1081 pload.set_name(
'ParticleLoader_' + decayString)
1082 pload.param(
'decayStrings', [decayString])
1083 pload.param(
'trackHypothesis', hypothesis)
1084 pload.param(
'writeOut', writeOut)
1085 pload.param(
"enforceFitHypothesis", enforceFitHypothesis)
1086 path.add_module(pload)
1088 from ROOT
import Belle2
1090 if not decayDescriptor.init(decayString):
1091 raise ValueError(
"Invalid decay string")
1092 if decayDescriptor.getMother().getLabel() !=
'all':
1095 copyList(decayString, decayDescriptor.getMother().getName() +
':all', writeOut, path)
1099 applyCuts(decayString, cut, path)
1102def fillConvertedPhotonsList(decayString, cut, writeOut=False, path=None):
1104 Creates photon Particle object for each e+e- combination
in the V0 StoreArray.
1107 You must specify the daughter ordering.
1109 .. code-block:: python
1111 fillConvertedPhotonsList(
'gamma:converted -> e+ e-',
'', path=mypath)
1114 decayString (str): Must be gamma to an e+e- pair. You must specify the daughter ordering.
1115 Will also determine the name of the particleList.
1116 cut (str): Particles need to
pass these selection criteria to be added to the ParticleList
1117 writeOut (bool): whether RootOutput module should save the created ParticleList
1118 path (basf2.Path): modules are added to this path
1124 B2ERROR(
'For Belle converted photons are available in the pre-defined list "gamma:v0mdst".')
1126 pload = register_module(
'ParticleLoader')
1127 pload.set_name(
'ParticleLoader_' + decayString)
1128 pload.param(
'decayStrings', [decayString])
1129 pload.param(
'addDaughters',
True)
1130 pload.param(
'writeOut', writeOut)
1131 path.add_module(pload)
1133 from ROOT
import Belle2
1135 if not decayDescriptor.init(decayString):
1136 raise ValueError(
"Invalid decay string")
1137 if decayDescriptor.getMother().getLabel() !=
'V0':
1140 copyList(decayDescriptor.getMother().getFullName(), decayDescriptor.getMother().getName() +
':V0', writeOut, path)
1144 applyCuts(decayDescriptor.getMother().getFullName(), cut, path)
1147def fillParticleListFromROE(decayString,
1150 sourceParticleListName='',
1155 Creates Particle object for each ROE of the desired type found
in the
1156 StoreArray<RestOfEvent>, loads them to the StoreArray<Particle>
1157 and fills the ParticleList. If useMissing
is True, then the missing
1158 momentum
is used instead of ROE.
1160 The type of the particles to be loaded
is specified via the decayString module parameter.
1162 @param decayString specifies type of Particles
and determines the name of the ParticleList.
1163 Source ROEs can be taken
as a daughter list,
for example:
1164 'B0:tagFromROE -> B0:signal'
1165 @param cut Particles need to
pass these selection criteria to be added to the ParticleList
1166 @param maskName Name of the ROE mask to use
1167 @param sourceParticleListName Use related ROEs to this particle list
as a source
1168 @param useMissing Use missing momentum instead of ROE momentum
1169 @param writeOut whether RootOutput module should save the created ParticleList
1170 @param path modules are added to this path
1173 pload = register_module('ParticleLoader')
1174 pload.set_name(
'ParticleLoader_' + decayString)
1175 pload.param(
'decayStrings', [decayString])
1176 pload.param(
'writeOut', writeOut)
1177 pload.param(
'roeMaskName', maskName)
1178 pload.param(
'useMissing', useMissing)
1179 pload.param(
'sourceParticleListName', sourceParticleListName)
1180 pload.param(
'useROEs',
True)
1181 path.add_module(pload)
1183 from ROOT
import Belle2
1185 if not decayDescriptor.init(decayString):
1186 raise ValueError(
"Invalid decay string")
1190 applyCuts(decayDescriptor.getMother().getFullName(), cut, path)
1193def fillParticleListFromDummy(decayString,
1196 treatAsInvisible=True,
1200 Creates a ParticleList and fills it
with dummy Particles. For self-conjugated Particles one dummy
1201 Particle
is created,
for Particles that are
not self-conjugated one Particle
and one anti-Particle
is
1202 created. The four-momentum
is set to zero.
1204 The type of the particles to be loaded
is specified via the decayString module parameter.
1206 @param decayString specifies type of Particles
and determines the name of the ParticleList
1207 @param mdstIndex sets the mdst index of Particles
1208 @param covMatrix sets the value of the diagonal covariance matrix of Particles
1209 @param treatAsInvisible whether treeFitter should treat the Particles
as invisible
1210 @param writeOut whether RootOutput module should save the created ParticleList
1211 @param path modules are added to this path
1214 pload = register_module('ParticleLoader')
1215 pload.set_name(
'ParticleLoader_' + decayString)
1216 pload.param(
'decayStrings', [decayString])
1217 pload.param(
'useDummy',
True)
1218 pload.param(
'dummyMDSTIndex', mdstIndex)
1219 pload.param(
'dummyCovMatrix', covMatrix)
1220 pload.param(
'dummyTreatAsInvisible', treatAsInvisible)
1221 pload.param(
'writeOut', writeOut)
1222 path.add_module(pload)
1225def fillParticleListFromMC(decayString,
1228 skipNonPrimaryDaughters=False,
1231 skipNonPrimary=False,
1234 Creates Particle object for each MCParticle of the desired type found
in the StoreArray<MCParticle>,
1235 loads them to the StoreArray<Particle>
and fills the ParticleList.
1237 The type of the particles to be loaded
is specified via the decayString module parameter.
1239 @param decayString specifies type of Particles
and determines the name of the ParticleList
1240 @param cut Particles need to
pass these selection criteria to be added to the ParticleList
1241 @param addDaughters adds the bottom part of the decay chain of the particle to the datastore
and
1242 sets mother-daughter relations
1243 @param skipNonPrimaryDaughters
if true, skip non primary daughters, useful to study final state daughter particles
1244 @param writeOut whether RootOutput module should save the created ParticleList
1245 @param path modules are added to this path
1246 @param skipNonPrimary
if true, skip non primary particle
1247 @param skipInitial
if true, skip initial particles
1250 pload = register_module('ParticleLoader')
1251 pload.set_name(
'ParticleLoader_' + decayString)
1252 pload.param(
'decayStrings', [decayString])
1253 pload.param(
'addDaughters', addDaughters)
1254 pload.param(
'skipNonPrimaryDaughters', skipNonPrimaryDaughters)
1255 pload.param(
'writeOut', writeOut)
1256 pload.param(
'useMCParticles',
True)
1257 pload.param(
'skipNonPrimary', skipNonPrimary)
1258 pload.param(
'skipInitial', skipInitial)
1259 path.add_module(pload)
1261 from ROOT
import Belle2
1263 if not decayDescriptor.init(decayString):
1264 raise ValueError(
"Invalid decay string")
1268 applyCuts(decayString, cut, path)
1271def fillParticleListsFromMC(decayStringsWithCuts,
1273 skipNonPrimaryDaughters=False,
1276 skipNonPrimary=False,
1279 Creates Particle object for each MCParticle of the desired type found
in the StoreArray<MCParticle>,
1280 loads them to the StoreArray<Particle>
and fills the ParticleLists.
1282 The types of the particles to be loaded are specified via the (decayString, cut) tuples given
in a list.
1285 .. code-block:: python
1287 kaons = (
'K+:gen',
'')
1288 pions = (
'pi+:gen',
'pionID>0.1')
1289 fillParticleListsFromMC([kaons, pions], path=mypath)
1292 Daughters of ``Lambda0`` are
not primary, but ``Lambda0``
is not final state particle.
1293 Thus, when one reconstructs a particle
from ``Lambda0``, that
is created
with
1294 ``addDaughters=
True``
and ``skipNonPrimaryDaughters=
True``, the particle always has ``isSignal==0``.
1295 Please set options
for ``Lambda0`` to use MC-matching variables properly
as follows,
1296 ``addDaughters=
True``
and ``skipNonPrimaryDaughters=
False``.
1298 @param decayString specifies type of Particles
and determines the name of the ParticleList
1299 @param cut Particles need to
pass these selection criteria to be added to the ParticleList
1300 @param addDaughters adds the bottom part of the decay chain of the particle to the datastore
and
1301 sets mother-daughter relations
1302 @param skipNonPrimaryDaughters
if true, skip non primary daughters, useful to study final state daughter particles
1303 @param writeOut whether RootOutput module should save the created ParticleList
1304 @param path modules are added to this path
1305 @param skipNonPrimary
if true, skip non primary particle
1306 @param skipInitial
if true, skip initial particles
1309 pload = register_module('ParticleLoader')
1310 pload.set_name(
'ParticleLoader_' +
'PLists')
1311 pload.param(
'decayStrings', [decayString
for decayString, cut
in decayStringsWithCuts])
1312 pload.param(
'addDaughters', addDaughters)
1313 pload.param(
'skipNonPrimaryDaughters', skipNonPrimaryDaughters)
1314 pload.param(
'writeOut', writeOut)
1315 pload.param(
'useMCParticles',
True)
1316 pload.param(
'skipNonPrimary', skipNonPrimary)
1317 pload.param(
'skipInitial', skipInitial)
1318 path.add_module(pload)
1320 from ROOT
import Belle2
1322 for decayString, cut
in decayStringsWithCuts:
1323 if not decayDescriptor.init(decayString):
1324 raise ValueError(
"Invalid decay string")
1328 applyCuts(decayString, cut, path)
1331def fillParticleListFromChargedCluster(outputParticleList,
1334 useOnlyMostEnergeticECLCluster=True,
1338 Creates the Particle object from ECLCluster
and KLMCluster that are being matched
with the Track of inputParticleList.
1340 @param outputParticleList The output ParticleList. Only neutral final state particles are supported.
1341 @param inputParticleList The input ParticleList that
is required to have the relation to the Track object.
1342 @param cut Particles need to
pass these selection criteria to be added to the ParticleList
1343 @param useOnlyMostEnergeticECLCluster If
True, only the most energetic ECLCluster among ones that are matched
with the Track
is
1344 used. If
False, all matched ECLClusters are loaded. The default
is True. Regardless of
1345 this option, the KLMCluster
is loaded.
1346 @param writeOut whether RootOutput module should save the created ParticleList
1347 @param path modules are added to this path
1350 pload = register_module('ParticleLoader')
1351 pload.set_name(
'ParticleLoader_' + outputParticleList)
1353 pload.param(
'decayStrings', [outputParticleList])
1354 pload.param(
'sourceParticleListName', inputParticleList)
1355 pload.param(
'writeOut', writeOut)
1356 pload.param(
'loadChargedCluster',
True)
1357 pload.param(
'useOnlyMostEnergeticECLCluster', useOnlyMostEnergeticECLCluster)
1358 path.add_module(pload)
1362 applyCuts(outputParticleList, cut, path)
1365def extractParticlesFromROE(particleLists,
1366 signalSideParticleList=None,
1371 Extract Particle objects that belong to the Rest-Of-Events and fill them into the ParticleLists.
1372 The types of the particles other than those specified by ``particleLists`` are
not stored.
1373 If one creates a ROE
with ``fillWithMostLikely=
True`` via `buildRestOfEvent`,
for example,
1374 one should create particleLists
for not only ``pi+``, ``gamma``, ``K_L0`` but also other charged final state particles.
1376 When one calls the function
in the main path, one has to set the argument ``signalSideParticleList``
and the signal side
1377 ParticleList must have only one candidate.
1379 .. code-block:: python
1381 buildRestOfEvent(
'B0:sig', fillWithMostLikely=
True, path=mypath)
1383 roe_path = create_path()
1384 deadEndPath = create_path()
1385 signalSideParticleFilter(
'B0:sig',
'', roe_path, deadEndPath)
1387 plists = [
'%s:in_roe' % ptype
for ptype
in [
'pi+',
'gamma',
'K_L0',
'K+',
'p+',
'e+',
'mu+']]
1388 extractParticlesFromROE(plists, maskName=
'all', path=roe_path)
1392 mypath.for_each(
'RestOfEvent',
'RestOfEvents', roe_path)
1394 rankByLowest(
'B0:sig',
'deltaE', numBest=1, path=mypath)
1395 extractParticlesFromROE(plists, signalSideParticleList=
'B0:sig', maskName=
'all', path=mypath)
1400 @param particleLists (str
or list(str)) Name of output ParticleLists
1401 @param signalSideParticleList (str) Name of signal side ParticleList
1402 @param maskName (str) Name of the ROE mask to be applied on Particles
1403 @param writeOut (bool) whether RootOutput module should save the created ParticleList
1404 @param path (basf2.Path) modules are added to this path
1407 if isinstance(particleLists, str):
1408 particleLists = [particleLists]
1410 pext = register_module(
'ParticleExtractorFromROE')
1411 pext.set_name(
'ParticleExtractorFromROE_' +
'_'.join(particleLists))
1412 pext.param(
'outputListNames', particleLists)
1413 if signalSideParticleList
is not None:
1414 pext.param(
'signalSideParticleListName', signalSideParticleList)
1415 pext.param(
'maskName', maskName)
1416 pext.param(
'writeOut', writeOut)
1417 path.add_module(pext)
1420def applyCuts(list_name, cut, path):
1422 Removes particle candidates from ``list_name`` that do
not pass ``cut``
1423 (given selection criteria).
1426 require energetic pions safely inside the cdc
1428 .. code-block:: python
1430 applyCuts(
"pi+:mypions",
"[E > 2] and thetaInCDCAcceptance", path=mypath)
1433 You must use square braces ``[``
and ``]``
for conditional statements.
1436 list_name (str): input ParticleList name
1437 cut (str): Candidates that do
not pass these selection criteria are removed
from the ParticleList
1438 path (basf2.Path): modules are added to this path
1441 pselect = register_module('ParticleSelector')
1442 pselect.set_name(
'ParticleSelector_applyCuts_' + list_name)
1443 pselect.param(
'decayString', list_name)
1444 pselect.param(
'cut', cut)
1445 path.add_module(pselect)
1448def applyEventCuts(cut, path, metavariables=None):
1450 Removes events that do not pass the ``cut`` (given selection criteria).
1453 continuum events (
in mc only)
with more than 5 tracks
1455 .. code-block:: python
1457 applyEventCuts(
"[nTracks > 5] and [isContinuumEvent], path=mypath)
1460 Only event-based variables are allowed in this function
1461 and only square brackets ``[``
and ``]``
for conditional statements.
1464 cut (str): Events that do
not pass these selection criteria are skipped
1465 path (basf2.Path): modules are added to this path
1466 metavariables (list(str)): List of meta variables to be considered
in decomposition of cut
1470 from variables
import variables
1472 def find_vars(t: tuple, var_list: list, meta_list: list) ->
None:
1473 """ Recursive helper function to find variable names """
1474 if not isinstance(t, tuple):
1476 if t[0] == b2parser.B2ExpressionParser.node_types[
'IdentifierNode']:
1479 if t[0] == b2parser.B2ExpressionParser.node_types[
'FunctionNode']:
1480 meta_list.append(list(t[1:]))
1483 if isinstance(i, tuple):
1484 find_vars(i, var_list, meta_list)
1486 def check_variable(var_list: list, metavar_ids: list) ->
None:
1487 for var_string
in var_list:
1489 orig_name = variables.resolveAlias(var_string)
1490 if orig_name != var_string:
1493 find_vars(
b2parser.parse(orig_name), var_list_temp, meta_list_temp)
1495 check_variable(var_list_temp, metavar_ids)
1496 check_meta(meta_list_temp, metavar_ids)
1499 var = variables.getVariable(var_string)
1500 if event_var_id
not in var.description:
1501 B2ERROR(f
'Variable {var_string} is not an event-based variable! "\
1502 "Please check your inputs to the applyEventCuts method!')
1504 def check_meta(meta_list: list, metavar_ids: list) ->
None:
1505 for meta_string_list
in meta_list:
1507 while meta_string_list[0]
in metavar_ids:
1509 meta_string_list.pop(0)
1510 for meta_string
in meta_string_list[0].split(
","):
1511 find_vars(
b2parser.parse(meta_string), var_list_temp, meta_string_list)
1512 if len(meta_string_list) > 0:
1513 meta_string_list.pop(0)
1514 if len(meta_string_list) == 0:
1516 if len(meta_string_list) > 1:
1517 meta_list += meta_string_list[1:]
1518 if isinstance(meta_string_list[0], list):
1519 meta_string_list = [element
for element
in meta_string_list[0]]
1521 check_variable(var_list_temp, metavar_ids)
1523 if len(meta_string_list) == 0:
1525 elif len(meta_string_list) == 1:
1526 var = variables.getVariable(meta_string_list[0])
1528 var = variables.getVariable(meta_string_list[0], meta_string_list[1].split(
","))
1530 if event_var_id
in var.description:
1533 B2ERROR(f
'Variable {var.name} is not an event-based variable! Please check your inputs to the applyEventCuts method!')
1535 event_var_id =
'[Eventbased]'
1536 metavar_ids = [
'formula',
'abs',
1540 'exp',
'log',
'log10',
1544 metavar_ids += metavariables
1548 find_vars(
b2parser.parse(cut), var_list=var_list, meta_list=meta_list)
1550 if len(var_list) == 0
and len(meta_list) == 0:
1551 B2WARNING(f
'Cut string "{cut}" has no variables for applyEventCuts helper function!')
1553 check_variable(var_list, metavar_ids)
1554 check_meta(meta_list, metavar_ids)
1556 eselect = register_module(
'VariableToReturnValue')
1557 eselect.param(
'variable',
'passesEventCut(' + cut +
')')
1558 path.add_module(eselect)
1559 empty_path = create_path()
1560 eselect.if_value(
'<1', empty_path)
1563def reconstructDecay(decayString,
1568 candidate_limit=None,
1569 ignoreIfTooManyCandidates=True,
1570 chargeConjugation=True,
1571 allowChargeViolation=False):
1573 Creates new Particles by making combinations of existing Particles - it reconstructs unstable particles via their specified
1574 decay mode, e.g. in form of a :ref:`DecayString`: :code:`D0 -> K- pi+`
or :code:`B+ -> anti-D0 pi+`, ... All possible
1575 combinations are created (particles are used only once per candidate)
and combinations that
pass the specified selection
1576 criteria are saved to a newly created (mother) ParticleList. By default the charge conjugated decay
is reconstructed
as well
1577 (meaning that the charge conjugated mother list
is created
as well) but this can be deactivated.
1579 One can use an ``@``-sign to mark a particle
as unspecified
for inclusive analyses,
1580 e.g.
in a DecayString: :code:`
'@Xsd -> K+ pi-'`.
1582 .. seealso:: :ref:`Marker_of_unspecified_particle`
1585 The input ParticleLists are typically ordered according to the upstream reconstruction algorithm.
1586 Therefore,
if you combine two
or more identical particles
in the decay chain you should
not expect to see the same
1587 distribution
for the daughter kinematics
as they may be sorted by geometry, momentum etc.
1589 For example,
in the decay :code:`D0 -> pi0 pi0` the momentum distributions of the two ``pi0`` s are
not identical.
1590 This can be solved by manually randomising the lists before combining.
1594 * `Particle combiner how does it work? <https://questions.belle2.org/question/4318/particle-combiner-how-does-it-work/>`_
1595 * `Identical particles
in decay chain <https://questions.belle2.org/question/5724/identical-particles-
in-decay-chain/>`_
1597 @param decayString :ref:`DecayString` specifying what kind of the decay should be reconstructed
1598 (
from the DecayString the mother
and daughter ParticleLists are determined)
1599 @param cut created (mother) Particles are added to the mother ParticleList
if they
1600 pass give cuts (
in VariableManager style)
and rejected otherwise
1601 @param dmID user specified decay mode identifier
1602 @param writeOut whether RootOutput module should save the created ParticleList
1603 @param path modules are added to this path
1604 @param candidate_limit Maximum amount of candidates to be reconstructed. If
1605 the number of candidates
is exceeded a Warning will be
1607 By default, all these candidates will be removed
and event will be ignored.
1608 This behaviour can be changed by \
'ignoreIfTooManyCandidates\' flag.
1609 If no value is given the amount
is limited to a sensible
1610 default. A value <=0 will disable this limit
and can
1611 cause huge memory amounts so be careful.
1612 @param ignoreIfTooManyCandidates whether event should be ignored
or not if number of reconstructed
1613 candidates reaches limit. If event
is ignored, no candidates are reconstructed,
1614 otherwise, number of candidates
in candidate_limit
is reconstructed.
1615 @param chargeConjugation boolean to decide whether charge conjugated mode should be reconstructed
as well (on by default)
1616 @param allowChargeViolation whether the decay string needs to conserve the electric charge
1619 pmake = register_module('ParticleCombiner')
1620 pmake.set_name(
'ParticleCombiner_' + decayString)
1621 pmake.param(
'decayString', decayString)
1622 pmake.param(
'cut', cut)
1623 pmake.param(
'decayMode', dmID)
1624 pmake.param(
'writeOut', writeOut)
1625 if candidate_limit
is not None:
1626 pmake.param(
"maximumNumberOfCandidates", candidate_limit)
1627 pmake.param(
"ignoreIfTooManyCandidates", ignoreIfTooManyCandidates)
1628 pmake.param(
'chargeConjugation', chargeConjugation)
1629 pmake.param(
"allowChargeViolation", allowChargeViolation)
1630 path.add_module(pmake)
1633def combineAllParticles(inputParticleLists, outputList, cut='', writeOut=False, path=None):
1635 Creates a new Particle as the combination of all Particles
from all
1636 provided inputParticleLists. However, each particle
is used only once
1637 (even
if duplicates are provided)
and the combination has to
pass the
1638 specified selection criteria to be saved
in the newly created (mother)
1641 @param inputParticleLists List of input particle lists which are combined to the new Particle
1642 @param outputList Name of the particle combination created
with this module
1643 @param cut created (mother) Particle
is added to the mother ParticleList
if it passes
1644 these given cuts (
in VariableManager style)
and is rejected otherwise
1645 @param writeOut whether RootOutput module should save the created ParticleList
1646 @param path module
is added to this path
1649 pmake = register_module('AllParticleCombiner')
1650 pmake.set_name(
'AllParticleCombiner_' + outputList)
1651 pmake.param(
'inputListNames', inputParticleLists)
1652 pmake.param(
'outputListName', outputList)
1653 pmake.param(
'cut', cut)
1654 pmake.param(
'writeOut', writeOut)
1655 path.add_module(pmake)
1658def reconstructMissingKlongDecayExpert(decayString,
1665 Creates a list of K_L0's and of B -> K_L0 + X, with X being a fully-reconstructed state.
1666 The K_L0 momentum is determined
from kinematic constraints of the two-body B decay into K_L0
and X
1668 @param decayString DecayString specifying what kind of the decay should be reconstructed
1669 (
from the DecayString the mother
and daughter ParticleLists are determined)
1670 @param cut Particles are added to the K_L0
and B ParticleList
if the B candidates
1671 pass the given cuts (
in VariableManager style)
and rejected otherwise
1672 @param dmID user specified decay mode identifier
1673 @param writeOut whether RootOutput module should save the created ParticleList
1674 @param path modules are added to this path
1675 @param recoList suffix appended to original K_L0
and B ParticleList that identify the newly created K_L0
and B lists
1678 pcalc = register_module('KlongMomentumCalculatorExpert')
1679 pcalc.set_name(
'KlongMomentumCalculatorExpert_' + decayString)
1680 pcalc.param(
'decayString', decayString)
1681 pcalc.param(
'writeOut', writeOut)
1682 pcalc.param(
'recoList', recoList)
1683 path.add_module(pcalc)
1685 rmake = register_module(
'KlongDecayReconstructorExpert')
1686 rmake.set_name(
'KlongDecayReconstructorExpert_' + decayString)
1687 rmake.param(
'decayString', decayString)
1688 rmake.param(
'cut', cut)
1689 rmake.param(
'decayMode', dmID)
1690 rmake.param(
'writeOut', writeOut)
1691 rmake.param(
'recoList', recoList)
1692 path.add_module(rmake)
1695def setBeamConstrainedMomentum(particleList, decayStringTarget, decayStringDaughters, path=None):
1697 Replace the four-momentum of the target Particle by p(beam) - p(selected daughters).
1698 The momentum of the mother Particle will not be changed.
1700 @param particleList mother Particlelist
1701 @param decayStringTarget DecayString specifying the target particle whose momentum
1703 @param decayStringDaughters DecayString specifying the daughter particles used to replace
1704 the momentum of the target particle by p(beam)-p(daughters)
1707 mod = register_module('ParticleMomentumUpdater')
1708 mod.set_name(
'ParticleMomentumUpdater' + particleList)
1709 mod.param(
'particleList', particleList)
1710 mod.param(
'decayStringTarget', decayStringTarget)
1711 mod.param(
'decayStringDaughters', decayStringDaughters)
1712 path.add_module(mod)
1715def updateKlongKinematicsExpert(particleList,
1719 Calculates and updates the kinematics of B->K_L0 + something
else with same method
as
1720 `reconstructMissingKlongDecayExpert`. This helps to revert the kinematics after the vertex fitting.
1722 @param particleList input ParticleList of B meson that decays to K_L0 + X
1723 @param writeOut whether RootOutput module should save the ParticleList
1724 @param path modules are added to this path
1727 mod = register_module('KlongMomentumUpdaterExpert')
1728 mod.set_name(
'KlongMomentumUpdaterExpert_' + particleList)
1729 mod.param(
'listName', particleList)
1730 mod.param(
'writeOut', writeOut)
1731 path.add_module(mod)
1734def replaceMass(replacerName, particleLists=None, pdgCode=22, path=None):
1736 replaces the mass of the particles inside the given particleLists
1737 with the invariant mass of the particle corresponding to the given pdgCode.
1739 @param particleLists new ParticleList filled
with copied Particles
1740 @param pdgCode PDG code
for mass reference
1741 @param path modules are added to this path
1744 if particleLists
is None:
1748 pmassupdater = register_module(
'ParticleMassUpdater')
1749 pmassupdater.set_name(
'ParticleMassUpdater_' + replacerName)
1750 pmassupdater.param(
'particleLists', particleLists)
1751 pmassupdater.param(
'pdgCode', pdgCode)
1752 path.add_module(pmassupdater)
1755def reconstructRecoil(decayString,
1760 candidate_limit=None,
1761 allowChargeViolation=False):
1763 Creates new Particles that recoil against the input particles.
1765 For example the decay string M -> D1 D2 D3 will:
1766 - create mother Particle M for each unique combination of D1, D2, D3 Particles
1767 - Particles D1, D2, D3 will be appended
as daughters to M
1768 - the 4-momentum of the mother Particle M
is given by
1769 p(M) = p(HER) + p(LER) - Sum_i p(Di)
1771 @param decayString DecayString specifying what kind of the decay should be reconstructed
1772 (
from the DecayString the mother
and daughter ParticleLists are determined)
1773 @param cut created (mother) Particles are added to the mother ParticleList
if they
1774 pass give cuts (
in VariableManager style)
and rejected otherwise
1775 @param dmID user specified decay mode identifier
1776 @param writeOut whether RootOutput module should save the created ParticleList
1777 @param path modules are added to this path
1778 @param candidate_limit Maximum amount of candidates to be reconstructed. If
1779 the number of candidates
is exceeded no candidate will be
1780 reconstructed
for that event
and a Warning will be
1782 If no value
is given the amount
is limited to a sensible
1783 default. A value <=0 will disable this limit
and can
1784 cause huge memory amounts so be careful.
1785 @param allowChargeViolation whether the decay string needs to conserve the electric charge
1788 pmake = register_module('ParticleCombiner')
1789 pmake.set_name(
'ParticleCombiner_' + decayString)
1790 pmake.param(
'decayString', decayString)
1791 pmake.param(
'cut', cut)
1792 pmake.param(
'decayMode', dmID)
1793 pmake.param(
'writeOut', writeOut)
1794 pmake.param(
'recoilParticleType', 1)
1795 if candidate_limit
is not None:
1796 pmake.param(
"maximumNumberOfCandidates", candidate_limit)
1797 pmake.param(
'allowChargeViolation', allowChargeViolation)
1798 path.add_module(pmake)
1801def reconstructRecoilDaughter(decayString,
1806 candidate_limit=None,
1807 allowChargeViolation=False):
1809 Creates new Particles that are daughters of the particle reconstructed in the recoil (always assumed to be the first daughter).
1811 For example the decay string M -> D1 D2 D3 will:
1812 - create mother Particle M
for each unique combination of D1, D2, D3 Particles
1813 - Particles D1, D2, D3 will be appended
as daughters to M
1814 - the 4-momentum of the mother Particle M
is given by
1815 p(M) = p(D1) - Sum_i p(Di), where i>1
1817 @param decayString DecayString specifying what kind of the decay should be reconstructed
1818 (
from the DecayString the mother
and daughter ParticleLists are determined)
1819 @param cut created (mother) Particles are added to the mother ParticleList
if they
1820 pass give cuts (
in VariableManager style)
and rejected otherwise
1821 @param dmID user specified decay mode identifier
1822 @param writeOut whether RootOutput module should save the created ParticleList
1823 @param path modules are added to this path
1824 @param candidate_limit Maximum amount of candidates to be reconstructed. If
1825 the number of candidates
is exceeded no candidate will be
1826 reconstructed
for that event
and a Warning will be
1828 If no value
is given the amount
is limited to a sensible
1829 default. A value <=0 will disable this limit
and can
1830 cause huge memory amounts so be careful.
1831 @param allowChargeViolation whether the decay string needs to conserve the electric charge taking into account that the first
1832 daughter
is actually the mother
1835 pmake = register_module('ParticleCombiner')
1836 pmake.set_name(
'ParticleCombiner_' + decayString)
1837 pmake.param(
'decayString', decayString)
1838 pmake.param(
'cut', cut)
1839 pmake.param(
'decayMode', dmID)
1840 pmake.param(
'writeOut', writeOut)
1841 pmake.param(
'recoilParticleType', 2)
1842 if candidate_limit
is not None:
1843 pmake.param(
"maximumNumberOfCandidates", candidate_limit)
1844 pmake.param(
'allowChargeViolation', allowChargeViolation)
1845 path.add_module(pmake)
1848def rankByHighest(particleList,
1852 allowMultiRank=False,
1854 overwriteRank=False,
1857 Ranks particles in the input list by the given variable (highest to lowest),
and stores an integer rank
for each Particle
1858 in an :b2:var:`extraInfo` field ``${variable}_rank`` starting at 1 (best).
1859 The list
is also sorted
from best to worst candidate
1860 (each charge, e.g. B+/B-, separately).
1861 This can be used to perform a best candidate selection by cutting on the corresponding rank value,
or by specifying
1862 a non-zero value
for 'numBest'.
1865 Extra-info fields can be accessed by the :b2:var:`extraInfo` metavariable.
1866 These variable names can become clunky, so it
's probably a good idea to set an alias.
1867 For example if you rank your B candidates by momentum,
1871 rankByHighest(
"B0:myCandidates",
"p", path=mypath)
1872 vm.addAlias(
"momentumRank",
"extraInfo(p_rank)")
1875 @param particleList The input ParticleList
1876 @param variable Variable to order Particles by.
1877 @param numBest If
not zero, only the $numBest Particles
in particleList
with rank <= numBest are kept.
1878 @param outputVariable Name
for the variable that will be created which contains the rank, Default
is '${variable}_rank'.
1879 @param allowMultiRank If true, candidates
with the same value will get the same rank.
1880 @param cut Only candidates passing the cut will be ranked. The others will have rank -1
1881 @param overwriteRank If true, the extraInfo of rank
is overwritten when the particle has already the extraInfo.
1882 @param path modules are added to this path
1885 bcs = register_module('BestCandidateSelection')
1886 bcs.set_name(
'BestCandidateSelection_' + particleList +
'_' + variable)
1887 bcs.param(
'particleList', particleList)
1888 bcs.param(
'variable', variable)
1889 bcs.param(
'numBest', numBest)
1890 bcs.param(
'outputVariable', outputVariable)
1891 bcs.param(
'allowMultiRank', allowMultiRank)
1892 bcs.param(
'cut', cut)
1893 bcs.param(
'overwriteRank', overwriteRank)
1894 path.add_module(bcs)
1897def rankByLowest(particleList,
1901 allowMultiRank=False,
1903 overwriteRank=False,
1906 Ranks particles in the input list by the given variable (lowest to highest),
and stores an integer rank
for each Particle
1907 in an :b2:var:`extraInfo` field ``${variable}_rank`` starting at 1 (best).
1908 The list
is also sorted
from best to worst candidate
1909 (each charge, e.g. B+/B-, separately).
1910 This can be used to perform a best candidate selection by cutting on the corresponding rank value,
or by specifying
1911 a non-zero value
for 'numBest'.
1914 Extra-info fields can be accessed by the :b2:var:`extraInfo` metavariable.
1915 These variable names can become clunky, so it
's probably a good idea to set an alias.
1916 For example if you rank your B candidates by :b2:var:`dM`,
1920 rankByLowest(
"B0:myCandidates",
"dM", path=mypath)
1921 vm.addAlias(
"massDifferenceRank",
"extraInfo(dM_rank)")
1924 @param particleList The input ParticleList
1925 @param variable Variable to order Particles by.
1926 @param numBest If
not zero, only the $numBest Particles
in particleList
with rank <= numBest are kept.
1927 @param outputVariable Name
for the variable that will be created which contains the rank, Default
is '${variable}_rank'.
1928 @param allowMultiRank If true, candidates
with the same value will get the same rank.
1929 @param cut Only candidates passing the cut will be ranked. The others will have rank -1
1930 @param overwriteRank If true, the extraInfo of rank
is overwritten when the particle has already the extraInfo.
1931 @param path modules are added to this path
1934 bcs = register_module('BestCandidateSelection')
1935 bcs.set_name(
'BestCandidateSelection_' + particleList +
'_' + variable)
1936 bcs.param(
'particleList', particleList)
1937 bcs.param(
'variable', variable)
1938 bcs.param(
'numBest', numBest)
1939 bcs.param(
'selectLowest',
True)
1940 bcs.param(
'allowMultiRank', allowMultiRank)
1941 bcs.param(
'outputVariable', outputVariable)
1942 bcs.param(
'cut', cut)
1943 bcs.param(
'overwriteRank', overwriteRank)
1944 path.add_module(bcs)
1947def applyRandomCandidateSelection(particleList, path=None):
1949 If there are multiple candidates in the provided particleList, all but one of them are removed randomly.
1950 This
is done on a event-by-event basis.
1952 @param particleList ParticleList
for which the random candidate selection should be applied
1953 @param path module
is added to this path
1956 rcs = register_module('BestCandidateSelection')
1957 rcs.set_name(
'RandomCandidateSelection_' + particleList)
1958 rcs.param(
'particleList', particleList)
1959 rcs.param(
'variable',
'random')
1960 rcs.param(
'selectLowest',
False)
1961 rcs.param(
'allowMultiRank',
False)
1962 rcs.param(
'numBest', 1)
1963 rcs.param(
'cut',
'')
1964 rcs.param(
'outputVariable',
'')
1965 path.add_module(rcs)
1970 Prints the contents of DataStore in the first event (
or a specific event number
or all events).
1971 Will list all objects
and arrays (including size).
1974 The command line tool: ``b2file-size``.
1977 eventNumber (int): Print the datastore only
for this event. The default
1978 (-1) prints only the first event, 0 means
print for all events (can produce large output)
1979 path (basf2.Path): the PrintCollections module
is added to this path
1982 This will
print a lot of output
if you
print it
for all events
and process many events.
1986 printDS = register_module('PrintCollections')
1987 printDS.param(
'printForEvent', eventNumber)
1988 path.add_module(printDS)
1991def printVariableValues(list_name, var_names, path):
1993 Prints out values of specified variables of all Particles included in given ParticleList. For debugging purposes.
1995 @param list_name input ParticleList name
1996 @param var_names vector of variable names to be printed
1997 @param path modules are added to this path
2000 prlist = register_module('ParticlePrinter')
2001 prlist.set_name(
'ParticlePrinter_' + list_name)
2002 prlist.param(
'listName', list_name)
2003 prlist.param(
'fullPrint',
False)
2004 prlist.param(
'variables', var_names)
2005 path.add_module(prlist)
2008def printList(list_name, full, path):
2010 Prints the size and executes Particle->print() (
if full=
True)
2011 method
for all Particles
in given ParticleList. For debugging purposes.
2013 @param list_name input ParticleList name
2014 @param full execute Particle->print() method
for all Particles
2015 @param path modules are added to this path
2018 prlist = register_module('ParticlePrinter')
2019 prlist.set_name(
'ParticlePrinter_' + list_name)
2020 prlist.param(
'listName', list_name)
2021 prlist.param(
'fullPrint', full)
2022 path.add_module(prlist)
2025def variablesToNtuple(decayString, variables, treename='variables', filename='ntuple.root', path=None, basketsize=1600,
2026 signalSideParticleList="", filenameSuffix="", useFloat=False, storeEventType=True,
2027 ignoreCommandLineOverride=False):
2029 Creates and fills a flat ntuple
with the specified variables
from the VariableManager.
2030 If a decayString
is provided, then there will be one entry per candidate (
for particle
in list of candidates).
2031 If an empty decayString
is provided, there will be one entry per event (useful
for trigger studies, etc).
2034 decayString (str): specifies type of Particles
and determines the name of the ParticleList
2035 variables (list(str)): the list of variables (which must be registered
in the VariableManager)
2036 treename (str): name of the ntuple tree
2037 filename (str): which
is used to store the variables
2038 path (basf2.Path): the basf2 path where the analysis
is processed
2039 basketsize (int): size of baskets
in the output ntuple
in bytes
2040 signalSideParticleList (str): The name of the signal-side ParticleList.
2041 Only valid
if the module
is called
in a for_each loop over the RestOfEvent.
2042 filenameSuffix (str): suffix to be appended to the filename before ``.root``.
2043 useFloat (bool): Use single precision (float) instead of double precision (double)
2044 for floating-point numbers.
2045 storeEventType (bool) :
if true, the branch __eventType__
is added
for the MC event type information.
2046 The information
is available
from MC16 on.
2047 ignoreCommandLineOverride (bool) :
if true, ignore override of file name via command line argument ``-o``.
2049 .. tip:: The output filename can be overridden using the ``-o`` argument of basf2.
2052 output = register_module('VariablesToNtuple')
2053 output.set_name(
'VariablesToNtuple_' + decayString)
2054 output.param(
'particleList', decayString)
2055 output.param(
'variables', variables)
2056 output.param(
'fileName', filename)
2057 output.param(
'treeName', treename)
2058 output.param(
'basketSize', basketsize)
2059 output.param(
'signalSideParticleList', signalSideParticleList)
2060 output.param(
'fileNameSuffix', filenameSuffix)
2061 output.param(
'useFloat', useFloat)
2062 output.param(
'storeEventType', storeEventType)
2063 output.param(
'ignoreCommandLineOverride', ignoreCommandLineOverride)
2064 path.add_module(output)
2070 filename='ntuple.root',
2073 prefixDecayString=False,
2075 ignoreCommandLineOverride=False):
2077 Creates and fills a flat ntuple
with the specified variables
from the VariableManager
2080 decayString (str): specifies type of Particles
and determines the name of the ParticleList
2081 variables (list(tuple))): variables + binning which must be registered
in the VariableManager
2082 variables_2d (list(tuple)): pair of variables + binning
for each which must be registered
in the VariableManager
2083 filename (str): which
is used to store the variables
2084 path (basf2.Path): the basf2 path where the analysis
is processed
2085 directory (str): directory inside the output file where the histograms should be saved.
2086 Useful
if you want to have different histograms
in the same file to separate them.
2087 prefixDecayString (bool): If
True the decayString will be prepended to the directory name to allow
for more
2088 programmatic naming of the structure
in the file.
2089 filenameSuffix (str): suffix to be appended to the filename before ``.root``.
2090 ignoreCommandLineOverride (bool) :
if true, ignore override of file name via command line argument ``-o``.
2092 .. tip:: The output filename can be overridden using the ``-o`` argument of basf2.
2095 if variables_2d
is None:
2097 output = register_module(
'VariablesToHistogram')
2098 output.set_name(
'VariablesToHistogram_' + decayString)
2099 output.param(
'particleList', decayString)
2100 output.param(
'variables', variables)
2101 output.param(
'variables_2d', variables_2d)
2102 output.param(
'fileName', filename)
2103 output.param(
'fileNameSuffix', filenameSuffix)
2104 output.param(
'ignoreCommandLineOverride', ignoreCommandLineOverride)
2105 if directory
is not None or prefixDecayString:
2106 if directory
is None:
2108 if prefixDecayString:
2109 directory = decayString +
"_" + directory
2110 output.param(
"directory", directory)
2111 path.add_module(output)
2116 For each particle in the input list the selected variables are saved
in an extra-info field
with the given name.
2117 Can be used when wanting to save variables before modifying them, e.g. when performing vertex fits.
2120 particleList (str): The input ParticleList
2121 variables (dict[str,str]): Dictionary of Variables (key)
and extraInfo names (value).
2122 option (int): Option to overwrite an existing extraInfo. Choose among -1, 0, 1, 2.
2123 An existing extra info
with the same name will be overwritten
if the new
2124 value
is lower / will never be overwritten / will be overwritten
if the
2125 new value
is higher / will always be overwritten (option = -1/0/1/2).
2126 path (basf2.Path): modules are added to this path
2129 mod = register_module('VariablesToExtraInfo')
2130 mod.set_name(
'VariablesToExtraInfo_' + particleList)
2131 mod.param(
'particleList', particleList)
2132 mod.param(
'variables', variables)
2133 mod.param(
'overwrite', option)
2134 path.add_module(mod)
2137def variablesToDaughterExtraInfo(particleList, decayString, variables, option=0, path=None):
2139 For each daughter particle specified via decay string the selected variables (estimated for the mother particle)
2140 are saved
in an extra-info field
with the given name. In other words, the property of mother
is saved
as extra-info
2141 to specified daughter particle.
2144 particleList (str): The input ParticleList
2145 decayString (str): Decay string that specifies to which daughter the extra info should be appended
2146 variables (dict[str,str]): Dictionary of Variables (key)
and extraInfo names (value).
2147 option (int): Option to overwrite an existing extraInfo. Choose among -1, 0, 1, 2.
2148 An existing extra info
with the same name will be overwritten
if the new
2149 value
is lower / will never be overwritten / will be overwritten
if the
2150 new value
is higher / will always be overwritten (option = -1/0/1/2).
2151 path (basf2.Path): modules are added to this path
2154 mod = register_module('VariablesToExtraInfo')
2155 mod.set_name(
'VariablesToDaughterExtraInfo_' + particleList)
2156 mod.param(
'particleList', particleList)
2157 mod.param(
'decayString', decayString)
2158 mod.param(
'variables', variables)
2159 mod.param(
'overwrite', option)
2160 path.add_module(mod)
2163def variablesToEventExtraInfo(particleList, variables, option=0, path=None):
2165 For each particle in the input list the selected variables are saved
in an event-extra-info field
with the given name,
2166 Can be used to save MC truth information,
for example,
in a ntuple of reconstructed particles.
2169 When the function
is called first time
not in the main path but
in a sub-path e.g. ``roe_path``,
2170 the eventExtraInfo cannot be accessed
from the main path because of the shorter lifetime of the event-extra-info field.
2171 If one wants to call the function
in a sub-path, one has to call the function
in the main path beforehand.
2174 particleList (str): The input ParticleList
2175 variables (dict[str,str]): Dictionary of Variables (key)
and extraInfo names (value).
2176 option (int): Option to overwrite an existing extraInfo. Choose among -1, 0, 1, 2.
2177 An existing extra info
with the same name will be overwritten
if the new
2178 value
is lower / will never be overwritten / will be overwritten
if the
2179 new value
is higher / will always be overwritten (option = -1/0/1/2).
2180 path (basf2.Path): modules are added to this path
2183 mod = register_module('VariablesToEventExtraInfo')
2184 mod.set_name(
'VariablesToEventExtraInfo_' + particleList)
2185 mod.param(
'particleList', particleList)
2186 mod.param(
'variables', variables)
2187 mod.param(
'overwrite', option)
2188 path.add_module(mod)
2191def variableToSignalSideExtraInfo(particleList, varToExtraInfo, path):
2193 Write the value of specified variables estimated for the single particle
in the input list (has to contain exactly 1
2194 particle)
as an extra info to the particle related to current ROE.
2195 Should be used only
in the for_each roe path.
2198 particleList (str): The input ParticleList
2199 varToExtraInfo (dict[str,str]): Dictionary of Variables (key)
and extraInfo names (value).
2200 path (basf2.Path): modules are added to this path
2203 mod = register_module('SignalSideVariablesToExtraInfo')
2204 mod.set_name(
'SigSideVarToExtraInfo_' + particleList)
2205 mod.param(
'particleListName', particleList)
2206 mod.param(
'variableToExtraInfo', varToExtraInfo)
2207 path.add_module(mod)
2210def signalRegion(particleList, cut, path=None, name="isSignalRegion", blind_data=True):
2212 Define and blind a signal region.
2213 Per default, the defined signal region
is cut out
if ran on data.
2214 This function will provide a new variable
'isSignalRegion' as default, which
is either 0
or 1 depending on the cut
2218 .. code-block:: python
2220 ma.reconstructDecay(
"B+:sig -> D+ pi0",
"Mbc>5.2", path=path)
2221 ma.signalRegion(
"B+:sig",
2222 "Mbc>5.27 and abs(deltaE)<0.2",
2225 ma.variablesToNtuples(
"B+:sig", [
"isSignalRegion"], path=path)
2228 particleList (str): The input ParticleList
2229 cut (str): Cut string describing the signal region
2230 path (basf2.Path):: Modules are added to this path
2231 name (str): Name of the Signal region
in the variable manager
2232 blind_data (bool): Automatically exclude signal region
from data
2236 from variables
import variables
2237 mod = register_module(
'VariablesToExtraInfo')
2238 mod.set_name(f
'{name}_' + particleList)
2239 mod.param(
'particleList', particleList)
2240 mod.param(
'variables', {f
"passesCut({cut})": name})
2241 variables.addAlias(name, f
"extraInfo({name})")
2242 path.add_module(mod)
2246 applyCuts(particleList, f
"{name}==0 or isMC==1", path=path)
2249def removeExtraInfo(particleLists=None, removeEventExtraInfo=False, path=None):
2251 Removes the ExtraInfo of the given particleLists. If specified (removeEventExtraInfo = True) also the EventExtraInfo
is removed.
2254 if particleLists
is None:
2256 mod = register_module(
'ExtraInfoRemover')
2257 mod.param(
'particleLists', particleLists)
2258 mod.param(
'removeEventExtraInfo', removeEventExtraInfo)
2259 path.add_module(mod)
2262def signalSideParticleFilter(particleList, selection, roe_path, deadEndPath):
2264 Checks if the current ROE object
in the for_each roe path (argument roe_path)
is related
2265 to the particle
from the input ParticleList. Additional selection criteria can be applied.
2266 If ROE
is not related to any of the Particles
from ParticleList
or the Particle doesn
't
2267 meet the selection criteria the execution of deadEndPath is started. This path,
as the name
2268 suggests should be empty
and its purpose
is to end the execution of for_each roe path
for
2269 the current ROE object.
2271 @param particleList The input ParticleList
2272 @param selection Selection criteria that Particle needs meet
in order
for for_each ROE path to
continue
2273 @param for_each roe path
in which this filter
is executed
2274 @param deadEndPath empty path that ends execution of or_each roe path
for the current ROE object.
2277 mod = register_module('SignalSideParticleFilter')
2278 mod.set_name(
'SigSideParticleFilter_' + particleList)
2279 mod.param(
'particleLists', [particleList])
2280 mod.param(
'selection', selection)
2281 roe_path.add_module(mod)
2282 mod.if_false(deadEndPath)
2285def signalSideParticleListsFilter(particleLists, selection, roe_path, deadEndPath):
2287 Checks if the current ROE object
in the for_each roe path (argument roe_path)
is related
2288 to the particle
from the input ParticleList. Additional selection criteria can be applied.
2289 If ROE
is not related to any of the Particles
from ParticleList
or the Particle doesn
't
2290 meet the selection criteria the execution of deadEndPath is started. This path,
as the name
2291 suggests should be empty
and its purpose
is to end the execution of for_each roe path
for
2292 the current ROE object.
2294 @param particleLists The input ParticleLists
2295 @param selection Selection criteria that Particle needs meet
in order
for for_each ROE path to
continue
2296 @param for_each roe path
in which this filter
is executed
2297 @param deadEndPath empty path that ends execution of or_each roe path
for the current ROE object.
2300 mod = register_module('SignalSideParticleFilter')
2301 mod.set_name(
'SigSideParticleFilter_' + particleLists[0])
2302 mod.param(
'particleLists', particleLists)
2303 mod.param(
'selection', selection)
2304 roe_path.add_module(mod)
2305 mod.if_false(deadEndPath)
2314 chargeConjugation=True,
2317 Finds and creates a ``ParticleList``
from given decay string.
2318 ``ParticleList`` of daughters
with sub-decay
is created.
2320 Only the particles made
from MCParticle, which can be loaded by `fillParticleListFromMC`, are accepted
as daughters.
2322 Only signal particle, which means :b2:var:`isSignal`
is equal to 1,
is stored. One can use the decay string grammar
2323 to change the behavior of :b2:var:`isSignal`. One can find detailed information
in :ref:`DecayString`.
2326 If one uses same sub-decay twice, same particles are registered to a ``ParticleList``. For example,
2327 ``K_S0:pi0pi0 =direct=> [pi0:gg =direct=> gamma:MC gamma:MC] [pi0:gg =direct=> gamma:MC gamma:MC]``.
2328 One can skip the second sub-decay, ``K_S0:pi0pi0 =direct=> [pi0:gg =direct=> gamma:MC gamma:MC] pi0:gg``.
2331 It
is recommended to use only primary particles
as daughter particles unless you want to explicitly study the secondary
2332 particles. The behavior of MC-matching
for secondary particles
from a stable particle decay
is not guaranteed.
2333 Please consider to use `fillParticleListFromMC`
with ``skipNonPrimary=
True`` to load daughter particles.
2334 Moreover, it
is recommended to load ``K_S0``
and ``Lambda0`` directly
from MCParticle by `fillParticleListFromMC` rather
2335 than reconstructing
from two pions
or a proton-pion pair, because their direct daughters can be the secondary particle.
2338 @param decayString :ref:`DecayString` specifying what kind of the decay should be reconstructed
2339 (
from the DecayString the mother
and daughter ParticleLists are determined)
2340 @param cut created (mother) Particles are added to the mother ParticleList
if they
2341 pass given cuts (
in VariableManager style)
and rejected otherwise
2342 isSignal==1
is always required by default.
2343 @param dmID user specified decay mode identifier
2344 @param writeOut whether RootOutput module should save the created ParticleList
2345 @param path modules are added to this path
2346 @param chargeConjugation boolean to decide whether charge conjugated mode should be reconstructed
as well (on by default)
2349 pmake = register_module('ParticleCombinerFromMC')
2350 pmake.set_name(
'ParticleCombinerFromMC_' + decayString)
2351 pmake.param(
'decayString', decayString)
2352 pmake.param(
'cut', cut)
2353 pmake.param(
'decayMode', dmID)
2354 pmake.param(
'writeOut', writeOut)
2355 pmake.param(
'chargeConjugation', chargeConjugation)
2356 path.add_module(pmake)
2363 appendAllDaughters=False,
2364 skipNonPrimaryDaughters=True,
2368 Finds and creates a ``ParticleList``
for all ``MCParticle`` decays matching a given :ref:`DecayString`.
2369 The decay string
is required to describe correctly what you want.
2370 In the case of inclusive decays, you can use :ref:`Grammar_for_custom_MCMatching`
2372 The output particles has only the daughter particles written
in the given decay string,
if
2373 ``appendAllDaughters=
False`` (default). If ``appendAllDaughters=
True``, all daughters of the matched MCParticle are
2374 appended
in the order defined at the MCParticle level. For example,
2376 .. code-block:: python
2378 findMCDecay(
'B0:Xee',
'B0 -> e+ e- ... ?gamma', appendAllDaughters=
False, path=mypath)
2380 The output ParticleList ``B0:Xee`` will match the inclusive ``B0 -> e+ e-`` decays (but neutrinos are
not included),
2381 in both cases of ``appendAllDaughters``
is false
and true.
2382 If the ``appendAllDaughters=
False``
as above example, the ``B0:Xee`` has only two electrons
as daughters.
2383 While,
if ``appendAllDaughters=
True``, all daughters of the matched MCParticles are appended. When the truth decay mode of
2384 the MCParticle
is ``B0 -> [K*0 -> K+ pi-] [J/psi -> e+ e-]``, the first daughter of ``B0:Xee``
is ``K*0``
and ``e+``
2385 will be the first daughter of second daughter of ``B0:Xee``.
2387 The option ``skipNonPrimaryDaughters`` only has an effect
if ``appendAllDaughters=
True``. If ``skipNonPrimaryDaughters=
True``,
2388 all primary daughters are appended but the secondary particles are
not.
2391 Daughters of ``Lambda0`` are
not primary, but ``Lambda0``
is not a final state particle.
2392 In order
for the MCMatching to work properly, the daughters of ``Lambda0`` are appended to
2393 ``Lambda0`` regardless of the value of the option ``skipNonPrimaryDaughters``.
2396 @param list_name The output particle list name
2397 @param decay The decay string which you want
2398 @param writeOut Whether `RootOutput` module should save the created ``outputList``
2399 @param skipNonPrimaryDaughters
if true, skip non primary daughters, useful to study final state daughter particles
2400 @param appendAllDaughters
if true,
not only the daughters described
in the decay string but all daughters are appended
2401 @param path modules are added to this path
2404 decayfinder = register_module('MCDecayFinder')
2405 decayfinder.set_name(
'MCDecayFinder_' + list_name)
2406 decayfinder.param(
'listName', list_name)
2407 decayfinder.param(
'decayString', decay)
2408 decayfinder.param(
'appendAllDaughters', appendAllDaughters)
2409 decayfinder.param(
'skipNonPrimaryDaughters', skipNonPrimaryDaughters)
2410 decayfinder.param(
'writeOut', writeOut)
2411 path.add_module(decayfinder)
2414def summaryOfLists(particleLists, outputFile=None, path=None):
2416 Prints out Particle statistics at the end of the job: number of events with at
2417 least one candidate, average number of candidates per event, etc.
2418 If an output file name
is provided the statistics
is also dumped into a json file
with that name.
2420 @param particleLists list of input ParticleLists
2421 @param outputFile output file name (
not created by default)
2424 particleStats = register_module('ParticleStats')
2425 particleStats.param(
'particleLists', particleLists)
2426 if outputFile
is not None:
2427 particleStats.param(
'outputFile', outputFile)
2428 path.add_module(particleStats)
2431def matchMCTruth(list_name, path):
2433 Performs MC matching (sets relation Particle->MCParticle) for
2434 all particles (
and its (grand)^N-daughter particles)
in the specified
2437 @param list_name name of the input ParticleList
2438 @param path modules are added to this path
2441 mcMatch = register_module('MCMatcherParticles')
2442 mcMatch.set_name(
'MCMatch_' + list_name)
2443 mcMatch.param(
'listName', list_name)
2444 path.add_module(mcMatch)
2447def looseMCTruth(list_name, path):
2449 Performs loose MC matching for all particles
in the specified
2451 The difference between loose
and normal mc matching algorithm
is that
2452 the loose algorithm will find the common mother of the majority of daughter
2453 particles
while the normal algorithm finds the common mother of all daughters.
2454 The results of loose mc matching algorithm are stored to the following extraInfo
2457 - looseMCMotherPDG: PDG code of most common mother
2458 - looseMCMotherIndex: 1-based StoreArray<MCParticle> index of most common mother
2459 - looseMCWrongDaughterN: number of daughters that don
't originate from the most common mother
2460 - looseMCWrongDaughterPDG: PDG code of the daughter that doesn't originate from the most common mother (only if
2461 looseMCWrongDaughterN = 1)
2462 - looseMCWrongDaughterBiB: 1 if the wrong daughter
is Beam Induced Background Particle
2464 @param list_name name of the input ParticleList
2465 @param path modules are added to this path
2468 mcMatch = register_module('MCMatcherParticles')
2469 mcMatch.set_name(
'LooseMCMatch_' + list_name)
2470 mcMatch.param(
'listName', list_name)
2471 mcMatch.param(
'looseMCMatching',
True)
2472 path.add_module(mcMatch)
2475def buildRestOfEvent(target_list_name, inputParticlelists=None,
2476 fillWithMostLikely=True,
2477 chargedPIDPriors=None, path=None):
2479 Creates for each Particle
in the given ParticleList a RestOfEvent
2480 dataobject
and makes basf2 relation between them. User can provide additional
2481 particle lists
with a different particle hypothesis like [
'K+:good, e+:good'], etc.
2483 @param target_list_name name of the input ParticleList
2484 @param inputParticlelists list of user-defined input particle list names, which serve
2485 as source of particles to build the ROE, the FSP particles
from
2486 target_list_name are automatically excluded
from the ROE object
2487 @param fillWithMostLikely By default the module uses the most likely particle mass hypothesis
for charged particles
2488 based on the PID likelihood. Turn this behavior off
if you want to configure your own
2489 input particle lists.
2490 @param chargedPIDPriors The prior PID fractions, that are used to regulate the
2491 amount of certain charged particle species, should be a list of
2492 six floats
if not None. The order of particle types
is
2493 the following: [e-, mu-, pi-, K-, p+, d+]
2494 @param path modules are added to this path
2497 if inputParticlelists
is None:
2498 inputParticlelists = []
2499 fillParticleList(
'pi+:all',
'', path=path)
2500 if fillWithMostLikely:
2501 from stdCharged
import stdMostLikely
2502 stdMostLikely(chargedPIDPriors,
'_roe', path=path)
2503 inputParticlelists = [f
'{ptype}:mostlikely_roe' for ptype
in [
'K+',
'p+',
'e+',
'mu+']]
2506 fillParticleList(
'gamma:all',
'', path=path)
2507 fillParticleList(
'K_L0:roe_default',
'isFromKLM > 0', path=path)
2508 inputParticlelists += [
'pi+:all',
'gamma:all',
'K_L0:roe_default']
2510 inputParticlelists += [
'pi+:all',
'gamma:mdst']
2511 roeBuilder = register_module(
'RestOfEventBuilder')
2512 roeBuilder.set_name(
'ROEBuilder_' + target_list_name)
2513 roeBuilder.param(
'particleList', target_list_name)
2514 roeBuilder.param(
'particleListsInput', inputParticlelists)
2515 roeBuilder.param(
'mostLikely', fillWithMostLikely)
2516 path.add_module(roeBuilder)
2519def buildNestedRestOfEvent(target_list_name, maskName='all', path=None):
2521 Creates for each Particle
in the given ParticleList a RestOfEvent
2522 @param target_list_name name of the input ParticleList
2523 @param mask_name name of the ROEMask to be used
2524 @param path modules are added to this path
2527 roeBuilder = register_module('RestOfEventBuilder')
2528 roeBuilder.set_name(
'NestedROEBuilder_' + target_list_name)
2529 roeBuilder.param(
'particleList', target_list_name)
2530 roeBuilder.param(
'nestedROEMask', maskName)
2531 roeBuilder.param(
'createNestedROE',
True)
2532 path.add_module(roeBuilder)
2535def buildRestOfEventFromMC(target_list_name, inputParticlelists=None, path=None):
2537 Creates for each Particle
in the given ParticleList a RestOfEvent
2538 @param target_list_name name of the input ParticleList
2539 @param inputParticlelists list of input particle list names, which serve
2540 as a source of particles to build ROE, the FSP particles
from
2541 target_list_name are excluded
from ROE object
2542 @param path modules are added to this path
2545 if inputParticlelists
is None:
2546 inputParticlelists = []
2547 if (len(inputParticlelists) == 0):
2551 types = [
'gamma',
'e+',
'mu+',
'pi+',
'K+',
'p+',
'K_L0',
2552 'n0',
'nu_e',
'nu_mu',
'nu_tau',
2555 fillParticleListFromMC(f
"{t}:roe_default_gen",
'mcPrimary > 0 and nDaughters == 0',
2556 True,
True, path=path)
2557 inputParticlelists += [f
"{t}:roe_default_gen"]
2558 roeBuilder = register_module(
'RestOfEventBuilder')
2559 roeBuilder.set_name(
'MCROEBuilder_' + target_list_name)
2560 roeBuilder.param(
'particleList', target_list_name)
2561 roeBuilder.param(
'particleListsInput', inputParticlelists)
2562 roeBuilder.param(
'fromMC',
True)
2563 path.add_module(roeBuilder)
2566def appendROEMask(list_name,
2569 eclClusterSelection,
2570 klmClusterSelection='',
2573 Loads the ROE object of a particle and creates a ROE mask
with a specific name. It applies
2574 selection criteria
for tracks
and eclClusters which will be used by variables
in ROEVariables.cc.
2576 - append a ROE mask
with all tracks
in ROE coming
from the IP region
2578 .. code-block:: python
2580 appendROEMask(
'B+:sig',
'IPtracks',
'[dr < 2] and [abs(dz) < 5]', path=mypath)
2582 - append a ROE mask
with only ECL-based particles that
pass as good photon candidates
2584 .. code-block:: python
2586 goodPhotons =
'inCDCAcceptance and clusterErrorTiming < 1e6 and [clusterE1E9 > 0.4 or E > 0.075]'
2587 appendROEMask(
'B+:sig',
'goodROEGamma',
'', goodPhotons, path=mypath)
2590 @param list_name name of the input ParticleList
2591 @param mask_name name of the appended ROEMask
2592 @param trackSelection decay string
for the track-based particles
in ROE
2593 @param eclClusterSelection decay string
for the ECL-based particles
in ROE
2594 @param klmClusterSelection decay string
for the KLM-based particles
in ROE
2595 @param path modules are added to this path
2598 roeMask = register_module('RestOfEventInterpreter')
2599 roeMask.set_name(
'RestOfEventInterpreter_' + list_name +
'_' + mask_name)
2600 roeMask.param(
'particleList', list_name)
2601 roeMask.param(
'ROEMasks', [(mask_name, trackSelection, eclClusterSelection, klmClusterSelection)])
2602 path.add_module(roeMask)
2605def appendROEMasks(list_name, mask_tuples, path=None):
2607 Loads the ROE object of a particle and creates a ROE mask
with a specific name. It applies
2608 selection criteria
for track-, ECL-
and KLM-based particles which will be used by ROE variables.
2610 The multiple ROE masks
with their own selection criteria are specified
2611 via list of tuples (mask_name, trackParticleSelection, eclParticleSelection, klmParticleSelection)
or
2612 (mask_name, trackSelection, eclClusterSelection)
in case
with fractions.
2614 - Example
for two tuples, one
with and one without fractions
2616 .. code-block:: python
2618 ipTracks = (
'IPtracks',
'[dr < 2] and [abs(dz) < 5]',
'',
'')
2619 goodPhotons =
'inCDCAcceptance and [clusterErrorTiming < 1e6] and [clusterE1E9 > 0.4 or E > 0.075]'
2620 goodROEGamma = (
'ROESel',
'[dr < 2] and [abs(dz) < 5]', goodPhotons,
'')
2621 goodROEKLM = (
'IPtracks',
'[dr < 2] and [abs(dz) < 5]',
'',
'nKLMClusterTrackMatches == 0')
2622 appendROEMasks(
'B+:sig', [ipTracks, goodROEGamma, goodROEKLM], path=mypath)
2624 @param list_name name of the input ParticleList
2625 @param mask_tuples array of ROEMask list tuples to be appended
2626 @param path modules are added to this path
2629 compatible_masks = []
2630 for mask
in mask_tuples:
2633 compatible_masks += [(*mask,
'')]
2635 compatible_masks += [mask]
2636 roeMask = register_module(
'RestOfEventInterpreter')
2637 roeMask.set_name(
'RestOfEventInterpreter_' + list_name +
'_' +
'MaskList')
2638 roeMask.param(
'particleList', list_name)
2639 roeMask.param(
'ROEMasks', compatible_masks)
2640 path.add_module(roeMask)
2643def updateROEMask(list_name,
2646 eclClusterSelection='',
2647 klmClusterSelection='',
2650 Update an existing ROE mask by applying additional selection cuts for
2651 tracks
and/
or clusters.
2653 See function `appendROEMask`!
2655 @param list_name name of the input ParticleList
2656 @param mask_name name of the ROEMask to update
2657 @param trackSelection decay string
for the track-based particles
in ROE
2658 @param eclClusterSelection decay string
for the ECL-based particles
in ROE
2659 @param klmClusterSelection decay string
for the KLM-based particles
in ROE
2660 @param path modules are added to this path
2663 roeMask = register_module('RestOfEventInterpreter')
2664 roeMask.set_name(
'RestOfEventInterpreter_' + list_name +
'_' + mask_name)
2665 roeMask.param(
'particleList', list_name)
2666 roeMask.param(
'ROEMasks', [(mask_name, trackSelection, eclClusterSelection, klmClusterSelection)])
2667 roeMask.param(
'update',
True)
2668 path.add_module(roeMask)
2671def updateROEMasks(list_name, mask_tuples, path):
2673 Update existing ROE masks by applying additional selection cuts for tracks
2676 The multiple ROE masks
with their own selection criteria are specified
2677 via list tuples (mask_name, trackSelection, eclClusterSelection, klmClusterSelection)
2679 See function `appendROEMasks`!
2681 @param list_name name of the input ParticleList
2682 @param mask_tuples array of ROEMask list tuples to be appended
2683 @param path modules are added to this path
2686 compatible_masks = []
2687 for mask
in mask_tuples:
2690 compatible_masks += [(*mask,
'')]
2692 compatible_masks += [mask]
2694 roeMask = register_module(
'RestOfEventInterpreter')
2695 roeMask.set_name(
'RestOfEventInterpreter_' + list_name +
'_' +
'MaskList')
2696 roeMask.param(
'particleList', list_name)
2697 roeMask.param(
'ROEMasks', compatible_masks)
2698 roeMask.param(
'update',
True)
2699 path.add_module(roeMask)
2702def keepInROEMasks(list_name, mask_names, cut_string, path=None):
2704 This function is used to apply particle list specific cuts on one
or more ROE masks (track
or eclCluster).
2705 With this function one can KEEP the tracks/eclclusters used
in particles
from provided particle list.
2706 This function should be executed only
in the for_each roe path
for the current ROE object.
2708 To avoid unnecessary computation, the input particle list should only contain particles
from ROE
2709 (use cut
'isInRestOfEvent == 1'). To update the ECLCluster masks, the input particle list should be a photon
2710 particle list (e.g.
'gamma:someLabel'). To update the Track masks, the input particle list should be a charged
2711 pion particle list (e.g.
'pi+:someLabel').
2713 Updating a non-existing mask will create a new one.
2715 - keep only those tracks that were used
in provided particle list
2717 .. code-block:: python
2719 keepInROEMasks(
'pi+:goodTracks',
'mask',
'', path=mypath)
2721 - keep only those clusters that were used
in provided particle list
and pass a cut, apply to several masks
2723 .. code-block:: python
2725 keepInROEMasks(
'gamma:goodClusters', [
'mask1',
'mask2'],
'E > 0.1', path=mypath)
2728 @param list_name name of the input ParticleList
2729 @param mask_names array of ROEMasks to be updated
2730 @param cut_string decay string
with which the mask will be updated
2731 @param path modules are added to this path
2734 updateMask = register_module('RestOfEventUpdater')
2735 updateMask.set_name(
'RestOfEventUpdater_' + list_name +
'_masks')
2736 updateMask.param(
'particleList', list_name)
2737 updateMask.param(
'updateMasks', mask_names)
2738 updateMask.param(
'cutString', cut_string)
2739 updateMask.param(
'discard',
False)
2740 path.add_module(updateMask)
2743def discardFromROEMasks(list_name, mask_names, cut_string, path=None):
2745 This function is used to apply particle list specific cuts on one
or more ROE masks (track
or eclCluster).
2746 With this function one can DISCARD the tracks/eclclusters used
in particles
from provided particle list.
2747 This function should be executed only
in the for_each roe path
for the current ROE object.
2749 To avoid unnecessary computation, the input particle list should only contain particles
from ROE
2750 (use cut
'isInRestOfEvent == 1'). To update the ECLCluster masks, the input particle list should be a photon
2751 particle list (e.g.
'gamma:someLabel'). To update the Track masks, the input particle list should be a charged
2752 pion particle list (e.g.
'pi+:someLabel').
2754 Updating a non-existing mask will create a new one.
2756 - discard tracks that were used
in provided particle list
2758 .. code-block:: python
2760 discardFromROEMasks(
'pi+:badTracks',
'mask',
'', path=mypath)
2762 - discard clusters that were used
in provided particle list
and pass a cut, apply to several masks
2764 .. code-block:: python
2766 discardFromROEMasks(
'gamma:badClusters', [
'mask1',
'mask2'],
'E < 0.1', path=mypath)
2769 @param list_name name of the input ParticleList
2770 @param mask_names array of ROEMasks to be updated
2771 @param cut_string decay string
with which the mask will be updated
2772 @param path modules are added to this path
2775 updateMask = register_module('RestOfEventUpdater')
2776 updateMask.set_name(
'RestOfEventUpdater_' + list_name +
'_masks')
2777 updateMask.param(
'particleList', list_name)
2778 updateMask.param(
'updateMasks', mask_names)
2779 updateMask.param(
'cutString', cut_string)
2780 updateMask.param(
'discard',
True)
2781 path.add_module(updateMask)
2784def optimizeROEWithV0(list_name, mask_names, cut_string, path=None):
2786 This function is used to apply particle list specific cuts on one
or more ROE masks
for Tracks.
2787 It
is possible to optimize the ROE selection by treating tracks
from V0
's separately, meaning,
2788 taking V0's 4-momentum into account instead of 4-momenta of tracks. A cut for only specific V0's
2789 passing it can be applied.
2791 The input particle list should be a V0 particle list: K_S0 (
'K_S0:someLabel',
''),
2792 Lambda (
'Lambda:someLabel',
'')
or converted photons (
'gamma:someLabel').
2794 Updating a non-existing mask will create a new one.
2796 - treat tracks
from K_S0 inside mass window separately, replace track momenta
with K_S0 momentum
2798 .. code-block:: python
2800 optimizeROEWithV0(
'K_S0:opt',
'mask',
'0.450 < M < 0.550', path=mypath)
2802 @param list_name name of the input ParticleList
2803 @param mask_names array of ROEMasks to be updated
2804 @param cut_string decay string
with which the mask will be updated
2805 @param path modules are added to this path
2808 updateMask = register_module('RestOfEventUpdater')
2809 updateMask.set_name(
'RestOfEventUpdater_' + list_name +
'_masks')
2810 updateMask.param(
'particleList', list_name)
2811 updateMask.param(
'updateMasks', mask_names)
2812 updateMask.param(
'cutString', cut_string)
2813 path.add_module(updateMask)
2816def updateROEUsingV0Lists(target_particle_list, mask_names, default_cleanup=True, selection_cuts=None,
2817 apply_mass_fit=False, fitter='treefit', path=None):
2819 This function creates V0 particle lists (photons, :math:`K^0_S` and :math:`\\Lambda^0`)
2820 and it uses V0 candidates to update the Rest Of Event, which
is associated to the target particle list.
2821 It
is possible to apply a standard
or customized selection
and mass fit to the V0 candidates.
2824 @param target_particle_list name of the input ParticleList
2825 @param mask_names array of ROE masks to be applied
2826 @param default_cleanup
if True, predefined cuts will be applied on the V0 lists
2827 @param selection_cuts a single string of selection cuts
or tuple of three strings (photon_cuts, K_S0_cuts, Lambda0_cuts),
2828 which will be applied to the V0 lists. These cuts will have a priority over the default ones.
2829 @param apply_mass_fit
if True, a mass fit will be applied to the V0 particles
2830 @param fitter string, that represent a fitter choice:
"treefit" for TreeFitter
and "kfit" for KFit
2831 @param path modules are added to this path
2834 roe_path = create_path()
2835 deadEndPath = create_path()
2836 signalSideParticleFilter(target_particle_list, '', roe_path, deadEndPath)
2838 if (default_cleanup
and selection_cuts
is None):
2839 B2INFO(
"Using default cleanup in updateROEUsingV0Lists.")
2840 selection_cuts =
'abs(dM) < 0.1 '
2841 selection_cuts +=
'and daughter(0,particleID) > 0.2 and daughter(1,particleID) > 0.2 '
2842 selection_cuts +=
'and daughter(0,thetaInCDCAcceptance) and daughter(1,thetaInCDCAcceptance)'
2843 if (selection_cuts
is None or selection_cuts ==
''):
2844 B2INFO(
"No cleanup in updateROEUsingV0Lists.")
2845 selection_cuts = (
'True',
'True',
'True')
2846 if (isinstance(selection_cuts, str)):
2847 selection_cuts = (selection_cuts, selection_cuts, selection_cuts)
2849 roe_cuts =
'isInRestOfEvent > 0'
2850 fillConvertedPhotonsList(
'gamma:v0_roe -> e+ e-', f
'{selection_cuts[0]} and {roe_cuts}',
2852 fillParticleList(
'K_S0:v0_roe -> pi+ pi-', f
'{selection_cuts[1]} and {roe_cuts}',
2854 fillParticleList(
'Lambda0:v0_roe -> p+ pi-', f
'{selection_cuts[2]} and {roe_cuts}',
2856 fitter = fitter.lower()
2857 if (fitter !=
'treefit' and fitter !=
'kfit'):
2858 B2WARNING(
'Argument "fitter" in updateROEUsingV0Lists has only "treefit" and "kfit" options, '
2859 f
'but "{fitter}" was provided! TreeFitter will be used instead.')
2861 from vertex
import kFit, treeFit
2862 for v0
in [
'gamma:v0_roe',
'K_S0:v0_roe',
'Lambda0:v0_roe']:
2863 if (apply_mass_fit
and fitter ==
'kfit'):
2864 kFit(v0, conf_level=0.0, fit_type=
'massvertex', path=roe_path)
2865 if (apply_mass_fit
and fitter ==
'treefit'):
2866 treeFit(v0, conf_level=0.0, massConstraint=[v0.split(
':')[0]], path=roe_path)
2867 optimizeROEWithV0(v0, mask_names,
'', path=roe_path)
2868 path.for_each(
'RestOfEvent',
'RestOfEvents', roe_path)
2871def printROEInfo(mask_names=None, full_print=False,
2872 unpackComposites=True, path=None):
2874 This function prints out the information for the current ROE, so it should only be used
in the for_each path.
2875 It prints out basic ROE object info.
2877 If mask names are provided, specific information
for those masks will be printed out.
2879 It
is also possible to
print out all particles
in a given mask
if the
2880 'full_print' is set to
True.
2882 @param mask_names array of ROEMask names
for printing out info
2883 @param unpackComposites
if true, replace composite particles by their daughters
2884 @param full_print
print out particles
in mask
2885 @param path modules are added to this path
2888 if mask_names
is None:
2890 printMask = register_module(
'RestOfEventPrinter')
2891 printMask.set_name(
'RestOfEventPrinter')
2892 printMask.param(
'maskNames', mask_names)
2893 printMask.param(
'fullPrint', full_print)
2894 printMask.param(
'unpackComposites', unpackComposites)
2895 path.add_module(printMask)
2898def buildContinuumSuppression(list_name, roe_mask, path):
2900 Creates for each Particle
in the given ParticleList a ContinuumSuppression
2901 dataobject
and makes basf2 relation between them.
2903 :param list_name: name of the input ParticleList
2904 :param roe_mask: name of the ROE mask
2905 :param path: modules are added to this path
2908 qqBuilder = register_module('ContinuumSuppressionBuilder')
2909 qqBuilder.set_name(
'QQBuilder_' + list_name)
2910 qqBuilder.param(
'particleList', list_name)
2911 qqBuilder.param(
'ROEMask', roe_mask)
2912 path.add_module(qqBuilder)
2917 Removes all Particles that are not in a given list of ParticleLists (
or daughters of those).
2918 All relations
from/to Particles, daughter indices,
and other ParticleLists are fixed.
2920 @param lists_to_keep Keep the Particles
and their daughters
in these ParticleLists.
2921 @param path modules are added to this path
2924 mod = register_module('RemoveParticlesNotInLists')
2925 mod.param(
'particleLists', lists_to_keep)
2926 path.add_module(mod)
2929def inclusiveBtagReconstruction(upsilon_list_name, bsig_list_name, btag_list_name, input_lists_names, path):
2931 Reconstructs Btag from particles
in given ParticleLists which do
not share any final state particles (mdstSource)
with Bsig.
2933 @param upsilon_list_name Name of the ParticleList to be filled
with 'Upsilon(4S) -> B:sig anti-B:tag'
2934 @param bsig_list_name Name of the Bsig ParticleList
2935 @param btag_list_name Name of the Bsig ParticleList
2936 @param input_lists_names List of names of the ParticleLists which are used to reconstruct Btag
from
2939 btag = register_module('InclusiveBtagReconstruction')
2940 btag.set_name(
'InclusiveBtagReconstruction_' + bsig_list_name)
2941 btag.param(
'upsilonListName', upsilon_list_name)
2942 btag.param(
'bsigListName', bsig_list_name)
2943 btag.param(
'btagListName', btag_list_name)
2944 btag.param(
'inputListsNames', input_lists_names)
2945 path.add_module(btag)
2948def selectDaughters(particle_list_name, decay_string, path):
2950 Redefine the Daughters of a particle: select from decayString
2952 @param particle_list_name input particle list
2953 @param decay_string
for selecting the Daughters to be preserved
2956 seld = register_module('SelectDaughters')
2957 seld.set_name(
'SelectDaughters_' + particle_list_name)
2958 seld.param(
'listName', particle_list_name)
2959 seld.param(
'decayString', decay_string)
2960 path.add_module(seld)
2963def markDuplicate(particleList, prioritiseV0, path):
2965 Call DuplicateVertexMarker to find duplicate particles in a list
and
2966 flag the ones that should be kept
2968 @param particleList input particle list
2969 @param prioritiseV0
if true, give V0s a higher priority
2972 markdup = register_module('DuplicateVertexMarker')
2973 markdup.param(
'particleList', particleList)
2974 markdup.param(
'prioritiseV0', prioritiseV0)
2975 path.add_module(markdup)
2978PI0ETAVETO_COUNTER = 0
2981def oldwritePi0EtaVeto(
2984 workingDirectory='.',
2985 pi0vetoname='Pi0_Prob',
2986 etavetoname='Eta_Prob',
2992 Give pi0/eta probability for hard photon.
2994 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.
2996 The current default weight files are optimised using MC9.
2997 The input variables are
as below. Aliases are set to some variables during training.
2999 * M: pi0/eta candidates Invariant mass
3000 * lowE: soft photon energy
in lab frame
3001 * cTheta: soft photon ECL cluster
's polar angle
3002 * Zmva: soft photon output of MVA using Zernike moments of the cluster
3003 * minC2Hdist: soft photon distance from eclCluster to nearest point on nearest Helix at the ECL cylindrical radius
3005 If you don
't have weight files in your workingDirectory,
3006 these files are downloaded from database to your workingDirectory automatically.
3007 Please refer to analysis/examples/tutorials/B2A306-B02RhoGamma-withPi0EtaVeto.py
3008 about how to use this function.
3011 Please don
't use following ParticleList names elsewhere:
3013 ``gamma:HARDPHOTON``, ``pi0:PI0VETO``, ``eta:ETAVETO``,
3014 ``gamma:PI0SOFT + str(PI0ETAVETO_COUNTER)``, ``gamma:ETASOFT + str(PI0ETAVETO_COUNTER)``
3016 Please don't use ``lowE``, ``cTheta``, ``Zmva``, ``minC2Hdist`` as alias elsewhere.
3018 @param particleList The input ParticleList
3019 @param decayString specify Particle to be added to the ParticleList
3020 @param workingDirectory The weight file directory
3021 @param downloadFlag whether download default weight files
or not
3022 @param pi0vetoname extraInfo name of pi0 probability
3023 @param etavetoname extraInfo name of eta probability
3024 @param selection Selection criteria that Particle needs meet
in order
for for_each ROE path to
continue
3025 @param path modules are added to this path
3030 B2ERROR(
"The old pi0 / eta veto is not suitable for Belle analyses.")
3035 global PI0ETAVETO_COUNTER
3037 if PI0ETAVETO_COUNTER == 0:
3038 from variables
import variables
3039 variables.addAlias(
'lowE',
'daughter(1,E)')
3040 variables.addAlias(
'cTheta',
'daughter(1,clusterTheta)')
3041 variables.addAlias(
'Zmva',
'daughter(1,clusterZernikeMVA)')
3042 variables.addAlias(
'minC2Tdist',
'daughter(1,minC2TDist)')
3043 variables.addAlias(
'cluNHits',
'daughter(1,clusterNHits)')
3044 variables.addAlias(
'E9E21',
'daughter(1,clusterE9E21)')
3046 PI0ETAVETO_COUNTER = PI0ETAVETO_COUNTER + 1
3048 roe_path = create_path()
3050 deadEndPath = create_path()
3052 signalSideParticleFilter(particleList, selection, roe_path, deadEndPath)
3054 fillSignalSideParticleList(
'gamma:HARDPHOTON', decayString, path=roe_path)
3056 pi0softname =
'gamma:PI0SOFT'
3057 etasoftname =
'gamma:ETASOFT'
3058 softphoton1 = pi0softname + str(PI0ETAVETO_COUNTER)
3059 softphoton2 = etasoftname + str(PI0ETAVETO_COUNTER)
3063 '[clusterReg==1 and E>0.025] or [clusterReg==2 and E>0.02] or [clusterReg==3 and E>0.02]',
3065 applyCuts(softphoton1,
'abs(clusterTiming)<120', path=roe_path)
3068 '[clusterReg==1 and E>0.035] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.03]',
3070 applyCuts(softphoton2,
'abs(clusterTiming)<120', path=roe_path)
3072 reconstructDecay(
'pi0:PI0VETO -> gamma:HARDPHOTON ' + softphoton1,
'', path=roe_path)
3073 reconstructDecay(
'eta:ETAVETO -> gamma:HARDPHOTON ' + softphoton2,
'', path=roe_path)
3075 if not os.path.isdir(workingDirectory):
3076 os.mkdir(workingDirectory)
3077 B2INFO(
'oldwritePi0EtaVeto: ' + workingDirectory +
' has been created as workingDirectory.')
3079 if not os.path.isfile(workingDirectory +
'/pi0veto.root'):
3081 basf2_mva.download(
'Pi0VetoIdentifier', workingDirectory +
'/pi0veto.root')
3082 B2INFO(
'oldwritePi0EtaVeto: pi0veto.root has been downloaded from database to workingDirectory.')
3084 if not os.path.isfile(workingDirectory +
'/etaveto.root'):
3086 basf2_mva.download(
'EtaVetoIdentifier', workingDirectory +
'/etaveto.root')
3087 B2INFO(
'oldwritePi0EtaVeto: etaveto.root has been downloaded from database to workingDirectory.')
3089 roe_path.add_module(
'MVAExpert', listNames=[
'pi0:PI0VETO'], extraInfoName=
'Pi0Veto',
3090 identifier=workingDirectory +
'/pi0veto.root')
3091 roe_path.add_module(
'MVAExpert', listNames=[
'eta:ETAVETO'], extraInfoName=
'EtaVeto',
3092 identifier=workingDirectory +
'/etaveto.root')
3094 rankByHighest(
'pi0:PI0VETO',
'extraInfo(Pi0Veto)', numBest=1, path=roe_path)
3095 rankByHighest(
'eta:ETAVETO',
'extraInfo(EtaVeto)', numBest=1, path=roe_path)
3097 variableToSignalSideExtraInfo(
'pi0:PI0VETO', {
'extraInfo(Pi0Veto)': pi0vetoname}, path=roe_path)
3098 variableToSignalSideExtraInfo(
'eta:ETAVETO', {
'extraInfo(EtaVeto)': etavetoname}, path=roe_path)
3100 path.for_each(
'RestOfEvent',
'RestOfEvents', roe_path)
3110 hardParticle='gamma',
3111 pi0PayloadNameOverride=None,
3112 pi0SoftPhotonCutOverride=None,
3113 etaPayloadNameOverride=None,
3114 etaSoftPhotonCutOverride=None
3117 Give pi0/eta probability for hard photon.
3119 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.
3121 The current default weight files are optimised using MC12.
3123 The input variables of the mva training are:
3125 * M: pi0/eta candidates Invariant mass
3126 * daughter(1,E): soft photon energy
in lab frame
3127 * daughter(1,clusterTheta): soft photon ECL cluster
's polar angle
3128 * daughter(1,minC2TDist): soft photon distance from eclCluster to nearest point on nearest Helix at the ECL cylindrical radius
3129 * daughter(1,clusterZernikeMVA): soft photon output of MVA using Zernike moments of the cluster
3130 * daughter(1,clusterNHits): soft photon total crystal weights sum(w_i)
with w_i<=1
3131 * daughter(1,clusterE9E21): soft photon ratio of energies
in inner 3x3 crystals
and 5x5 crystals without corners
3132 * cosHelicityAngleMomentum: pi0/eta candidates cosHelicityAngleMomentum
3134 The following strings are available
for mode:
3136 * standard: loose energy cut
and no clusterNHits cut are applied to soft photon
3137 * tight: tight energy cut
and no clusterNHits cut are applied to soft photon
3138 * cluster: loose energy cut
and clusterNHits cut are applied to soft photon
3139 * both: tight energy cut
and clusterNHits cut are applied to soft photon
3141 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
3142 `pi0Prob`/`etaProb`. Otherwise, it
is available
as '{Pi0, Eta}ProbOrigin',
'{Pi0, Eta}ProbTightEnergyThreshold',
'{Pi0,
3143 Eta}ProbLargeClusterSize', or '{Pi0, Eta}ProbTightEnergyThresholdAndLargeClusterSize
'} for the four modes described above, with
3144 the chosen suffix appended.
3147 Please don't use following ParticleList names elsewhere:
3149 ``gamma:HardPhoton``,
3150 ``gamma:Pi0Soft + ListName + '_' + particleList.replace(
':',
'_')``,
3151 ``gamma:EtaSoft + ListName +
'_' + particleList.replace(
':',
'_')``,
3152 ``pi0:EtaVeto + ListName``,
3153 ``eta:EtaVeto + ListName``
3155 @param particleList the input ParticleList
3156 @param decayString specify Particle to be added to the ParticleList
3157 @param mode choose one mode out of
'standard',
'tight',
'cluster' and 'both'
3158 @param selection selection criteria that Particle needs meet
in order
for for_each ROE path to
continue
3159 @param path modules are added to this path
3160 @param suffix optional suffix to be appended to the usual extraInfo name
3161 @param hardParticle particle name which
is used to calculate the pi0/eta probability (default
is gamma)
3162 @param pi0PayloadNameOverride specify the payload name of pi0 veto only
if one wants to use non-default one. (default
is None)
3163 @param pi0SoftPhotonCutOverride specify the soft photon selection criteria of pi0 veto only
if one wants to use non-default one.
3165 @param etaPayloadNameOverride specify the payload name of eta veto only
if one wants to use non-default one. (default
is None)
3166 @param etaSoftPhotonCutOverride specify the soft photon selection criteria of eta veto only
if one wants to use non-default one.
3172 B2ERROR(
"The pi0 / eta veto is not suitable for Belle analyses.")
3174 renameSuffix =
False
3176 for module
in path.modules():
3177 if module.type() ==
"SubEvent" and not renameSuffix:
3178 for subpath
in [p.values
for p
in module.available_params()
if p.name ==
"path"]:
3181 for submodule
in subpath.modules():
3182 if f
'{hardParticle}:HardPhoton{suffix}' in submodule.name():
3184 B2WARNING(
"Same extension already used in writePi0EtaVeto, append '_0'")
3188 roe_path = create_path()
3189 deadEndPath = create_path()
3190 signalSideParticleFilter(particleList, selection, roe_path, deadEndPath)
3191 fillSignalSideParticleList(f
'{hardParticle}:HardPhoton{suffix}', decayString, path=roe_path)
3193 dictListName = {
'standard':
'Origin',
3194 'tight':
'TightEnergyThreshold',
3195 'cluster':
'LargeClusterSize',
3196 'both':
'TightEnrgyThresholdAndLargeClusterSize'}
3198 dictPi0EnergyCut = {
'standard':
'[[clusterReg==1 and E>0.025] or [clusterReg==2 and E>0.02] or [clusterReg==3 and E>0.02]]',
3199 'tight':
'[[clusterReg==1 and E>0.03] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.04]]',
3200 'cluster':
'[[clusterReg==1 and E>0.025] or [clusterReg==2 and E>0.02] or [clusterReg==3 and E>0.02]]',
3201 'both':
'[[clusterReg==1 and E>0.03] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.04]]'}
3203 dictEtaEnergyCut = {
'standard':
'[[clusterReg==1 and E>0.035] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.03]]',
3204 'tight':
'[[clusterReg==1 and E>0.06] or [clusterReg==2 and E>0.06] or [clusterReg==3 and E>0.06]]',
3205 'cluster':
'[[clusterReg==1 and E>0.035] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.03]]',
3206 'both':
'[[clusterReg==1 and E>0.06] or [clusterReg==2 and E>0.06] or [clusterReg==3 and E>0.06]]'}
3208 dictNHitsCut = {
'standard':
'clusterNHits >= 0',
3209 'tight':
'clusterNHits >= 0',
3210 'cluster':
'clusterNHits >= 2',
3211 'both':
'clusterNHits >= 2'}
3213 dictPi0PayloadName = {
'standard':
'Pi0VetoIdentifierStandard',
3214 'tight':
'Pi0VetoIdentifierWithHigherEnergyThreshold',
3215 'cluster':
'Pi0VetoIdentifierWithLargerClusterSize',
3216 'both':
'Pi0VetoIdentifierWithHigherEnergyThresholdAndLargerClusterSize'}
3218 dictEtaPayloadName = {
'standard':
'EtaVetoIdentifierStandard',
3219 'tight':
'EtaVetoIdentifierWithHigherEnergyThreshold',
3220 'cluster':
'EtaVetoIdentifierWithLargerClusterSize',
3221 'both':
'EtaVetoIdentifierWithHigherEnergyThresholdAndLargerClusterSize'}
3223 dictPi0ExtraInfoName = {
'standard':
'Pi0ProbOrigin',
3224 'tight':
'Pi0ProbTightEnergyThreshold',
3225 'cluster':
'Pi0ProbLargeClusterSize',
3226 'both':
'Pi0ProbTightEnergyThresholdAndLargeClusterSize'}
3228 dictEtaExtraInfoName = {
'standard':
'EtaProbOrigin',
3229 'tight':
'EtaProbTightEnergyThreshold',
3230 'cluster':
'EtaProbLargeClusterSize',
3231 'both':
'EtaProbTightEnergyThresholdAndLargeClusterSize'}
3233 ListName = dictListName[mode]
3234 Pi0EnergyCut = dictPi0EnergyCut[mode]
3235 EtaEnergyCut = dictEtaEnergyCut[mode]
3236 TimingCut =
'abs(clusterTiming)<clusterErrorTiming'
3237 NHitsCut = dictNHitsCut[mode]
3238 Pi0PayloadName = dictPi0PayloadName[mode]
3239 EtaPayloadName = dictEtaPayloadName[mode]
3240 Pi0ExtraInfoName = dictPi0ExtraInfoName[mode]
3241 EtaExtraInfoName = dictEtaExtraInfoName[mode]
3244 if pi0PayloadNameOverride
is not None:
3245 Pi0PayloadName = pi0PayloadNameOverride
3246 if pi0SoftPhotonCutOverride
is None:
3247 Pi0SoftPhotonCut = Pi0EnergyCut +
' and ' + NHitsCut
3251 Pi0SoftPhotonCut +=
' and ' + TimingCut
3253 Pi0SoftPhotonCut = pi0SoftPhotonCutOverride
3256 pi0soft = f
'gamma:Pi0Soft{suffix}' + ListName +
'_' + particleList.replace(
':',
'_')
3258 fillParticleList(pi0soft, Pi0SoftPhotonCut, path=roe_path)
3260 reconstructDecay(
'pi0:Pi0Veto' + ListName + f
' -> {hardParticle}:HardPhoton{suffix} ' + pi0soft,
'',
3261 allowChargeViolation=
True, path=roe_path)
3263 roe_path.add_module(
'MVAExpert', listNames=[
'pi0:Pi0Veto' + ListName],
3264 extraInfoName=Pi0ExtraInfoName, identifier=Pi0PayloadName)
3266 rankByHighest(
'pi0:Pi0Veto' + ListName,
'extraInfo(' + Pi0ExtraInfoName +
')', numBest=1, path=roe_path)
3268 variableToSignalSideExtraInfo(
'pi0:Pi0Veto' + ListName,
3269 {
'extraInfo(' + Pi0ExtraInfoName +
')': Pi0ExtraInfoName + suffix}, path=roe_path)
3272 if etaPayloadNameOverride
is not None:
3273 EtaPayloadName = etaPayloadNameOverride
3274 if etaSoftPhotonCutOverride
is None:
3275 EtaSoftPhotonCut = EtaEnergyCut +
' and ' + NHitsCut
3279 EtaSoftPhotonCut +=
' and ' + TimingCut
3281 EtaSoftPhotonCut = etaSoftPhotonCutOverride
3283 etasoft = f
'gamma:EtaSoft{suffix}' + ListName +
'_' + particleList.replace(
':',
'_')
3284 fillParticleList(etasoft, EtaSoftPhotonCut, path=roe_path)
3285 reconstructDecay(
'eta:EtaVeto' + ListName + f
' -> {hardParticle}:HardPhoton{suffix} ' + etasoft,
'',
3286 allowChargeViolation=
True, path=roe_path)
3287 roe_path.add_module(
'MVAExpert', listNames=[
'eta:EtaVeto' + ListName],
3288 extraInfoName=EtaExtraInfoName, identifier=EtaPayloadName)
3289 rankByHighest(
'eta:EtaVeto' + ListName,
'extraInfo(' + EtaExtraInfoName +
')', numBest=1, path=roe_path)
3290 variableToSignalSideExtraInfo(
'eta:EtaVeto' + ListName,
3291 {
'extraInfo(' + EtaExtraInfoName +
')': EtaExtraInfoName + suffix}, path=roe_path)
3293 path.for_each(
'RestOfEvent',
'RestOfEvents', roe_path)
3296def lowEnergyPi0Identification(pi0List, gammaList, payloadNameSuffix,
3299 Calculate low-energy pi0 identification.
3300 The result is stored
as ExtraInfo ``lowEnergyPi0Identification``
for
3304 pi0List (str): Pi0 list.
3306 gammaList (str): Gamma list. First, an energy cut E > 0.2
is applied to the photons
from this list.
3307 Then, all possible combinations
with a pi0 daughter photon are formed
except the one
3308 corresponding to the reconstructed pi0.
3309 The maximum low-energy pi0 veto value
is calculated
for such photon pairs
3310 and used
as one of the input variables
for the identification classifier.
3312 payloadNameSuffix (str): Payload name suffix. The weight payloads are stored
in the analysis
global
3313 tag
and have the following names:\n
3314 * ``
'LowEnergyPi0Veto' + payloadNameSuffix``
3315 * ``
'LowEnergyPi0Identification' + payloadNameSuffix``\n
3316 The possible suffixes are:\n
3317 * ``
'Belle1'``
for Belle data.
3318 * ``
'Belle2Release5'``
for Belle II release 5 data (MC14, proc12, buckets 16 - 25).
3319 * ``
'Belle2Release6'``
for Belle II release 6 data (MC15, proc13, buckets 26 - 36).
3321 path (basf2.Path): Module path.
3325 gammaListVeto = f
'{gammaList}_pi0veto'
3326 cutAndCopyList(gammaListVeto, gammaList,
'E > 0.2', path=path)
3328 payload_name =
'LowEnergyPi0Veto' + payloadNameSuffix
3329 path.add_module(
'LowEnergyPi0VetoExpert', identifier=payload_name,
3330 VetoPi0Daughters=
True, GammaListName=gammaListVeto,
3332 payload_name =
'LowEnergyPi0Identification' + payloadNameSuffix
3333 path.add_module(
'LowEnergyPi0IdentificationExpert',
3334 identifier=payload_name, Pi0ListName=pi0List,
3338def getNeutralHadronGeomMatches(
3342 efficiencyCorrectionKl=0.83,
3343 efficiencyCorrectionNeutrons=1.0,
3346 For an ECL-based list, assign the mcdistanceKL and mcdistanceNeutron variables that correspond
3347 to the distance to the closest MC KL
and neutron, respectively.
3348 @param particleLists the input ParticleLists, must be ECL-based lists (e.g. photons)
3349 @param addKL (default
True) add distance to MC KL
3350 @param addNeutrons (default
False) add distance to MC neutrons
3351 @param efficiencyCorrectionKl (default 0.83) apply overall efficiency correction
3352 @param efficiencyCorrectionNeutrons (default 1.0) apply overall efficiency correction
3353 @param path modules are added to this path
3355 from ROOT
import Belle2
3360 "NeutralHadronMatcher",
3361 particleLists=particleLists,
3362 mcPDGcode=Const.Klong.getPDGCode(),
3363 efficiencyCorrection=efficiencyCorrectionKl)
3366 "NeutralHadronMatcher",
3367 particleLists=particleLists,
3368 mcPDGcode=Const.neutron.getPDGCode(),
3369 efficiencyCorrection=efficiencyCorrectionNeutrons)
3372def getBeamBackgroundProbability(particleList, weight, path=None):
3374 Assign a probability to each ECL cluster as being signal like (1) compared to beam background like (0)
3375 @param particleList the input ParticleList, must be a photon list
3376 @param weight type of weight file to use
3377 @param path modules are added to this path
3382 B2WARNING(
"weight type must be 'Belle' for b2bii.")
3384 path.add_module(
'MVAExpert',
3385 listNames=particleList,
3386 extraInfoName=
'beamBackgroundSuppression',
3387 identifier=f
'BeamBackgroundMVA_{weight}')
3390def getFakePhotonProbability(particleList, weight, path=None):
3392 Assign a probability to each ECL cluster as being signal like (1) compared to fake photon like (0)
3393 @param particleList the input ParticleList, must be a photon list
3394 @param weight type of weight file to use
3395 @param path modules are added to this path
3400 B2WARNING(
"weight type must be 'Belle' for b2bii.")
3402 path.add_module(
'MVAExpert',
3403 listNames=particleList,
3404 extraInfoName=
'fakePhotonSuppression',
3405 identifier=f
'FakePhotonMVA_{weight}')
3408def buildEventKinematics(inputListNames=None, default_cleanup=True, custom_cuts=None,
3409 chargedPIDPriors=None, fillWithMostLikely=False, path=None):
3411 Calculates the global kinematics of the event (visible energy, missing momentum, missing mass...)
3412 using ParticleLists provided. If no ParticleList
is provided, default ParticleLists are used
3413 (all track
and all hits
in ECL without associated track).
3415 The visible energy missing values are
3416 stored
in a EventKinematics dataobject.
3418 @param inputListNames list of ParticleLists used to calculate the
global event kinematics.
3419 If the list
is empty, default ParticleLists pi+:evtkin
and gamma:evtkin are filled.
3420 @param fillWithMostLikely
if True, the module uses the most likely particle mass hypothesis
for charged particles
3421 according to the PID likelihood
and the option inputListNames will be ignored.
3422 @param chargedPIDPriors The prior PID fractions, that are used to regulate
3423 amount of certain charged particle species, should be a list of
3424 six floats
if not None. The order of particle types
is
3425 the following: [e-, mu-, pi-, K-, p+, d+]
3426 @param default_cleanup
if True and either inputListNames empty
or fillWithMostLikely
True, default clean up cuts are applied
3427 @param custom_cuts tuple of selection cut strings of form (trackCuts, photonCuts), default
is None,
3428 which would result
in a standard predefined selection cuts
3429 @param path modules are added to this path
3432 if inputListNames
is None:
3434 trackCuts =
'pt > 0.1'
3435 trackCuts +=
' and thetaInCDCAcceptance'
3436 trackCuts +=
' and abs(dz) < 3'
3437 trackCuts +=
' and dr < 0.5'
3439 gammaCuts =
'E > 0.05'
3440 gammaCuts +=
' and thetaInCDCAcceptance'
3442 gammaCuts +=
' and abs(clusterTiming) < 200'
3443 if (custom_cuts
is not None):
3444 trackCuts, gammaCuts = custom_cuts
3446 if fillWithMostLikely:
3447 from stdCharged
import stdMostLikely
3448 stdMostLikely(chargedPIDPriors,
'_evtkin', path=path)
3449 inputListNames = [f
'{ptype}:mostlikely_evtkin' for ptype
in [
'K+',
'p+',
'e+',
'mu+',
'pi+']]
3451 copyList(
'gamma:evtkin',
'gamma:mdst', path=path)
3453 fillParticleList(
'gamma:evtkin',
'', path=path)
3454 inputListNames += [
'gamma:evtkin']
3456 B2INFO(
"Using default cleanup in EventKinematics module.")
3457 for ptype
in [
'K+',
'p+',
'e+',
'mu+',
'pi+']:
3458 applyCuts(f
'{ptype}:mostlikely_evtkin', trackCuts, path=path)
3459 applyCuts(
'gamma:evtkin', gammaCuts, path=path)
3461 B2INFO(
"No cleanup in EventKinematics module.")
3462 if not inputListNames:
3463 B2INFO(
"Creating particle lists pi+:evtkin and gamma:evtkin to get the global kinematics of the event.")
3464 fillParticleList(
'pi+:evtkin',
'', path=path)
3466 copyList(
'gamma:evtkin',
'gamma:mdst', path=path)
3468 fillParticleList(
'gamma:evtkin',
'', path=path)
3469 particleLists = [
'pi+:evtkin',
'gamma:evtkin']
3471 if (custom_cuts
is not None):
3472 B2INFO(
"Using default cleanup in EventKinematics module.")
3473 applyCuts(
'pi+:evtkin', trackCuts, path=path)
3474 applyCuts(
'gamma:evtkin', gammaCuts, path=path)
3476 B2INFO(
"No cleanup in EventKinematics module.")
3478 particleLists = inputListNames
3480 eventKinematicsModule = register_module(
'EventKinematics')
3481 eventKinematicsModule.set_name(
'EventKinematics_reco')
3482 eventKinematicsModule.param(
'particleLists', particleLists)
3483 path.add_module(eventKinematicsModule)
3486def buildEventKinematicsFromMC(inputListNames=None, selectionCut='', path=None):
3488 Calculates the global kinematics of the event (visible energy, missing momentum, missing mass...)
3489 using generated particles. If no ParticleList
is provided, default generated ParticleLists are used.
3491 @param inputListNames list of ParticleLists used to calculate the
global event kinematics.
3492 If the list
is empty, default ParticleLists are filled.
3493 @param selectionCut optional selection cuts
3494 @param path Path to append the eventKinematics module to.
3497 if inputListNames
is None:
3499 if (len(inputListNames) == 0):
3503 types = [
'gamma',
'e+',
'mu+',
'pi+',
'K+',
'p+',
3506 fillParticleListFromMC(f
"{t}:evtkin_default_gen",
'mcPrimary > 0 and nDaughters == 0',
3507 True,
True, path=path)
3508 if (selectionCut !=
''):
3509 applyCuts(f
"{t}:evtkin_default_gen", selectionCut, path=path)
3510 inputListNames += [f
"{t}:evtkin_default_gen"]
3512 eventKinematicsModule = register_module(
'EventKinematics')
3513 eventKinematicsModule.set_name(
'EventKinematics_gen')
3514 eventKinematicsModule.param(
'particleLists', inputListNames)
3515 eventKinematicsModule.param(
'usingMC',
True)
3516 path.add_module(eventKinematicsModule)
3519def buildEventShape(inputListNames=None,
3520 default_cleanup=True,
3526 harmonicMoments=True,
3530 checkForDuplicates=False,
3533 Calculates the event-level shape quantities (thrust, sphericity, Fox-Wolfram moments...)
3534 using the particles in the lists provided by the user. If no particle list
is provided,
3535 the function will internally create a list of good tracks
and a list of good photons
3536 with (optionally) minimal quality cuts.
3539 The results of the calculation are then stored into the EventShapeContainer dataobject,
3540 and are accessible using the variables of the EventShape group.
3542 The user can switch the calculation of certain quantities on
or off to save computing
3543 time. By default the calculation of the high-order moments (5-8)
is turned off.
3544 Switching off an option will make the corresponding variables
not available.
3547 The user can provide
as many particle lists
3548 as needed, using also combined particles, but the function will always assume that
3549 the lists are independent.
3550 If the lists provided by the user contain several times the same track (either
with
3551 different mass hypothesis,
or once
as an independent particle
and once
as daughter of a
3552 combined particle) the results won
't be reliable.
3553 A basic check for duplicates
is available setting the checkForDuplicate flags.
3556 @param inputListNames List of ParticleLists used to calculate the
3557 event shape variables. If the list
is empty the default
3558 particleLists pi+:evtshape
and gamma:evtshape are filled.
3559 @param default_cleanup If
True, applies standard cuts on pt
and cosTheta when
3560 defining the internal lists. This option
is ignored
if the
3561 particleLists are provided by the user.
3562 @param custom_cuts tuple of selection cut strings of form (trackCuts, photonCuts), default
is None,
3563 which would result
in a standard predefined selection cuts
3564 @param path Path to append the eventShape modules to.
3565 @param thrust Enables the calculation of thrust-related quantities (CLEO
3566 cones, Harmonic moments, jets).
3567 @param collisionAxis Enables the calculation of the quantities related to the
3569 @param foxWolfram Enables the calculation of the Fox-Wolfram moments.
3570 @param harmonicMoments Enables the calculation of the Harmonic moments
with respect
3571 to both the thrust axis
and,
if collisionAxis =
True, the collision axis.
3572 @param allMoments If
True, calculates also the FW
and harmonic moments
from order
3573 5 to 8 instead of the low-order ones only.
3574 @param cleoCones Enables the calculation of the CLEO cones
with respect to both the thrust
3575 axis
and,
if collisionAxis =
True, the collision axis.
3576 @param jets Enables the calculation of the hemisphere momenta
and masses.
3577 Requires thrust =
True.
3578 @param sphericity Enables the calculation of the sphericity-related quantities.
3579 @param checkForDuplicates Perform a check
for duplicate particles before adding them. Regardless of the value of this option,
3580 it
is recommended to consider sanitizing the lists you are passing to the function.
3584 if inputListNames
is None:
3586 trackCuts =
'pt > 0.1'
3587 trackCuts +=
' and thetaInCDCAcceptance'
3588 trackCuts +=
' and abs(dz) < 3.0'
3589 trackCuts +=
' and dr < 0.5'
3591 gammaCuts =
'E > 0.05'
3592 gammaCuts +=
' and thetaInCDCAcceptance'
3594 gammaCuts +=
' and abs(clusterTiming) < 200'
3595 if (custom_cuts
is not None):
3596 trackCuts, gammaCuts = custom_cuts
3598 if not inputListNames:
3599 B2INFO(
"Creating particle lists pi+:evtshape and gamma:evtshape to get the event shape variables.")
3600 fillParticleList(
'pi+:evtshape',
'', path=path)
3602 copyList(
'gamma:evtshape',
'gamma:mdst', path=path)
3608 particleLists = [
'pi+:evtshape',
'gamma:evtshape']
3611 if (custom_cuts
is not None):
3612 B2INFO(
"Applying standard cuts")
3613 applyCuts(
'pi+:evtshape', trackCuts, path=path)
3615 applyCuts(
'gamma:evtshape', gammaCuts, path=path)
3617 B2WARNING(
"Creating the default lists with no cleanup.")
3619 particleLists = inputListNames
3621 eventShapeModule = register_module(
'EventShapeCalculator')
3622 eventShapeModule.set_name(
'EventShape')
3623 eventShapeModule.param(
'particleListNames', particleLists)
3624 eventShapeModule.param(
'enableAllMoments', allMoments)
3625 eventShapeModule.param(
'enableCleoCones', cleoCones)
3626 eventShapeModule.param(
'enableCollisionAxis', collisionAxis)
3627 eventShapeModule.param(
'enableFoxWolfram', foxWolfram)
3628 eventShapeModule.param(
'enableJets', jets)
3629 eventShapeModule.param(
'enableHarmonicMoments', harmonicMoments)
3630 eventShapeModule.param(
'enableSphericity', sphericity)
3631 eventShapeModule.param(
'enableThrust', thrust)
3632 eventShapeModule.param(
'checkForDuplicates', checkForDuplicates)
3634 path.add_module(eventShapeModule)
3637def labelTauPairMC(printDecayInfo=False, path=None, TauolaBelle=False, mapping_minus=None, mapping_plus=None):
3639 Search tau leptons into the MC information of the event. If confirms it's a generated tau pair decay,
3640 labels the decay generated of the positive and negative leptons using the ID of KKMC tau decay table.
3642 @param printDecayInfo: If true, prints ID
and prong of each tau lepton
in the event.
3643 @param path: module
is added to this path
3644 @param TauolaBelle:
if False, TauDecayMode
is set. If
True, TauDecayMarker
is set.
3645 @param mapping_minus:
if None, the map
is the default one,
else the path
for the map
is given by the user
for tau-
3646 @param mapping_plus:
if None, the map
is the default one,
else the path
for the map
is given by the user
for tau+
3649 from basf2
import find_file
3655 m_printmode =
'default'
3657 if mapping_minus
is None:
3658 mp_file_minus = find_file(
'data/analysis/modules/TauDecayMode/map_tauminus.txt')
3660 mp_file_minus = mapping_minus
3662 if mapping_plus
is None:
3663 mp_file_plus = find_file(
'data/analysis/modules/TauDecayMode/map_tauplus.txt')
3665 mp_file_plus = mapping_plus
3667 path.add_module(
'TauDecayMode', printmode=m_printmode, file_minus=mp_file_minus, file_plus=mp_file_plus)
3670 tauDecayMarker = register_module(
'TauDecayMarker')
3671 tauDecayMarker.set_name(
'TauDecayMarker_')
3673 path.add_module(tauDecayMarker, printDecayInfo=printDecayInfo)
3676def tagCurlTracks(particleLists,
3686 The cut selector is not calibrated
with Belle II data
and should
not be used without extensive study.
3688 Identifies curl tracks
and tags them
with extraInfo(isCurl=1)
for later removal.
3689 For Belle data
with a `b2bii` analysis the available cut based selection
is described
in `BN1079`_.
3691 .. _BN1079: https://belle.kek.jp/secured/belle_note/gn1079/bn1079.pdf
3694 The module loops over all particles
in a given list
with a transverse momentum below the pre-selection **ptCut**
3695 and assigns them to bundles based on the response of the chosen **selector**
and the required minimum response set by the
3696 **responseCut**. Once all particles are assigned they are ranked by 25dr^2+dz^2. All but the lowest are tagged
3697 with extraInfo(isCurl=1) to allow
for later removal by cutting the list
or removing these
from ROE
as
3701 @param particleLists: list of particle lists to check
for curls.
3702 @param mcTruth: bool flag to additionally assign particles
with extraInfo(isTruthCurl)
and
3703 extraInfo(truthBundleSize). To calculate these particles are assigned to bundles by their
3704 genParticleIndex then ranked
and tagged
as normal.
3705 @param responseCut: float min classifier response that considers two tracks to come
from the same particle.
3706 If set to ``-1`` a cut value optimised to maximise the accuracy on a BBbar sample
is used.
3707 Note
'cut' selector
is binary 0/1.
3708 @param selectorType: string name of selector to use. The available options are
'cut' and 'mva'.
3709 It
is strongly recommended to used the
'mva' selection. The
'cut' selection
3710 is based on BN1079
and is only calibrated
for Belle data.
3712 @param ptCut: Pre-selection cut on transverse momentum. Only tracks below that are considered
as curler candidates.
3714 @param expert_train: flag to set training mode
if selector has a training mode (mva).
3715 @param expert_filename: set file name of produced training ntuple (mva).
3716 @param path: module
is added to this path.
3722 if (
not isinstance(particleLists, list)):
3723 particleLists = [particleLists]
3725 curlTagger = register_module(
'CurlTagger')
3726 curlTagger.set_name(
'CurlTagger_')
3727 curlTagger.param(
'particleLists', particleLists)
3728 curlTagger.param(
'belle', belle)
3729 curlTagger.param(
'mcTruth', mcTruth)
3730 curlTagger.param(
'responseCut', responseCut)
3731 if abs(responseCut + 1) < 1e-9:
3732 curlTagger.param(
'usePayloadCut',
True)
3734 curlTagger.param(
'usePayloadCut',
False)
3736 curlTagger.param(
'selectorType', selectorType)
3737 curlTagger.param(
'ptCut', ptCut)
3738 curlTagger.param(
'train', expert_train)
3739 curlTagger.param(
'trainFilename', expert_filename)
3741 path.add_module(curlTagger)
3744def applyChargedPidMVA(particleLists, path, trainingMode, chargeIndependent=False, binaryHypoPDGCodes=(0, 0)):
3746 Use an MVA to perform particle identification for charged stable particles, using the `ChargedPidMVA` module.
3748 The module decorates Particle objects
in the input ParticleList(s)
with variables
3749 containing the appropriate MVA score, which can be used to select candidates by placing a cut on it.
3752 The MVA algorithm used
is a gradient boosted decision tree (**TMVA 4.3.0**, **ROOT 6.20/04**).
3754 The module can perform either
'binary' PID between input S, B particle mass hypotheses according to the following scheme:
3756 * e (11) vs. pi (211)
3757 * mu (13) vs. pi (211)
3758 * pi (211) vs. K (321)
3759 * K (321) vs. pi (211)
3761 ,
or 'global' PID, namely
"one-vs-others" separation. The latter exploits an MVA algorithm trained
in multi-
class mode,
3762 and it
's the default behaviour. Currently, the multi-class training separates the following standard charged hypotheses:
3764 - e (11), mu (13), pi (211), K (321)
3767 In order to run the `ChargedPidMVA` and ensure the most up-to-date MVA training weights are applied,
3768 it
is necessary to append the latest analysis
global tag (GT) to the steering script.
3771 particleLists (list(str)): the input list of DecayStrings, where each selected (^) daughter should correspond to a
3772 standard charged ParticleList, e.g. ``[
'Lambda0:sig -> ^p+ ^pi-',
'J/psi:sig -> ^mu+ ^mu-']``.
3773 One can also directly
pass a list of standard charged ParticleLists,
3774 e.g. ``[
'e+:my_electrons',
'pi+:my_pions']``.
3775 Note that charge-conjugated ParticleLists will automatically be included.
3776 path (basf2.Path): the module
is added to this path.
3777 trainingMode (``Belle2.ChargedPidMVAWeights.ChargedPidMVATrainingMode``): enum identifier of the training mode.
3778 Needed to pick up the correct payload
from the DB. Available choices:
3780 * c_Classification=0
3782 * c_ECL_Classification=2
3783 * c_ECL_Multiclass=3
3784 * c_PSD_Classification=4
3785 * c_PSD_Multiclass=5
3786 * c_ECL_PSD_Classification=6
3787 * c_ECL_PSD_Multiclass=7
3789 chargeIndependent (bool, ``optional``): use a BDT trained on a sample of inclusively charged particles.
3790 binaryHypoPDGCodes (tuple(int, int), ``optional``): the pdgIds of the signal, background mass hypothesis.
3791 Required only
for binary PID mode.
3796 B2ERROR(
"Charged PID via MVA is not available for Belle data.")
3798 from ROOT
import Belle2
3800 TrainingMode = Belle2.ChargedPidMVAWeights.ChargedPidMVATrainingMode
3803 plSet = set(particleLists)
3807 TrainingMode.c_Classification:
3808 {
"mode":
"Classification",
"detector":
"ALL"},
3809 TrainingMode.c_Multiclass:
3810 {
"mode":
"Multiclass",
"detector":
"ALL"},
3811 TrainingMode.c_ECL_Classification:
3812 {
"mode":
"ECL_Classification",
"detector":
"ECL"},
3813 TrainingMode.c_ECL_Multiclass:
3814 {
"mode":
"ECL_Multiclass",
"detector":
"ECL"},
3815 TrainingMode.c_PSD_Classification:
3816 {
"mode":
"PSD_Classification",
"detector":
"ALL"},
3817 TrainingMode.c_PSD_Multiclass:
3818 {
"mode":
"PSD_Multiclass",
"detector":
"ALL"},
3819 TrainingMode.c_ECL_PSD_Classification:
3820 {
"mode":
"ECL_PSD_Classification",
"detector":
"ECL"},
3821 TrainingMode.c_ECL_PSD_Multiclass:
3822 {
"mode":
"ECL_PSD_Multiclass",
"detector":
"ECL"},
3825 if payloadNames.get(trainingMode)
is None:
3826 B2FATAL(
"The chosen training mode integer identifier:\n", trainingMode,
3827 "\nis not supported. Please choose among the following:\n",
3828 "\n".join(f
"{key}:{val.get('mode')}" for key, val
in sorted(payloadNames.items())))
3830 mode = payloadNames.get(trainingMode).get(
"mode")
3831 detector = payloadNames.get(trainingMode).get(
"detector")
3833 payloadName = f
"ChargedPidMVAWeights_{mode}"
3838 Const.electron.getPDGCode():
3839 {
"pName":
"e",
"pFullName":
"electron",
"pNameBkg":
"pi",
"pdgIdBkg": Const.pion.getPDGCode()},
3840 Const.muon.getPDGCode():
3841 {
"pName":
"mu",
"pFullName":
"muon",
"pNameBkg":
"pi",
"pdgIdBkg": Const.pion.getPDGCode()},
3842 Const.pion.getPDGCode():
3843 {
"pName":
"pi",
"pFullName":
"pion",
"pNameBkg":
"K",
"pdgIdBkg": Const.kaon.getPDGCode()},
3844 Const.kaon.getPDGCode():
3845 {
"pName":
"K",
"pFullName":
"kaon",
"pNameBkg":
"pi",
"pdgIdBkg": Const.pion.getPDGCode()},
3846 Const.proton.getPDGCode():
3847 {
"pName":
"p",
"pFullName":
"proton",
"pNameBkg":
"pi",
"pdgIdBkg": Const.pion.getPDGCode()},
3848 Const.deuteron.getPDGCode():
3849 {
"pName":
"d",
"pFullName":
"deuteron",
"pNameBkg":
"pi",
"pdgIdBkg": Const.pion.getPDGCode()},
3852 if binaryHypoPDGCodes == (0, 0):
3855 chargedpid = register_module(
"ChargedPidMVAMulticlass")
3856 chargedpid.set_name(f
"ChargedPidMVAMulticlass_{mode}")
3863 binaryOpts = [(pdgIdSig, info[
"pdgIdBkg"])
for pdgIdSig, info
in stdChargedMap.items()]
3865 if binaryHypoPDGCodes
not in binaryOpts:
3866 B2FATAL(
"No charged pid MVA was trained to separate ", binaryHypoPDGCodes[0],
" vs. ", binaryHypoPDGCodes[1],
3867 ". Please choose among the following pairs:\n",
3868 "\n".join(f
"{opt[0]} vs. {opt[1]}" for opt
in binaryOpts))
3872 if not decayDescriptor.init(name):
3873 raise ValueError(f
"Invalid particle list {name} in applyChargedPidMVA!")
3874 msg = f
"Input ParticleList: {name}"
3875 pdgs = [abs(decayDescriptor.getMother().getPDGCode())]
3876 daughter_pdgs = decayDescriptor.getSelectionPDGCodes()
3877 if len(daughter_pdgs) > 0:
3878 pdgs = daughter_pdgs
3879 for idaughter, pdg
in enumerate(pdgs):
3880 if abs(pdg)
not in binaryHypoPDGCodes:
3882 msg = f
"Selected daughter {idaughter} in ParticleList: {name}"
3884 f
"{msg} (PDG={pdg}) is neither signal ({binaryHypoPDGCodes[0]}) nor background ({binaryHypoPDGCodes[1]}).")
3886 chargedpid = register_module(
"ChargedPidMVA")
3887 chargedpid.set_name(f
"ChargedPidMVA_{binaryHypoPDGCodes[0]}_vs_{binaryHypoPDGCodes[1]}_{mode}")
3888 chargedpid.param(
"sigHypoPDGCode", binaryHypoPDGCodes[0])
3889 chargedpid.param(
"bkgHypoPDGCode", binaryHypoPDGCodes[1])
3891 chargedpid.param(
"particleLists", list(plSet))
3892 chargedpid.param(
"payloadName", payloadName)
3893 chargedpid.param(
"chargeIndependent", chargeIndependent)
3896 if detector ==
"ECL":
3897 chargedpid.param(
"useECLOnlyTraining",
True)
3899 path.add_module(chargedpid)
3902def calculateTrackIsolation(
3906 reference_list_name=None,
3907 vars_for_nearest_part=[],
3908 highest_prob_mass_for_ext=True,
3909 exclude_pid_det_weights=False):
3911 Given an input decay string, compute variables that quantify track helix-based isolation of the charged
3912 stable particles in the input decay chain.
3915 An
"isolation score" can be defined using the distance
3916 of each particle to its closest neighbour, defined
as the segment connecting the two
3917 extrapolated track helices intersection points on a given cylindrical surface.
3918 The distance variables defined
in the `VariableManager`
is named `minET2ETDist`,
3919 the isolation scores are named `minET2ETIsoScore`, `minET2ETIsoScoreAsWeightedAvg`.
3921 The definition of distance
and the number of distances that are calculated per sub-detector
is based on
3922 the following recipe:
3924 * **CDC**:
as the segmentation
is very coarse along :math:`z`,
3925 the distance
is defined
as the cord length on the :math:`(\\rho=R, \\phi)` plane.
3926 A total of 9 distances are calculated: the cylindrical surfaces are defined at radiuses
3927 that correspond to the positions of the 9 CDC wire superlayers: :math:`R_{i}^{\\mathrm{CDC}}~(i \\
in \\{0,...,8\\})`.
3929 * **TOP**:
as there
is no segmentation along :math:`z`,
3930 the distance
is defined
as the cord length on the :math:`(\\rho=R, \\phi)` plane.
3931 Only one distance at the TOP entry radius :math:`R_{0}^{\\mathrm{TOP}}`
is calculated.
3933 * **ARICH**:
as there
is no segmentation along :math:`z`,
3934 the distance
is defined
as the distance on the :math:`(\\rho=R, \\phi)` plane at fixed :math:`z=Z`.
3935 Only one distance at the ARICH photon detector entry coordinate :math:`Z_{0}^{\\mathrm{ARICH}}`
is calculated.
3937 * **ECL**: the distance
is defined on the :math:`(\\rho=R, \\phi, z)` surface
in the barrel,
3938 on the :math:`(\\rho, \\phi, z=Z)` surface
in the endcaps.
3939 Two distances are calculated: one at the ECL entry surface :math:`R_{0}^{\\mathrm{ECL}}` (barrel),
3940 :math:`Z_{0}^{\\mathrm{ECL}}` (endcaps),
and one at :math:`R_{1}^{\\mathrm{ECL}}` (barrel),
3941 :math:`Z_{1}^{\\mathrm{ECL}}` (endcaps), corresponding roughly to the mid-point
3942 of the longitudinal size of the crystals.
3944 * **KLM**: the distance
is defined on the :math:`(\\rho=R, \\phi, z)` surface
in the barrel,
3945 on the :math:`(\\rho, \\phi, z=Z)` surface
in the endcaps.
3946 Only one distance at the KLM first strip entry surface :math:`R_{0}^{\\mathrm{KLM}}` (barrel),
3947 :math:`Z_{0}^{\\mathrm{KLM}}` (endcaps)
is calculated.
3950 decay_string (str): name of the input decay string
with selected charged stable daughters,
3951 for example: ``Lambda0:merged -> ^p+ ^pi-``.
3952 Alternatively, it can be a particle list
for charged stable particles
3953 as defined
in ``Const::chargedStableSet``,
for example: ``mu+:all``.
3954 The charge-conjugate particle list will be also processed automatically.
3955 path (basf2.Path): path to which module(s) will be added.
3956 *detectors: detectors
for which track isolation variables will be calculated.
3957 Choose among: ``{
'CDC',
'TOP',
'ARICH',
'ECL',
'KLM'}``.
3958 reference_list_name (Optional[str]): name of the input charged stable particle list
for the reference tracks.
3959 By default, the ``:all`` ParticleList of the same type
3960 of the selected particle
in ``decay_string``
is used.
3961 The charge-conjugate particle list will be also processed automatically.
3962 vars_for_nearest_part (Optional[list(str)]): a list of variables to calculate
for the nearest particle
in the reference
3963 list at each detector surface. It uses the metavariable `minET2ETDistVar`.
3964 If unset, only the distances to the nearest neighbour
3965 per detector are calculated.
3966 highest_prob_mass_for_hex (Optional[bool]):
if this option
is set to
True (default), the helix extrapolation
3967 for the particles will use the track fit result
for the most
3968 probable mass hypothesis, namely, the one that gives the highest
3969 chi2Prob of the fit. Otherwise, it uses the mass hypothesis that
3970 corresponds to the particle lists PDG.
3971 exclude_pid_det_weights (Optional[bool]):
if this option
is set to
False (default), the isolation score
3972 calculation will take into account the weight that each detector has on the PID
3973 for the particle species of interest.
3976 dict(int, list(str)): a dictionary mapping the PDG of each reference particle list to its isolation variables.
3981 from ROOT
import Belle2, TDatabasePDG
3984 if not decayDescriptor.init(decay_string):
3985 B2FATAL(f
"Invalid particle list {decay_string} in calculateTrackIsolation!")
3986 no_reference_list_name =
not reference_list_name
3989 "CDC": list(range(9)),
3995 if any(d
not in det_and_layers
for d
in detectors):
3997 "Your input detector list: ",
3999 " contains an invalid choice. Please select among: ",
4001 det_and_layers.keys()))
4006 processed_decay_strings = []
4007 if select_symbol
in decay_string:
4008 splitted_ds = decay_string.split(select_symbol)
4009 for i
in range(decay_string.count(select_symbol)):
4010 tmp = list(splitted_ds)
4011 tmp.insert(i+1, select_symbol)
4012 processed_decay_strings += [
''.join(tmp)]
4014 processed_decay_strings += [decay_string]
4016 reference_lists_to_vars = {}
4018 for processed_dec
in processed_decay_strings:
4019 if no_reference_list_name:
4020 decayDescriptor.init(processed_dec)
4021 selected_daughter_pdgs = decayDescriptor.getSelectionPDGCodes()
4022 if len(selected_daughter_pdgs) > 0:
4023 reference_list_name = f
'{TDatabasePDG.Instance().GetParticle(abs(selected_daughter_pdgs[-1])).GetName()}:all'
4025 reference_list_name = f
'{processed_dec.split(":")[0]}:all'
4029 trackiso = path.add_module(
"TrackIsoCalculator",
4030 decayString=processed_dec,
4031 detectorNames=list(detectors),
4032 particleListReference=reference_list_name,
4033 useHighestProbMassForExt=highest_prob_mass_for_ext,
4034 excludePIDDetWeights=exclude_pid_det_weights)
4035 trackiso.set_name(f
"TrackIsoCalculator_{'_'.join(detectors)}_{processed_dec}_VS_{reference_list_name}")
4041 f
"minET2ETDist({d}, {d_layer}, {reference_list_name}, {int(highest_prob_mass_for_ext)})"
4042 for d
in detectors
for d_layer
in det_and_layers[d]]
4045 f
"minET2ETIsoScore({reference_list_name}, {int(highest_prob_mass_for_ext)}, {', '.join(detectors)})",
4046 f
"minET2ETIsoScoreAsWeightedAvg({reference_list_name}, {int(highest_prob_mass_for_ext)}, {', '.join(detectors)})",
4049 if vars_for_nearest_part:
4050 trackiso_vars.extend(
4052 f
"minET2ETDistVar({d}, {d_layer}, {reference_list_name}, {v})"
4053 for d
in detectors
for d_layer
in det_and_layers[d]
for v
in vars_for_nearest_part
4055 trackiso_vars.sort()
4057 reference_lists_to_vars[ref_pdg] = trackiso_vars
4059 return reference_lists_to_vars
4062def calculateDistance(list_name, decay_string, mode='vertextrack', path=None):
4064 Calculates distance between two vertices, distance of closest approach between a vertex and a track,\
4065 distance of closest approach between a vertex
and btube. For track, this calculation ignores track curvature,\
4066 it
's negligible for small distances.The user should use extraInfo(CalculatedDistance)\
4067 to get it. A full example steering file is at analysis/tests/test_DistanceCalculator.py
4070 .. code-block:: python
4072 from modularAnalysis
import calculateDistance
4073 calculateDistance(
'list_name',
'decay_string',
"mode", path=user_path)
4075 @param list_name name of the input ParticleList
4076 @param decay_string select particles between the distance of closest approach will be calculated
4077 @param mode Specifies how the distance
is calculated
4078 vertextrack: calculate the distance of closest approach between a track
and a\
4079 vertex, taking the first candidate
as vertex, default
4080 trackvertex: calculate the distance of closest approach between a track
and a\
4081 vertex, taking the first candidate
as track
4082 2tracks: calculates the distance of closest approach between two tracks
4083 2vertices: calculates the distance between two vertices
4084 vertexbtube: calculates the distance of closest approach between a vertex
and btube
4085 trackbtube: calculates the distance of closest approach between a track
and btube
4086 @param path modules are added to this path
4090 dist_mod = register_module('DistanceCalculator')
4092 dist_mod.set_name(
'DistanceCalculator_' + list_name)
4093 dist_mod.param(
'listName', list_name)
4094 dist_mod.param(
'decayString', decay_string)
4095 dist_mod.param(
'mode', mode)
4096 path.add_module(dist_mod)
4099def addInclusiveDstarReconstruction(decayString, slowPionCut, DstarCut, path):
4101 Adds the InclusiveDstarReconstruction module to the given path.
4102 This module creates a D* particle list by estimating the D* four momenta
4103 from slow pions, specified by a given cut. The D* energy
is approximated
4104 as E(D*) = m(D*)/(m(D*) - m(D)) * E(pi). The absolute value of the D*
4105 momentum
is calculated using the D* PDG mass
and the direction
is collinear
4106 to the slow pion direction. The charge of the given pion list has to be consistent
4109 @param decayString Decay string, must be of form ``D* -> pi``
4110 @param slowPionCut Cut applied to the input pion list to identify slow pions
4111 @param DstarCut Cut applied to the output D* list
4112 @param path the module
is added to this path
4115 incl_dstar = register_module("InclusiveDstarReconstruction")
4116 incl_dstar.param(
"decayString", decayString)
4117 incl_dstar.param(
"slowPionCut", slowPionCut)
4118 incl_dstar.param(
"DstarCut", DstarCut)
4119 path.add_module(incl_dstar)
4122def scaleError(outputListName, inputListName,
4123 scaleFactors=[1.149631, 1.085547, 1.151704, 1.096434, 1.086659],
4124 scaleFactorsNoPXD=[1.149631, 1.085547, 1.151704, 1.096434, 1.086659],
4125 d0Resolution=[0.00115328, 0.00134704],
4126 z0Resolution=[0.00124327, 0.0013272],
4131 This module creates a new charged particle list.
4132 The helix errors of the new particles are scaled by constant factors.
4133 Two sets of five scale factors are defined for tracks
with and without a PXD hit.
4134 The scale factors are
in order of (d0, phi0, omega, z0, tanlambda).
4135 For tracks
with a PXD hit,
in order to avoid severe underestimation of d0
and z0 errors,
4136 lower limits (best resolution) can be set
in a momentum-dependent form.
4137 This module
is supposed to be used only
for TDCPV analysis
and for low-momentum (0-3 GeV/c) tracks
in BBbar events.
4138 Details will be documented
in a Belle II note, BELLE2-NOTE-PH-2021-038.
4140 @param inputListName Name of input charged particle list to be scaled
4141 @param outputListName Name of output charged particle list
with scaled error
4142 @param scaleFactors List of five constants to be multiplied to each of helix errors (
for tracks
with a PXD hit)
4143 @param scaleFactorsNoPXD List of five constants to be multiplied to each of helix errors (
for tracks without a PXD hit)
4144 @param d0Resolution List of two parameters, (a [cm], b [cm/(GeV/c)]),
4145 defining d0 best resolution
as sqrt{ a**2 + (b / (p*beta*sinTheta**1.5))**2 }
4146 @param z0Resolution List of two parameters, (a [cm], b [cm/(GeV/c)]),
4147 defining z0 best resolution
as sqrt{ a**2 + (b / (p*beta*sinTheta**2.5))**2 }
4148 @param d0MomThr d0 best resolution
is kept constant below this momentum
4149 @param z0MomThr z0 best resolution
is kept constant below this momentum
4153 scale_error = register_module("HelixErrorScaler")
4154 scale_error.set_name(
'ScaleError_' + inputListName)
4155 scale_error.param(
'inputListName', inputListName)
4156 scale_error.param(
'outputListName', outputListName)
4157 scale_error.param(
'scaleFactors_PXD', scaleFactors)
4158 scale_error.param(
'scaleFactors_noPXD', scaleFactorsNoPXD)
4159 scale_error.param(
'd0ResolutionParameters', d0Resolution)
4160 scale_error.param(
'z0ResolutionParameters', z0Resolution)
4161 scale_error.param(
'd0MomentumThreshold', d0MomThr)
4162 scale_error.param(
'z0MomentumThreshold', z0MomThr)
4163 path.add_module(scale_error)
4166def estimateAndAttachTrackFitResult(inputListName, path=None):
4168 Create a TrackFitResult from the momentum of the Particle assuming it originates
from the IP
and make a relation between them.
4169 The covariance, detector hit information,
and fit-related information (pValue, NDF) are assigned meaningless values. The input
4170 Particles must
not have already Track
or TrackFitResult
and thus are supposed to be composite particles, recoil, dummy
4171 particles,
and so on.
4174 .. warning:: Since the source type
is not overwritten
as Track,
not all track-related variables are guaranteed to be available.
4177 @param inputListName Name of input ParticleList
4180 estimator = register_module("TrackFitResultEstimator")
4181 estimator.set_name(
"trackFitResultEstimator_" + inputListName)
4182 estimator.param(
"inputListName", inputListName)
4183 path.add_module(estimator)
4186def correctEnergyBias(inputListNames, tableName, path=None):
4188 Scale energy of the particles according to the scaling factor.
4189 If the particle list contains composite particles, the energy of the daughters are scaled.
4190 Subsequently, the energy of the mother particle is updated
as well.
4193 inputListNames (list(str)): input particle list names
4194 tableName : stored
in localdb
and created using ParticleWeightingLookUpCreator
4195 path (basf2.Path): module
is added to this path
4200 B2ERROR(
"The energy bias cannot be corrected with this tool for Belle data.")
4202 correctenergybias = register_module(
'EnergyBiasCorrection')
4203 correctenergybias.param(
'particleLists', inputListNames)
4204 correctenergybias.param(
'tableName', tableName)
4205 path.add_module(correctenergybias)
4208def twoBodyISRPhotonCorrector(outputListName, inputListName, massiveParticle, path=None):
4210 Sets photon kinematics to corrected values in two body decays
with an ISR photon
4211 and a massive particle. The original photon kinematics are kept
in the input
4212 particleList
and can be accessed using the originalParticle() metavariable on the
4215 @param ouputListName new ParticleList filled
with copied Particles
4216 @param inputListName input ParticleList
with original Particles
4217 @param massiveParticle name
or PDG code of massive particle participating
in the two
4218 body decay
with the ISR photon
4219 @param path modules are added to this path
4223 photon_energy_correction = register_module(
'TwoBodyISRPhotonCorrector')
4224 photon_energy_correction.set_name(
'TwoBodyISRPhotonCorrector_' + outputListName)
4225 photon_energy_correction.param(
'outputGammaList', outputListName)
4226 photon_energy_correction.param(
'inputGammaList', inputListName)
4229 if isinstance(massiveParticle, int):
4230 photon_energy_correction.param(
'massiveParticlePDGCode', massiveParticle)
4232 from ROOT
import Belle2
4234 if not decayDescriptor.init(massiveParticle):
4235 raise ValueError(
"TwoBodyISRPhotonCorrector: value of massiveParticle must be" +
4236 " an int or valid decay string.")
4237 pdgCode = decayDescriptor.getMother().getPDGCode()
4238 photon_energy_correction.param(
'massiveParticlePDGCode', pdgCode)
4240 path.add_module(photon_energy_correction)
4243def addPhotonEfficiencyRatioVariables(inputListNames, tableName, path=None):
4245 Add photon Data/MC detection efficiency ratio weights to the specified particle list
4248 inputListNames (list(str)): input particle list names
4249 tableName : taken from database
with appropriate name
4250 path (basf2.Path): module
is added to this path
4255 B2ERROR(
"For Belle data the photon data/MC detection efficiency ratio is not available with this tool.")
4257 photon_efficiency_correction = register_module(
'PhotonEfficiencySystematics')
4258 photon_efficiency_correction.param(
'particleLists', inputListNames)
4259 photon_efficiency_correction.param(
'tableName', tableName)
4260 path.add_module(photon_efficiency_correction)
4263def addPi0VetoEfficiencySystematics(particleList, decayString, tableName, threshold, mode='standard', suffix='', path=None):
4265 Add pi0 veto Data/MC efficiency ratio weights to the specified particle list
4267 @param particleList the input ParticleList
4268 @param decayString specify hard photon to be performed pi0 veto (e.g.
'B+:sig -> rho+:sig ^gamma:hard')
4269 @param tableName table name corresponding to payload version (e.g.
'Pi0VetoEfficiencySystematics_Mar2022')
4270 @param threshold pi0 veto threshold (0.10, 0.11, ..., 0.99)
4271 @param mode choose one mode (same
as writePi0EtaVeto) out of
'standard',
'tight',
'cluster' and 'both'
4272 @param suffix optional suffix to be appended to the usual extraInfo name
4273 @param path the module
is added to this path
4275 The following extraInfo are available related
with the given particleList:
4277 * Pi0VetoEfficiencySystematics_{mode}{suffix}_data_MC_ratio : weight of Data/MC
for the veto efficiency
4278 * Pi0VetoEfficiencySystematics_{mode}{suffix}_data_MC_uncertainty_stat : the statistical uncertainty of the weight
4279 * Pi0VetoEfficiencySystematics_{mode}{suffix}_data_MC_uncertainty_sys : the systematic uncertainty of the weight
4280 * Pi0VetoEfficiencySystematics_{mode}{suffix}_data_MC_uncertainty_total : the total uncertainty of the weight
4281 * Pi0VetoEfficiencySystematics_{mode}{suffix}_threshold : threshold of the pi0 veto
4286 B2ERROR(
"For Belle data the pi0 veto data/MC efficiency ratio weights are not available via this tool.")
4288 pi0veto_efficiency_correction = register_module(
'Pi0VetoEfficiencySystematics')
4289 pi0veto_efficiency_correction.param(
'particleLists', particleList)
4290 pi0veto_efficiency_correction.param(
'decayString', decayString)
4291 pi0veto_efficiency_correction.param(
'tableName', tableName)
4292 pi0veto_efficiency_correction.param(
'threshold', threshold)
4293 pi0veto_efficiency_correction.param(
'mode', mode)
4294 pi0veto_efficiency_correction.param(
'suffix', suffix)
4295 path.add_module(pi0veto_efficiency_correction)
4298def getAnalysisGlobaltag(timeout=180) -> str:
4300 Returns a string containing the name of the latest and recommended analysis globaltag.
4303 timeout: Seconds to wait
for b2conditionsdb-recommend
4308 B2ERROR(
"The getAnalysisGlobaltag() function cannot be used for Belle data.")
4313 tags = subprocess.check_output(
4314 [
'b2conditionsdb-recommend',
'--oneline'],
4316 ).decode(
'UTF-8').rstrip().split(
' ')
4319 if tag.startswith(
'analysis_tools'):
4323 except subprocess.TimeoutExpired
as te:
4324 B2FATAL(f
'A {te} exception was raised during the call of getAnalysisGlobaltag(). '
4325 'The function took too much time to retrieve the requested information '
4326 'from the versioning repository.\n'
4327 'Please try to re-run your job. In case of persistent failures, there may '
4328 'be issues with the DESY collaborative services, so please contact the experts.')
4329 except subprocess.CalledProcessError
as ce:
4330 B2FATAL(f
'A {ce} exception was raised during the call of getAnalysisGlobaltag(). '
4331 'Please try to re-run your job. In case of persistent failures, please contact '
4335def getAnalysisGlobaltagB2BII() -> str:
4337 Get recommended global tag
for B2BII analysis.
4342 B2ERROR(
'The getAnalysisGlobaltagB2BII() function cannot be used for Belle II data.')
4343 from versioning
import recommended_b2bii_analysis_global_tag
4344 return recommended_b2bii_analysis_global_tag()
4347def getNbarIDMVA(particleList: str, path=
None):
4349 This function can give a score to predict if it
is a anti-n0.
4350 It
is not used to predict n0.
4351 Currently, this can be used only
for ECL cluster.
4352 output will be stored
in extraInfo(nbarID); -1 means MVA invalid
4354 @param particleList The input ParticleList name
or a decay string which contains a full mother particle list name.
4355 Only one selected daughter
is supported.
4356 @param path modules are added to this path
4359 from ROOT
import Belle2
4362 B2ERROR(
"The MVA-based anti-neutron PID is only available for Belle II data.")
4364 from variables
import variables
4366 variables.addAlias(
'V1',
'clusterHasPulseShapeDiscrimination')
4367 variables.addAlias(
'V2',
'clusterE')
4368 variables.addAlias(
'V3',
'clusterLAT')
4369 variables.addAlias(
'V4',
'clusterE1E9')
4370 variables.addAlias(
'V5',
'clusterE9E21')
4371 variables.addAlias(
'V6',
'clusterZernikeMVA')
4372 variables.addAlias(
'V7',
'clusterAbsZernikeMoment40')
4373 variables.addAlias(
'V8',
'clusterAbsZernikeMoment51')
4377 'passesCut(V1 == 1 and V2 >= 0 and V3 >= 0 and V4 >= 0 and V5 >= 0 and V6 >= 0 and V7 >= 0 and V8 >= 0)')
4378 variables.addAlias(
'nbarIDmod',
'conditionalVariableSelector(nbarIDValid == 1, extraInfo(nbarIDFromMVA), constant(-1.0))')
4380 path.add_module(
'MVAExpert', listNames=particleList, extraInfoName=
'nbarIDFromMVA', identifier=
'db_nbarIDECL')
4382 if not decayDescriptor.init(particleList):
4383 raise ValueError(f
"Provided decay string is invalid: {particleList}")
4384 if decayDescriptor.getNDaughters() == 0:
4387 listname = decayDescriptor.getMother().getFullName()
4388 variablesToDaughterExtraInfo(listname, particleList, {
'nbarIDmod':
'nbarID'}, option=2, path=path)
4391def reconstructDecayWithNeutralHadron(decayString, cut, allowGamma=False, allowAnyParticleSource=False, path=None, **kwargs):
4393 Reconstructs decay with a long-lived neutral hadron e.g.
4394 :math:`B^0 \to J/\psi K_L^0`,
4395 :math:`B^0 \to p \bar{n} D^*(2010)^-`.
4397 The calculation
is done
with IP constraint
and mother mass constraint.
4399 The decay string passed
in must satisfy the following rules:
4401 - The neutral hadron must be **selected**
in the decay string
with the
4402 caret (``^``) e.g. ``B0:sig -> J/psi:sig ^K_L0:sig``. (Note the caret
4403 next to the neutral hadron.)
4404 - There can only be **one neutral hadron
in a decay**.
4405 - The neutral hadron has to be a direct daughter of its mother.
4407 .. note:: This function forwards its arguments to `reconstructDecay`,
4408 so please check the documentation of `reconstructDecay`
for all
4411 @param decayString A decay string following the mentioned rules
4412 @param cut Cut to apply to the particle list
4413 @param allowGamma Whether allow the selected particle to be ``gamma``
4414 @param allowAnyParticleSource Whether allow the selected particle to be
from any source.
4415 Should only be used when studying control sample.
4416 @param path The path to put
in the module
4419 reconstructDecay(decayString, cut, path=path, **kwargs)
4420 module = register_module('NeutralHadron4MomentumCalculator')
4421 module.set_name(
'NeutralHadron4MomentumCalculator_' + decayString)
4422 module.param(
'decayString', decayString)
4423 module.param(
'allowGamma', allowGamma)
4424 module.param(
'allowAnyParticleSource', allowAnyParticleSource)
4425 path.add_module(module)
4428def updateMassHypothesis(particleList, pdg, writeOut=False, path=None):
4430 Module to update the mass hypothesis of a given input particle list with the chosen PDG.
4431 A new particle list
is created
with updated mass hypothesis.
4432 The allowed mass hypotheses
for both input
and output are electrons, muons, pions, kaons
and protons.
4435 The new particle list
is named after the input one,
with the additional suffix ``_converted_from_OLDHYPOTHESIS``,
4436 e.g. ``e+:all`` converted to muons becomes ``mu+:all_converted_from_e``.
4438 @param particleList The input particle list name
4439 @param pdg The PDG code
for the new mass hypothesis,
in [11, 13, 211, 321, 2212]
4440 @param writeOut Whether `RootOutput` module should save the new particle list
4441 @param path Modules are added to this path
4443 mass_updater = register_module("ParticleMassHypothesesUpdater")
4444 mass_updater.set_name(
"ParticleMassHypothesesUpdater_" + particleList +
"_to_" + str(pdg))
4445 mass_updater.param(
"particleList", particleList)
4446 mass_updater.param(
"writeOut", writeOut)
4447 mass_updater.param(
"pdgCode", pdg)
4448 path.add_module(mass_updater)
4451func_requiring_analysisGT = [
4452 correctTrackEnergy, scaleTrackMomenta, smearTrackMomenta, oldwritePi0EtaVeto, writePi0EtaVeto, lowEnergyPi0Identification,
4453 getBeamBackgroundProbability, getFakePhotonProbability, tagCurlTracks, applyChargedPidMVA, correctEnergyBias,
4454 addPhotonEfficiencyRatioVariables, addPi0VetoEfficiencySystematics, getNbarIDMVA]
4455for _
in func_requiring_analysisGT:
4456 _.__doc__ +=
"\n .. note:: This function (optionally) requires a payload stored in the analysis GlobalTag. "\
4457 "Please append or prepend the latest one from `getAnalysisGlobaltag` or `getAnalysisGlobaltagB2BII`.\n"
4460if __name__ ==
'__main__':
4462 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)