Belle II Software development
root_input.py
1#!/usr/bin/env python3
2
3
10
11import os
12import basf2
13from ROOT import Belle2
14from b2test_utils import safe_process, clean_working_directory
15
16basf2.conditions.disable_globaltag_replay()
17basf2.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
20basf2.logging.set_info(basf2.LogLevel.FATAL, basf2.logging.get_info(basf2.LogLevel.ERROR))
21basf2.logging.enable_summary(False)
22
23
24class NoopModule(basf2.Module):
25 """Doesn't do anything."""
26
27
28with 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, 7):
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, 1, 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.emd = Belle2.PyStoreObj('EventMetaData')
88
90
92
93 def event(self):
94 """
95 Called for each event
96 """
97 self._processed_event_numbers.append(self.emd.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
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, 1, 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, 1, 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.emd = Belle2.PyStoreObj('EventMetaData')
154
155 self._accepted = accepted
156
157 def event(self):
158 """Set error flag if required"""
159 if self.emd.getEvent() not in self._accepted:
160 error = Belle2.EventMetaData.c_HLTDiscard if self.emd.getEvent() % 2 == 0 else \
161 Belle2.EventMetaData.c_HLTCrash
162 self.emd.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