Belle II Software  release-08-01-10
root_input.py
1 #!/usr/bin/env python3
2 
3 
10 
11 import os
12 import basf2
13 from ROOT import Belle2
14 from b2test_utils import safe_process, clean_working_directory
15 
16 basf2.conditions.disable_globaltag_replay()
17 basf2.set_random_seed("something important")
18 # make sure FATAL messages don't have the function signature as this makes
19 # problems with clang printing namespaces differently
20 basf2.logging.set_info(basf2.LogLevel.FATAL, basf2.logging.get_info(basf2.LogLevel.ERROR))
21 basf2.logging.enable_summary(False)
22 
23 
24 class NoopModule(basf2.Module):
25  """Doesn't do anything."""
26 
27 
28 with clean_working_directory():
29  for filename in ["root_input.root", "chaintest_empty.root", "chaintest_1.root", "chaintest_2.root"]:
30  os.symlink(basf2.find_file(f'framework/tests/{filename}'), filename)
31 
32  main = basf2.Path()
33  # not used for anything, just checking wether the master module
34  # can be found if it's not the first module in the path.
35  main.add_module(NoopModule())
36  # load all branches, minus PXDClusters (relations with PXDClusters are automatically excluded)
37  # (yes, we also added PXDClusters in branchNames, to check if it's overridden by excludeBranchNames)
38  input_module = main.add_module("RootInput", inputFileName="root_input.root",
39  branchNames=['EventMetaData', 'PXDDigits', 'PXDTrueHits', 'PXDClusters'],
40  excludeBranchNames=['PXDClusters'], skipNEvents=1, logLevel=basf2.LogLevel.WARNING)
41  # print event information and datastore contents
42  main.add_module("EventInfoPrinter")
43  main.add_module("PrintCollections", printForEvent=0)
44 
45  # Process events
46  assert safe_process(main) == 0
47 
48  # Test restricting the number of events per file
49  # This issues a warning because a part of the events is out of range
50  input_module.param('entrySequences', ["0,3:10,23"])
51  assert safe_process(main) == 0
52 
53  # Test starting directly with a given event. There will be a fatal error if the
54  # event is not found in the file so let's call process() in a child process to
55  # not be aborted
56  for evtNo in range(1, 6):
57  main = basf2.Path()
58  main.add_module("RootInput", inputFileName='root_input.root',
59  branchNames=["EventMetaData"], skipToEvent=[0, 1, evtNo], logLevel=basf2.LogLevel.WARNING)
60  main.add_module("EventInfoPrinter")
61  safe_process(main)
62 
63  # Test eventSequences in detail
64  main = basf2.Path()
65  input_module = main.add_module('RootInput', inputFileNames=['chaintest_1.root', 'chaintest_2.root'],
66  logLevel=basf2.LogLevel.WARNING)
67  # The first file contains the following event numbers (in this order)
68  # 2, 6, 5, 9, 10, 11, 8, 12, 0, 13, 15, 16
69  # We select more event than the file contains, to check if it works anyway
70  # The second file contains the following event numbers (in this order)
71  # 7, 6, 3, 8, 9, 12, 4, 11, 10, 16, 13, 17, 18, 14, 15
72  input_module.param('entrySequences', ['0,3:4,10:100', '1:2,4,12:13'])
73 
74  class TestingModule(basf2.Module):
75  """
76  Test module which writes out the processed event numbers
77  into the global processed_event_numbers list
78  """
79 
80  def __init__(self, expected):
81  """
82  Initialize this nice class with the list of expected event
83  numbers to see in the correct order
84  """
85  super().__init__()
86 
87  self.emdemd = Belle2.PyStoreObj('EventMetaData')
88 
89  self._expected_event_numbers_expected_event_numbers = expected
90 
91  self._processed_event_numbers_processed_event_numbers = []
92 
93  def event(self):
94  """
95  Called for each event
96  """
97  self._processed_event_numbers_processed_event_numbers.append(self.emdemd.getEvent())
98 
99  def terminate(self):
100  """
101  perform check
102  """
103  # We only want to do the check if we actually execute the process() but
104  # since this script is called from basf2_args with --dry-run this is not
105  # always the case
106  assert self._expected_event_numbers_expected_event_numbers == self._processed_event_numbers_processed_event_numbers
107 
108  main.add_module(TestingModule([2, 9, 10, 15, 16, 6, 3, 9, 18, 14]))
109  assert safe_process(main) == 0
110 
111  basf2.set_random_seed("something important")
112  # make sure FATAL messages don't have the function signature as this makes
113  # problems with clang printing namespaces differently
114  basf2.logging.set_info(basf2.LogLevel.FATAL, basf2.logging.get_info(basf2.LogLevel.ERROR))
115 
116  # Test eventSequences parameter ':' in detail
117  main = basf2.Path()
118  input_module = main.add_module('RootInput', inputFileNames=['chaintest_1.root', 'chaintest_2.root'],
119  logLevel=basf2.LogLevel.WARNING)
120  # The first file contains the following event numbers (in this order)
121  # 2, 6, 5, 9, 10, 11, 8, 12, 0, 13, 15, 16
122  # We select the complete first file.
123  # The second file contains the following event numbers (in this order)
124  # 7, 6, 3, 8, 9, 12, 4, 11, 10, 16, 13, 17, 18, 14, 15
125  input_module.param('entrySequences', [':', '1:2,4,12:13'])
126 
127  expected_event_numbers = [2, 6, 5, 9, 10, 11, 8, 12, 0, 13, 15, 16, 6, 3, 9, 18, 14]
128  main.add_module(TestingModule(expected_event_numbers))
129 
130  assert safe_process(main) == 0
131 
132  full_list = ["chaintest_empty.root", "chaintest_1.root", "chaintest_2.root", "chaintest_1.root"]
133  for i in range(len(full_list)):
134  main = basf2.Path()
135  main.add_module('RootInput', inputFileNames=full_list[:i + 1])
136  main.add_module("EventInfoPrinter")
137  safe_process(main)
138 
139  class BrokenEventsModule(basf2.Module):
140  """
141  Small module to mark all events except for the ones in the given list as
142  discarded by the HLT
143  """
144 
145  def __init__(self, accepted):
146  """
147  Initialize this nice class with the list/set of accepted event
148  numbers to see. Order not important. All other events will be flagged
149  as discarded.
150  """
151  super().__init__()
152 
153  self.emdemd = Belle2.PyStoreObj('EventMetaData')
154 
155  self._accepted_accepted = accepted
156 
157  def event(self):
158  """Set error flag if required"""
159  if self.emdemd.getEvent() not in self._accepted_accepted:
160  error = Belle2.EventMetaData.c_HLTDiscard if self.emdemd.getEvent() % 2 == 0 else \
161  Belle2.EventMetaData.c_HLTCrash
162  self.emdemd.addErrorFlag(error)
163 
164  main = basf2.Path()
165  main.add_module("EventInfoSetter", evtNumList=10)
166  main.add_module(BrokenEventsModule({3, 5, 6, 8}))
167  main.add_module("RootOutput", outputFileName="brokenevents.root")
168  assert safe_process(main) == 0
169 
170  main = basf2.Path()
171  main.add_module("RootInput", inputFileName="brokenevents.root")
172  main.add_module(TestingModule([3, 5, 6, 8]))
173  assert safe_process(main) == 0
a (simplified) python wrapper for StoreObjPtr.
Definition: PyStoreObj.h:67
_accepted
list/set of accepted events
Definition: root_input.py:155
def __init__(self, accepted)
Definition: root_input.py:145
_expected_event_numbers
list of expected event numbers
Definition: root_input.py:89
_processed_event_numbers
list of seen event numbers
Definition: root_input.py:91
def __init__(self, expected)
Definition: root_input.py:80