3 """Custom calibration strategy for KLM strip efficiency."""
9 from ROOT
import Belle2
11 from caf.utils
import ExpRun, IoV, AlgResult
12 from caf.utils
import runs_overlapping_iov, runs_from_vector
13 from caf.utils
import split_runs_by_exp
14 from caf.strategies
import AlgorithmStrategy
15 from caf.state_machines
import AlgorithmMachine
16 from ROOT.Belle2
import KLMStripEfficiencyAlgorithm
17 from klm_strategies_common
import get_lowest_exprun, get_highest_exprun, \
18 calibration_result_string
23 Custom strategy for executing the KLM strip efficiency. Requires complex
26 This uses a `caf.state_machines.AlgorithmMachine` to actually execute
27 the various steps rather than operating on a CalibrationAlgorithm
33 usable_params = {
'iov_coverage': IoV}
42 self.
machine = AlgorithmMachine(self.algorithm)
46 def run(self, iov, iteration, queue):
48 Runs the algorithm machine over the collected data and
51 if not self.is_valid():
52 raise StrategyError(
'The strategy KLMStripEfficiency was not '
57 basf2.B2INFO(f
'Setting up {self.__class__.__name__} strategy '
58 f
'for {self.algorithm.name}')
61 machine_params[
'database_chain'] = self.database_chain
62 machine_params[
'dependent_databases'] = self.dependent_databases
63 machine_params[
'output_dir'] = self.output_dir
64 machine_params[
'output_database_dir'] = self.output_database_dir
65 machine_params[
'input_files'] = self.input_files
66 machine_params[
'ignored_runs'] = self.ignored_runs
67 self.
machine.setup_from_dict(machine_params)
69 basf2.B2INFO(f
'Starting AlgorithmMachine of {self.algorithm.name}')
70 self.algorithm.algorithm.setCalibrationStage(
71 KLMStripEfficiencyAlgorithm.c_EfficiencyMeasurement)
74 self.
machine.setup_algorithm(iteration=iteration)
76 basf2.B2INFO(f
'Beginning execution of {self.algorithm.name} using '
77 f
'strategy {self.__class__.__name__}')
80 runs = self.algorithm.algorithm.getRunListFromAllData()
81 all_runs_collected = set(runs_from_vector(runs))
84 runs_to_execute = runs_overlapping_iov(iov, all_runs_collected)
86 runs_to_execute = all_runs_collected
89 basf2.B2INFO(f
'Removing the ignored_runs from the runs '
90 f
'to execute for {self.algorithm.name}')
91 runs_to_execute.difference_update(set(self.ignored_runs))
94 runs_to_execute = sorted(runs_to_execute)
95 runs_to_execute = split_runs_by_exp(runs_to_execute)
99 if 'iov_coverage' in self.algorithm.params:
100 iov_coverage = self.algorithm.params[
'iov_coverage']
103 number_of_experiments = len(runs_to_execute)
104 for i_exp, run_list
in enumerate(runs_to_execute, start=1):
105 lowest_exprun = get_lowest_exprun(number_of_experiments, i_exp,
106 run_list, iov_coverage)
107 highest_exprun = get_highest_exprun(number_of_experiments, i_exp,
108 run_list, iov_coverage)
110 lowest_exprun, highest_exprun)
113 self.send_result(self.
machine.result)
114 if (self.
machine.result.result == AlgResult.ok.value)
or \
115 (self.
machine.result.result == AlgResult.iterate.value):
116 self.send_final_state(self.COMPLETED)
118 self.send_final_state(self.FAILED)
121 calibration_stage, output_file):
123 Execute over run list.
129 self.
machine.algorithm.algorithm.setForcedCalibration(
131 self.
machine.algorithm.algorithm.setCalibrationStage(calibration_stage)
132 if (output_file
is not None):
133 self.
machine.algorithm.algorithm.setOutputFileName(output_file)
134 self.
machine.execute_runs(runs=run_list, iteration=iteration,
136 if (self.
machine.result.result == AlgResult.ok.value)
or \
137 (self.
machine.result.result == AlgResult.iterate.value):
143 lowest_exprun, highest_exprun):
145 Process runs from experiment.
153 for exp_run
in experiment_runs:
155 [exp_run], iteration,
False,
156 KLMStripEfficiencyAlgorithm.c_MeasurablePlaneCheck,
None)
157 result = self.
machine.result.result
158 algorithm_results = KLMStripEfficiencyAlgorithm.Results(
159 self.
machine.algorithm.algorithm.getResults())
162 if (algorithm_results.getExtHits() > 0):
163 run_data.append([exp_run.run, result, [exp_run],
164 algorithm_results,
'',
None])
165 result_str = calibration_result_string(result)
166 basf2.B2INFO(
'Run %d: %s.' % (exp_run.run, result_str))
169 run_data.sort(key=
lambda x: x[0])
174 while (i < len(run_data)):
175 if (run_data[i][1] == 2):
177 while (run_data[j][1] == 2):
179 if (j >= len(run_data)):
181 run_ranges.append([i, j])
188 def can_merge(run_data, run_not_enough_data, run_normal):
189 return run_data[run_not_enough_data][3].newExtHitsPlanes(
190 run_data[run_normal][3].getExtHitsPlane()) == 0
192 for run_range
in run_ranges:
193 next_run = run_range[1]
197 if (next_run < len(run_data)):
198 while (i >= run_range[0]):
199 if (can_merge(run_data, i, next_run)):
200 basf2.B2INFO(
'Run %d (not enough data) can be merged '
201 'into the next normal run %d.' %
202 (run_data[i][0], run_data[next_run][0]))
203 run_data[i][4] =
'next'
205 basf2.B2INFO(
'Run %d (not enough data) cannot be '
206 'merged into the next normal run %d, '
207 'will try the previous one.' %
208 (run_data[i][0], run_data[next_run][0]))
211 if (i < run_range[0]):
213 previous_run = run_range[0] - 1
214 if (previous_run >= 0):
216 if (can_merge(run_data, j, previous_run)):
217 basf2.B2INFO(
'Run %d (not enough data) can be merged '
218 'into the previous normal run %d.' %
220 run_data[previous_run][0]))
221 run_data[j][4] =
'previous'
223 basf2.B2INFO(
'Run %d (not enough data) cannot be '
224 'merged into the previous normal run %d.' %
226 run_data[previous_run][0]))
231 basf2.B2INFO(
'A range of runs with not enough data is found '
232 'that cannot be merged into neither previous nor '
233 'next normal run: from %d to %d.' %
234 (run_data[j][0], run_data[i][0]))
236 run_data[j][4] =
'none'
243 while (i < len(run_data) - 1):
244 while ((run_data[i][1] == 2)
and (run_data[i + 1][1] == 2)):
245 if (run_data[i][4] != run_data[i + 1][4]):
247 basf2.B2INFO(
'Merging run %d (not enough data) into '
248 'run %d (not enough data).' %
249 (run_data[i + 1][0], run_data[i][0]))
250 run_data[i][2].extend(run_data[i + 1][2])
253 run_data[i][2], iteration,
False,
254 KLMStripEfficiencyAlgorithm.c_MeasurablePlaneCheck,
None)
255 run_data[i][1] = self.
machine.result.result
256 run_data[i][3] = KLMStripEfficiencyAlgorithm.Results(
257 self.
machine.algorithm.algorithm.getResults())
258 result_str = calibration_result_string(run_data[i][1])
259 basf2.B2INFO(
'Run %d: %s.' % (run_data[i][0], result_str))
260 if (i >= len(run_data) - 1):
265 def merge_runs(run_data, run_not_enough_data, run_normal, forced):
266 basf2.B2INFO(
'Merging run %d (not enough data) into '
268 (run_data[run_not_enough_data][0],
269 run_data[run_normal][0]))
270 run_data[run_normal][2].extend(run_data[run_not_enough_data][2])
272 run_data[run_normal][2], iteration, forced,
273 KLMStripEfficiencyAlgorithm.c_MeasurablePlaneCheck,
None)
274 run_data[run_normal][1] = self.
machine.result.result
275 run_data[run_normal][3] = KLMStripEfficiencyAlgorithm.Results(
276 self.
machine.algorithm.algorithm.getResults())
277 result_str = calibration_result_string(run_data[run_normal][1])
278 basf2.B2INFO(
'Run %d: %s.' % (run_data[run_normal][0], result_str))
279 if (run_data[run_normal][1] != 0):
280 basf2.B2FATAL(
'Merging run %d into run %d failed.' %
281 (run_data[run_not_enough_data][0],
282 run_data[run_normal][0]))
283 del run_data[run_not_enough_data]
286 while (i < len(run_data)):
287 if (run_data[i][1] == 2):
288 if (run_data[i][4] ==
'next'):
289 merge_runs(run_data, i, i + 1,
False)
290 elif (run_data[i][4] ==
'previous'):
291 merge_runs(run_data, i, i - 1,
False)
297 while (i < len(run_data)):
298 if (run_data[i][1] == 2
and run_data[i][4] ==
'none'):
299 new_planes_previous = -1
301 if (i < len(run_data) - 1):
302 new_planes_next = run_data[i][3].newExtHitsPlanes(
303 run_data[i + 1][3].getExtHitsPlane())
304 basf2.B2INFO(
'There are %d new active modules in run %d '
305 'relatively to run %d.' %
306 (new_planes_next, run_data[i][0],
309 new_planes_previous = run_data[i][3].newExtHitsPlanes(
310 run_data[i - 1][3].getExtHitsPlane())
311 basf2.B2INFO(
'There are %d new active modules in run %d '
312 'relatively to run %d.' %
313 (new_planes_previous,
314 run_data[i][0], run_data[i - 1][0]))
323 if (new_planes_previous >= 0
and new_planes_next < 0):
324 run_for_merging = i - 1
325 elif (new_planes_previous < 0
and new_planes_next >= 0):
326 run_for_merging = i + 1
327 elif (new_planes_previous >= 0
and new_planes_next >= 0):
328 if (new_planes_previous < new_planes_next):
329 run_for_merging = i - 1
331 run_for_merging = i + 1
333 basf2.B2INFO(
'Cannot determine run for merging for run %d, '
334 'performing its forced calibration.' %
337 run_data[i][2], iteration,
True,
338 KLMStripEfficiencyAlgorithm.c_MeasurablePlaneCheck,
340 run_data[i][1] = self.
machine.result.result
341 run_data[i][3] = KLMStripEfficiencyAlgorithm.Results(
342 self.
machine.algorithm.algorithm.getResults())
343 result_str = calibration_result_string(run_data[i][1])
344 basf2.B2INFO(
'Run %d: %s.' % (run_data[i][0], result_str))
345 if (run_data[i][1] != 0):
346 basf2.B2FATAL(
'Forced calibration of run %d failed.' %
348 if (run_for_merging >= 0):
349 merge_runs(run_data, i, run_for_merging,
True)
358 while (i < len(run_data)):
360 while (j < len(run_data)):
361 planes_differ =
False
362 if (run_data[j][3].newMeasuredPlanes(
363 run_data[i][3].getEfficiency()) != 0):
365 if (run_data[i][3].newMeasuredPlanes(
366 run_data[j][3].getEfficiency()) != 0):
369 basf2.B2INFO(
'Run %d: the set of planes is different '
371 % (run_data[j][0], run_data[i][0]))
374 basf2.B2INFO(
'Run %d: the set of planes is the same '
376 % (run_data[j][0], run_data[i][0]))
378 run_ranges.append([i, j])
384 if (
not os.path.isdir(
'efficiency')):
385 os.mkdir(
'efficiency')
388 def merge_runs_2(run_data, run_1, run_2, forced):
389 basf2.B2INFO(
'Merging run %d into run %d.' %
390 (run_data[run_2][0], run_data[run_1][0]))
391 run_data[run_1][2].extend(run_data[run_2][2])
392 output_file =
'efficiency/efficiency_%d_%d.root' % \
393 (run_data[run_1][2][0].exp, run_data[run_1][2][0].run)
395 run_data[run_1][2], iteration, forced,
396 KLMStripEfficiencyAlgorithm.c_EfficiencyMeasurement,
398 run_data[run_1][1] = self.
machine.result.result
399 run_data[run_1][3] = KLMStripEfficiencyAlgorithm.Results(
400 self.
machine.algorithm.algorithm.getResults())
401 run_data[run_1][5] = \
402 self.
machine.algorithm.algorithm.getPayloadValues()
403 result_str = calibration_result_string(run_data[run_1][1])
404 basf2.B2INFO(
'Run %d: %s; requested precision %f, achieved '
406 (run_data[run_1][0], result_str, 0.02,
408 run_data[run_1][3].getAchievedPrecision()))
410 for run_range
in run_ranges:
412 while (i < run_range[1]):
413 output_file =
'efficiency/efficiency_%d_%d.root' % \
414 (run_data[i][2][0].exp, run_data[i][2][0].run)
416 if (i == run_range[1] - 1):
417 forced_calibration =
True
419 forced_calibration =
False
421 run_data[i][2], iteration, forced_calibration,
422 KLMStripEfficiencyAlgorithm.c_EfficiencyMeasurement,
424 run_data[i][1] = self.
machine.result.result
425 run_data[i][3] = KLMStripEfficiencyAlgorithm.Results(
426 self.
machine.algorithm.algorithm.getResults())
428 self.
machine.algorithm.algorithm.getPayloadValues()
429 result_str = calibration_result_string(run_data[i][1])
430 basf2.B2INFO(
'Run %d: %s; requested precision %f, achieved '
432 (run_data[i][0], result_str, 0.02,
434 run_data[i][3].getAchievedPrecision()))
435 if (run_data[i][1] == 2):
437 while (j < run_range[1]):
440 if (j == run_range[1] - 1):
441 forced_calibration =
True
443 forced_calibration =
False
444 merge_runs_2(run_data, i, j, forced_calibration)
447 if (run_data[i][1] == 0):
454 while (i < len(run_data)):
455 if (run_data[i][1] == -1):
461 def commit_payload(run_data, run):
462 basf2.B2INFO(
'Writing run %d.' % (run_data[run][0]))
463 self.
machine.algorithm.algorithm.commit(run_data[run][5])
465 for i
in range(0, len(run_data)):
467 run_data[i][2].sort(key=
lambda x: x.run)
468 first_run = run_data[i][2][0].run
471 run_data[i][5].front().iov = \
475 iov = run_data[previous_run][5].front().iov
476 if (previous_run == 0):
477 run_data[previous_run][5].front().iov = \
479 lowest_exprun.exp, lowest_exprun.run,
480 experiment, first_run - 1)
482 run_data[previous_run][5].front().iov = \
484 experiment, first_run - 1)
485 commit_payload(run_data, previous_run)
490 if (i == len(run_data) - 1):
491 iov = run_data[i][5].front().iov
492 run_data[i][5].front().iov = \
494 experiment, iov.getRunLow(),
495 highest_exprun.exp, highest_exprun.run)
496 commit_payload(run_data, i)