19from simulation
import add_simulation
20from rawdata
import add_packers
21from softwaretrigger
import constants
23from ROOT
import Belle2
27 """Test module for assuring correct data store content"""
30 """reimplementation of Module::event()."""
33 if not sft_trigger.isValid():
34 basf2.B2FATAL(
"SoftwareTriggerResult object not created")
35 elif len(sft_trigger.getResults()) == 0:
36 basf2.B2FATAL(
"SoftwareTriggerResult exists but has no entries")
39 basf2.B2FATAL(
"ROIs are not present")
42def get_file_name(base_path, run_type, location, passthrough, simulate_events_of_doom_buster):
45 mode +=
"_passthrough"
46 if simulate_events_of_doom_buster:
48 return os.path.join(base_path, f
"{location.name}_{run_type.name}{mode}.root")
51def generate_input_file(run_type, location, output_file_name, exp_number, passthrough,
52 simulate_events_of_doom_buster):
54 Generate an input file for usage
in the test.
55 Simulate uubar
for "beam" and two muons
for "cosmic" setting.
57 Only raw data will be stored to the given output file.
58 :param run_type: Whether to simulate cosmic
or beam
59 :param location: Whether to simulate expressreco (
with ROIs)
or hlt (no PXD)
60 :param output_file_name: where to store the result file
61 :param exp_number: which experiment number to simulate
62 :param passthrough:
if true don
't generate a trigger result in the input file
63 :param simulate_events_of_doom_buster: if true, simulate the effect of the
64 EventsOfDoomBuster module by inflating the number of CDC hits
66 if os.path.exists(output_file_name):
69 basf2.set_random_seed(12345)
72 path.add_module(
'EventInfoSetter', evtNumList=[4], expList=[exp_number])
74 if run_type == constants.RunTypes.beam:
76 elif run_type == constants.RunTypes.cosmic:
80 path.add_module(
"ParticleGun", pdgCodes=[-13, 13], momentumParams=[10, 200])
82 add_simulation(path, usePXDDataReduction=(location == constants.Location.expressreco))
86 if simulate_events_of_doom_buster:
88 class InflateCDCHits(basf2.Module):
89 """Artificially inflate the number of CDC hits."""
94 self.cdc_hits.isRequired()
96 if not eodb_parameters.isValid():
97 basf2.B2FATAL(
"EventsOfDoomParameters is not valid")
98 self.cdc_hits_threshold = eodb_parameters.getNCDCHitsMax() + 1
102 if self.cdc_hits.isValid():
104 for i
in range(self.cdc_hits_threshold):
105 self.cdc_hits.appendNew()
107 path.add_module(InflateCDCHits())
109 if location == constants.Location.hlt:
110 components = DEFAULT_HLT_COMPONENTS
111 elif location == constants.Location.expressreco:
112 components = DEFAULT_EXPRESSRECO_COMPONENTS
114 basf2.B2FATAL(f
"Location {location.name} for test is not supported")
116 components.append(
"TRG")
118 add_packers(path, components=components)
121 if location == constants.Location.expressreco
and not passthrough:
122 class FakeHLTResult(basf2.Module):
123 def initialize(self):
124 self.results =
Belle2.PyStoreObj(Belle2.SoftwareTriggerResult.Class(),
"SoftwareTriggerResult")
125 self.results.registerInDataStore()
130 self.results.create()
132 if (self.EventMetaData.obj().getEvent() == 1):
133 self.results.addResult(
"software_trigger_cut&all&total_result", 1)
134 self.results.addResult(
"software_trigger_cut&skim&accept_mumutight", 1)
135 self.results.addResult(
"software_trigger_cut&skim&accept_dstar_1", 1)
136 self.results.addResult(
"software_trigger_cut&filter&L1_trigger", 1)
138 elif (self.EventMetaData.obj().getEvent() == 2):
139 self.results.addResult(
"software_trigger_cut&all&total_result", 1)
140 self.results.addResult(
"software_trigger_cut&filter&L1_trigger", 1)
142 elif (self.EventMetaData.obj().getEvent() == 3):
143 self.results.addResult(
"software_trigger_cut&all&total_result", 1)
144 self.results.addResult(
"software_trigger_cut&skim&accept_mumutight", 1)
145 self.results.addResult(
"software_trigger_cut&skim&accept_dstar_1", 1)
146 self.results.addResult(
"software_trigger_cut&filter&L1_trigger", 0)
148 elif (self.EventMetaData.obj().getEvent() == 4):
149 self.results.addResult(
"software_trigger_cut&all&total_result", 0)
150 self.results.addResult(
"software_trigger_cut&skim&accept_mumutight", 1)
151 self.results.addResult(
"software_trigger_cut&skim&accept_dstar_1", 1)
152 self.results.addResult(
"software_trigger_cut&filter&L1_trigger", 0)
154 path.add_module(FakeHLTResult())
157 branch_names = RAWDATA_OBJECTS + [
"EventMetaData",
"TRGSummary"]
159 branch_names += [
"SoftwareTriggerResult"]
160 if location == constants.Location.hlt:
161 branch_names.remove(
"RawPXDs")
162 branch_names.remove(
"ROIs")
165 branch_names.remove(
"RawTRGs")
167 path.add_module(
"RootOutput", outputFileName=output_file_name, branchNames=branch_names)
174def test_script(script_location, input_file_name, temp_dir):
176 Test a script with the given file path using the given input file.
177 Raises an exception
if the execution fails
or if the needed output
is not in
179 The results are stored
in the temporary directory location.
181 :param script_location: the script to test
182 :param input_file_name: the file path of the input file
183 :param temp_dir: where to store
and run
185 input_buffer = "UNUSED"
186 output_buffer =
"UNUSED"
189 random_seed =
"".join(random.choices(
"abcdef", k=4))
191 histos_file_name = f
"{random_seed}_histos.root"
192 output_file_name = os.path.join(temp_dir, f
"{random_seed}_output.root")
193 globaltags = list(basf2.conditions.default_globaltags)
199 os.chdir(os.path.dirname(script_location))
200 cmd1 = [sys.executable, script_location,
"--central-db-tag"] + globaltags + [
201 "--input-file", os.path.abspath(input_file_name),
202 "--histo-output-file", os.path.join(temp_dir, f
"{histos_file_name}"),
203 "--output-file", os.path.abspath(output_file_name),
204 "--number-processes", str(num_processes),
205 input_buffer, output_buffer, str(histo_port)
207 subprocess.check_call(cmd1)
212 final_histos_file_name = os.path.join(temp_dir, histos_file_name)
213 if os.path.exists(histos_file_name):
214 shutil.copy(histos_file_name, os.path.join(temp_dir, final_histos_file_name))
215 os.unlink(histos_file_name)
220 if "beam_reco" in script_location:
222 if "expressreco" not in script_location
and "beam_reco" in script_location:
224 test_path = basf2.Path()
225 test_path.add_module(
"RootInput", inputFileName=output_file_name)
230 cmd2 = [
"hlt-check-dqm-size", final_histos_file_name]
231 subprocess.check_call(cmd2)
234def test_folder(location, run_type, exp_number, phase, passthrough=False,
235 simulate_events_of_doom_buster=False):
237 Run all hlt operation scripts in a given folder
238 and test the outputs of the files.
240 Will call the test_script function on all files
in the folder given
241 by the location after having created a suitable input file
with the given
244 :param location: hlt
or expressreco, depending on which operation files to run
245 and which input to simulate
246 :param run_type: cosmic
or beam, depending on which operation files to run
247 and which input to simulate
248 :param exp_number: which experiment number to simulate
249 :param phase: where to look
for the operation files (will search
in the folder
250 hlt/operation/{phase}/
global/{location}/evp_scripts/)
251 :param passthrough: only relevant
for express reco: If true don
't create a
252 software trigger result in the input file to test running
253 express reco
if hlt
is in passthrough mode
254 :param simulate_events_of_doom_buster:
if true, simulate the effect of the
255 EventsOfDoomBuster module by inflating the number of CDC hits
259 temp_dir = os.getcwd()
260 prepare_path = os.environ[
"BELLE2_PREPARE_PATH"]
261 input_file_name = get_file_name(
262 prepare_path, run_type, location, passthrough, simulate_events_of_doom_buster)
264 script_dir = basf2.find_file(f
"hlt/operation/{phase}/global/{location.name}/evp_scripts/")
265 run_at_least_one =
False
266 for script_location
in glob(os.path.join(script_dir, f
"run_{run_type.name}*.py")):
267 run_at_least_one =
True
268 test_script(script_location, input_file_name=input_file_name, temp_dir=temp_dir)
270 assert run_at_least_one
Class to access a DBObjPtr from Python.
A (simplified) python wrapper for StoreArray.
a (simplified) python wrapper for StoreObjPtr.
def safe_process(*args, **kwargs)
def add_continuum_generator(path, finalstate, userdecfile='', *skip_on_failure=True, eventType='')