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)
337 │ │ ├── D- (-411)
338 │ │ │ ├── K*- (-323)
339 │ │ │ │ ├── anti-K0 (-311)
340 │ │ │ │ │ ╰── K_S0 (310)
341 │ │ │ │ │ ├── pi+ (211)
342 │ │ │ │ │ │ ╰╶╶ p+ (2212)
343 │ │ │ │ │ ╰── pi- (-211)
344 │ │ │ │ │ ├╶╶ e- (11)
345 │ │ │ │ │ ├╶╶ n0 (2112)
346 │ │ │ │ │ ├╶╶ n0 (2112)
347 │ │ │ │ │ ╰╶╶ n0 (2112)
348 │ │ │ │ ╰── pi- (-211)
349 │ │ │ │ ├╶╶ anti-nu_mu (-14)
350 │ │ │ │ ╰╶╶ mu- (13)
351 │ │ │ │ ├╶╶ nu_mu (14)
352 │ │ │ │ ├╶╶ anti-nu_e (-12)
353 │ │ │ │ ╰╶╶ e- (11)
354 │ │ │ ╰── K_S0 (310)
355 │ │ │ ├── pi0 (111)
356 │ │ │ │ ├── gamma (22)
357 │ │ │ │ ╰── gamma (22)
358 │ │ │ ╰── pi0 (111)
359 │ │ │ ├── gamma (22)
360 │ │ │ ╰── gamma (22)
361 │ │ ╰── pi+ (211)
362 │ ├── mu+ (-13)
363 │ │ ├╶╶ anti-nu_mu (-14)
364 │ │ ├╶╶ nu_e (12)
365 │ │ ╰╶╶ e+ (-11)
366 │ ├── nu_mu (14)
367 │ ╰── gamma (22)
371 There
's a distinction between primary and secondary particles. Primary particles are the ones created by the physics generator while secondary
372 particles are ones generated by the simulation of the detector interaction.
374 Secondaries are indicated
with a dashed line leading to the particle name
375 and if the output
is to the terminal they will be printed
in red. If
376 ``onlyPrimaries``
is True they will
not be included
in the tree.
378 On demand, extra information on all the particles can be displayed by
379 enabling any of the ``showProperties``, ``showMomenta``, ``showVertices``
380 and ``showStatus`` flags. Enabling all of them will look like
385 │ mass=0.14 energy=0.445 charge=-1 lifetime=6.36
386 │ p=(0.257, -0.335, 0.0238) |p|=0.423
387 │ production vertex=(0.113, -0.0531, 0.0156), time=0.00589
388 │ status flags=PrimaryParticle, StableInGenerator, StoppedInDetector
392 mass=0.94 energy=0.94 charge=0 lifetime=5.28e+03
393 p=(-0.000238, -0.0127, 0.0116) |p|=0.0172
394 production vertex=(144, 21.9, -1.29), time=39
395 status flags=StoppedInDetector
396 creation process=HadronInelastic
399 The first line of extra information
is enabled by ``showProperties``, the
400 second line by ``showMomenta``, the third line by ``showVertices``
and the
401 last two lines by ``showStatus``. Note that all values are given
in Belle II
402 standard units, that
is GeV, centimeter
and nanoseconds.
404 The depth of the tree can be limited
with the ``maxLevel`` argument: If it
's
405 bigger than zero it will limit the tree to the given number of generations.
406 A visual indicator will be added after each particle which would have
407 additional daughters that are skipped due to this limit. An example event
408 with ``maxLevel=3``
is given below. In this case only the tau neutrino
and
409 the pion don
't have additional daughters. ::
411 [INFO] Content of MCParticle list
414 ╰── Upsilon(4S) (300553)
416 │ ├── anti-D*0 (-423) → …
417 │ ├── tau+ (-15) → …
418 │ ╰── nu_tau (16)
420 ├── D*0 (423) → …
421 ├── K*- (-323) → …
422 ├── K*+ (323) → …
425 The same information will be stored in the branch ``__MCDecayString__`` of
426 TTree created by `VariablesToNtuple`
or `VariablesToEventBasedTree` module.
427 This branch
is automatically created when `PrintMCParticles` modules
is called.
428 Printing the information on the log message can be suppressed
if ``suppressPrint``
429 is True,
while the branch ``__MCDecayString__``. This option helps to reduce the
430 size of the log message.
433 onlyPrimaries (bool): If
True show only primary particles, that
is particles coming
from
434 the generator
and not created by the simulation.
435 maxLevel (int): If 0
or less
print the whole tree, otherwise stop after n generations
436 showProperties (bool): If
True show mass, energy
and charge of the particles
437 showMomenta (bool):
if True show the momenta of the particles
438 showVertices (bool):
if True show production vertex
and production time of all particles
439 showStatus (bool):
if True show some status information on the particles.
440 For secondary particles this includes creation process.
441 suppressPrint (bool):
if True printing the information on the log message
is suppressed.
442 Even
if True, the branch ``__MCDecayString__``
is created.
445 return path.add_module(
447 onlyPrimaries=onlyPrimaries,
449 showProperties=showProperties,
450 showMomenta=showMomenta,
451 showVertices=showVertices,
452 showStatus=showStatus,
453 suppressPrint=suppressPrint,
457def correctBrems(outputList,
460 maximumAcceptance=3.0,
461 multiplePhotons=False,
462 usePhotonOnlyOnce=True,
466 For each particle in the given ``inputList``, copies it to the ``outputList``
and adds the
467 4-vector of the photon(s)
in the ``gammaList`` which has(have) a weighted named relation to
468 the particle
's track, set by the ``ECLTrackBremFinder`` module during reconstruction.
471 This can only work if the mdst file contains the *Bremsstrahlung* named relation. Official MC samples
472 up to
and including MC12
and proc9 **do
not** contain this. Newer production campaigns (
from proc10
and MC13) do.
473 However, studies by the tau WG revealed that the cuts applied by the ``ECLTrackBremFinder`` module are too tight.
474 These will be loosened but this will only have effect
with proc13
and MC15.
475 If your analysis
is very sensitive to the Bremsstrahlung corrections, it
is advised to use `correctBremsBelle`.
478 A detailed description of how the weights are set can be found directly at the documentation of the
479 `BremsFinder` module.
481 Please note that a new particle
is always generated,
with the old particle
and -
if found- one
or more
482 photons
as daughters.
484 The ``inputList`` should contain particles
with associated tracks. Otherwise, the module will exit
with an error.
486 The ``gammaList`` should contain photons. Otherwise, the module will exit
with an error.
488 @param outputList The output particle list name containing the corrected particles
489 @param inputList The initial particle list name containing the particles to correct. *It should already exist.*
490 @param gammaList The photon list containing possibly bremsstrahlung photons; *It should already exist.*
491 @param maximumAcceptance Maximum value of the relation weight. Should be a number between [0,3)
492 @param multiplePhotons Whether to use only one photon (the one
with the smallest acceptance)
or as many
as possible
493 @param usePhotonOnlyOnce If true, each brems candidate
is used to correct only the track
with the smallest relation weight
494 @param writeOut Whether `RootOutput` module should save the created ``outputList``
495 @param path The module
is added to this path
500 B2ERROR(
"The BremsFinder can only be run over Belle II data.")
502 bremscorrector = register_module(
'BremsFinder')
503 bremscorrector.set_name(
'bremsCorrector_' + outputList)
504 bremscorrector.param(
'inputList', inputList)
505 bremscorrector.param(
'outputList', outputList)
506 bremscorrector.param(
'gammaList', gammaList)
507 bremscorrector.param(
'maximumAcceptance', maximumAcceptance)
508 bremscorrector.param(
'multiplePhotons', multiplePhotons)
509 bremscorrector.param(
'usePhotonOnlyOnce', usePhotonOnlyOnce)
510 bremscorrector.param(
'writeOut', writeOut)
511 path.add_module(bremscorrector)
514def copyList(outputListName, inputListName, writeOut=False, path=None):
516 Copy all Particle indices from input ParticleList to the output ParticleList.
517 Note that the Particles themselves are
not copied. The original
and copied
518 ParticleLists will point to the same Particles.
520 @param ouputListName copied ParticleList
521 @param inputListName original ParticleList to be copied
522 @param writeOut whether RootOutput module should save the created ParticleList
523 @param path modules are added to this path
526 copyLists(outputListName, [inputListName], writeOut, path)
529def correctBremsBelle(outputListName,
532 multiplePhotons=True,
534 usePhotonOnlyOnce=False,
538 Run the Belle - like brems finding on the ``inputListName`` of charged particles.
539 Adds all photons in ``gammaListName`` to a copy of the charged particle that are within
543 Studies by the tau WG show that using a rather wide opening angle (up to
544 0.2 rad)
and rather low energetic photons results
in good correction.
545 However, this should only serve
as a starting point
for your own studies
546 because the optimal criteria are likely mode-dependent
549 outputListName (str): The output charged particle list containing the corrected charged particles
550 inputListName (str): The initial charged particle list containing the charged particles to correct.
551 gammaListName (str): The gammas list containing possibly radiative gammas, should already exist.
552 multiplePhotons (bool): How many photons should be added to the charged particle? nearest one ->
False,
553 add all the photons within the cone ->
True
554 angleThreshold (float): The maximum angle
in radians between the charged particle
and the (radiative)
555 gamma to be accepted.
556 writeOut (bool): whether RootOutput module should save the created ParticleList
557 usePhotonOnlyOnce (bool): If true, a photon
is used
for correction of the closest charged particle
in the inputList.
558 If false, a photon
is allowed to be used
for correction multiple times (Default).
561 One cannot use a photon twice to reconstruct a composite particle. Thus,
for example,
if ``e+``
and ``e-`` are corrected
562 with a ``gamma``, the pair of ``e+``
and ``e-`` cannot form a ``J/psi -> e+ e-`` candidate.
564 path (basf2.Path): modules are added to this path
567 fsrcorrector = register_module('BelleBremRecovery')
568 fsrcorrector.set_name(
'BelleFSRCorrection_' + outputListName)
569 fsrcorrector.param(
'inputListName', inputListName)
570 fsrcorrector.param(
'outputListName', outputListName)
571 fsrcorrector.param(
'gammaListName', gammaListName)
572 fsrcorrector.param(
'multiplePhotons', multiplePhotons)
573 fsrcorrector.param(
'angleThreshold', angleThreshold)
574 fsrcorrector.param(
'usePhotonOnlyOnce', usePhotonOnlyOnce)
575 fsrcorrector.param(
'writeOut', writeOut)
576 path.add_module(fsrcorrector)
579def copyLists(outputListName, inputListNames, writeOut=False, path=None):
581 Copy all Particle indices from all input ParticleLists to the
582 single output ParticleList.
583 Note that the Particles themselves are
not copied.
584 The original
and copied ParticleLists will point to the same Particles.
586 Duplicates are removed based on the first-come, first-served principle.
587 Therefore, the order of the input ParticleLists matters.
590 If you want to select the best duplicate based on another criterion, have
591 a look at the function `mergeListsWithBestDuplicate`.
594 Two particles that differ only by the order of their daughters are
595 considered duplicates
and one of them will be removed.
597 @param ouputListName copied ParticleList
598 @param inputListName vector of original ParticleLists to be copied
599 @param writeOut whether RootOutput module should save the created ParticleList
600 @param path modules are added to this path
603 pmanipulate = register_module('ParticleListManipulator')
604 pmanipulate.set_name(
'PListCopy_' + outputListName)
605 pmanipulate.param(
'outputListName', outputListName)
606 pmanipulate.param(
'inputListNames', inputListNames)
607 pmanipulate.param(
'writeOut', writeOut)
608 path.add_module(pmanipulate)
611def copyParticles(outputListName, inputListName, writeOut=False, path=None):
613 Create copies of Particles given in the input ParticleList
and add them to the output ParticleList.
615 The existing relations of the original Particle (
or it
's (grand-)^n-daughters)
616 are copied as well. Note that only the relation
is copied
and that the related
617 object
is not. Copied particles are therefore related to the *same* object
as
620 @param ouputListName new ParticleList filled
with copied Particles
621 @param inputListName input ParticleList
with original Particles
622 @param writeOut whether RootOutput module should save the created ParticleList
623 @param path modules are added to this path
627 pmanipulate = register_module(
'ParticleListManipulator')
628 pmanipulate.set_name(
'PListCopy_' + outputListName)
629 pmanipulate.param(
'outputListName', outputListName)
630 pmanipulate.param(
'inputListNames', [inputListName])
631 pmanipulate.param(
'writeOut', writeOut)
632 path.add_module(pmanipulate)
635 pcopy = register_module(
'ParticleCopier')
636 pcopy.param(
'inputListNames', [outputListName])
637 path.add_module(pcopy)
640def cutAndCopyLists(outputListName, inputListNames, cut, writeOut=False, path=None):
642 Copy candidates from all lists
in ``inputListNames`` to
643 ``outputListName``
if they
pass ``cut`` (given selection criteria).
646 Note that the Particles themselves are
not copied.
647 The original
and copied ParticleLists will point to the same Particles.
650 Require energetic pions safely inside the cdc
652 .. code-block:: python
654 cutAndCopyLists(
"pi+:energeticPions", [
"pi+:good",
"pi+:loose"],
"[E > 2] and thetaInCDCAcceptance", path=mypath)
657 You must use square braces ``[``
and ``]``
for conditional statements.
660 outputListName (str): the new ParticleList name
661 inputListName (list(str)): list of input ParticleList names
662 cut (str): Candidates that do
not pass these selection criteria are removed
from the ParticleList
663 writeOut (bool): whether RootOutput module should save the created ParticleList
664 path (basf2.Path): modules are added to this path
667 pmanipulate = register_module('ParticleListManipulator')
668 pmanipulate.set_name(
'PListCutAndCopy_' + outputListName)
669 pmanipulate.param(
'outputListName', outputListName)
670 pmanipulate.param(
'inputListNames', inputListNames)
671 pmanipulate.param(
'cut', cut)
672 pmanipulate.param(
'writeOut', writeOut)
673 path.add_module(pmanipulate)
676def cutAndCopyList(outputListName, inputListName, cut, writeOut=False, path=None):
678 Copy candidates from ``inputListName`` to ``outputListName``
if they
pass
679 ``cut`` (given selection criteria).
682 Note the Particles themselves are
not copied.
683 The original
and copied ParticleLists will point to the same Particles.
686 require energetic pions safely inside the cdc
688 .. code-block:: python
690 cutAndCopyList(
"pi+:energeticPions",
"pi+:loose",
"[E > 2] and thetaInCDCAcceptance", path=mypath)
693 You must use square braces ``[``
and ``]``
for conditional statements.
696 outputListName (str): the new ParticleList name
697 inputListName (str): input ParticleList name
698 cut (str): Candidates that do
not pass these selection criteria are removed
from the ParticleList
699 writeOut (bool): whether RootOutput module should save the created ParticleList
700 path (basf2.Path): modules are added to this path
703 cutAndCopyLists(outputListName, [inputListName], cut, writeOut, path)
706def removeTracksForTrackingEfficiencyCalculation(inputListNames, fraction, path=None):
708 Randomly remove tracks from the provided particle lists to estimate the tracking efficiency.
709 Takes care of the duplicates,
if any.
712 inputListNames (list(str)): input particle list names
713 fraction (float): fraction of particles to be removed randomly
714 path (basf2.Path): module
is added to this path
717 trackingefficiency = register_module('TrackingEfficiency')
718 trackingefficiency.param(
'particleLists', inputListNames)
719 trackingefficiency.param(
'frac', fraction)
720 path.add_module(trackingefficiency)
723def scaleTrackMomenta(inputListNames, scale=float(
'nan'), payloadName=
"", scalingFactorName=
"SF", path=
None):
725 Scale momenta of the particles according to a scaling factor scale.
726 This scaling factor can either be given as constant number
or as the name of the payload which contains
727 the variable scale factors.
728 If the particle list contains composite particles, the momenta of the track-based daughters are scaled.
729 Subsequently, the momentum of the mother particle
is updated
as well.
732 inputListNames (list(str)): input particle list names
733 scale (float): scaling factor (1.0 -- no scaling)
734 payloadName (str): name of the payload which contains the phase-space dependent scaling factors
735 scalingFactorName (str): name of scaling factor variable
in the payload.
736 path (basf2.Path): module
is added to this path
741 B2ERROR(
"The tracking momentum scaler can only be run over Belle II data.")
743 TrackingMomentumScaleFactors = register_module(
'TrackingMomentumScaleFactors')
744 TrackingMomentumScaleFactors.param(
'particleLists', inputListNames)
745 TrackingMomentumScaleFactors.param(
'scale', scale)
746 TrackingMomentumScaleFactors.param(
'payloadName', payloadName)
747 TrackingMomentumScaleFactors.param(
'scalingFactorName', scalingFactorName)
749 path.add_module(TrackingMomentumScaleFactors)
752def correctTrackEnergy(inputListNames, correction=float(
'nan'), payloadName=
"", correctionName=
"SF", path=
None):
754 Correct the energy loss of tracks according to a 'correction' value.
755 This correction can either be given
as constant number
or as the name of the payload which contains
756 the variable corrections.
757 If the particle list contains composite particles, the momenta of the track-based daughters are corrected.
758 Subsequently, the momentum of the mother particle
is updated
as well.
761 inputListNames (list(str)): input particle list names
762 correction (float): correction value to be subtracted to the particle energy (0.0 -- no correction)
763 payloadName (str): name of the payload which contains the phase-space dependent scaling factors
764 correctionName (str): name of correction variable
in the payload.
765 path (basf2.Path): module
is added to this path
770 B2ERROR(
"The tracking energy correction can only be run over Belle II data.")
772 TrackingEnergyLossCorrection = register_module(
'TrackingEnergyLossCorrection')
773 TrackingEnergyLossCorrection.param(
'particleLists', inputListNames)
774 TrackingEnergyLossCorrection.param(
'correction', correction)
775 TrackingEnergyLossCorrection.param(
'payloadName', payloadName)
776 TrackingEnergyLossCorrection.param(
'correctionName', correctionName)
778 path.add_module(TrackingEnergyLossCorrection)
781def smearTrackMomenta(inputListNames, payloadName="", smearingFactorName="smear", path=None):
783 Smear the momenta of the particles according the values read from the given payload.
784 If the particle list contains composite particles, the momenta of the track-based daughters are smeared.
785 Subsequently, the momentum of the mother particle
is updated
as well.
788 inputListNames (list(str)): input particle list names
789 payloadName (str): name of the payload which contains the smearing values
790 smearingFactorName (str): name of smearing factor variable
in the payload.
791 path (basf2.Path): module
is added to this path
794 TrackingMomentumScaleFactors = register_module('TrackingMomentumScaleFactors')
795 TrackingMomentumScaleFactors.param(
'particleLists', inputListNames)
796 TrackingMomentumScaleFactors.param(
'payloadName', payloadName)
797 TrackingMomentumScaleFactors.param(
'smearingFactorName', smearingFactorName)
799 path.add_module(TrackingMomentumScaleFactors)
802def mergeListsWithBestDuplicate(outputListName,
807 ignoreMotherFlavor=False,
810 Merge input ParticleLists into one output ParticleList. Only the best
811 among duplicates is kept. The lowest
or highest value (configurable via
812 preferLowest) of the provided variable determines which duplicate
is the
815 @param ouputListName name of merged ParticleList
816 @param inputListName vector of original ParticleLists to be merged
817 @param variable variable to determine best duplicate
818 @param preferLowest whether lowest
or highest value of variable should be preferred
819 @param writeOut whether RootOutput module should save the created ParticleList
820 @param ignoreMotherFlavor whether the flavor of the mother particle
is ignored when trying to find duplicates
821 @param path modules are added to this path
824 pmanipulate = register_module('ParticleListManipulator')
825 pmanipulate.set_name(
'PListMerger_' + outputListName)
826 pmanipulate.param(
'outputListName', outputListName)
827 pmanipulate.param(
'inputListNames', inputListNames)
828 pmanipulate.param(
'variable', variable)
829 pmanipulate.param(
'preferLowest', preferLowest)
830 pmanipulate.param(
'writeOut', writeOut)
831 pmanipulate.param(
'ignoreMotherFlavor', ignoreMotherFlavor)
832 path.add_module(pmanipulate)
835def fillSignalSideParticleList(outputListName, decayString, path):
837 This function should only be used in the ROE path, that
is a path
838 that
is executed
for each ROE object
in the DataStore.
840 Example: fillSignalSideParticleList(
'gamma:sig',
'B0 -> K*0 ^gamma', roe_path)
842 Function will create a ParticleList
with name
'gamma:sig' which will be filled
843 with the existing photon Particle, being the second daughter of the B0 candidate
844 to which the ROE object has to be related.
846 @param ouputListName name of the created ParticleList
847 @param decayString specify Particle to be added to the ParticleList
850 pload = register_module('SignalSideParticleListCreator')
851 pload.set_name(
'SSParticleList_' + outputListName)
852 pload.param(
'particleListName', outputListName)
853 pload.param(
'decayString', decayString)
854 path.add_module(pload)
857def fillParticleLists(decayStringsWithCuts, writeOut=False, path=None, enforceFitHypothesis=False,
858 loadPhotonsFromKLM=False):
860 Creates Particles of the desired types from the corresponding ``mdst`` dataobjects,
861 loads them to the ``StoreArray<Particle>``
and fills the ParticleLists.
863 The multiple ParticleLists
with their own selection criteria are specified
864 via list tuples (decayString, cut),
for example
866 .. code-block:: python
868 kaons = (
'K+:mykaons',
'kaonID>0.1')
869 pions = (
'pi+:mypions',
'pionID>0.1')
870 fillParticleLists([kaons, pions], path=mypath)
872 If you are unsure what selection you want, you might like to see the
873 :doc:`StandardParticles` functions.
875 The type of the particles to be loaded
is specified via the decayString module parameter.
876 The type of the ``mdst`` dataobject that
is used
as an input
is determined
from the type of
877 the particle. The following types of the particles can be loaded:
879 * charged final state particles (input ``mdst`` type = Tracks)
880 - e+, mu+, pi+, K+, p, deuteron (
and charge conjugated particles)
882 * neutral final state particles
883 -
"gamma" (input ``mdst`` type = ECLCluster)
884 -
"K_S0",
"Lambda0" (input ``mdst`` type = V0)
885 -
"K_L0" (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):
2028 Creates and fills a flat ntuple
with the specified variables
from the VariableManager.
2029 If a decayString
is provided, then there will be one entry per candidate (
for particle
in list of candidates).
2030 If an empty decayString
is provided, there will be one entry per event (useful
for trigger studies, etc).
2033 decayString (str): specifies type of Particles
and determines the name of the ParticleList
2034 variables (list(str)): the list of variables (which must be registered
in the VariableManager)
2035 treename (str): name of the ntuple tree
2036 filename (str): which
is used to store the variables
2037 path (basf2.Path): the basf2 path where the analysis
is processed
2038 basketsize (int): size of baskets
in the output ntuple
in bytes
2039 signalSideParticleList (str): The name of the signal-side ParticleList.
2040 Only valid
if the module
is called
in a for_each loop over the RestOfEvent.
2041 filenameSuffix (str): suffix to be appended to the filename before ``.root``.
2042 useFloat (bool): Use single precision (float) instead of double precision (double)
2043 for floating-point numbers.
2044 storeEventType (bool) :
if true, the branch __eventType__
is added
for the MC event type information.
2045 The information
is available
from MC16 on.
2047 .. tip:: The output filename can be overridden using the ``-o`` argument of basf2.
2050 output = register_module('VariablesToNtuple')
2051 output.set_name(
'VariablesToNtuple_' + decayString)
2052 output.param(
'particleList', decayString)
2053 output.param(
'variables', variables)
2054 output.param(
'fileName', filename)
2055 output.param(
'treeName', treename)
2056 output.param(
'basketSize', basketsize)
2057 output.param(
'signalSideParticleList', signalSideParticleList)
2058 output.param(
'fileNameSuffix', filenameSuffix)
2059 output.param(
'useFloat', useFloat)
2060 output.param(
'storeEventType', storeEventType)
2061 path.add_module(output)
2067 filename='ntuple.root',
2070 prefixDecayString=False,
2073 Creates and fills a flat ntuple
with the specified variables
from the VariableManager
2076 decayString (str): specifies type of Particles
and determines the name of the ParticleList
2077 variables (list(tuple))): variables + binning which must be registered
in the VariableManager
2078 variables_2d (list(tuple)): pair of variables + binning
for each which must be registered
in the VariableManager
2079 filename (str): which
is used to store the variables
2080 path (basf2.Path): the basf2 path where the analysis
is processed
2081 directory (str): directory inside the output file where the histograms should be saved.
2082 Useful
if you want to have different histograms
in the same file to separate them.
2083 prefixDecayString (bool): If
True the decayString will be prepended to the directory name to allow
for more
2084 programmatic naming of the structure
in the file.
2085 filenameSuffix (str): suffix to be appended to the filename before ``.root``.
2087 .. tip:: The output filename can be overridden using the ``-o`` argument of basf2.
2090 if variables_2d
is None:
2092 output = register_module(
'VariablesToHistogram')
2093 output.set_name(
'VariablesToHistogram_' + decayString)
2094 output.param(
'particleList', decayString)
2095 output.param(
'variables', variables)
2096 output.param(
'variables_2d', variables_2d)
2097 output.param(
'fileName', filename)
2098 output.param(
'fileNameSuffix', filenameSuffix)
2099 if directory
is not None or prefixDecayString:
2100 if directory
is None:
2102 if prefixDecayString:
2103 directory = decayString +
"_" + directory
2104 output.param(
"directory", directory)
2105 path.add_module(output)
2110 For each particle in the input list the selected variables are saved
in an extra-info field
with the given name.
2111 Can be used when wanting to save variables before modifying them, e.g. when performing vertex fits.
2114 particleList (str): The input ParticleList
2115 variables (dict[str,str]): Dictionary of Variables (key)
and extraInfo names (value).
2116 option (int): Option to overwrite an existing extraInfo. Choose among -1, 0, 1, 2.
2117 An existing extra info
with the same name will be overwritten
if the new
2118 value
is lower / will never be overwritten / will be overwritten
if the
2119 new value
is higher / will always be overwritten (option = -1/0/1/2).
2120 path (basf2.Path): modules are added to this path
2123 mod = register_module('VariablesToExtraInfo')
2124 mod.set_name(
'VariablesToExtraInfo_' + particleList)
2125 mod.param(
'particleList', particleList)
2126 mod.param(
'variables', variables)
2127 mod.param(
'overwrite', option)
2128 path.add_module(mod)
2131def variablesToDaughterExtraInfo(particleList, decayString, variables, option=0, path=None):
2133 For each daughter particle specified via decay string the selected variables (estimated for the mother particle)
2134 are saved
in an extra-info field
with the given name. In other words, the property of mother
is saved
as extra-info
2135 to specified daughter particle.
2138 particleList (str): The input ParticleList
2139 decayString (str): Decay string that specifies to which daughter the extra info should be appended
2140 variables (dict[str,str]): Dictionary of Variables (key)
and extraInfo names (value).
2141 option (int): Option to overwrite an existing extraInfo. Choose among -1, 0, 1, 2.
2142 An existing extra info
with the same name will be overwritten
if the new
2143 value
is lower / will never be overwritten / will be overwritten
if the
2144 new value
is higher / will always be overwritten (option = -1/0/1/2).
2145 path (basf2.Path): modules are added to this path
2148 mod = register_module('VariablesToExtraInfo')
2149 mod.set_name(
'VariablesToDaughterExtraInfo_' + particleList)
2150 mod.param(
'particleList', particleList)
2151 mod.param(
'decayString', decayString)
2152 mod.param(
'variables', variables)
2153 mod.param(
'overwrite', option)
2154 path.add_module(mod)
2157def variablesToEventExtraInfo(particleList, variables, option=0, path=None):
2159 For each particle in the input list the selected variables are saved
in an event-extra-info field
with the given name,
2160 Can be used to save MC truth information,
for example,
in a ntuple of reconstructed particles.
2163 When the function
is called first time
not in the main path but
in a sub-path e.g. ``roe_path``,
2164 the eventExtraInfo cannot be accessed
from the main path because of the shorter lifetime of the event-extra-info field.
2165 If one wants to call the function
in a sub-path, one has to call the function
in the main path beforehand.
2168 particleList (str): The input ParticleList
2169 variables (dict[str,str]): Dictionary of Variables (key)
and extraInfo names (value).
2170 option (int): Option to overwrite an existing extraInfo. Choose among -1, 0, 1, 2.
2171 An existing extra info
with the same name will be overwritten
if the new
2172 value
is lower / will never be overwritten / will be overwritten
if the
2173 new value
is higher / will always be overwritten (option = -1/0/1/2).
2174 path (basf2.Path): modules are added to this path
2177 mod = register_module('VariablesToEventExtraInfo')
2178 mod.set_name(
'VariablesToEventExtraInfo_' + particleList)
2179 mod.param(
'particleList', particleList)
2180 mod.param(
'variables', variables)
2181 mod.param(
'overwrite', option)
2182 path.add_module(mod)
2185def variableToSignalSideExtraInfo(particleList, varToExtraInfo, path):
2187 Write the value of specified variables estimated for the single particle
in the input list (has to contain exactly 1
2188 particle)
as an extra info to the particle related to current ROE.
2189 Should be used only
in the for_each roe path.
2192 particleList (str): The input ParticleList
2193 varToExtraInfo (dict[str,str]): Dictionary of Variables (key)
and extraInfo names (value).
2194 path (basf2.Path): modules are added to this path
2197 mod = register_module('SignalSideVariablesToExtraInfo')
2198 mod.set_name(
'SigSideVarToExtraInfo_' + particleList)
2199 mod.param(
'particleListName', particleList)
2200 mod.param(
'variableToExtraInfo', varToExtraInfo)
2201 path.add_module(mod)
2204def signalRegion(particleList, cut, path=None, name="isSignalRegion", blind_data=True):
2206 Define and blind a signal region.
2207 Per default, the defined signal region
is cut out
if ran on data.
2208 This function will provide a new variable
'isSignalRegion' as default, which
is either 0
or 1 depending on the cut
2212 .. code-block:: python
2214 ma.reconstructDecay(
"B+:sig -> D+ pi0",
"Mbc>5.2", path=path)
2215 ma.signalRegion(
"B+:sig",
2216 "Mbc>5.27 and abs(deltaE)<0.2",
2219 ma.variablesToNtuples(
"B+:sig", [
"isSignalRegion"], path=path)
2222 particleList (str): The input ParticleList
2223 cut (str): Cut string describing the signal region
2224 path (basf2.Path):: Modules are added to this path
2225 name (str): Name of the Signal region
in the variable manager
2226 blind_data (bool): Automatically exclude signal region
from data
2230 from variables
import variables
2231 mod = register_module(
'VariablesToExtraInfo')
2232 mod.set_name(f
'{name}_' + particleList)
2233 mod.param(
'particleList', particleList)
2234 mod.param(
'variables', {f
"passesCut({cut})": name})
2235 variables.addAlias(name, f
"extraInfo({name})")
2236 path.add_module(mod)
2240 applyCuts(particleList, f
"{name}==0 or isMC==1", path=path)
2243def removeExtraInfo(particleLists=None, removeEventExtraInfo=False, path=None):
2245 Removes the ExtraInfo of the given particleLists. If specified (removeEventExtraInfo = True) also the EventExtraInfo
is removed.
2248 if particleLists
is None:
2250 mod = register_module(
'ExtraInfoRemover')
2251 mod.param(
'particleLists', particleLists)
2252 mod.param(
'removeEventExtraInfo', removeEventExtraInfo)
2253 path.add_module(mod)
2256def signalSideParticleFilter(particleList, selection, roe_path, deadEndPath):
2258 Checks if the current ROE object
in the for_each roe path (argument roe_path)
is related
2259 to the particle
from the input ParticleList. Additional selection criteria can be applied.
2260 If ROE
is not related to any of the Particles
from ParticleList
or the Particle doesn
't
2261 meet the selection criteria the execution of deadEndPath is started. This path,
as the name
2262 suggests should be empty
and its purpose
is to end the execution of for_each roe path
for
2263 the current ROE object.
2265 @param particleList The input ParticleList
2266 @param selection Selection criteria that Particle needs meet
in order
for for_each ROE path to
continue
2267 @param for_each roe path
in which this filter
is executed
2268 @param deadEndPath empty path that ends execution of or_each roe path
for the current ROE object.
2271 mod = register_module('SignalSideParticleFilter')
2272 mod.set_name(
'SigSideParticleFilter_' + particleList)
2273 mod.param(
'particleLists', [particleList])
2274 mod.param(
'selection', selection)
2275 roe_path.add_module(mod)
2276 mod.if_false(deadEndPath)
2279def signalSideParticleListsFilter(particleLists, selection, roe_path, deadEndPath):
2281 Checks if the current ROE object
in the for_each roe path (argument roe_path)
is related
2282 to the particle
from the input ParticleList. Additional selection criteria can be applied.
2283 If ROE
is not related to any of the Particles
from ParticleList
or the Particle doesn
't
2284 meet the selection criteria the execution of deadEndPath is started. This path,
as the name
2285 suggests should be empty
and its purpose
is to end the execution of for_each roe path
for
2286 the current ROE object.
2288 @param particleLists The input ParticleLists
2289 @param selection Selection criteria that Particle needs meet
in order
for for_each ROE path to
continue
2290 @param for_each roe path
in which this filter
is executed
2291 @param deadEndPath empty path that ends execution of or_each roe path
for the current ROE object.
2294 mod = register_module('SignalSideParticleFilter')
2295 mod.set_name(
'SigSideParticleFilter_' + particleLists[0])
2296 mod.param(
'particleLists', particleLists)
2297 mod.param(
'selection', selection)
2298 roe_path.add_module(mod)
2299 mod.if_false(deadEndPath)
2308 chargeConjugation=True,
2311 Finds and creates a ``ParticleList``
from given decay string.
2312 ``ParticleList`` of daughters
with sub-decay
is created.
2314 Only the particles made
from MCParticle, which can be loaded by `fillParticleListFromMC`, are accepted
as daughters.
2316 Only signal particle, which means :b2:var:`isSignal`
is equal to 1,
is stored. One can use the decay string grammar
2317 to change the behavior of :b2:var:`isSignal`. One can find detailed information
in :ref:`DecayString`.
2320 If one uses same sub-decay twice, same particles are registered to a ``ParticleList``. For example,
2321 ``K_S0:pi0pi0 =direct=> [pi0:gg =direct=> gamma:MC gamma:MC] [pi0:gg =direct=> gamma:MC gamma:MC]``.
2322 One can skip the second sub-decay, ``K_S0:pi0pi0 =direct=> [pi0:gg =direct=> gamma:MC gamma:MC] pi0:gg``.
2325 It
is recommended to use only primary particles
as daughter particles unless you want to explicitly study the secondary
2326 particles. The behavior of MC-matching
for secondary particles
from a stable particle decay
is not guaranteed.
2327 Please consider to use `fillParticleListFromMC`
with ``skipNonPrimary=
True`` to load daughter particles.
2328 Moreover, it
is recommended to load ``K_S0``
and ``Lambda0`` directly
from MCParticle by `fillParticleListFromMC` rather
2329 than reconstructing
from two pions
or a proton-pion pair, because their direct daughters can be the secondary particle.
2332 @param decayString :ref:`DecayString` specifying what kind of the decay should be reconstructed
2333 (
from the DecayString the mother
and daughter ParticleLists are determined)
2334 @param cut created (mother) Particles are added to the mother ParticleList
if they
2335 pass given cuts (
in VariableManager style)
and rejected otherwise
2336 isSignal==1
is always required by default.
2337 @param dmID user specified decay mode identifier
2338 @param writeOut whether RootOutput module should save the created ParticleList
2339 @param path modules are added to this path
2340 @param chargeConjugation boolean to decide whether charge conjugated mode should be reconstructed
as well (on by default)
2343 pmake = register_module('ParticleCombinerFromMC')
2344 pmake.set_name(
'ParticleCombinerFromMC_' + decayString)
2345 pmake.param(
'decayString', decayString)
2346 pmake.param(
'cut', cut)
2347 pmake.param(
'decayMode', dmID)
2348 pmake.param(
'writeOut', writeOut)
2349 pmake.param(
'chargeConjugation', chargeConjugation)
2350 path.add_module(pmake)
2357 appendAllDaughters=False,
2358 skipNonPrimaryDaughters=True,
2362 Finds and creates a ``ParticleList``
for all ``MCParticle`` decays matching a given :ref:`DecayString`.
2363 The decay string
is required to describe correctly what you want.
2364 In the case of inclusive decays, you can use :ref:`Grammar_for_custom_MCMatching`
2366 The output particles has only the daughter particles written
in the given decay string,
if
2367 ``appendAllDaughters=
False`` (default). If ``appendAllDaughters=
True``, all daughters of the matched MCParticle are
2368 appended
in the order defined at the MCParticle level. For example,
2370 .. code-block:: python
2372 findMCDecay(
'B0:Xee',
'B0 -> e+ e- ... ?gamma', appendAllDaughters=
False, path=mypath)
2374 The output ParticleList ``B0:Xee`` will match the inclusive ``B0 -> e+ e-`` decays (but neutrinos are
not included),
2375 in both cases of ``appendAllDaughters``
is false
and true.
2376 If the ``appendAllDaughters=
False``
as above example, the ``B0:Xee`` has only two electrons
as daughters.
2377 While,
if ``appendAllDaughters=
True``, all daughters of the matched MCParticles are appended. When the truth decay mode of
2378 the MCParticle
is ``B0 -> [K*0 -> K+ pi-] [J/psi -> e+ e-]``, the first daughter of ``B0:Xee``
is ``K*0``
and ``e+``
2379 will be the first daughter of second daughter of ``B0:Xee``.
2381 The option ``skipNonPrimaryDaughters`` only has an effect
if ``appendAllDaughters=
True``. If ``skipNonPrimaryDaughters=
True``,
2382 all primary daughters are appended but the secondary particles are
not.
2385 Daughters of ``Lambda0`` are
not primary, but ``Lambda0``
is not a final state particle.
2386 In order
for the MCMatching to work properly, the daughters of ``Lambda0`` are appended to
2387 ``Lambda0`` regardless of the value of the option ``skipNonPrimaryDaughters``.
2390 @param list_name The output particle list name
2391 @param decay The decay string which you want
2392 @param writeOut Whether `RootOutput` module should save the created ``outputList``
2393 @param skipNonPrimaryDaughters
if true, skip non primary daughters, useful to study final state daughter particles
2394 @param appendAllDaughters
if true,
not only the daughters described
in the decay string but all daughters are appended
2395 @param path modules are added to this path
2398 decayfinder = register_module('MCDecayFinder')
2399 decayfinder.set_name(
'MCDecayFinder_' + list_name)
2400 decayfinder.param(
'listName', list_name)
2401 decayfinder.param(
'decayString', decay)
2402 decayfinder.param(
'appendAllDaughters', appendAllDaughters)
2403 decayfinder.param(
'skipNonPrimaryDaughters', skipNonPrimaryDaughters)
2404 decayfinder.param(
'writeOut', writeOut)
2405 path.add_module(decayfinder)
2408def summaryOfLists(particleLists, outputFile=None, path=None):
2410 Prints out Particle statistics at the end of the job: number of events with at
2411 least one candidate, average number of candidates per event, etc.
2412 If an output file name
is provided the statistics
is also dumped into a json file
with that name.
2414 @param particleLists list of input ParticleLists
2415 @param outputFile output file name (
not created by default)
2418 particleStats = register_module('ParticleStats')
2419 particleStats.param(
'particleLists', particleLists)
2420 if outputFile
is not None:
2421 particleStats.param(
'outputFile', outputFile)
2422 path.add_module(particleStats)
2425def matchMCTruth(list_name, path):
2427 Performs MC matching (sets relation Particle->MCParticle) for
2428 all particles (
and its (grand)^N-daughter particles)
in the specified
2431 @param list_name name of the input ParticleList
2432 @param path modules are added to this path
2435 mcMatch = register_module('MCMatcherParticles')
2436 mcMatch.set_name(
'MCMatch_' + list_name)
2437 mcMatch.param(
'listName', list_name)
2438 path.add_module(mcMatch)
2441def looseMCTruth(list_name, path):
2443 Performs loose MC matching for all particles
in the specified
2445 The difference between loose
and normal mc matching algorithm
is that
2446 the loose algorithm will find the common mother of the majority of daughter
2447 particles
while the normal algorithm finds the common mother of all daughters.
2448 The results of loose mc matching algorithm are stored to the following extraInfo
2451 - looseMCMotherPDG: PDG code of most common mother
2452 - looseMCMotherIndex: 1-based StoreArray<MCParticle> index of most common mother
2453 - looseMCWrongDaughterN: number of daughters that don
't originate from the most common mother
2454 - looseMCWrongDaughterPDG: PDG code of the daughter that doesn't originate from the most common mother (only if
2455 looseMCWrongDaughterN = 1)
2456 - looseMCWrongDaughterBiB: 1 if the wrong daughter
is Beam Induced Background Particle
2458 @param list_name name of the input ParticleList
2459 @param path modules are added to this path
2462 mcMatch = register_module('MCMatcherParticles')
2463 mcMatch.set_name(
'LooseMCMatch_' + list_name)
2464 mcMatch.param(
'listName', list_name)
2465 mcMatch.param(
'looseMCMatching',
True)
2466 path.add_module(mcMatch)
2469def buildRestOfEvent(target_list_name, inputParticlelists=None,
2470 fillWithMostLikely=True,
2471 chargedPIDPriors=None, path=None):
2473 Creates for each Particle
in the given ParticleList a RestOfEvent
2474 dataobject
and makes basf2 relation between them. User can provide additional
2475 particle lists
with a different particle hypothesis like [
'K+:good, e+:good'], etc.
2477 @param target_list_name name of the input ParticleList
2478 @param inputParticlelists list of user-defined input particle list names, which serve
2479 as source of particles to build the ROE, the FSP particles
from
2480 target_list_name are automatically excluded
from the ROE object
2481 @param fillWithMostLikely By default the module uses the most likely particle mass hypothesis
for charged particles
2482 based on the PID likelihood. Turn this behavior off
if you want to configure your own
2483 input particle lists.
2484 @param chargedPIDPriors The prior PID fractions, that are used to regulate the
2485 amount of certain charged particle species, should be a list of
2486 six floats
if not None. The order of particle types
is
2487 the following: [e-, mu-, pi-, K-, p+, d+]
2488 @param path modules are added to this path
2491 if inputParticlelists
is None:
2492 inputParticlelists = []
2493 fillParticleList(
'pi+:all',
'', path=path)
2494 if fillWithMostLikely:
2495 from stdCharged
import stdMostLikely
2496 stdMostLikely(chargedPIDPriors,
'_roe', path=path)
2497 inputParticlelists = [f
'{ptype}:mostlikely_roe' for ptype
in [
'K+',
'p+',
'e+',
'mu+']]
2500 fillParticleList(
'gamma:all',
'', path=path)
2501 fillParticleList(
'K_L0:roe_default',
'isFromKLM > 0', path=path)
2502 inputParticlelists += [
'pi+:all',
'gamma:all',
'K_L0:roe_default']
2504 inputParticlelists += [
'pi+:all',
'gamma:mdst']
2505 roeBuilder = register_module(
'RestOfEventBuilder')
2506 roeBuilder.set_name(
'ROEBuilder_' + target_list_name)
2507 roeBuilder.param(
'particleList', target_list_name)
2508 roeBuilder.param(
'particleListsInput', inputParticlelists)
2509 roeBuilder.param(
'mostLikely', fillWithMostLikely)
2510 path.add_module(roeBuilder)
2513def buildNestedRestOfEvent(target_list_name, maskName='all', path=None):
2515 Creates for each Particle
in the given ParticleList a RestOfEvent
2516 @param target_list_name name of the input ParticleList
2517 @param mask_name name of the ROEMask to be used
2518 @param path modules are added to this path
2521 roeBuilder = register_module('RestOfEventBuilder')
2522 roeBuilder.set_name(
'NestedROEBuilder_' + target_list_name)
2523 roeBuilder.param(
'particleList', target_list_name)
2524 roeBuilder.param(
'nestedROEMask', maskName)
2525 roeBuilder.param(
'createNestedROE',
True)
2526 path.add_module(roeBuilder)
2529def buildRestOfEventFromMC(target_list_name, inputParticlelists=None, path=None):
2531 Creates for each Particle
in the given ParticleList a RestOfEvent
2532 @param target_list_name name of the input ParticleList
2533 @param inputParticlelists list of input particle list names, which serve
2534 as a source of particles to build ROE, the FSP particles
from
2535 target_list_name are excluded
from ROE object
2536 @param path modules are added to this path
2539 if inputParticlelists
is None:
2540 inputParticlelists = []
2541 if (len(inputParticlelists) == 0):
2545 types = [
'gamma',
'e+',
'mu+',
'pi+',
'K+',
'p+',
'K_L0',
2546 'n0',
'nu_e',
'nu_mu',
'nu_tau',
2549 fillParticleListFromMC(f
"{t}:roe_default_gen",
'mcPrimary > 0 and nDaughters == 0',
2550 True,
True, path=path)
2551 inputParticlelists += [f
"{t}:roe_default_gen"]
2552 roeBuilder = register_module(
'RestOfEventBuilder')
2553 roeBuilder.set_name(
'MCROEBuilder_' + target_list_name)
2554 roeBuilder.param(
'particleList', target_list_name)
2555 roeBuilder.param(
'particleListsInput', inputParticlelists)
2556 roeBuilder.param(
'fromMC',
True)
2557 path.add_module(roeBuilder)
2560def appendROEMask(list_name,
2563 eclClusterSelection,
2564 klmClusterSelection='',
2567 Loads the ROE object of a particle and creates a ROE mask
with a specific name. It applies
2568 selection criteria
for tracks
and eclClusters which will be used by variables
in ROEVariables.cc.
2570 - append a ROE mask
with all tracks
in ROE coming
from the IP region
2572 .. code-block:: python
2574 appendROEMask(
'B+:sig',
'IPtracks',
'[dr < 2] and [abs(dz) < 5]', path=mypath)
2576 - append a ROE mask
with only ECL-based particles that
pass as good photon candidates
2578 .. code-block:: python
2580 goodPhotons =
'inCDCAcceptance and clusterErrorTiming < 1e6 and [clusterE1E9 > 0.4 or E > 0.075]'
2581 appendROEMask(
'B+:sig',
'goodROEGamma',
'', goodPhotons, path=mypath)
2584 @param list_name name of the input ParticleList
2585 @param mask_name name of the appended ROEMask
2586 @param trackSelection decay string
for the track-based particles
in ROE
2587 @param eclClusterSelection decay string
for the ECL-based particles
in ROE
2588 @param klmClusterSelection decay string
for the KLM-based particles
in ROE
2589 @param path modules are added to this path
2592 roeMask = register_module('RestOfEventInterpreter')
2593 roeMask.set_name(
'RestOfEventInterpreter_' + list_name +
'_' + mask_name)
2594 roeMask.param(
'particleList', list_name)
2595 roeMask.param(
'ROEMasks', [(mask_name, trackSelection, eclClusterSelection, klmClusterSelection)])
2596 path.add_module(roeMask)
2599def appendROEMasks(list_name, mask_tuples, path=None):
2601 Loads the ROE object of a particle and creates a ROE mask
with a specific name. It applies
2602 selection criteria
for track-, ECL-
and KLM-based particles which will be used by ROE variables.
2604 The multiple ROE masks
with their own selection criteria are specified
2605 via list of tuples (mask_name, trackParticleSelection, eclParticleSelection, klmParticleSelection)
or
2606 (mask_name, trackSelection, eclClusterSelection)
in case
with fractions.
2608 - Example
for two tuples, one
with and one without fractions
2610 .. code-block:: python
2612 ipTracks = (
'IPtracks',
'[dr < 2] and [abs(dz) < 5]',
'',
'')
2613 goodPhotons =
'inCDCAcceptance and [clusterErrorTiming < 1e6] and [clusterE1E9 > 0.4 or E > 0.075]'
2614 goodROEGamma = (
'ROESel',
'[dr < 2] and [abs(dz) < 5]', goodPhotons,
'')
2615 goodROEKLM = (
'IPtracks',
'[dr < 2] and [abs(dz) < 5]',
'',
'nKLMClusterTrackMatches == 0')
2616 appendROEMasks(
'B+:sig', [ipTracks, goodROEGamma, goodROEKLM], path=mypath)
2618 @param list_name name of the input ParticleList
2619 @param mask_tuples array of ROEMask list tuples to be appended
2620 @param path modules are added to this path
2623 compatible_masks = []
2624 for mask
in mask_tuples:
2627 compatible_masks += [(*mask,
'')]
2629 compatible_masks += [mask]
2630 roeMask = register_module(
'RestOfEventInterpreter')
2631 roeMask.set_name(
'RestOfEventInterpreter_' + list_name +
'_' +
'MaskList')
2632 roeMask.param(
'particleList', list_name)
2633 roeMask.param(
'ROEMasks', compatible_masks)
2634 path.add_module(roeMask)
2637def updateROEMask(list_name,
2640 eclClusterSelection='',
2641 klmClusterSelection='',
2644 Update an existing ROE mask by applying additional selection cuts for
2645 tracks
and/
or clusters.
2647 See function `appendROEMask`!
2649 @param list_name name of the input ParticleList
2650 @param mask_name name of the ROEMask to update
2651 @param trackSelection decay string
for the track-based particles
in ROE
2652 @param eclClusterSelection decay string
for the ECL-based particles
in ROE
2653 @param klmClusterSelection decay string
for the KLM-based particles
in ROE
2654 @param path modules are added to this path
2657 roeMask = register_module('RestOfEventInterpreter')
2658 roeMask.set_name(
'RestOfEventInterpreter_' + list_name +
'_' + mask_name)
2659 roeMask.param(
'particleList', list_name)
2660 roeMask.param(
'ROEMasks', [(mask_name, trackSelection, eclClusterSelection, klmClusterSelection)])
2661 roeMask.param(
'update',
True)
2662 path.add_module(roeMask)
2665def updateROEMasks(list_name, mask_tuples, path):
2667 Update existing ROE masks by applying additional selection cuts for tracks
2670 The multiple ROE masks
with their own selection criteria are specified
2671 via list tuples (mask_name, trackSelection, eclClusterSelection, klmClusterSelection)
2673 See function `appendROEMasks`!
2675 @param list_name name of the input ParticleList
2676 @param mask_tuples array of ROEMask list tuples to be appended
2677 @param path modules are added to this path
2680 compatible_masks = []
2681 for mask
in mask_tuples:
2684 compatible_masks += [(*mask,
'')]
2686 compatible_masks += [mask]
2688 roeMask = register_module(
'RestOfEventInterpreter')
2689 roeMask.set_name(
'RestOfEventInterpreter_' + list_name +
'_' +
'MaskList')
2690 roeMask.param(
'particleList', list_name)
2691 roeMask.param(
'ROEMasks', compatible_masks)
2692 roeMask.param(
'update',
True)
2693 path.add_module(roeMask)
2696def keepInROEMasks(list_name, mask_names, cut_string, path=None):
2698 This function is used to apply particle list specific cuts on one
or more ROE masks (track
or eclCluster).
2699 With this function one can KEEP the tracks/eclclusters used
in particles
from provided particle list.
2700 This function should be executed only
in the for_each roe path
for the current ROE object.
2702 To avoid unnecessary computation, the input particle list should only contain particles
from ROE
2703 (use cut
'isInRestOfEvent == 1'). To update the ECLCluster masks, the input particle list should be a photon
2704 particle list (e.g.
'gamma:someLabel'). To update the Track masks, the input particle list should be a charged
2705 pion particle list (e.g.
'pi+:someLabel').
2707 Updating a non-existing mask will create a new one.
2709 - keep only those tracks that were used
in provided particle list
2711 .. code-block:: python
2713 keepInROEMasks(
'pi+:goodTracks',
'mask',
'', path=mypath)
2715 - keep only those clusters that were used
in provided particle list
and pass a cut, apply to several masks
2717 .. code-block:: python
2719 keepInROEMasks(
'gamma:goodClusters', [
'mask1',
'mask2'],
'E > 0.1', path=mypath)
2722 @param list_name name of the input ParticleList
2723 @param mask_names array of ROEMasks to be updated
2724 @param cut_string decay string
with which the mask will be updated
2725 @param path modules are added to this path
2728 updateMask = register_module('RestOfEventUpdater')
2729 updateMask.set_name(
'RestOfEventUpdater_' + list_name +
'_masks')
2730 updateMask.param(
'particleList', list_name)
2731 updateMask.param(
'updateMasks', mask_names)
2732 updateMask.param(
'cutString', cut_string)
2733 updateMask.param(
'discard',
False)
2734 path.add_module(updateMask)
2737def discardFromROEMasks(list_name, mask_names, cut_string, path=None):
2739 This function is used to apply particle list specific cuts on one
or more ROE masks (track
or eclCluster).
2740 With this function one can DISCARD the tracks/eclclusters used
in particles
from provided particle list.
2741 This function should be executed only
in the for_each roe path
for the current ROE object.
2743 To avoid unnecessary computation, the input particle list should only contain particles
from ROE
2744 (use cut
'isInRestOfEvent == 1'). To update the ECLCluster masks, the input particle list should be a photon
2745 particle list (e.g.
'gamma:someLabel'). To update the Track masks, the input particle list should be a charged
2746 pion particle list (e.g.
'pi+:someLabel').
2748 Updating a non-existing mask will create a new one.
2750 - discard tracks that were used
in provided particle list
2752 .. code-block:: python
2754 discardFromROEMasks(
'pi+:badTracks',
'mask',
'', path=mypath)
2756 - discard clusters that were used
in provided particle list
and pass a cut, apply to several masks
2758 .. code-block:: python
2760 discardFromROEMasks(
'gamma:badClusters', [
'mask1',
'mask2'],
'E < 0.1', path=mypath)
2763 @param list_name name of the input ParticleList
2764 @param mask_names array of ROEMasks to be updated
2765 @param cut_string decay string
with which the mask will be updated
2766 @param path modules are added to this path
2769 updateMask = register_module('RestOfEventUpdater')
2770 updateMask.set_name(
'RestOfEventUpdater_' + list_name +
'_masks')
2771 updateMask.param(
'particleList', list_name)
2772 updateMask.param(
'updateMasks', mask_names)
2773 updateMask.param(
'cutString', cut_string)
2774 updateMask.param(
'discard',
True)
2775 path.add_module(updateMask)
2778def optimizeROEWithV0(list_name, mask_names, cut_string, path=None):
2780 This function is used to apply particle list specific cuts on one
or more ROE masks
for Tracks.
2781 It
is possible to optimize the ROE selection by treating tracks
from V0
's separately, meaning,
2782 taking V0's 4-momentum into account instead of 4-momenta of tracks. A cut for only specific V0's
2783 passing it can be applied.
2785 The input particle list should be a V0 particle list: K_S0 (
'K_S0:someLabel',
''),
2786 Lambda (
'Lambda:someLabel',
'')
or converted photons (
'gamma:someLabel').
2788 Updating a non-existing mask will create a new one.
2790 - treat tracks
from K_S0 inside mass window separately, replace track momenta
with K_S0 momentum
2792 .. code-block:: python
2794 optimizeROEWithV0(
'K_S0:opt',
'mask',
'0.450 < M < 0.550', path=mypath)
2796 @param list_name name of the input ParticleList
2797 @param mask_names array of ROEMasks to be updated
2798 @param cut_string decay string
with which the mask will be updated
2799 @param path modules are added to this path
2802 updateMask = register_module('RestOfEventUpdater')
2803 updateMask.set_name(
'RestOfEventUpdater_' + list_name +
'_masks')
2804 updateMask.param(
'particleList', list_name)
2805 updateMask.param(
'updateMasks', mask_names)
2806 updateMask.param(
'cutString', cut_string)
2807 path.add_module(updateMask)
2810def updateROEUsingV0Lists(target_particle_list, mask_names, default_cleanup=True, selection_cuts=None,
2811 apply_mass_fit=False, fitter='treefit', path=None):
2813 This function creates V0 particle lists (photons, :math:`K^0_S` and :math:`\\Lambda^0`)
2814 and it uses V0 candidates to update the Rest Of Event, which
is associated to the target particle list.
2815 It
is possible to apply a standard
or customized selection
and mass fit to the V0 candidates.
2818 @param target_particle_list name of the input ParticleList
2819 @param mask_names array of ROE masks to be applied
2820 @param default_cleanup
if True, predefined cuts will be applied on the V0 lists
2821 @param selection_cuts a single string of selection cuts
or tuple of three strings (photon_cuts, K_S0_cuts, Lambda0_cuts),
2822 which will be applied to the V0 lists. These cuts will have a priority over the default ones.
2823 @param apply_mass_fit
if True, a mass fit will be applied to the V0 particles
2824 @param fitter string, that represent a fitter choice:
"treefit" for TreeFitter
and "kfit" for KFit
2825 @param path modules are added to this path
2828 roe_path = create_path()
2829 deadEndPath = create_path()
2830 signalSideParticleFilter(target_particle_list, '', roe_path, deadEndPath)
2832 if (default_cleanup
and selection_cuts
is None):
2833 B2INFO(
"Using default cleanup in updateROEUsingV0Lists.")
2834 selection_cuts =
'abs(dM) < 0.1 '
2835 selection_cuts +=
'and daughter(0,particleID) > 0.2 and daughter(1,particleID) > 0.2 '
2836 selection_cuts +=
'and daughter(0,thetaInCDCAcceptance) and daughter(1,thetaInCDCAcceptance)'
2837 if (selection_cuts
is None or selection_cuts ==
''):
2838 B2INFO(
"No cleanup in updateROEUsingV0Lists.")
2839 selection_cuts = (
'True',
'True',
'True')
2840 if (isinstance(selection_cuts, str)):
2841 selection_cuts = (selection_cuts, selection_cuts, selection_cuts)
2843 roe_cuts =
'isInRestOfEvent > 0'
2844 fillConvertedPhotonsList(
'gamma:v0_roe -> e+ e-', f
'{selection_cuts[0]} and {roe_cuts}',
2846 fillParticleList(
'K_S0:v0_roe -> pi+ pi-', f
'{selection_cuts[1]} and {roe_cuts}',
2848 fillParticleList(
'Lambda0:v0_roe -> p+ pi-', f
'{selection_cuts[2]} and {roe_cuts}',
2850 fitter = fitter.lower()
2851 if (fitter !=
'treefit' and fitter !=
'kfit'):
2852 B2WARNING(
'Argument "fitter" in updateROEUsingV0Lists has only "treefit" and "kfit" options, '
2853 f
'but "{fitter}" was provided! TreeFitter will be used instead.')
2855 from vertex
import kFit, treeFit
2856 for v0
in [
'gamma:v0_roe',
'K_S0:v0_roe',
'Lambda0:v0_roe']:
2857 if (apply_mass_fit
and fitter ==
'kfit'):
2858 kFit(v0, conf_level=0.0, fit_type=
'massvertex', path=roe_path)
2859 if (apply_mass_fit
and fitter ==
'treefit'):
2860 treeFit(v0, conf_level=0.0, massConstraint=[v0.split(
':')[0]], path=roe_path)
2861 optimizeROEWithV0(v0, mask_names,
'', path=roe_path)
2862 path.for_each(
'RestOfEvent',
'RestOfEvents', roe_path)
2865def printROEInfo(mask_names=None, full_print=False,
2866 unpackComposites=True, path=None):
2868 This function prints out the information for the current ROE, so it should only be used
in the for_each path.
2869 It prints out basic ROE object info.
2871 If mask names are provided, specific information
for those masks will be printed out.
2873 It
is also possible to
print out all particles
in a given mask
if the
2874 'full_print' is set to
True.
2876 @param mask_names array of ROEMask names
for printing out info
2877 @param unpackComposites
if true, replace composite particles by their daughters
2878 @param full_print
print out particles
in mask
2879 @param path modules are added to this path
2882 if mask_names
is None:
2884 printMask = register_module(
'RestOfEventPrinter')
2885 printMask.set_name(
'RestOfEventPrinter')
2886 printMask.param(
'maskNames', mask_names)
2887 printMask.param(
'fullPrint', full_print)
2888 printMask.param(
'unpackComposites', unpackComposites)
2889 path.add_module(printMask)
2892def buildContinuumSuppression(list_name, roe_mask, path):
2894 Creates for each Particle
in the given ParticleList a ContinuumSuppression
2895 dataobject
and makes basf2 relation between them.
2897 :param list_name: name of the input ParticleList
2898 :param roe_mask: name of the ROE mask
2899 :param path: modules are added to this path
2902 qqBuilder = register_module('ContinuumSuppressionBuilder')
2903 qqBuilder.set_name(
'QQBuilder_' + list_name)
2904 qqBuilder.param(
'particleList', list_name)
2905 qqBuilder.param(
'ROEMask', roe_mask)
2906 path.add_module(qqBuilder)
2911 Removes all Particles that are not in a given list of ParticleLists (
or daughters of those).
2912 All relations
from/to Particles, daughter indices,
and other ParticleLists are fixed.
2914 @param lists_to_keep Keep the Particles
and their daughters
in these ParticleLists.
2915 @param path modules are added to this path
2918 mod = register_module('RemoveParticlesNotInLists')
2919 mod.param(
'particleLists', lists_to_keep)
2920 path.add_module(mod)
2923def inclusiveBtagReconstruction(upsilon_list_name, bsig_list_name, btag_list_name, input_lists_names, path):
2925 Reconstructs Btag from particles
in given ParticleLists which do
not share any final state particles (mdstSource)
with Bsig.
2927 @param upsilon_list_name Name of the ParticleList to be filled
with 'Upsilon(4S) -> B:sig anti-B:tag'
2928 @param bsig_list_name Name of the Bsig ParticleList
2929 @param btag_list_name Name of the Bsig ParticleList
2930 @param input_lists_names List of names of the ParticleLists which are used to reconstruct Btag
from
2933 btag = register_module('InclusiveBtagReconstruction')
2934 btag.set_name(
'InclusiveBtagReconstruction_' + bsig_list_name)
2935 btag.param(
'upsilonListName', upsilon_list_name)
2936 btag.param(
'bsigListName', bsig_list_name)
2937 btag.param(
'btagListName', btag_list_name)
2938 btag.param(
'inputListsNames', input_lists_names)
2939 path.add_module(btag)
2942def selectDaughters(particle_list_name, decay_string, path):
2944 Redefine the Daughters of a particle: select from decayString
2946 @param particle_list_name input particle list
2947 @param decay_string
for selecting the Daughters to be preserved
2950 seld = register_module('SelectDaughters')
2951 seld.set_name(
'SelectDaughters_' + particle_list_name)
2952 seld.param(
'listName', particle_list_name)
2953 seld.param(
'decayString', decay_string)
2954 path.add_module(seld)
2957def markDuplicate(particleList, prioritiseV0, path):
2959 Call DuplicateVertexMarker to find duplicate particles in a list
and
2960 flag the ones that should be kept
2962 @param particleList input particle list
2963 @param prioritiseV0
if true, give V0s a higher priority
2966 markdup = register_module('DuplicateVertexMarker')
2967 markdup.param(
'particleList', particleList)
2968 markdup.param(
'prioritiseV0', prioritiseV0)
2969 path.add_module(markdup)
2972PI0ETAVETO_COUNTER = 0
2975def oldwritePi0EtaVeto(
2978 workingDirectory='.',
2979 pi0vetoname='Pi0_Prob',
2980 etavetoname='Eta_Prob',
2986 Give pi0/eta probability for hard photon.
2988 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.
2990 The current default weight files are optimised using MC9.
2991 The input variables are
as below. Aliases are set to some variables during training.
2993 * M: pi0/eta candidates Invariant mass
2994 * lowE: soft photon energy
in lab frame
2995 * cTheta: soft photon ECL cluster
's polar angle
2996 * Zmva: soft photon output of MVA using Zernike moments of the cluster
2997 * minC2Hdist: soft photon distance from eclCluster to nearest point on nearest Helix at the ECL cylindrical radius
2999 If you don
't have weight files in your workingDirectory,
3000 these files are downloaded from database to your workingDirectory automatically.
3001 Please refer to analysis/examples/tutorials/B2A306-B02RhoGamma-withPi0EtaVeto.py
3002 about how to use this function.
3005 Please don
't use following ParticleList names elsewhere:
3007 ``gamma:HARDPHOTON``, ``pi0:PI0VETO``, ``eta:ETAVETO``,
3008 ``gamma:PI0SOFT + str(PI0ETAVETO_COUNTER)``, ``gamma:ETASOFT + str(PI0ETAVETO_COUNTER)``
3010 Please don't use ``lowE``, ``cTheta``, ``Zmva``, ``minC2Hdist`` as alias elsewhere.
3012 @param particleList The input ParticleList
3013 @param decayString specify Particle to be added to the ParticleList
3014 @param workingDirectory The weight file directory
3015 @param downloadFlag whether download default weight files
or not
3016 @param pi0vetoname extraInfo name of pi0 probability
3017 @param etavetoname extraInfo name of eta probability
3018 @param selection Selection criteria that Particle needs meet
in order
for for_each ROE path to
continue
3019 @param path modules are added to this path
3024 B2ERROR(
"The old pi0 / eta veto is not suitable for Belle analyses.")
3029 global PI0ETAVETO_COUNTER
3031 if PI0ETAVETO_COUNTER == 0:
3032 from variables
import variables
3033 variables.addAlias(
'lowE',
'daughter(1,E)')
3034 variables.addAlias(
'cTheta',
'daughter(1,clusterTheta)')
3035 variables.addAlias(
'Zmva',
'daughter(1,clusterZernikeMVA)')
3036 variables.addAlias(
'minC2Tdist',
'daughter(1,minC2TDist)')
3037 variables.addAlias(
'cluNHits',
'daughter(1,clusterNHits)')
3038 variables.addAlias(
'E9E21',
'daughter(1,clusterE9E21)')
3040 PI0ETAVETO_COUNTER = PI0ETAVETO_COUNTER + 1
3042 roe_path = create_path()
3044 deadEndPath = create_path()
3046 signalSideParticleFilter(particleList, selection, roe_path, deadEndPath)
3048 fillSignalSideParticleList(
'gamma:HARDPHOTON', decayString, path=roe_path)
3050 pi0softname =
'gamma:PI0SOFT'
3051 etasoftname =
'gamma:ETASOFT'
3052 softphoton1 = pi0softname + str(PI0ETAVETO_COUNTER)
3053 softphoton2 = etasoftname + str(PI0ETAVETO_COUNTER)
3057 '[clusterReg==1 and E>0.025] or [clusterReg==2 and E>0.02] or [clusterReg==3 and E>0.02]',
3059 applyCuts(softphoton1,
'abs(clusterTiming)<120', path=roe_path)
3062 '[clusterReg==1 and E>0.035] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.03]',
3064 applyCuts(softphoton2,
'abs(clusterTiming)<120', path=roe_path)
3066 reconstructDecay(
'pi0:PI0VETO -> gamma:HARDPHOTON ' + softphoton1,
'', path=roe_path)
3067 reconstructDecay(
'eta:ETAVETO -> gamma:HARDPHOTON ' + softphoton2,
'', path=roe_path)
3069 if not os.path.isdir(workingDirectory):
3070 os.mkdir(workingDirectory)
3071 B2INFO(
'oldwritePi0EtaVeto: ' + workingDirectory +
' has been created as workingDirectory.')
3073 if not os.path.isfile(workingDirectory +
'/pi0veto.root'):
3075 basf2_mva.download(
'Pi0VetoIdentifier', workingDirectory +
'/pi0veto.root')
3076 B2INFO(
'oldwritePi0EtaVeto: pi0veto.root has been downloaded from database to workingDirectory.')
3078 if not os.path.isfile(workingDirectory +
'/etaveto.root'):
3080 basf2_mva.download(
'EtaVetoIdentifier', workingDirectory +
'/etaveto.root')
3081 B2INFO(
'oldwritePi0EtaVeto: etaveto.root has been downloaded from database to workingDirectory.')
3083 roe_path.add_module(
'MVAExpert', listNames=[
'pi0:PI0VETO'], extraInfoName=
'Pi0Veto',
3084 identifier=workingDirectory +
'/pi0veto.root')
3085 roe_path.add_module(
'MVAExpert', listNames=[
'eta:ETAVETO'], extraInfoName=
'EtaVeto',
3086 identifier=workingDirectory +
'/etaveto.root')
3088 rankByHighest(
'pi0:PI0VETO',
'extraInfo(Pi0Veto)', numBest=1, path=roe_path)
3089 rankByHighest(
'eta:ETAVETO',
'extraInfo(EtaVeto)', numBest=1, path=roe_path)
3091 variableToSignalSideExtraInfo(
'pi0:PI0VETO', {
'extraInfo(Pi0Veto)': pi0vetoname}, path=roe_path)
3092 variableToSignalSideExtraInfo(
'eta:ETAVETO', {
'extraInfo(EtaVeto)': etavetoname}, path=roe_path)
3094 path.for_each(
'RestOfEvent',
'RestOfEvents', roe_path)
3104 hardParticle='gamma',
3105 pi0PayloadNameOverride=None,
3106 pi0SoftPhotonCutOverride=None,
3107 etaPayloadNameOverride=None,
3108 etaSoftPhotonCutOverride=None
3111 Give pi0/eta probability for hard photon.
3113 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.
3115 The current default weight files are optimised using MC12.
3117 The input variables of the mva training are:
3119 * M: pi0/eta candidates Invariant mass
3120 * daughter(1,E): soft photon energy
in lab frame
3121 * daughter(1,clusterTheta): soft photon ECL cluster
's polar angle
3122 * daughter(1,minC2TDist): soft photon distance from eclCluster to nearest point on nearest Helix at the ECL cylindrical radius
3123 * daughter(1,clusterZernikeMVA): soft photon output of MVA using Zernike moments of the cluster
3124 * daughter(1,clusterNHits): soft photon total crystal weights sum(w_i)
with w_i<=1
3125 * daughter(1,clusterE9E21): soft photon ratio of energies
in inner 3x3 crystals
and 5x5 crystals without corners
3126 * cosHelicityAngleMomentum: pi0/eta candidates cosHelicityAngleMomentum
3128 The following strings are available
for mode:
3130 * standard: loose energy cut
and no clusterNHits cut are applied to soft photon
3131 * tight: tight energy cut
and no clusterNHits cut are applied to soft photon
3132 * cluster: loose energy cut
and clusterNHits cut are applied to soft photon
3133 * both: tight energy cut
and clusterNHits cut are applied to soft photon
3135 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
3136 `pi0Prob`/`etaProb`. Otherwise, it
is available
as '{Pi0, Eta}ProbOrigin',
'{Pi0, Eta}ProbTightEnergyThreshold',
'{Pi0,
3137 Eta}ProbLargeClusterSize', or '{Pi0, Eta}ProbTightEnergyThresholdAndLargeClusterSize
'} for the four modes described above, with
3138 the chosen suffix appended.
3141 Please don't use following ParticleList names elsewhere:
3143 ``gamma:HardPhoton``,
3144 ``gamma:Pi0Soft + ListName + '_' + particleList.replace(
':',
'_')``,
3145 ``gamma:EtaSoft + ListName +
'_' + particleList.replace(
':',
'_')``,
3146 ``pi0:EtaVeto + ListName``,
3147 ``eta:EtaVeto + ListName``
3149 @param particleList the input ParticleList
3150 @param decayString specify Particle to be added to the ParticleList
3151 @param mode choose one mode out of
'standard',
'tight',
'cluster' and 'both'
3152 @param selection selection criteria that Particle needs meet
in order
for for_each ROE path to
continue
3153 @param path modules are added to this path
3154 @param suffix optional suffix to be appended to the usual extraInfo name
3155 @param hardParticle particle name which
is used to calculate the pi0/eta probability (default
is gamma)
3156 @param pi0PayloadNameOverride specify the payload name of pi0 veto only
if one wants to use non-default one. (default
is None)
3157 @param pi0SoftPhotonCutOverride specify the soft photon selection criteria of pi0 veto only
if one wants to use non-default one.
3159 @param etaPayloadNameOverride specify the payload name of eta veto only
if one wants to use non-default one. (default
is None)
3160 @param etaSoftPhotonCutOverride specify the soft photon selection criteria of eta veto only
if one wants to use non-default one.
3166 B2ERROR(
"The pi0 / eta veto is not suitable for Belle analyses.")
3168 renameSuffix =
False
3170 for module
in path.modules():
3171 if module.type() ==
"SubEvent" and not renameSuffix:
3172 for subpath
in [p.values
for p
in module.available_params()
if p.name ==
"path"]:
3175 for submodule
in subpath.modules():
3176 if f
'{hardParticle}:HardPhoton{suffix}' in submodule.name():
3178 B2WARNING(
"Same extension already used in writePi0EtaVeto, append '_0'")
3182 roe_path = create_path()
3183 deadEndPath = create_path()
3184 signalSideParticleFilter(particleList, selection, roe_path, deadEndPath)
3185 fillSignalSideParticleList(f
'{hardParticle}:HardPhoton{suffix}', decayString, path=roe_path)
3187 dictListName = {
'standard':
'Origin',
3188 'tight':
'TightEnergyThreshold',
3189 'cluster':
'LargeClusterSize',
3190 'both':
'TightEnrgyThresholdAndLargeClusterSize'}
3192 dictPi0EnergyCut = {
'standard':
'[[clusterReg==1 and E>0.025] or [clusterReg==2 and E>0.02] or [clusterReg==3 and E>0.02]]',
3193 'tight':
'[[clusterReg==1 and E>0.03] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.04]]',
3194 'cluster':
'[[clusterReg==1 and E>0.025] or [clusterReg==2 and E>0.02] or [clusterReg==3 and E>0.02]]',
3195 'both':
'[[clusterReg==1 and E>0.03] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.04]]'}
3197 dictEtaEnergyCut = {
'standard':
'[[clusterReg==1 and E>0.035] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.03]]',
3198 'tight':
'[[clusterReg==1 and E>0.06] or [clusterReg==2 and E>0.06] or [clusterReg==3 and E>0.06]]',
3199 'cluster':
'[[clusterReg==1 and E>0.035] or [clusterReg==2 and E>0.03] or [clusterReg==3 and E>0.03]]',
3200 'both':
'[[clusterReg==1 and E>0.06] or [clusterReg==2 and E>0.06] or [clusterReg==3 and E>0.06]]'}
3202 dictNHitsCut = {
'standard':
'clusterNHits >= 0',
3203 'tight':
'clusterNHits >= 0',
3204 'cluster':
'clusterNHits >= 2',
3205 'both':
'clusterNHits >= 2'}
3207 dictPi0PayloadName = {
'standard':
'Pi0VetoIdentifierStandard',
3208 'tight':
'Pi0VetoIdentifierWithHigherEnergyThreshold',
3209 'cluster':
'Pi0VetoIdentifierWithLargerClusterSize',
3210 'both':
'Pi0VetoIdentifierWithHigherEnergyThresholdAndLargerClusterSize'}
3212 dictEtaPayloadName = {
'standard':
'EtaVetoIdentifierStandard',
3213 'tight':
'EtaVetoIdentifierWithHigherEnergyThreshold',
3214 'cluster':
'EtaVetoIdentifierWithLargerClusterSize',
3215 'both':
'EtaVetoIdentifierWithHigherEnergyThresholdAndLargerClusterSize'}
3217 dictPi0ExtraInfoName = {
'standard':
'Pi0ProbOrigin',
3218 'tight':
'Pi0ProbTightEnergyThreshold',
3219 'cluster':
'Pi0ProbLargeClusterSize',
3220 'both':
'Pi0ProbTightEnergyThresholdAndLargeClusterSize'}
3222 dictEtaExtraInfoName = {
'standard':
'EtaProbOrigin',
3223 'tight':
'EtaProbTightEnergyThreshold',
3224 'cluster':
'EtaProbLargeClusterSize',
3225 'both':
'EtaProbTightEnergyThresholdAndLargeClusterSize'}
3227 ListName = dictListName[mode]
3228 Pi0EnergyCut = dictPi0EnergyCut[mode]
3229 EtaEnergyCut = dictEtaEnergyCut[mode]
3230 TimingCut =
'abs(clusterTiming)<clusterErrorTiming'
3231 NHitsCut = dictNHitsCut[mode]
3232 Pi0PayloadName = dictPi0PayloadName[mode]
3233 EtaPayloadName = dictEtaPayloadName[mode]
3234 Pi0ExtraInfoName = dictPi0ExtraInfoName[mode]
3235 EtaExtraInfoName = dictEtaExtraInfoName[mode]
3238 if pi0PayloadNameOverride
is not None:
3239 Pi0PayloadName = pi0PayloadNameOverride
3240 if pi0SoftPhotonCutOverride
is None:
3241 Pi0SoftPhotonCut = Pi0EnergyCut +
' and ' + NHitsCut
3245 Pi0SoftPhotonCut +=
' and ' + TimingCut
3247 Pi0SoftPhotonCut = pi0SoftPhotonCutOverride
3250 pi0soft = f
'gamma:Pi0Soft{suffix}' + ListName +
'_' + particleList.replace(
':',
'_')
3252 fillParticleList(pi0soft, Pi0SoftPhotonCut, path=roe_path)
3254 reconstructDecay(
'pi0:Pi0Veto' + ListName + f
' -> {hardParticle}:HardPhoton{suffix} ' + pi0soft,
'',
3255 allowChargeViolation=
True, path=roe_path)
3257 roe_path.add_module(
'MVAExpert', listNames=[
'pi0:Pi0Veto' + ListName],
3258 extraInfoName=Pi0ExtraInfoName, identifier=Pi0PayloadName)
3260 rankByHighest(
'pi0:Pi0Veto' + ListName,
'extraInfo(' + Pi0ExtraInfoName +
')', numBest=1, path=roe_path)
3262 variableToSignalSideExtraInfo(
'pi0:Pi0Veto' + ListName,
3263 {
'extraInfo(' + Pi0ExtraInfoName +
')': Pi0ExtraInfoName + suffix}, path=roe_path)
3266 if etaPayloadNameOverride
is not None:
3267 EtaPayloadName = etaPayloadNameOverride
3268 if etaSoftPhotonCutOverride
is None:
3269 EtaSoftPhotonCut = EtaEnergyCut +
' and ' + NHitsCut
3273 EtaSoftPhotonCut +=
' and ' + TimingCut
3275 EtaSoftPhotonCut = etaSoftPhotonCutOverride
3277 etasoft = f
'gamma:EtaSoft{suffix}' + ListName +
'_' + particleList.replace(
':',
'_')
3278 fillParticleList(etasoft, EtaSoftPhotonCut, path=roe_path)
3279 reconstructDecay(
'eta:EtaVeto' + ListName + f
' -> {hardParticle}:HardPhoton{suffix} ' + etasoft,
'',
3280 allowChargeViolation=
True, path=roe_path)
3281 roe_path.add_module(
'MVAExpert', listNames=[
'eta:EtaVeto' + ListName],
3282 extraInfoName=EtaExtraInfoName, identifier=EtaPayloadName)
3283 rankByHighest(
'eta:EtaVeto' + ListName,
'extraInfo(' + EtaExtraInfoName +
')', numBest=1, path=roe_path)
3284 variableToSignalSideExtraInfo(
'eta:EtaVeto' + ListName,
3285 {
'extraInfo(' + EtaExtraInfoName +
')': EtaExtraInfoName + suffix}, path=roe_path)
3287 path.for_each(
'RestOfEvent',
'RestOfEvents', roe_path)
3290def lowEnergyPi0Identification(pi0List, gammaList, payloadNameSuffix,
3293 Calculate low-energy pi0 identification.
3294 The result is stored
as ExtraInfo ``lowEnergyPi0Identification``
for
3298 pi0List (str): Pi0 list.
3300 gammaList (str): Gamma list. First, an energy cut E > 0.2
is applied to the photons
from this list.
3301 Then, all possible combinations
with a pi0 daughter photon are formed
except the one
3302 corresponding to the reconstructed pi0.
3303 The maximum low-energy pi0 veto value
is calculated
for such photon pairs
3304 and used
as one of the input variables
for the identification classifier.
3306 payloadNameSuffix (str): Payload name suffix. The weight payloads are stored
in the analysis
global
3307 tag
and have the following names:\n
3308 * ``
'LowEnergyPi0Veto' + payloadNameSuffix``
3309 * ``
'LowEnergyPi0Identification' + payloadNameSuffix``\n
3310 The possible suffixes are:\n
3311 * ``
'Belle1'``
for Belle data.
3312 * ``
'Belle2Release5'``
for Belle II release 5 data (MC14, proc12, buckets 16 - 25).
3313 * ``
'Belle2Release6'``
for Belle II release 6 data (MC15, proc13, buckets 26 - 36).
3315 path (basf2.Path): Module path.
3319 gammaListVeto = f
'{gammaList}_pi0veto'
3320 cutAndCopyList(gammaListVeto, gammaList,
'E > 0.2', path=path)
3322 payload_name =
'LowEnergyPi0Veto' + payloadNameSuffix
3323 path.add_module(
'LowEnergyPi0VetoExpert', identifier=payload_name,
3324 VetoPi0Daughters=
True, GammaListName=gammaListVeto,
3326 payload_name =
'LowEnergyPi0Identification' + payloadNameSuffix
3327 path.add_module(
'LowEnergyPi0IdentificationExpert',
3328 identifier=payload_name, Pi0ListName=pi0List,
3332def getNeutralHadronGeomMatches(
3336 efficiencyCorrectionKl=0.83,
3337 efficiencyCorrectionNeutrons=1.0,
3340 For an ECL-based list, assign the mcdistanceKL and mcdistanceNeutron variables that correspond
3341 to the distance to the closest MC KL
and neutron, respectively.
3342 @param particleLists the input ParticleLists, must be ECL-based lists (e.g. photons)
3343 @param addKL (default
True) add distance to MC KL
3344 @param addNeutrons (default
False) add distance to MC neutrons
3345 @param efficiencyCorrectionKl (default 0.83) apply overall efficiency correction
3346 @param efficiencyCorrectionNeutrons (default 1.0) apply overall efficiency correction
3347 @param path modules are added to this path
3349 from ROOT
import Belle2
3354 "NeutralHadronMatcher",
3355 particleLists=particleLists,
3356 mcPDGcode=Const.Klong.getPDGCode(),
3357 efficiencyCorrection=efficiencyCorrectionKl)
3360 "NeutralHadronMatcher",
3361 particleLists=particleLists,
3362 mcPDGcode=Const.neutron.getPDGCode(),
3363 efficiencyCorrection=efficiencyCorrectionNeutrons)
3366def getBeamBackgroundProbability(particleList, weight, path=None):
3368 Assign a probability to each ECL cluster as being signal like (1) compared to beam background like (0)
3369 @param particleList the input ParticleList, must be a photon list
3370 @param weight type of weight file to use
3371 @param path modules are added to this path
3376 B2WARNING(
"weight type must be 'Belle' for b2bii.")
3378 path.add_module(
'MVAExpert',
3379 listNames=particleList,
3380 extraInfoName=
'beamBackgroundSuppression',
3381 identifier=f
'BeamBackgroundMVA_{weight}')
3384def getFakePhotonProbability(particleList, weight, path=None):
3386 Assign a probability to each ECL cluster as being signal like (1) compared to fake photon like (0)
3387 @param particleList the input ParticleList, must be a photon list
3388 @param weight type of weight file to use
3389 @param path modules are added to this path
3394 B2WARNING(
"weight type must be 'Belle' for b2bii.")
3396 path.add_module(
'MVAExpert',
3397 listNames=particleList,
3398 extraInfoName=
'fakePhotonSuppression',
3399 identifier=f
'FakePhotonMVA_{weight}')
3402def buildEventKinematics(inputListNames=None, default_cleanup=True, custom_cuts=None,
3403 chargedPIDPriors=None, fillWithMostLikely=False, path=None):
3405 Calculates the global kinematics of the event (visible energy, missing momentum, missing mass...)
3406 using ParticleLists provided. If no ParticleList
is provided, default ParticleLists are used
3407 (all track
and all hits
in ECL without associated track).
3409 The visible energy missing values are
3410 stored
in a EventKinematics dataobject.
3412 @param inputListNames list of ParticleLists used to calculate the
global event kinematics.
3413 If the list
is empty, default ParticleLists pi+:evtkin
and gamma:evtkin are filled.
3414 @param fillWithMostLikely
if True, the module uses the most likely particle mass hypothesis
for charged particles
3415 according to the PID likelihood
and the option inputListNames will be ignored.
3416 @param chargedPIDPriors The prior PID fractions, that are used to regulate
3417 amount of certain charged particle species, should be a list of
3418 six floats
if not None. The order of particle types
is
3419 the following: [e-, mu-, pi-, K-, p+, d+]
3420 @param default_cleanup
if True and either inputListNames empty
or fillWithMostLikely
True, default clean up cuts are applied
3421 @param custom_cuts tuple of selection cut strings of form (trackCuts, photonCuts), default
is None,
3422 which would result
in a standard predefined selection cuts
3423 @param path modules are added to this path
3426 if inputListNames
is None:
3428 trackCuts =
'pt > 0.1'
3429 trackCuts +=
' and thetaInCDCAcceptance'
3430 trackCuts +=
' and abs(dz) < 3'
3431 trackCuts +=
' and dr < 0.5'
3433 gammaCuts =
'E > 0.05'
3434 gammaCuts +=
' and thetaInCDCAcceptance'
3436 gammaCuts +=
' and abs(clusterTiming) < 200'
3437 if (custom_cuts
is not None):
3438 trackCuts, gammaCuts = custom_cuts
3440 if fillWithMostLikely:
3441 from stdCharged
import stdMostLikely
3442 stdMostLikely(chargedPIDPriors,
'_evtkin', path=path)
3443 inputListNames = [f
'{ptype}:mostlikely_evtkin' for ptype
in [
'K+',
'p+',
'e+',
'mu+',
'pi+']]
3445 copyList(
'gamma:evtkin',
'gamma:mdst', path=path)
3447 fillParticleList(
'gamma:evtkin',
'', path=path)
3448 inputListNames += [
'gamma:evtkin']
3450 B2INFO(
"Using default cleanup in EventKinematics module.")
3451 for ptype
in [
'K+',
'p+',
'e+',
'mu+',
'pi+']:
3452 applyCuts(f
'{ptype}:mostlikely_evtkin', trackCuts, path=path)
3453 applyCuts(
'gamma:evtkin', gammaCuts, path=path)
3455 B2INFO(
"No cleanup in EventKinematics module.")
3456 if not inputListNames:
3457 B2INFO(
"Creating particle lists pi+:evtkin and gamma:evtkin to get the global kinematics of the event.")
3458 fillParticleList(
'pi+:evtkin',
'', path=path)
3460 copyList(
'gamma:evtkin',
'gamma:mdst', path=path)
3462 fillParticleList(
'gamma:evtkin',
'', path=path)
3463 particleLists = [
'pi+:evtkin',
'gamma:evtkin']
3465 if (custom_cuts
is not None):
3466 B2INFO(
"Using default cleanup in EventKinematics module.")
3467 applyCuts(
'pi+:evtkin', trackCuts, path=path)
3468 applyCuts(
'gamma:evtkin', gammaCuts, path=path)
3470 B2INFO(
"No cleanup in EventKinematics module.")
3472 particleLists = inputListNames
3474 eventKinematicsModule = register_module(
'EventKinematics')
3475 eventKinematicsModule.set_name(
'EventKinematics_reco')
3476 eventKinematicsModule.param(
'particleLists', particleLists)
3477 path.add_module(eventKinematicsModule)
3480def buildEventKinematicsFromMC(inputListNames=None, selectionCut='', path=None):
3482 Calculates the global kinematics of the event (visible energy, missing momentum, missing mass...)
3483 using generated particles. If no ParticleList
is provided, default generated ParticleLists are used.
3485 @param inputListNames list of ParticleLists used to calculate the
global event kinematics.
3486 If the list
is empty, default ParticleLists are filled.
3487 @param selectionCut optional selection cuts
3488 @param path Path to append the eventKinematics module to.
3491 if inputListNames
is None:
3493 if (len(inputListNames) == 0):
3497 types = [
'gamma',
'e+',
'mu+',
'pi+',
'K+',
'p+',
3500 fillParticleListFromMC(f
"{t}:evtkin_default_gen",
'mcPrimary > 0 and nDaughters == 0',
3501 True,
True, path=path)
3502 if (selectionCut !=
''):
3503 applyCuts(f
"{t}:evtkin_default_gen", selectionCut, path=path)
3504 inputListNames += [f
"{t}:evtkin_default_gen"]
3506 eventKinematicsModule = register_module(
'EventKinematics')
3507 eventKinematicsModule.set_name(
'EventKinematics_gen')
3508 eventKinematicsModule.param(
'particleLists', inputListNames)
3509 eventKinematicsModule.param(
'usingMC',
True)
3510 path.add_module(eventKinematicsModule)
3513def buildEventShape(inputListNames=None,
3514 default_cleanup=True,
3520 harmonicMoments=True,
3524 checkForDuplicates=False,
3527 Calculates the event-level shape quantities (thrust, sphericity, Fox-Wolfram moments...)
3528 using the particles in the lists provided by the user. If no particle list
is provided,
3529 the function will internally create a list of good tracks
and a list of good photons
3530 with (optionally) minimal quality cuts.
3533 The results of the calculation are then stored into the EventShapeContainer dataobject,
3534 and are accessible using the variables of the EventShape group.
3536 The user can switch the calculation of certain quantities on
or off to save computing
3537 time. By default the calculation of the high-order moments (5-8)
is turned off.
3538 Switching off an option will make the corresponding variables
not available.
3541 The user can provide
as many particle lists
3542 as needed, using also combined particles, but the function will always assume that
3543 the lists are independent.
3544 If the lists provided by the user contain several times the same track (either
with
3545 different mass hypothesis,
or once
as an independent particle
and once
as daughter of a
3546 combined particle) the results won
't be reliable.
3547 A basic check for duplicates
is available setting the checkForDuplicate flags.
3550 @param inputListNames List of ParticleLists used to calculate the
3551 event shape variables. If the list
is empty the default
3552 particleLists pi+:evtshape
and gamma:evtshape are filled.
3553 @param default_cleanup If
True, applies standard cuts on pt
and cosTheta when
3554 defining the internal lists. This option
is ignored
if the
3555 particleLists are provided by the user.
3556 @param custom_cuts tuple of selection cut strings of form (trackCuts, photonCuts), default
is None,
3557 which would result
in a standard predefined selection cuts
3558 @param path Path to append the eventShape modules to.
3559 @param thrust Enables the calculation of thrust-related quantities (CLEO
3560 cones, Harmonic moments, jets).
3561 @param collisionAxis Enables the calculation of the quantities related to the
3563 @param foxWolfram Enables the calculation of the Fox-Wolfram moments.
3564 @param harmonicMoments Enables the calculation of the Harmonic moments
with respect
3565 to both the thrust axis
and,
if collisionAxis =
True, the collision axis.
3566 @param allMoments If
True, calculates also the FW
and harmonic moments
from order
3567 5 to 8 instead of the low-order ones only.
3568 @param cleoCones Enables the calculation of the CLEO cones
with respect to both the thrust
3569 axis
and,
if collisionAxis =
True, the collision axis.
3570 @param jets Enables the calculation of the hemisphere momenta
and masses.
3571 Requires thrust =
True.
3572 @param sphericity Enables the calculation of the sphericity-related quantities.
3573 @param checkForDuplicates Perform a check
for duplicate particles before adding them. Regardless of the value of this option,
3574 it
is recommended to consider sanitizing the lists you are passing to the function.
3578 if inputListNames
is None:
3580 trackCuts =
'pt > 0.1'
3581 trackCuts +=
' and thetaInCDCAcceptance'
3582 trackCuts +=
' and abs(dz) < 3.0'
3583 trackCuts +=
' and dr < 0.5'
3585 gammaCuts =
'E > 0.05'
3586 gammaCuts +=
' and thetaInCDCAcceptance'
3588 gammaCuts +=
' and abs(clusterTiming) < 200'
3589 if (custom_cuts
is not None):
3590 trackCuts, gammaCuts = custom_cuts
3592 if not inputListNames:
3593 B2INFO(
"Creating particle lists pi+:evtshape and gamma:evtshape to get the event shape variables.")
3594 fillParticleList(
'pi+:evtshape',
'', path=path)
3596 copyList(
'gamma:evtshape',
'gamma:mdst', path=path)
3602 particleLists = [
'pi+:evtshape',
'gamma:evtshape']
3605 if (custom_cuts
is not None):
3606 B2INFO(
"Applying standard cuts")
3607 applyCuts(
'pi+:evtshape', trackCuts, path=path)
3609 applyCuts(
'gamma:evtshape', gammaCuts, path=path)
3611 B2WARNING(
"Creating the default lists with no cleanup.")
3613 particleLists = inputListNames
3615 eventShapeModule = register_module(
'EventShapeCalculator')
3616 eventShapeModule.set_name(
'EventShape')
3617 eventShapeModule.param(
'particleListNames', particleLists)
3618 eventShapeModule.param(
'enableAllMoments', allMoments)
3619 eventShapeModule.param(
'enableCleoCones', cleoCones)
3620 eventShapeModule.param(
'enableCollisionAxis', collisionAxis)
3621 eventShapeModule.param(
'enableFoxWolfram', foxWolfram)
3622 eventShapeModule.param(
'enableJets', jets)
3623 eventShapeModule.param(
'enableHarmonicMoments', harmonicMoments)
3624 eventShapeModule.param(
'enableSphericity', sphericity)
3625 eventShapeModule.param(
'enableThrust', thrust)
3626 eventShapeModule.param(
'checkForDuplicates', checkForDuplicates)
3628 path.add_module(eventShapeModule)
3631def labelTauPairMC(printDecayInfo=False, path=None, TauolaBelle=False, mapping_minus=None, mapping_plus=None):
3633 Search tau leptons into the MC information of the event. If confirms it's a generated tau pair decay,
3634 labels the decay generated of the positive and negative leptons using the ID of KKMC tau decay table.
3636 @param printDecayInfo: If true, prints ID
and prong of each tau lepton
in the event.
3637 @param path: module
is added to this path
3638 @param TauolaBelle:
if False, TauDecayMode
is set. If
True, TauDecayMarker
is set.
3639 @param mapping_minus:
if None, the map
is the default one,
else the path
for the map
is given by the user
for tau-
3640 @param mapping_plus:
if None, the map
is the default one,
else the path
for the map
is given by the user
for tau+
3643 from basf2
import find_file
3649 m_printmode =
'default'
3651 if mapping_minus
is None:
3652 mp_file_minus = find_file(
'data/analysis/modules/TauDecayMode/map_tauminus.txt')
3654 mp_file_minus = mapping_minus
3656 if mapping_plus
is None:
3657 mp_file_plus = find_file(
'data/analysis/modules/TauDecayMode/map_tauplus.txt')
3659 mp_file_plus = mapping_plus
3661 path.add_module(
'TauDecayMode', printmode=m_printmode, file_minus=mp_file_minus, file_plus=mp_file_plus)
3664 tauDecayMarker = register_module(
'TauDecayMarker')
3665 tauDecayMarker.set_name(
'TauDecayMarker_')
3667 path.add_module(tauDecayMarker, printDecayInfo=printDecayInfo)
3670def tagCurlTracks(particleLists,
3680 The cut selector is not calibrated
with Belle II data
and should
not be used without extensive study.
3682 Identifies curl tracks
and tags them
with extraInfo(isCurl=1)
for later removal.
3683 For Belle data
with a `b2bii` analysis the available cut based selection
is described
in `BN1079`_.
3685 .. _BN1079: https://belle.kek.jp/secured/belle_note/gn1079/bn1079.pdf
3688 The module loops over all particles
in a given list
with a transverse momentum below the pre-selection **ptCut**
3689 and assigns them to bundles based on the response of the chosen **selector**
and the required minimum response set by the
3690 **responseCut**. Once all particles are assigned they are ranked by 25dr^2+dz^2. All but the lowest are tagged
3691 with extraInfo(isCurl=1) to allow
for later removal by cutting the list
or removing these
from ROE
as
3695 @param particleLists: list of particle lists to check
for curls.
3696 @param mcTruth: bool flag to additionally assign particles
with extraInfo(isTruthCurl)
and
3697 extraInfo(truthBundleSize). To calculate these particles are assigned to bundles by their
3698 genParticleIndex then ranked
and tagged
as normal.
3699 @param responseCut: float min classifier response that considers two tracks to come
from the same particle.
3700 If set to ``-1`` a cut value optimised to maximise the accuracy on a BBbar sample
is used.
3701 Note
'cut' selector
is binary 0/1.
3702 @param selectorType: string name of selector to use. The available options are
'cut' and 'mva'.
3703 It
is strongly recommended to used the
'mva' selection. The
'cut' selection
3704 is based on BN1079
and is only calibrated
for Belle data.
3706 @param ptCut: Pre-selection cut on transverse momentum. Only tracks below that are considered
as curler candidates.
3708 @param expert_train: flag to set training mode
if selector has a training mode (mva).
3709 @param expert_filename: set file name of produced training ntuple (mva).
3710 @param path: module
is added to this path.
3716 if (
not isinstance(particleLists, list)):
3717 particleLists = [particleLists]
3719 curlTagger = register_module(
'CurlTagger')
3720 curlTagger.set_name(
'CurlTagger_')
3721 curlTagger.param(
'particleLists', particleLists)
3722 curlTagger.param(
'belle', belle)
3723 curlTagger.param(
'mcTruth', mcTruth)
3724 curlTagger.param(
'responseCut', responseCut)
3725 if abs(responseCut + 1) < 1e-9:
3726 curlTagger.param(
'usePayloadCut',
True)
3728 curlTagger.param(
'usePayloadCut',
False)
3730 curlTagger.param(
'selectorType', selectorType)
3731 curlTagger.param(
'ptCut', ptCut)
3732 curlTagger.param(
'train', expert_train)
3733 curlTagger.param(
'trainFilename', expert_filename)
3735 path.add_module(curlTagger)
3738def applyChargedPidMVA(particleLists, path, trainingMode, chargeIndependent=False, binaryHypoPDGCodes=(0, 0)):
3740 Use an MVA to perform particle identification for charged stable particles, using the `ChargedPidMVA` module.
3742 The module decorates Particle objects
in the input ParticleList(s)
with variables
3743 containing the appropriate MVA score, which can be used to select candidates by placing a cut on it.
3746 The MVA algorithm used
is a gradient boosted decision tree (**TMVA 4.3.0**, **ROOT 6.20/04**).
3748 The module can perform either
'binary' PID between input S, B particle mass hypotheses according to the following scheme:
3750 * e (11) vs. pi (211)
3751 * mu (13) vs. pi (211)
3752 * pi (211) vs. K (321)
3753 * K (321) vs. pi (211)
3755 ,
or 'global' PID, namely
"one-vs-others" separation. The latter exploits an MVA algorithm trained
in multi-
class mode,
3756 and it
's the default behaviour. Currently, the multi-class training separates the following standard charged hypotheses:
3758 - e (11), mu (13), pi (211), K (321)
3761 In order to run the `ChargedPidMVA` and ensure the most up-to-date MVA training weights are applied,
3762 it
is necessary to append the latest analysis
global tag (GT) to the steering script.
3765 particleLists (list(str)): the input list of DecayStrings, where each selected (^) daughter should correspond to a
3766 standard charged ParticleList, e.g. ``[
'Lambda0:sig -> ^p+ ^pi-',
'J/psi:sig -> ^mu+ ^mu-']``.
3767 One can also directly
pass a list of standard charged ParticleLists,
3768 e.g. ``[
'e+:my_electrons',
'pi+:my_pions']``.
3769 Note that charge-conjugated ParticleLists will automatically be included.
3770 path (basf2.Path): the module
is added to this path.
3771 trainingMode (``Belle2.ChargedPidMVAWeights.ChargedPidMVATrainingMode``): enum identifier of the training mode.
3772 Needed to pick up the correct payload
from the DB. Available choices:
3774 * c_Classification=0
3776 * c_ECL_Classification=2
3777 * c_ECL_Multiclass=3
3778 * c_PSD_Classification=4
3779 * c_PSD_Multiclass=5
3780 * c_ECL_PSD_Classification=6
3781 * c_ECL_PSD_Multiclass=7
3783 chargeIndependent (bool, ``optional``): use a BDT trained on a sample of inclusively charged particles.
3784 binaryHypoPDGCodes (tuple(int, int), ``optional``): the pdgIds of the signal, background mass hypothesis.
3785 Required only
for binary PID mode.
3790 B2ERROR(
"Charged PID via MVA is not available for Belle data.")
3792 from ROOT
import Belle2
3794 TrainingMode = Belle2.ChargedPidMVAWeights.ChargedPidMVATrainingMode
3797 plSet = set(particleLists)
3801 TrainingMode.c_Classification:
3802 {
"mode":
"Classification",
"detector":
"ALL"},
3803 TrainingMode.c_Multiclass:
3804 {
"mode":
"Multiclass",
"detector":
"ALL"},
3805 TrainingMode.c_ECL_Classification:
3806 {
"mode":
"ECL_Classification",
"detector":
"ECL"},
3807 TrainingMode.c_ECL_Multiclass:
3808 {
"mode":
"ECL_Multiclass",
"detector":
"ECL"},
3809 TrainingMode.c_PSD_Classification:
3810 {
"mode":
"PSD_Classification",
"detector":
"ALL"},
3811 TrainingMode.c_PSD_Multiclass:
3812 {
"mode":
"PSD_Multiclass",
"detector":
"ALL"},
3813 TrainingMode.c_ECL_PSD_Classification:
3814 {
"mode":
"ECL_PSD_Classification",
"detector":
"ECL"},
3815 TrainingMode.c_ECL_PSD_Multiclass:
3816 {
"mode":
"ECL_PSD_Multiclass",
"detector":
"ECL"},
3819 if payloadNames.get(trainingMode)
is None:
3820 B2FATAL(
"The chosen training mode integer identifier:\n", trainingMode,
3821 "\nis not supported. Please choose among the following:\n",
3822 "\n".join(f
"{key}:{val.get('mode')}" for key, val
in sorted(payloadNames.items())))
3824 mode = payloadNames.get(trainingMode).get(
"mode")
3825 detector = payloadNames.get(trainingMode).get(
"detector")
3827 payloadName = f
"ChargedPidMVAWeights_{mode}"
3832 Const.electron.getPDGCode():
3833 {
"pName":
"e",
"pFullName":
"electron",
"pNameBkg":
"pi",
"pdgIdBkg": Const.pion.getPDGCode()},
3834 Const.muon.getPDGCode():
3835 {
"pName":
"mu",
"pFullName":
"muon",
"pNameBkg":
"pi",
"pdgIdBkg": Const.pion.getPDGCode()},
3836 Const.pion.getPDGCode():
3837 {
"pName":
"pi",
"pFullName":
"pion",
"pNameBkg":
"K",
"pdgIdBkg": Const.kaon.getPDGCode()},
3838 Const.kaon.getPDGCode():
3839 {
"pName":
"K",
"pFullName":
"kaon",
"pNameBkg":
"pi",
"pdgIdBkg": Const.pion.getPDGCode()},
3840 Const.proton.getPDGCode():
3841 {
"pName":
"p",
"pFullName":
"proton",
"pNameBkg":
"pi",
"pdgIdBkg": Const.pion.getPDGCode()},
3842 Const.deuteron.getPDGCode():
3843 {
"pName":
"d",
"pFullName":
"deuteron",
"pNameBkg":
"pi",
"pdgIdBkg": Const.pion.getPDGCode()},
3846 if binaryHypoPDGCodes == (0, 0):
3849 chargedpid = register_module(
"ChargedPidMVAMulticlass")
3850 chargedpid.set_name(f
"ChargedPidMVAMulticlass_{mode}")
3857 binaryOpts = [(pdgIdSig, info[
"pdgIdBkg"])
for pdgIdSig, info
in stdChargedMap.items()]
3859 if binaryHypoPDGCodes
not in binaryOpts:
3860 B2FATAL(
"No charged pid MVA was trained to separate ", binaryHypoPDGCodes[0],
" vs. ", binaryHypoPDGCodes[1],
3861 ". Please choose among the following pairs:\n",
3862 "\n".join(f
"{opt[0]} vs. {opt[1]}" for opt
in binaryOpts))
3866 if not decayDescriptor.init(name):
3867 raise ValueError(f
"Invalid particle list {name} in applyChargedPidMVA!")
3868 msg = f
"Input ParticleList: {name}"
3869 pdgs = [abs(decayDescriptor.getMother().getPDGCode())]
3870 daughter_pdgs = decayDescriptor.getSelectionPDGCodes()
3871 if len(daughter_pdgs) > 0:
3872 pdgs = daughter_pdgs
3873 for idaughter, pdg
in enumerate(pdgs):
3874 if abs(pdg)
not in binaryHypoPDGCodes:
3876 msg = f
"Selected daughter {idaughter} in ParticleList: {name}"
3878 f
"{msg} (PDG={pdg}) is neither signal ({binaryHypoPDGCodes[0]}) nor background ({binaryHypoPDGCodes[1]}).")
3880 chargedpid = register_module(
"ChargedPidMVA")
3881 chargedpid.set_name(f
"ChargedPidMVA_{binaryHypoPDGCodes[0]}_vs_{binaryHypoPDGCodes[1]}_{mode}")
3882 chargedpid.param(
"sigHypoPDGCode", binaryHypoPDGCodes[0])
3883 chargedpid.param(
"bkgHypoPDGCode", binaryHypoPDGCodes[1])
3885 chargedpid.param(
"particleLists", list(plSet))
3886 chargedpid.param(
"payloadName", payloadName)
3887 chargedpid.param(
"chargeIndependent", chargeIndependent)
3890 if detector ==
"ECL":
3891 chargedpid.param(
"useECLOnlyTraining",
True)
3893 path.add_module(chargedpid)
3896def calculateTrackIsolation(
3900 reference_list_name=None,
3901 vars_for_nearest_part=[],
3902 highest_prob_mass_for_ext=True,
3903 exclude_pid_det_weights=False):
3905 Given an input decay string, compute variables that quantify track helix-based isolation of the charged
3906 stable particles in the input decay chain.
3909 An
"isolation score" can be defined using the distance
3910 of each particle to its closest neighbour, defined
as the segment connecting the two
3911 extrapolated track helices intersection points on a given cylindrical surface.
3912 The distance variables defined
in the `VariableManager`
is named `minET2ETDist`,
3913 the isolation scores are named `minET2ETIsoScore`, `minET2ETIsoScoreAsWeightedAvg`.
3915 The definition of distance
and the number of distances that are calculated per sub-detector
is based on
3916 the following recipe:
3918 * **CDC**:
as the segmentation
is very coarse along :math:`z`,
3919 the distance
is defined
as the cord length on the :math:`(\\rho=R, \\phi)` plane.
3920 A total of 9 distances are calculated: the cylindrical surfaces are defined at radiuses
3921 that correspond to the positions of the 9 CDC wire superlayers: :math:`R_{i}^{\\mathrm{CDC}}~(i \\
in \\{0,...,8\\})`.
3923 * **TOP**:
as there
is no segmentation along :math:`z`,
3924 the distance
is defined
as the cord length on the :math:`(\\rho=R, \\phi)` plane.
3925 Only one distance at the TOP entry radius :math:`R_{0}^{\\mathrm{TOP}}`
is calculated.
3927 * **ARICH**:
as there
is no segmentation along :math:`z`,
3928 the distance
is defined
as the distance on the :math:`(\\rho=R, \\phi)` plane at fixed :math:`z=Z`.
3929 Only one distance at the ARICH photon detector entry coordinate :math:`Z_{0}^{\\mathrm{ARICH}}`
is calculated.
3931 * **ECL**: the distance
is defined on the :math:`(\\rho=R, \\phi, z)` surface
in the barrel,
3932 on the :math:`(\\rho, \\phi, z=Z)` surface
in the endcaps.
3933 Two distances are calculated: one at the ECL entry surface :math:`R_{0}^{\\mathrm{ECL}}` (barrel),
3934 :math:`Z_{0}^{\\mathrm{ECL}}` (endcaps),
and one at :math:`R_{1}^{\\mathrm{ECL}}` (barrel),
3935 :math:`Z_{1}^{\\mathrm{ECL}}` (endcaps), corresponding roughly to the mid-point
3936 of the longitudinal size of the crystals.
3938 * **KLM**: the distance
is defined on the :math:`(\\rho=R, \\phi, z)` surface
in the barrel,
3939 on the :math:`(\\rho, \\phi, z=Z)` surface
in the endcaps.
3940 Only one distance at the KLM first strip entry surface :math:`R_{0}^{\\mathrm{KLM}}` (barrel),
3941 :math:`Z_{0}^{\\mathrm{KLM}}` (endcaps)
is calculated.
3944 decay_string (str): name of the input decay string
with selected charged stable daughters,
3945 for example: ``Lambda0:merged -> ^p+ ^pi-``.
3946 Alternatively, it can be a particle list
for charged stable particles
3947 as defined
in ``Const::chargedStableSet``,
for example: ``mu+:all``.
3948 The charge-conjugate particle list will be also processed automatically.
3949 path (basf2.Path): path to which module(s) will be added.
3950 *detectors: detectors
for which track isolation variables will be calculated.
3951 Choose among: ``{
'CDC',
'TOP',
'ARICH',
'ECL',
'KLM'}``.
3952 reference_list_name (Optional[str]): name of the input charged stable particle list
for the reference tracks.
3953 By default, the ``:all`` ParticleList of the same type
3954 of the selected particle
in ``decay_string``
is used.
3955 The charge-conjugate particle list will be also processed automatically.
3956 vars_for_nearest_part (Optional[list(str)]): a list of variables to calculate
for the nearest particle
in the reference
3957 list at each detector surface. It uses the metavariable `minET2ETDistVar`.
3958 If unset, only the distances to the nearest neighbour
3959 per detector are calculated.
3960 highest_prob_mass_for_hex (Optional[bool]):
if this option
is set to
True (default), the helix extrapolation
3961 for the particles will use the track fit result
for the most
3962 probable mass hypothesis, namely, the one that gives the highest
3963 chi2Prob of the fit. Otherwise, it uses the mass hypothesis that
3964 corresponds to the particle lists PDG.
3965 exclude_pid_det_weights (Optional[bool]):
if this option
is set to
False (default), the isolation score
3966 calculation will take into account the weight that each detector has on the PID
3967 for the particle species of interest.
3970 dict(int, list(str)): a dictionary mapping the PDG of each reference particle list to its isolation variables.
3975 from ROOT
import Belle2, TDatabasePDG
3978 if not decayDescriptor.init(decay_string):
3979 B2FATAL(f
"Invalid particle list {decay_string} in calculateTrackIsolation!")
3980 no_reference_list_name =
not reference_list_name
3983 "CDC": list(range(9)),
3989 if any(d
not in det_and_layers
for d
in detectors):
3991 "Your input detector list: ",
3993 " contains an invalid choice. Please select among: ",
3995 det_and_layers.keys()))
4000 processed_decay_strings = []
4001 if select_symbol
in decay_string:
4002 splitted_ds = decay_string.split(select_symbol)
4003 for i
in range(decay_string.count(select_symbol)):
4004 tmp = list(splitted_ds)
4005 tmp.insert(i+1, select_symbol)
4006 processed_decay_strings += [
''.join(tmp)]
4008 processed_decay_strings += [decay_string]
4010 reference_lists_to_vars = {}
4012 for processed_dec
in processed_decay_strings:
4013 if no_reference_list_name:
4014 decayDescriptor.init(processed_dec)
4015 selected_daughter_pdgs = decayDescriptor.getSelectionPDGCodes()
4016 if len(selected_daughter_pdgs) > 0:
4017 reference_list_name = f
'{TDatabasePDG.Instance().GetParticle(abs(selected_daughter_pdgs[-1])).GetName()}:all'
4019 reference_list_name = f
'{processed_dec.split(":")[0]}:all'
4023 trackiso = path.add_module(
"TrackIsoCalculator",
4024 decayString=processed_dec,
4025 detectorNames=list(detectors),
4026 particleListReference=reference_list_name,
4027 useHighestProbMassForExt=highest_prob_mass_for_ext,
4028 excludePIDDetWeights=exclude_pid_det_weights)
4029 trackiso.set_name(f
"TrackIsoCalculator_{'_'.join(detectors)}_{processed_dec}_VS_{reference_list_name}")
4035 f
"minET2ETDist({d}, {d_layer}, {reference_list_name}, {int(highest_prob_mass_for_ext)})"
4036 for d
in detectors
for d_layer
in det_and_layers[d]]
4039 f
"minET2ETIsoScore({reference_list_name}, {int(highest_prob_mass_for_ext)}, {', '.join(detectors)})",
4040 f
"minET2ETIsoScoreAsWeightedAvg({reference_list_name}, {int(highest_prob_mass_for_ext)}, {', '.join(detectors)})",
4043 if vars_for_nearest_part:
4044 trackiso_vars.extend(
4046 f
"minET2ETDistVar({d}, {d_layer}, {reference_list_name}, {v})"
4047 for d
in detectors
for d_layer
in det_and_layers[d]
for v
in vars_for_nearest_part
4049 trackiso_vars.sort()
4051 reference_lists_to_vars[ref_pdg] = trackiso_vars
4053 return reference_lists_to_vars
4056def calculateDistance(list_name, decay_string, mode='vertextrack', path=None):
4058 Calculates distance between two vertices, distance of closest approach between a vertex and a track,\
4059 distance of closest approach between a vertex
and btube. For track, this calculation ignores track curvature,\
4060 it
's negligible for small distances.The user should use extraInfo(CalculatedDistance)\
4061 to get it. A full example steering file is at analysis/tests/test_DistanceCalculator.py
4064 .. code-block:: python
4066 from modularAnalysis
import calculateDistance
4067 calculateDistance(
'list_name',
'decay_string',
"mode", path=user_path)
4069 @param list_name name of the input ParticleList
4070 @param decay_string select particles between the distance of closest approach will be calculated
4071 @param mode Specifies how the distance
is calculated
4072 vertextrack: calculate the distance of closest approach between a track
and a\
4073 vertex, taking the first candidate
as vertex, default
4074 trackvertex: calculate the distance of closest approach between a track
and a\
4075 vertex, taking the first candidate
as track
4076 2tracks: calculates the distance of closest approach between two tracks
4077 2vertices: calculates the distance between two vertices
4078 vertexbtube: calculates the distance of closest approach between a vertex
and btube
4079 trackbtube: calculates the distance of closest approach between a track
and btube
4080 @param path modules are added to this path
4084 dist_mod = register_module('DistanceCalculator')
4086 dist_mod.set_name(
'DistanceCalculator_' + list_name)
4087 dist_mod.param(
'listName', list_name)
4088 dist_mod.param(
'decayString', decay_string)
4089 dist_mod.param(
'mode', mode)
4090 path.add_module(dist_mod)
4093def addInclusiveDstarReconstruction(decayString, slowPionCut, DstarCut, path):
4095 Adds the InclusiveDstarReconstruction module to the given path.
4096 This module creates a D* particle list by estimating the D* four momenta
4097 from slow pions, specified by a given cut. The D* energy
is approximated
4098 as E(D*) = m(D*)/(m(D*) - m(D)) * E(pi). The absolute value of the D*
4099 momentum
is calculated using the D* PDG mass
and the direction
is collinear
4100 to the slow pion direction. The charge of the given pion list has to be consistent
4103 @param decayString Decay string, must be of form ``D* -> pi``
4104 @param slowPionCut Cut applied to the input pion list to identify slow pions
4105 @param DstarCut Cut applied to the output D* list
4106 @param path the module
is added to this path
4109 incl_dstar = register_module("InclusiveDstarReconstruction")
4110 incl_dstar.param(
"decayString", decayString)
4111 incl_dstar.param(
"slowPionCut", slowPionCut)
4112 incl_dstar.param(
"DstarCut", DstarCut)
4113 path.add_module(incl_dstar)
4116def scaleError(outputListName, inputListName,
4117 scaleFactors=[1.149631, 1.085547, 1.151704, 1.096434, 1.086659],
4118 scaleFactorsNoPXD=[1.149631, 1.085547, 1.151704, 1.096434, 1.086659],
4119 d0Resolution=[0.00115328, 0.00134704],
4120 z0Resolution=[0.00124327, 0.0013272],
4125 This module creates a new charged particle list.
4126 The helix errors of the new particles are scaled by constant factors.
4127 Two sets of five scale factors are defined for tracks
with and without a PXD hit.
4128 The scale factors are
in order of (d0, phi0, omega, z0, tanlambda).
4129 For tracks
with a PXD hit,
in order to avoid severe underestimation of d0
and z0 errors,
4130 lower limits (best resolution) can be set
in a momentum-dependent form.
4131 This module
is supposed to be used only
for TDCPV analysis
and for low-momentum (0-3 GeV/c) tracks
in BBbar events.
4132 Details will be documented
in a Belle II note, BELLE2-NOTE-PH-2021-038.
4134 @param inputListName Name of input charged particle list to be scaled
4135 @param outputListName Name of output charged particle list
with scaled error
4136 @param scaleFactors List of five constants to be multiplied to each of helix errors (
for tracks
with a PXD hit)
4137 @param scaleFactorsNoPXD List of five constants to be multiplied to each of helix errors (
for tracks without a PXD hit)
4138 @param d0Resolution List of two parameters, (a [cm], b [cm/(GeV/c)]),
4139 defining d0 best resolution
as sqrt{ a**2 + (b / (p*beta*sinTheta**1.5))**2 }
4140 @param z0Resolution List of two parameters, (a [cm], b [cm/(GeV/c)]),
4141 defining z0 best resolution
as sqrt{ a**2 + (b / (p*beta*sinTheta**2.5))**2 }
4142 @param d0MomThr d0 best resolution
is kept constant below this momentum
4143 @param z0MomThr z0 best resolution
is kept constant below this momentum
4147 scale_error = register_module("HelixErrorScaler")
4148 scale_error.set_name(
'ScaleError_' + inputListName)
4149 scale_error.param(
'inputListName', inputListName)
4150 scale_error.param(
'outputListName', outputListName)
4151 scale_error.param(
'scaleFactors_PXD', scaleFactors)
4152 scale_error.param(
'scaleFactors_noPXD', scaleFactorsNoPXD)
4153 scale_error.param(
'd0ResolutionParameters', d0Resolution)
4154 scale_error.param(
'z0ResolutionParameters', z0Resolution)
4155 scale_error.param(
'd0MomentumThreshold', d0MomThr)
4156 scale_error.param(
'z0MomentumThreshold', z0MomThr)
4157 path.add_module(scale_error)
4160def estimateAndAttachTrackFitResult(inputListName, path=None):
4162 Create a TrackFitResult from the momentum of the Particle assuming it originates
from the IP
and make a relation between them.
4163 The covariance, detector hit information,
and fit-related information (pValue, NDF) are assigned meaningless values. The input
4164 Particles must
not have already Track
or TrackFitResult
and thus are supposed to be composite particles, recoil, dummy
4165 particles,
and so on.
4168 .. warning:: Since the source type
is not overwritten
as Track,
not all track-related variables are guaranteed to be available.
4171 @param inputListName Name of input ParticleList
4174 estimator = register_module("TrackFitResultEstimator")
4175 estimator.set_name(
"trackFitResultEstimator_" + inputListName)
4176 estimator.param(
"inputListName", inputListName)
4177 path.add_module(estimator)
4180def correctEnergyBias(inputListNames, tableName, path=None):
4182 Scale energy of the particles according to the scaling factor.
4183 If the particle list contains composite particles, the energy of the daughters are scaled.
4184 Subsequently, the energy of the mother particle is updated
as well.
4187 inputListNames (list(str)): input particle list names
4188 tableName : stored
in localdb
and created using ParticleWeightingLookUpCreator
4189 path (basf2.Path): module
is added to this path
4194 B2ERROR(
"The energy bias cannot be corrected with this tool for Belle data.")
4196 correctenergybias = register_module(
'EnergyBiasCorrection')
4197 correctenergybias.param(
'particleLists', inputListNames)
4198 correctenergybias.param(
'tableName', tableName)
4199 path.add_module(correctenergybias)
4202def twoBodyISRPhotonCorrector(outputListName, inputListName, massiveParticle, path=None):
4204 Sets photon kinematics to corrected values in two body decays
with an ISR photon
4205 and a massive particle. The original photon kinematics are kept
in the input
4206 particleList
and can be accessed using the originalParticle() metavariable on the
4209 @param ouputListName new ParticleList filled
with copied Particles
4210 @param inputListName input ParticleList
with original Particles
4211 @param massiveParticle name
or PDG code of massive particle participating
in the two
4212 body decay
with the ISR photon
4213 @param path modules are added to this path
4217 photon_energy_correction = register_module(
'TwoBodyISRPhotonCorrector')
4218 photon_energy_correction.set_name(
'TwoBodyISRPhotonCorrector_' + outputListName)
4219 photon_energy_correction.param(
'outputGammaList', outputListName)
4220 photon_energy_correction.param(
'inputGammaList', inputListName)
4223 if isinstance(massiveParticle, int):
4224 photon_energy_correction.param(
'massiveParticlePDGCode', massiveParticle)
4226 from ROOT
import Belle2
4228 if not decayDescriptor.init(massiveParticle):
4229 raise ValueError(
"TwoBodyISRPhotonCorrector: value of massiveParticle must be" +
4230 " an int or valid decay string.")
4231 pdgCode = decayDescriptor.getMother().getPDGCode()
4232 photon_energy_correction.param(
'massiveParticlePDGCode', pdgCode)
4234 path.add_module(photon_energy_correction)
4237def addPhotonEfficiencyRatioVariables(inputListNames, tableName, path=None):
4239 Add photon Data/MC detection efficiency ratio weights to the specified particle list
4242 inputListNames (list(str)): input particle list names
4243 tableName : taken from database
with appropriate name
4244 path (basf2.Path): module
is added to this path
4249 B2ERROR(
"For Belle data the photon data/MC detection efficiency ratio is not available with this tool.")
4251 photon_efficiency_correction = register_module(
'PhotonEfficiencySystematics')
4252 photon_efficiency_correction.param(
'particleLists', inputListNames)
4253 photon_efficiency_correction.param(
'tableName', tableName)
4254 path.add_module(photon_efficiency_correction)
4257def addPi0VetoEfficiencySystematics(particleList, decayString, tableName, threshold, mode='standard', suffix='', path=None):
4259 Add pi0 veto Data/MC efficiency ratio weights to the specified particle list
4261 @param particleList the input ParticleList
4262 @param decayString specify hard photon to be performed pi0 veto (e.g.
'B+:sig -> rho+:sig ^gamma:hard')
4263 @param tableName table name corresponding to payload version (e.g.
'Pi0VetoEfficiencySystematics_Mar2022')
4264 @param threshold pi0 veto threshold (0.10, 0.11, ..., 0.99)
4265 @param mode choose one mode (same
as writePi0EtaVeto) out of
'standard',
'tight',
'cluster' and 'both'
4266 @param suffix optional suffix to be appended to the usual extraInfo name
4267 @param path the module
is added to this path
4269 The following extraInfo are available related
with the given particleList:
4271 * Pi0VetoEfficiencySystematics_{mode}{suffix}_data_MC_ratio : weight of Data/MC
for the veto efficiency
4272 * Pi0VetoEfficiencySystematics_{mode}{suffix}_data_MC_uncertainty_stat : the statistical uncertainty of the weight
4273 * Pi0VetoEfficiencySystematics_{mode}{suffix}_data_MC_uncertainty_sys : the systematic uncertainty of the weight
4274 * Pi0VetoEfficiencySystematics_{mode}{suffix}_data_MC_uncertainty_total : the total uncertainty of the weight
4275 * Pi0VetoEfficiencySystematics_{mode}{suffix}_threshold : threshold of the pi0 veto
4280 B2ERROR(
"For Belle data the pi0 veto data/MC efficiency ratio weights are not available via this tool.")
4282 pi0veto_efficiency_correction = register_module(
'Pi0VetoEfficiencySystematics')
4283 pi0veto_efficiency_correction.param(
'particleLists', particleList)
4284 pi0veto_efficiency_correction.param(
'decayString', decayString)
4285 pi0veto_efficiency_correction.param(
'tableName', tableName)
4286 pi0veto_efficiency_correction.param(
'threshold', threshold)
4287 pi0veto_efficiency_correction.param(
'mode', mode)
4288 pi0veto_efficiency_correction.param(
'suffix', suffix)
4289 path.add_module(pi0veto_efficiency_correction)
4292def getAnalysisGlobaltag(timeout=180) -> str:
4294 Returns a string containing the name of the latest and recommended analysis globaltag.
4297 timeout: Seconds to wait
for b2conditionsdb-recommend
4302 B2ERROR(
"The getAnalysisGlobaltag() function cannot be used for Belle data.")
4307 tags = subprocess.check_output(
4308 [
'b2conditionsdb-recommend',
'--oneline'],
4310 ).decode(
'UTF-8').rstrip().split(
' ')
4313 if tag.startswith(
'analysis_tools'):
4317 except subprocess.TimeoutExpired
as te:
4318 B2FATAL(f
'A {te} exception was raised during the call of getAnalysisGlobaltag(). '
4319 'The function took too much time to retrieve the requested information '
4320 'from the versioning repository.\n'
4321 'Please try to re-run your job. In case of persistent failures, there may '
4322 'be issues with the DESY collaborative services, so please contact the experts.')
4323 except subprocess.CalledProcessError
as ce:
4324 B2FATAL(f
'A {ce} exception was raised during the call of getAnalysisGlobaltag(). '
4325 'Please try to re-run your job. In case of persistent failures, please contact '
4329def getAnalysisGlobaltagB2BII() -> str:
4331 Get recommended global tag
for B2BII analysis.
4336 B2ERROR(
'The getAnalysisGlobaltagB2BII() function cannot be used for Belle II data.')
4337 from versioning
import recommended_b2bii_analysis_global_tag
4338 return recommended_b2bii_analysis_global_tag()
4341def getNbarIDMVA(particleList: str, path=
None):
4343 This function can give a score to predict if it
is a anti-n0.
4344 It
is not used to predict n0.
4345 Currently, this can be used only
for ECL cluster.
4346 output will be stored
in extraInfo(nbarID); -1 means MVA invalid
4348 @param particleList The input ParticleList name
or a decay string which contains a full mother particle list name.
4349 Only one selected daughter
is supported.
4350 @param path modules are added to this path
4353 from ROOT
import Belle2
4356 B2ERROR(
"The MVA-based anti-neutron PID is only available for Belle II data.")
4358 from variables
import variables
4360 variables.addAlias(
'V1',
'clusterHasPulseShapeDiscrimination')
4361 variables.addAlias(
'V2',
'clusterE')
4362 variables.addAlias(
'V3',
'clusterLAT')
4363 variables.addAlias(
'V4',
'clusterE1E9')
4364 variables.addAlias(
'V5',
'clusterE9E21')
4365 variables.addAlias(
'V6',
'clusterZernikeMVA')
4366 variables.addAlias(
'V7',
'clusterAbsZernikeMoment40')
4367 variables.addAlias(
'V8',
'clusterAbsZernikeMoment51')
4371 'passesCut(V1 == 1 and V2 >= 0 and V3 >= 0 and V4 >= 0 and V5 >= 0 and V6 >= 0 and V7 >= 0 and V8 >= 0)')
4372 variables.addAlias(
'nbarIDmod',
'conditionalVariableSelector(nbarIDValid == 1, extraInfo(nbarIDFromMVA), constant(-1.0))')
4374 path.add_module(
'MVAExpert', listNames=particleList, extraInfoName=
'nbarIDFromMVA', identifier=
'db_nbarIDECL')
4376 if not decayDescriptor.init(particleList):
4377 raise ValueError(f
"Provided decay string is invalid: {particleList}")
4378 if decayDescriptor.getNDaughters() == 0:
4381 listname = decayDescriptor.getMother().getFullName()
4382 variablesToDaughterExtraInfo(listname, particleList, {
'nbarIDmod':
'nbarID'}, option=2, path=path)
4385def reconstructDecayWithNeutralHadron(decayString, cut, allowGamma=False, allowAnyParticleSource=False, path=None, **kwargs):
4387 Reconstructs decay with a long-lived neutral hadron e.g.
4388 :math:`B^0 \to J/\psi K_L^0`,
4389 :math:`B^0 \to p \bar{n} D^*(2010)^-`.
4391 The calculation
is done
with IP constraint
and mother mass constraint.
4393 The decay string passed
in must satisfy the following rules:
4395 - The neutral hadron must be **selected**
in the decay string
with the
4396 caret (``^``) e.g. ``B0:sig -> J/psi:sig ^K_L0:sig``. (Note the caret
4397 next to the neutral hadron.)
4398 - There can only be **one neutral hadron
in a decay**.
4399 - The neutral hadron has to be a direct daughter of its mother.
4401 .. note:: This function forwards its arguments to `reconstructDecay`,
4402 so please check the documentation of `reconstructDecay`
for all
4405 @param decayString A decay string following the mentioned rules
4406 @param cut Cut to apply to the particle list
4407 @param allowGamma Whether allow the selected particle to be ``gamma``
4408 @param allowAnyParticleSource Whether allow the selected particle to be
from any source.
4409 Should only be used when studying control sample.
4410 @param path The path to put
in the module
4413 reconstructDecay(decayString, cut, path=path, **kwargs)
4414 module = register_module('NeutralHadron4MomentumCalculator')
4415 module.set_name(
'NeutralHadron4MomentumCalculator_' + decayString)
4416 module.param(
'decayString', decayString)
4417 module.param(
'allowGamma', allowGamma)
4418 module.param(
'allowAnyParticleSource', allowAnyParticleSource)
4419 path.add_module(module)
4422func_requiring_analysisGT = [
4423 correctTrackEnergy, scaleTrackMomenta, smearTrackMomenta, oldwritePi0EtaVeto, writePi0EtaVeto, lowEnergyPi0Identification,
4424 getBeamBackgroundProbability, getFakePhotonProbability, tagCurlTracks, applyChargedPidMVA, correctEnergyBias,
4425 addPhotonEfficiencyRatioVariables, addPi0VetoEfficiencySystematics, getNbarIDMVA]
4426for _
in func_requiring_analysisGT:
4427 _.__doc__ +=
"\n .. note:: This function (optionally) requires a payload stored in the analysis GlobalTag. "\
4428 "Please append or prepend the latest one from `getAnalysisGlobaltag` or `getAnalysisGlobaltagB2BII`.\n"
4431if __name__ ==
'__main__':
4433 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)