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