9"""ECL timing calibration that performs the crystal and crate calibrations,
10 merges the relevant crystal payloads, and makes validation plots. It
is the
11 main script
for executing the ECL timing calibrations.
"""
13from prompt import CalibrationSettings, INPUT_DATA_FILTERS
14from reconstruction import prepare_cdst_analysis, prepare_user_cdst_analysis
15from caf.utils import IoV, ExpRun
18##############################
20##############################
21# Used to identify the keys in input_data that your get_calibrations function will need in order
22# to assign data correctly.
23# Will be used to construct the calibration in the automated system, as well as set up the submission web forms.
24# You can view the available input data formats from CalibrationSettings.allowed_data_formats
26## Tells the automated system some details of this script.
27# Default is to read
in "bhabha_all_calib" since we want to
30settings = CalibrationSettings(
31 name=
"ECL crystal and crate time calibrations and validations",
32 expert_username=
"hearty",
34 input_data_formats=[
"cdst"],
35 input_data_names=[
"bhabha_all_calib",
"hadron_calib"],
36 input_data_filters={
"bhabha_all_calib": [INPUT_DATA_FILTERS[
"Data Tag"][
"bhabha_all_calib"],
37 INPUT_DATA_FILTERS[
"Beam Energy"][
"4S"],
38 INPUT_DATA_FILTERS[
"Beam Energy"][
"Continuum"],
39 INPUT_DATA_FILTERS[
"Beam Energy"][
"Scan"],
40 INPUT_DATA_FILTERS[
"Data Quality Tag"][
"Good"],
41 INPUT_DATA_FILTERS[
"Run Type"][
"physics"],
42 INPUT_DATA_FILTERS[
"Magnet"][
"On"]],
43 "hadron_calib": [INPUT_DATA_FILTERS[
"Data Tag"][
"hadron_calib"],
44 INPUT_DATA_FILTERS[
"Beam Energy"][
"4S"],
45 INPUT_DATA_FILTERS[
"Beam Energy"][
"Continuum"],
46 INPUT_DATA_FILTERS[
"Beam Energy"][
"Scan"],
47 INPUT_DATA_FILTERS[
"Data Quality Tag"][
"Good"],
48 INPUT_DATA_FILTERS[
"Run Type"][
"physics"],
49 INPUT_DATA_FILTERS[
"Magnet"][
"On"]]},
51 expert_config={
"numCrysCrateIterations": 1,
52 "maxNumberEvents": 50000000,
53 "payload_boundaries": [],
54 "t0_bhabhaToHadron_correction": 0})
68def get_calibrations(input_data, **kwargs):
71 input_data (dict): Should contain every name from the
'input_data_names' variable
as a key.
72 Each value
is a dictionary
with {
"/path/to/file_e1_r5.root": IoV(1,5,1,5), ...}. Useful
for
73 assigning to calibration.files_to_iov
75 **kwargs: Configuration options to be sent
in. Since this may change we use kwargs
as a way to help prevent
76 backwards compatibility problems. But you could use the correct arguments
in b2caf-prompt-run
for this
77 release explicitly
if you want to.
79 Currently only kwargs[
"output_iov"]
is used. This
is the output IoV range that your payloads should
80 correspond to. Generally your highest ExpRun payload should be open ended e.g. IoV(3,4,-1,-1)
83 list(caf.framework.Calibration): All of the calibration objects we want to assign to the CAF process
90 expert_config = kwargs.get(
"expert_config")
94 numCrysCrateIterations = expert_config[
"numCrysCrateIterations"]
95 print(
"expert_config: numCrysCrateIterations = ", numCrysCrateIterations)
102 maxNumEventsCrystalCalib = expert_config[
"maxNumberEvents"]
103 print(
"expert_config: maxNumEventsCrystalCalib = ", maxNumEventsCrystalCalib)
107 t0_bhabhaToHadron_correction = expert_config[
"t0_bhabhaToHadron_correction"]
108 print(
"expert_config: t0_bhabhaToHadron_correction = ", t0_bhabhaToHadron_correction)
110 from caf.strategies
import SimpleRunByRun, SingleIOV, SequentialBoundaries
117 payload_boundaries = []
118 payload_boundaries.extend([ExpRun(*boundary)
for boundary
in expert_config[
"payload_boundaries"]])
119 basf2.B2INFO(f
"Expert set payload boundaries are: {expert_config['payload_boundaries']}")
120 print(
"payload_boundaries = ", payload_boundaries)
126 file_to_iov_bhabha = input_data[
"bhabha_all_calib"]
127 file_to_iov_hadron = input_data[
"hadron_calib"]
134 max_files_per_run_calibration = 26
135 max_files_per_run_validation = 4
136 max_events_per_run_plotting = 1
138 setMaxEventsPerCrystalCalib =
True
139 max_events_per_crystalCalib = 50000000
140 if (maxNumEventsCrystalCalib == -1):
141 setMaxEventsPerCrystalCalib =
False
142 elif (maxNumEventsCrystalCalib > 0):
143 max_events_per_crystalCalib = maxNumEventsCrystalCalib
145 print(
"max_events_per_crystalCalib = ", max_events_per_crystalCalib)
158 from prompt.utils import filter_by_select_max_events_from_files
160 reduced_file_to_iov_bhabha = filter_by_max_files_per_run(file_to_iov_bhabha, max_files_per_run_calibration)
161 input_files_bhabha = list(reduced_file_to_iov_bhabha.keys())
162 basf2.B2INFO(f
"Total number of bhabha files actually used as input for crates = {len(input_files_bhabha)}")
164 reduced_file_to_iov_bhabha_1perRun = filter_by_max_files_per_run(file_to_iov_bhabha, 1)
165 input_files_bhabha_1perRun = list(reduced_file_to_iov_bhabha_1perRun.keys())
166 basf2.B2INFO(f
"Total number of bhabha files actually used for dummy collectors = {len(input_files_bhabha_1perRun)}")
168 input_files_bhabha_full = list(file_to_iov_bhabha.keys())
169 basf2.B2INFO(f
"Total number of bhabha files as input = {len(input_files_bhabha_full)}")
171 if (setMaxEventsPerCrystalCalib):
172 temp_input_files_bhabha_full = input_files_bhabha_full.copy()
173 input_files_bhabha_crystal_maxEvents = filter_by_select_max_events_from_files(
174 temp_input_files_bhabha_full, max_events_per_crystalCalib)
175 basf2.B2INFO(
"Total number of bhabha files that could be used as input for crystal calibration ...")
176 basf2.B2INFO(f
"(ignoring payload boundaries) if a max # events is used = {len(input_files_bhabha_crystal_maxEvents)}")
178 if not input_files_bhabha_crystal_maxEvents:
179 input_files_bhabha_crystal_maxEvents = input_files_bhabha_full.copy()
180 print(
"Number of events < maximum so set the input files list equal to the full list of input bhabha files.")
182 input_files_bhabha_crystal = input_files_bhabha_full.copy()
183 if (setMaxEventsPerCrystalCalib):
184 input_files_bhabha_crystal = input_files_bhabha_crystal_maxEvents.copy()
185 print(
"List of input files slimmed for crystals.")
187 print(
"User requested max number of events filter to not be used so all bhabha input files being used for crystals")
189 basf2.B2INFO(f
"Total number of bhabha files being used for crystal calibration = {len(input_files_bhabha_crystal)}")
191 reduced_file_to_iov_hadron = filter_by_max_files_per_run(file_to_iov_hadron, max_files_per_run_validation)
192 input_files_hadron = list(reduced_file_to_iov_hadron.keys())
193 basf2.B2INFO(f
"Total number of hadron files actually used as input = {len(input_files_hadron)}")
198 reduced_file_to_iov_plotting = filter_by_max_events_per_run(file_to_iov_bhabha, max_events_per_run_plotting)
199 input_files_plotting = list(reduced_file_to_iov_plotting.keys())
202 intermediate_iov = IoV(0, 0, -1, -1)
203 requested_iov = kwargs.get(
"requested_iov",
None)
204 output_iov = IoV(requested_iov.exp_low, requested_iov.run_low, -1, -1)
207 from basf2
import register_module, create_path
208 from ROOT
import Belle2
209 from caf.framework
import Collection
213 print(
"Set up the base for the collectors for the calibrations")
215 root_input = register_module(
'RootInput')
216 rec_path_bhabha = create_path()
217 rec_path_bhabha.add_module(root_input)
218 if 'Gearbox' not in rec_path_bhabha:
219 rec_path_bhabha.add_module(
'Gearbox')
220 if 'Geometry' not in rec_path_bhabha:
221 rec_path_bhabha.add_module(
'Geometry', useDB=
True)
223 prepare_cdst_analysis(rec_path_bhabha, components=[
'SVD',
'CDC',
'ECL',
'KLM'])
226 t0BiasCorrection = t0_bhabhaToHadron_correction
229 col_bhabha = register_module(
'ECLBhabhaTCollector')
230 col_bhabha.param(
'timeAbsMax', 250)
231 col_bhabha.param(
'minCrystal', 1)
232 col_bhabha.param(
'maxCrystal', 8736)
233 col_bhabha.param(
'saveTree',
False)
234 col_bhabha.param(
'skipTrgSel',
False)
235 col_bhabha.param(
'hadronEventT0_TO_bhabhaEventT0_correction', t0BiasCorrection)
238 input_files=input_files_bhabha,
239 pre_collector_path=rec_path_bhabha)
241 eclTCol_crys =
Collection(collector=col_bhabha,
242 input_files=input_files_bhabha_crystal,
243 pre_collector_path=rec_path_bhabha)
247 print(
"Set up the base for the crate calibration algorithm")
254 eclTAlgCrates.cellIDLo = 3
255 eclTAlgCrates.cellIDHi = 2
256 eclTAlgCrates.debugOutput =
True
257 eclTAlgCrates.meanCleanRebinFactor = 3
258 eclTAlgCrates.meanCleanCutMinFactor = 0.3
259 eclTAlgCrates.debugFilenameBase =
"eclBhabhaTAlgorithm"
263 print(
"Set up the base for the crystal calibration algorithm")
270 eclTAlgCrystals.crateIDLo = 3
271 eclTAlgCrystals.crateIDHi = 2
272 eclTAlgCrystals.debugOutput =
True
273 eclTAlgCrystals.meanCleanRebinFactor = 3
274 eclTAlgCrystals.meanCleanCutMinFactor = 0.3
275 eclTAlgCrystals.debugFilenameBase =
"eclBhabhaTAlgorithm"
281 eclTAlgCrystals_saveNotReadPrevPayload = copy.deepcopy(eclTAlgCrystals)
282 eclTAlgCrystals_readNotSavePrevPayload = copy.deepcopy(eclTAlgCrystals)
284 eclTAlgCrystals_saveNotReadPrevPayload.savePrevCrysPayload =
True
285 eclTAlgCrystals_saveNotReadPrevPayload.readPrevCrysPayload =
False
287 eclTAlgCrystals_readNotSavePrevPayload.savePrevCrysPayload =
False
288 eclTAlgCrystals_readNotSavePrevPayload.readPrevCrysPayload =
True
292 print(
"Set up the base for the crystal merger algorithm")
295 merging_alg.readPrevCrysPayload =
True
304 if numCrysCrateIterations <= 0:
305 print(
"numCrysCrateIterations NEEDS TO BE > 0 !!!")
306 elif numCrysCrateIterations > 0:
310 from caf.framework
import Calibration
311 print(
"Performing ", numCrysCrateIterations,
" iterations of crate and crystal calibrations.")
313 crysCalibBaseName =
"ECLcrystalTimeCalibration_physics_"
314 crateCalibBaseName =
"ECLcrateTimeCalibration_physics_"
315 mergeCalibBaseName =
"ecl_t_merge_"
323 for i
in range(numCrysCrateIterations):
324 crysCalibName = crysCalibBaseName + str(i)
325 crateCalibName = crateCalibBaseName + str(i)
326 mergeCalibName = mergeCalibBaseName + str(i)
328 print(
"iteration = ", i)
329 print(
"crysCalibName = ", crysCalibName)
330 print(
"crateCalibName = ", crateCalibName)
335 cal_crates_i.add_collection(name=
"bhabha", collection=eclTCol)
336 cal_crates_i.algorithms = [eclTAlgCrates]
337 cal_crates_i.save_payloads =
False
338 cal_crates_i.strategies = SimpleRunByRun
339 cal_crates_i.backend_args = {
"request_memory":
"4 GB"}
345 cal_crystals_i.add_collection(name=
"bhabha", collection=eclTCol_crys)
346 cal_crystals_i.backend_args = {
"request_memory":
"4 GB"}
352 cal_crystals_i.algorithms = [eclTAlgCrystals_saveNotReadPrevPayload]
353 print(
"crystal algorithm: save previous payload for comparison purposes but do not read it")
354 print(
"eclTAlgCrystals_saveNotReadPrevPayload.savePrevCrysPayload = ",
355 eclTAlgCrystals_saveNotReadPrevPayload.savePrevCrysPayload)
356 print(
"eclTAlgCrystals_saveNotReadPrevPayload.readPrevCrysPayload = ",
357 eclTAlgCrystals_saveNotReadPrevPayload.readPrevCrysPayload)
359 cal_crystals_i.algorithms = [eclTAlgCrystals_readNotSavePrevPayload]
360 print(
"crystal algorithm: do not save previous payload but do read it in for comparison purposes")
361 print(
"eclTAlgCrystals_readNotSavePrevPayload.savePrevCrysPayload = ",
362 eclTAlgCrystals_readNotSavePrevPayload.savePrevCrysPayload)
363 print(
"eclTAlgCrystals_readNotSavePrevPayload.readPrevCrysPayload = ",
364 eclTAlgCrystals_readNotSavePrevPayload.readPrevCrysPayload)
366 cal_crystals_i.save_payloads =
False
370 if payload_boundaries:
371 cal_crystals_i.strategies = SequentialBoundaries
373 cal_crystals_i.strategies = SingleIOV
378 cal_ecl_merge_i =
Calibration(name=mergeCalibName, collector=
"DummyCollector",
379 input_files=input_files_bhabha_1perRun)
382 cal_ecl_merge_i.algorithms = [merging_alg]
383 print(
"merge algorithm: read previous payload for comparison purposes")
384 print(
"merging_alg.readPrevCrysPayload = ", merging_alg.readPrevCrysPayload)
386 cal_ecl_merge_i.save_payloads =
False
387 ecl_merge_pre_path_i = basf2.create_path()
388 prepare_cdst_analysis(ecl_merge_pre_path_i, components=[
'SVD',
'CDC',
'ECL',
'KLM'])
389 ecl_merge_pre_path_i.pre_collector_path = ecl_merge_pre_path_i
393 if payload_boundaries:
394 cal_ecl_merge_i.strategies = SequentialBoundaries
396 cal_ecl_merge_i.strategies = SingleIOV
399 for algorithm
in cal_crystals_i.algorithms:
402 if i == numCrysCrateIterations - 1:
405 if payload_boundaries:
406 algorithm.params = {
"iov_coverage": output_iov,
407 "payload_boundaries": payload_boundaries}
409 print(
"Set iov for final crystals alg - SequentialBoundaries")
411 algorithm.params = {
"apply_iov": output_iov}
412 print(
"Set iov for final crystals alg - SingleIOV ")
416 if payload_boundaries:
417 algorithm.params = {
"iov_coverage": intermediate_iov,
418 "payload_boundaries": payload_boundaries}
419 print(
"Set iov for intermediate crystals alg - SequentialBoundaries")
421 algorithm.params = {
"apply_iov": intermediate_iov}
422 print(
"Set iov for intermediate crystals alg - SingleIOV ")
425 for algorithm
in cal_ecl_merge_i.algorithms:
428 if i == numCrysCrateIterations - 1:
431 if payload_boundaries:
432 algorithm.params = {
"iov_coverage": output_iov,
433 "payload_boundaries": payload_boundaries}
435 print(
"Set iov for final merging alg - SequentialBoundaries")
437 algorithm.params = {
"apply_iov": output_iov}
438 print(
"Set iov for final merging alg - SingleIOV ")
442 if payload_boundaries:
443 algorithm.params = {
"iov_coverage": intermediate_iov,
444 "payload_boundaries": payload_boundaries}
445 print(
"Set iov for intermediate merging alg - SequentialBoundaries")
447 algorithm.params = {
"apply_iov": intermediate_iov}
448 print(
"Set iov for intermediate merging alg - SingleIOV ")
451 calibs = np.append(calibs, [cal_crates_i, cal_crystals_i, cal_ecl_merge_i])
454 calibs[len(calibs) - 3].save_payloads =
True
455 calibs[len(calibs) - 1].save_payloads =
True
466 root_input = register_module(
'RootInput')
467 rec_path_bhabha_val = create_path()
468 rec_path_bhabha_val.add_module(root_input)
469 if 'Gearbox' not in rec_path_bhabha_val:
470 rec_path_bhabha_val.add_module(
'Gearbox')
471 if 'Geometry' not in rec_path_bhabha_val:
472 rec_path_bhabha_val.add_module(
'Geometry', useDB=
True)
475 prepare_user_cdst_analysis(rec_path_bhabha_val, components=[
'SVD',
'CDC',
'ECL',
'KLM'])
476 col_bhabha_val = register_module(
'eclBhabhaTimeCalibrationValidationCollector')
477 col_bhabha_val.param(
'timeAbsMax', 70)
478 col_bhabha_val.param(
'saveTree',
False)
479 col_bhabha_val.param(
'skipTrgSel',
False)
481 eclValTCol =
Collection(collector=col_bhabha_val,
482 input_files=input_files_bhabha_crystal,
483 pre_collector_path=rec_path_bhabha_val)
493 eclValTAlgBhabha.meanCleanRebinFactor = 3
494 eclValTAlgBhabha.meanCleanCutMinFactor = 0.4
495 eclValTAlgBhabha.clusterTimesFractionWindow_maxtime = 1.5
496 eclValTAlgBhabha.debugFilenameBase =
"eclBhabhaTValidationAlgorithm"
501 from caf.framework
import Calibration
503 valid_cal_bhabha =
Calibration(
"ECLcrystalTimeCalValidation_bhabhaPhysics")
504 valid_cal_bhabha.add_collection(name=
"bhabha", collection=eclValTCol)
505 valid_cal_bhabha.save_payloads =
False
506 valid_cal_bhabha.backend_args = {
"request_memory":
"4 GB"}
512 eclValTAlgBhabha_readPrevPayload = copy.deepcopy(eclValTAlgBhabha)
513 eclValTAlgBhabha_readPrevPayload.readPrevCrysPayload =
True
515 valid_cal_bhabha.algorithms = [eclValTAlgBhabha_readPrevPayload]
516 print(
"bhabha validation: read previous payload for comparison purposes")
517 print(
"eclValTAlgBhabha_readPrevPayload.readPrevCrysPayload = ",
518 eclValTAlgBhabha_readPrevPayload.readPrevCrysPayload)
522 if payload_boundaries:
523 valid_cal_bhabha.strategies = SequentialBoundaries
525 valid_cal_bhabha.strategies = SingleIOV
527 for algorithm
in valid_cal_bhabha.algorithms:
530 if payload_boundaries:
531 algorithm.params = {
"iov_coverage": output_iov,
532 "payload_boundaries": payload_boundaries}
534 print(
"Set iov for bhabha validation alg - SequentialBoundaries")
536 algorithm.params = {
"apply_iov": output_iov}
537 print(
"Set iov for bhabha validation alg - SingleIOV")
542 root_input = register_module(
'RootInput')
543 rec_path_hadron_val = create_path()
544 rec_path_hadron_val.add_module(root_input)
545 if 'Gearbox' not in rec_path_hadron_val:
546 rec_path_hadron_val.add_module(
'Gearbox')
547 if 'Geometry' not in rec_path_hadron_val:
548 rec_path_hadron_val.add_module(
'Geometry', useDB=
True)
551 prepare_user_cdst_analysis(rec_path_hadron_val, components=[
'SVD',
'CDC',
'ECL',
'KLM'])
552 col_hadron_val = register_module(
'eclHadronTimeCalibrationValidationCollector')
553 col_hadron_val.param(
'timeAbsMax', 70)
554 col_hadron_val.param(
'saveTree',
False)
556 eclValTCol =
Collection(collector=col_hadron_val,
557 input_files=input_files_hadron,
558 pre_collector_path=rec_path_hadron_val)
568 eclValTAlgHadronic.meanCleanRebinFactor = 3
569 eclValTAlgHadronic.meanCleanCutMinFactor = 0.4
570 eclValTAlgHadronic.clusterTimesFractionWindow_maxtime = 8
571 eclValTAlgHadronic.debugFilenameBase =
"eclHadronTValidationAlgorithm"
576 from caf.framework
import Calibration
578 valid_cal_hadron =
Calibration(
"ECLcrystalTimeCalValidation_hadronPhysics")
579 valid_cal_hadron.add_collection(name=
"hadron", collection=eclValTCol)
580 valid_cal_hadron.save_payloads =
False
581 valid_cal_hadron.backend_args = {
"request_memory":
"4 GB"}
585 eclValTAlgHadron_readPrevPayload = copy.deepcopy(eclValTAlgHadronic)
586 eclValTAlgHadron_readPrevPayload.readPrevCrysPayload =
True
592 valid_cal_hadron.algorithms = [eclValTAlgHadron_readPrevPayload]
593 print(
"hadron validation: read previous payload for comparison purposes")
594 print(
"eclValTAlgHadron_readPrevPayload.readPrevCrysPayload = ",
595 eclValTAlgHadron_readPrevPayload.readPrevCrysPayload)
599 if payload_boundaries:
600 valid_cal_hadron.strategies = SequentialBoundaries
602 valid_cal_hadron.strategies = SingleIOV
604 for algorithm
in valid_cal_hadron.algorithms:
607 if payload_boundaries:
608 algorithm.params = {
"iov_coverage": output_iov,
609 "payload_boundaries": payload_boundaries}
611 print(
"Set iov for hadron validation alg - SequentialBoundaries")
613 algorithm.params = {
"apply_iov": output_iov}
614 print(
"Set iov for hadron validation alg - SingleIOV")
621 root_input = register_module(
'RootInput', entrySequences=[f
'0:{1}'])
623 rec_path_bhabha_plotting = create_path()
624 rec_path_bhabha_plotting.add_module(root_input)
625 if 'Gearbox' not in rec_path_bhabha_plotting:
626 rec_path_bhabha_plotting.add_module(
'Gearbox')
627 if 'Geometry' not in rec_path_bhabha_plotting:
628 rec_path_bhabha_plotting.add_module(
'Geometry', useDB=
True)
630 prepare_cdst_analysis(rec_path_bhabha_plotting, components=[
'SVD',
'CDC',
'ECL',
'KLM'])
632 col_bhabha_plotting = register_module(
'eclTimeShiftsPlottingCollector')
633 eclTCol =
Collection(collector=col_bhabha_plotting,
634 input_files=input_files_plotting,
635 pre_collector_path=rec_path_bhabha_plotting)
642 tShifts_alg.debugFilenameBase =
"eclTimeShiftsAlgorithm"
645 tShifts_alg.crysCrateShift_min = -30
646 tShifts_alg.crysCrateShift_max = 30
651 cal_ecl_timeShifts =
Calibration(name=
"ecl_t_shifts", algorithms=[tShifts_alg],
652 input_files=input_files_plotting)
653 cal_ecl_timeShifts.add_collection(name=
"bhabha", collection=eclTCol)
655 cal_ecl_timeShifts.save_payloads =
False
659 if payload_boundaries:
660 cal_ecl_timeShifts.strategies = SequentialBoundaries
662 cal_ecl_timeShifts.strategies = SingleIOV
664 for algorithm
in cal_ecl_timeShifts.algorithms:
667 if payload_boundaries:
668 algorithm.params = {
"iov_coverage": output_iov,
669 "payload_boundaries": payload_boundaries}
671 print(
"Set iov for crate time plotting alg - SequentialBoundaries")
673 algorithm.params = {
"apply_iov": output_iov}
674 print(
"Set iov for crate time plotting alg - SingleIOV")
684 for i
in range(len(calibs) - 1):
685 calibs[i + 1].depends_on(calibs[i])
689 valid_cal_bhabha.depends_on(calibs[len(calibs) - 1])
690 valid_cal_hadron.depends_on(calibs[len(calibs) - 1])
691 cal_ecl_timeShifts.depends_on(calibs[len(calibs) - 1])
696 calibs = np.append(calibs, [valid_cal_bhabha, valid_cal_hadron, cal_ecl_timeShifts])
698 print(
"##############")
699 print(
"List of calibrations:")
701 print(
" ", c.name,
" depends on ", c.dependencies,
", save payloads = ", c.save_payloads)
702 print(
"##############")
Calibrate ecl crystals using bhabha events.
Calibrate ecl crystals using previously created payloads.
Validate the ecl timing calibrations using a hadronic event selection.
Calibrate ecl crystals using previously created payloads.