Belle II Software  release-05-02-19
parallel_processing.py
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3 
4 # Test the parallel processing functionality by simulating a few events
5 # using 2 processes (so nothing too taxing)
6 
7 import os
8 import basf2
9 from ROOT import TFile, Belle2
10 from b2test_utils import skip_test_if_light
11 skip_test_if_light() # cannot simulate events in a light release
12 
13 
14 class CheckEventNumbers(basf2.Module):
15  """Class to check that we see all events we expect exactly once and nothing else"""
16 
17  def __init__(self, evtNumList):
18  """Remember number of events to process"""
19  super().__init__()
20 
21  self.__evtNumList = evtNumList
22 
23  self.__evtNumbers = []
24 
25  def event(self):
26  """Accumulate all event numbers we see"""
27  evtNr = Belle2.PyStoreObj("EventMetaData").obj().getEvent()
28  self.__evtNumbers.append(evtNr)
29 
30  def terminate(self):
31  """Check if event numbers are as they should be"""
32  seen = self.__evtNumbers
33  should = list(range(1, self.__evtNumList+1))
34  all_numbers = sorted(set(seen) | set(should))
35  all_ok = True
36  for evtNr in all_numbers:
37  c = seen.count(evtNr)
38  if not (evtNr in should and c == 1):
39  basf2.B2ERROR("event number %d seen %d times" % (evtNr, c))
40  all_ok = False
41  if not all_ok:
42  basf2.B2FATAL("Missing/extra events")
43 
44 
45 main = basf2.Path()
46 # init path
47 main.add_module("EventInfoSetter", evtNumList=[5])
48 particlegun = main.add_module("ParticleGun", pdgCodes=[211, -211, 321, -321],
49  momentumGeneration="fixed", momentumParams=[3])
50 main.add_module("Gearbox")
51 
52 # event path
53 main.add_module("Geometry", components=['MagneticField', 'BeamPipe', 'PXD'], logLevel=basf2.LogLevel.ERROR)
54 simulation = main.add_module("FullSim", logLevel=basf2.LogLevel.ERROR)
55 
56 # output path
57 main.add_module("RootOutput", outputFileName='parallel_processing_test.root')
58 main.add_module("Progress")
59 main.add_module(CheckEventNumbers(5))
60 
61 # test wether flags are what we expect
62 if particlegun.has_properties(basf2.ModulePropFlags.PARALLELPROCESSINGCERTIFIED):
63  basf2.B2FATAL("ParticleGun has pp flag?")
64 if not simulation.has_properties(basf2.ModulePropFlags.PARALLELPROCESSINGCERTIFIED):
65  basf2.B2FATAL("Simulation doesn't have pp flag?")
66 
67 # Process events in one more process than we have events to make sure at least
68 # one of them doesn't get an event
69 basf2.set_nprocesses(5)
70 basf2.process(main)
71 
72 print(basf2.statistics)
73 print(basf2.statistics(basf2.statistics.TOTAL))
74 assert basf2.statistics.get(simulation).calls(basf2.statistics.EVENT) == 5
75 # +1 because of extra call to master module
76 assert basf2.statistics.get_global().calls(basf2.statistics.EVENT) == 6
77 
78 # check wether output file contains correct number of events
79 file = TFile('parallel_processing_test.root')
80 tree = file.Get('tree')
81 if tree.GetEntries() != 5:
82  B2FATAL('Created output file contains wrong number of events! (' + str(tree.GetEntries()) + ')')
83 
84 nummcparticles = tree.Project("", "MCParticles.m_pdg")
85 if nummcparticles < 5:
86  B2FATAL('Output file should contain at least five MCParticles!')
87 
88 numhits = tree.Project("", "PXDSimHits.getArrayIndex()")
89 if numhits < 5: # usually much more, existence is most important thing here
90  B2FATAL('Output file should contain at least 5 hits!')
91 
92 
93 os.remove('parallel_processing_test.root')
parallel_processing.CheckEventNumbers.__evtNumbers
__evtNumbers
event numbers we actually saw
Definition: parallel_processing.py:23
parallel_processing.CheckEventNumbers.__evtNumList
__evtNumList
the number of events so we expect the event numbers 0..(evtNumList-1)
Definition: parallel_processing.py:21
parallel_processing.CheckEventNumbers.terminate
def terminate(self)
Definition: parallel_processing.py:30
Belle2::PyStoreObj
a (simplified) python wrapper for StoreObjPtr.
Definition: PyStoreObj.h:69
basf2.process
def process(path, max_event=0)
Definition: __init__.py:25
parallel_processing.CheckEventNumbers.event
def event(self)
Definition: parallel_processing.py:25
parallel_processing.CheckEventNumbers.__init__
def __init__(self, evtNumList)
Definition: parallel_processing.py:17
parallel_processing.CheckEventNumbers
Definition: parallel_processing.py:14