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'])
227 t0BiasCorrection = t0_bhabhaToHadron_correction
230 col_bhabha = register_module(
'ECLBhabhaTCollector')
231 col_bhabha.param(
'timeAbsMax', 250)
232 col_bhabha.param(
'minCrystal', 1)
233 col_bhabha.param(
'maxCrystal', 8736)
234 col_bhabha.param(
'saveTree',
False)
235 col_bhabha.param(
'skipTrgSel',
False)
236 col_bhabha.param(
'hadronEventT0_TO_bhabhaEventT0_correction', t0BiasCorrection)
239 input_files=input_files_bhabha,
240 pre_collector_path=rec_path_bhabha)
242 eclTCol_crys =
Collection(collector=col_bhabha,
243 input_files=input_files_bhabha_crystal,
244 pre_collector_path=rec_path_bhabha)
248 print(
"Set up the base for the crate calibration algorithm")
255 eclTAlgCrates.cellIDLo = 3
256 eclTAlgCrates.cellIDHi = 2
257 eclTAlgCrates.debugOutput =
True
258 eclTAlgCrates.meanCleanRebinFactor = 3
259 eclTAlgCrates.meanCleanCutMinFactor = 0.3
260 eclTAlgCrates.debugFilenameBase =
"eclBhabhaTAlgorithm"
264 print(
"Set up the base for the crystal calibration algorithm")
271 eclTAlgCrystals.crateIDLo = 3
272 eclTAlgCrystals.crateIDHi = 2
273 eclTAlgCrystals.debugOutput =
True
274 eclTAlgCrystals.meanCleanRebinFactor = 3
275 eclTAlgCrystals.meanCleanCutMinFactor = 0.3
276 eclTAlgCrystals.debugFilenameBase =
"eclBhabhaTAlgorithm"
282 eclTAlgCrystals_saveNotReadPrevPayload = copy.deepcopy(eclTAlgCrystals)
283 eclTAlgCrystals_readNotSavePrevPayload = copy.deepcopy(eclTAlgCrystals)
285 eclTAlgCrystals_saveNotReadPrevPayload.savePrevCrysPayload =
True
286 eclTAlgCrystals_saveNotReadPrevPayload.readPrevCrysPayload =
False
288 eclTAlgCrystals_readNotSavePrevPayload.savePrevCrysPayload =
False
289 eclTAlgCrystals_readNotSavePrevPayload.readPrevCrysPayload =
True
293 print(
"Set up the base for the crystal merger algorithm")
296 merging_alg.readPrevCrysPayload =
True
305 if numCrysCrateIterations <= 0:
306 print(
"numCrysCrateIterations NEEDS TO BE > 0 !!!")
307 elif numCrysCrateIterations > 0:
311 from caf.framework
import Calibration
312 print(
"Performing ", numCrysCrateIterations,
" iterations of crate and crystal calibrations.")
314 crysCalibBaseName =
"ECLcrystalTimeCalibration_physics_"
315 crateCalibBaseName =
"ECLcrateTimeCalibration_physics_"
316 mergeCalibBaseName =
"ecl_t_merge_"
324 for i
in range(numCrysCrateIterations):
325 crysCalibName = crysCalibBaseName + str(i)
326 crateCalibName = crateCalibBaseName + str(i)
327 mergeCalibName = mergeCalibBaseName + str(i)
329 print(
"iteration = ", i)
330 print(
"crysCalibName = ", crysCalibName)
331 print(
"crateCalibName = ", crateCalibName)
336 cal_crates_i.add_collection(name=
"bhabha", collection=eclTCol)
337 cal_crates_i.algorithms = [eclTAlgCrates]
338 cal_crates_i.save_payloads =
False
339 cal_crates_i.strategies = SimpleRunByRun
340 cal_crates_i.backend_args = {
"request_memory":
"4 GB"}
346 cal_crystals_i.add_collection(name=
"bhabha", collection=eclTCol_crys)
347 cal_crystals_i.backend_args = {
"request_memory":
"4 GB"}
353 cal_crystals_i.algorithms = [eclTAlgCrystals_saveNotReadPrevPayload]
354 print(
"crystal algorithm: save previous payload for comparison purposes but do not read it")
355 print(
"eclTAlgCrystals_saveNotReadPrevPayload.savePrevCrysPayload = ",
356 eclTAlgCrystals_saveNotReadPrevPayload.savePrevCrysPayload)
357 print(
"eclTAlgCrystals_saveNotReadPrevPayload.readPrevCrysPayload = ",
358 eclTAlgCrystals_saveNotReadPrevPayload.readPrevCrysPayload)
360 cal_crystals_i.algorithms = [eclTAlgCrystals_readNotSavePrevPayload]
361 print(
"crystal algorithm: do not save previous payload but do read it in for comparison purposes")
362 print(
"eclTAlgCrystals_readNotSavePrevPayload.savePrevCrysPayload = ",
363 eclTAlgCrystals_readNotSavePrevPayload.savePrevCrysPayload)
364 print(
"eclTAlgCrystals_readNotSavePrevPayload.readPrevCrysPayload = ",
365 eclTAlgCrystals_readNotSavePrevPayload.readPrevCrysPayload)
367 cal_crystals_i.save_payloads =
False
371 if payload_boundaries:
372 cal_crystals_i.strategies = SequentialBoundaries
374 cal_crystals_i.strategies = SingleIOV
379 cal_ecl_merge_i =
Calibration(name=mergeCalibName, collector=
"DummyCollector",
380 input_files=input_files_bhabha_1perRun)
383 cal_ecl_merge_i.algorithms = [merging_alg]
384 print(
"merge algorithm: read previous payload for comparison purposes")
385 print(
"merging_alg.readPrevCrysPayload = ", merging_alg.readPrevCrysPayload)
387 cal_ecl_merge_i.save_payloads =
False
388 ecl_merge_pre_path_i = basf2.create_path()
389 prepare_cdst_analysis(ecl_merge_pre_path_i, components=[
'SVD',
'CDC',
'ECL',
'KLM'])
390 ecl_merge_pre_path_i.pre_collector_path = ecl_merge_pre_path_i
394 if payload_boundaries:
395 cal_ecl_merge_i.strategies = SequentialBoundaries
397 cal_ecl_merge_i.strategies = SingleIOV
400 for algorithm
in cal_crystals_i.algorithms:
403 if i == numCrysCrateIterations - 1:
406 if payload_boundaries:
407 algorithm.params = {
"iov_coverage": output_iov,
408 "payload_boundaries": payload_boundaries}
410 print(
"Set iov for final crystals alg - SequentialBoundaries")
412 algorithm.params = {
"apply_iov": output_iov}
413 print(
"Set iov for final crystals alg - SingleIOV ")
417 if payload_boundaries:
418 algorithm.params = {
"iov_coverage": intermediate_iov,
419 "payload_boundaries": payload_boundaries}
420 print(
"Set iov for intermediate crystals alg - SequentialBoundaries")
422 algorithm.params = {
"apply_iov": intermediate_iov}
423 print(
"Set iov for intermediate crystals alg - SingleIOV ")
426 for algorithm
in cal_ecl_merge_i.algorithms:
429 if i == numCrysCrateIterations - 1:
432 if payload_boundaries:
433 algorithm.params = {
"iov_coverage": output_iov,
434 "payload_boundaries": payload_boundaries}
436 print(
"Set iov for final merging alg - SequentialBoundaries")
438 algorithm.params = {
"apply_iov": output_iov}
439 print(
"Set iov for final merging alg - SingleIOV ")
443 if payload_boundaries:
444 algorithm.params = {
"iov_coverage": intermediate_iov,
445 "payload_boundaries": payload_boundaries}
446 print(
"Set iov for intermediate merging alg - SequentialBoundaries")
448 algorithm.params = {
"apply_iov": intermediate_iov}
449 print(
"Set iov for intermediate merging alg - SingleIOV ")
452 calibs = np.append(calibs, [cal_crates_i, cal_crystals_i, cal_ecl_merge_i])
455 calibs[len(calibs) - 3].save_payloads =
True
456 calibs[len(calibs) - 1].save_payloads =
True
467 root_input = register_module(
'RootInput')
468 rec_path_bhabha_val = create_path()
469 rec_path_bhabha_val.add_module(root_input)
470 if 'Gearbox' not in rec_path_bhabha_val:
471 rec_path_bhabha_val.add_module(
'Gearbox')
472 if 'Geometry' not in rec_path_bhabha_val:
473 rec_path_bhabha_val.add_module(
'Geometry', useDB=
True)
476 prepare_user_cdst_analysis(rec_path_bhabha_val, components=[
'SVD',
'CDC',
'ECL',
'KLM'])
477 col_bhabha_val = register_module(
'eclBhabhaTimeCalibrationValidationCollector')
478 col_bhabha_val.param(
'timeAbsMax', 70)
479 col_bhabha_val.param(
'saveTree',
False)
480 col_bhabha_val.param(
'skipTrgSel',
False)
482 eclValTCol =
Collection(collector=col_bhabha_val,
483 input_files=input_files_bhabha_crystal,
484 pre_collector_path=rec_path_bhabha_val)
494 eclValTAlgBhabha.meanCleanRebinFactor = 3
495 eclValTAlgBhabha.meanCleanCutMinFactor = 0.4
496 eclValTAlgBhabha.clusterTimesFractionWindow_maxtime = 1.5
497 eclValTAlgBhabha.debugFilenameBase =
"eclBhabhaTValidationAlgorithm"
502 from caf.framework
import Calibration
504 valid_cal_bhabha =
Calibration(
"ECLcrystalTimeCalValidation_bhabhaPhysics")
505 valid_cal_bhabha.add_collection(name=
"bhabha", collection=eclValTCol)
506 valid_cal_bhabha.save_payloads =
False
507 valid_cal_bhabha.backend_args = {
"request_memory":
"4 GB"}
513 eclValTAlgBhabha_readPrevPayload = copy.deepcopy(eclValTAlgBhabha)
514 eclValTAlgBhabha_readPrevPayload.readPrevCrysPayload =
True
516 valid_cal_bhabha.algorithms = [eclValTAlgBhabha_readPrevPayload]
517 print(
"bhabha validation: read previous payload for comparison purposes")
518 print(
"eclValTAlgBhabha_readPrevPayload.readPrevCrysPayload = ",
519 eclValTAlgBhabha_readPrevPayload.readPrevCrysPayload)
523 if payload_boundaries:
524 valid_cal_bhabha.strategies = SequentialBoundaries
526 valid_cal_bhabha.strategies = SingleIOV
528 for algorithm
in valid_cal_bhabha.algorithms:
531 if payload_boundaries:
532 algorithm.params = {
"iov_coverage": output_iov,
533 "payload_boundaries": payload_boundaries}
535 print(
"Set iov for bhabha validation alg - SequentialBoundaries")
537 algorithm.params = {
"apply_iov": output_iov}
538 print(
"Set iov for bhabha validation alg - SingleIOV")
543 root_input = register_module(
'RootInput')
544 rec_path_hadron_val = create_path()
545 rec_path_hadron_val.add_module(root_input)
546 if 'Gearbox' not in rec_path_hadron_val:
547 rec_path_hadron_val.add_module(
'Gearbox')
548 if 'Geometry' not in rec_path_hadron_val:
549 rec_path_hadron_val.add_module(
'Geometry', useDB=
True)
552 prepare_user_cdst_analysis(rec_path_hadron_val, components=[
'SVD',
'CDC',
'ECL',
'KLM'])
553 col_hadron_val = register_module(
'eclHadronTimeCalibrationValidationCollector')
554 col_hadron_val.param(
'timeAbsMax', 70)
555 col_hadron_val.param(
'saveTree',
False)
557 eclValTCol =
Collection(collector=col_hadron_val,
558 input_files=input_files_hadron,
559 pre_collector_path=rec_path_hadron_val)
569 eclValTAlgHadronic.meanCleanRebinFactor = 3
570 eclValTAlgHadronic.meanCleanCutMinFactor = 0.4
571 eclValTAlgHadronic.clusterTimesFractionWindow_maxtime = 8
572 eclValTAlgHadronic.debugFilenameBase =
"eclHadronTValidationAlgorithm"
577 from caf.framework
import Calibration
579 valid_cal_hadron =
Calibration(
"ECLcrystalTimeCalValidation_hadronPhysics")
580 valid_cal_hadron.add_collection(name=
"hadron", collection=eclValTCol)
581 valid_cal_hadron.save_payloads =
False
582 valid_cal_hadron.backend_args = {
"request_memory":
"4 GB"}
586 eclValTAlgHadron_readPrevPayload = copy.deepcopy(eclValTAlgHadronic)
587 eclValTAlgHadron_readPrevPayload.readPrevCrysPayload =
True
593 valid_cal_hadron.algorithms = [eclValTAlgHadron_readPrevPayload]
594 print(
"hadron validation: read previous payload for comparison purposes")
595 print(
"eclValTAlgHadron_readPrevPayload.readPrevCrysPayload = ",
596 eclValTAlgHadron_readPrevPayload.readPrevCrysPayload)
600 if payload_boundaries:
601 valid_cal_hadron.strategies = SequentialBoundaries
603 valid_cal_hadron.strategies = SingleIOV
605 for algorithm
in valid_cal_hadron.algorithms:
608 if payload_boundaries:
609 algorithm.params = {
"iov_coverage": output_iov,
610 "payload_boundaries": payload_boundaries}
612 print(
"Set iov for hadron validation alg - SequentialBoundaries")
614 algorithm.params = {
"apply_iov": output_iov}
615 print(
"Set iov for hadron validation alg - SingleIOV")
622 root_input = register_module(
'RootInput', entrySequences=[f
'0:{1}'])
624 rec_path_bhabha_plotting = create_path()
625 rec_path_bhabha_plotting.add_module(root_input)
626 if 'Gearbox' not in rec_path_bhabha_plotting:
627 rec_path_bhabha_plotting.add_module(
'Gearbox')
628 if 'Geometry' not in rec_path_bhabha_plotting:
629 rec_path_bhabha_plotting.add_module(
'Geometry', useDB=
True)
631 prepare_cdst_analysis(rec_path_bhabha_plotting, components=[
'SVD',
'CDC',
'ECL',
'KLM'])
633 col_bhabha_plotting = register_module(
'eclTimeShiftsPlottingCollector')
634 eclTCol =
Collection(collector=col_bhabha_plotting,
635 input_files=input_files_plotting,
636 pre_collector_path=rec_path_bhabha_plotting)
643 tShifts_alg.debugFilenameBase =
"eclTimeShiftsAlgorithm"
646 tShifts_alg.crysCrateShift_min = -30
647 tShifts_alg.crysCrateShift_max = 30
652 cal_ecl_timeShifts =
Calibration(name=
"ecl_t_shifts", algorithms=[tShifts_alg],
653 input_files=input_files_plotting)
654 cal_ecl_timeShifts.add_collection(name=
"bhabha", collection=eclTCol)
656 cal_ecl_timeShifts.save_payloads =
False
660 if payload_boundaries:
661 cal_ecl_timeShifts.strategies = SequentialBoundaries
663 cal_ecl_timeShifts.strategies = SingleIOV
665 for algorithm
in cal_ecl_timeShifts.algorithms:
668 if payload_boundaries:
669 algorithm.params = {
"iov_coverage": output_iov,
670 "payload_boundaries": payload_boundaries}
672 print(
"Set iov for crate time plotting alg - SequentialBoundaries")
674 algorithm.params = {
"apply_iov": output_iov}
675 print(
"Set iov for crate time plotting alg - SingleIOV")
685 for i
in range(len(calibs) - 1):
686 calibs[i + 1].depends_on(calibs[i])
690 valid_cal_bhabha.depends_on(calibs[len(calibs) - 1])
691 valid_cal_hadron.depends_on(calibs[len(calibs) - 1])
692 cal_ecl_timeShifts.depends_on(calibs[len(calibs) - 1])
697 calibs = np.append(calibs, [valid_cal_bhabha, valid_cal_hadron, cal_ecl_timeShifts])
699 print(
"##############")
700 print(
"List of calibrations:")
702 print(
" ", c.name,
" depends on ", c.dependencies,
", save payloads = ", c.save_payloads)
703 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.