11 """ECL timing calibration that performs the crystal and crate calibrations,
12 merges the relevant crystal payloads, and makes validation plots. It is the
13 main script for executing the ECL timing calibrations."""
15 from prompt
import CalibrationSettings, INPUT_DATA_FILTERS
16 from reconstruction
import prepare_cdst_analysis, prepare_user_cdst_analysis
17 from caf.utils
import IoV, ExpRun
32 settings = CalibrationSettings(
33 name=
"ECL crystal and crate time calibrations and validations",
34 expert_username=
"hearty",
36 input_data_formats=[
"cdst"],
37 input_data_names=[
"bhabha_all_calib",
"hadron_calib"],
38 input_data_filters={
"bhabha_all_calib": [INPUT_DATA_FILTERS[
"Data Tag"][
"bhabha_all_calib"],
39 INPUT_DATA_FILTERS[
"Beam Energy"][
"4S"],
40 INPUT_DATA_FILTERS[
"Beam Energy"][
"Continuum"],
41 INPUT_DATA_FILTERS[
"Beam Energy"][
"Scan"],
42 INPUT_DATA_FILTERS[
"Data Quality Tag"][
"Good"],
43 INPUT_DATA_FILTERS[
"Run Type"][
"physics"],
44 INPUT_DATA_FILTERS[
"Magnet"][
"On"]],
45 "hadron_calib": [INPUT_DATA_FILTERS[
"Data Tag"][
"hadron_calib"],
46 INPUT_DATA_FILTERS[
"Beam Energy"][
"4S"],
47 INPUT_DATA_FILTERS[
"Beam Energy"][
"Continuum"],
48 INPUT_DATA_FILTERS[
"Beam Energy"][
"Scan"],
49 INPUT_DATA_FILTERS[
"Data Quality Tag"][
"Good"],
50 INPUT_DATA_FILTERS[
"Run Type"][
"physics"],
51 INPUT_DATA_FILTERS[
"Magnet"][
"On"]]},
53 expert_config={
"numCrysCrateIterations": 1,
54 "maxNumberEvents": 50000000,
55 "payload_boundaries": [],
56 "t0_bhabhaToHadron_correction": 0})
70 def get_calibrations(input_data, **kwargs):
73 input_data (dict): Should contain every name from the 'input_data_names' variable as a key.
74 Each value is a dictionary with {"/path/to/file_e1_r5.root": IoV(1,5,1,5), ...}. Useful for
75 assigning to calibration.files_to_iov
77 **kwargs: Configuration options to be sent in. Since this may change we use kwargs as a way to help prevent
78 backwards compatibility problems. But you could use the correct arguments in b2caf-prompt-run for this
79 release explicitly if you want to.
81 Currently only kwargs["output_iov"] is used. This is the output IoV range that your payloads should
82 correspond to. Generally your highest ExpRun payload should be open ended e.g. IoV(3,4,-1,-1)
85 list(caf.framework.Calibration): All of the calibration objects we want to assign to the CAF process
92 expert_config = kwargs.get(
"expert_config")
96 numCrysCrateIterations = expert_config[
"numCrysCrateIterations"]
97 print(
"expert_config: numCrysCrateIterations = ", numCrysCrateIterations)
104 maxNumEventsCrystalCalib = expert_config[
"maxNumberEvents"]
105 print(
"expert_config: maxNumEventsCrystalCalib = ", maxNumEventsCrystalCalib)
109 t0_bhabhaToHadron_correction = expert_config[
"t0_bhabhaToHadron_correction"]
110 print(
"expert_config: t0_bhabhaToHadron_correction = ", t0_bhabhaToHadron_correction)
112 from caf.strategies
import SimpleRunByRun, SingleIOV, SequentialBoundaries
119 payload_boundaries = []
120 payload_boundaries.extend([ExpRun(*boundary)
for boundary
in expert_config[
"payload_boundaries"]])
121 basf2.B2INFO(f
"Expert set payload boundaries are: {expert_config['payload_boundaries']}")
122 print(
"payload_boundaries = ", payload_boundaries)
128 file_to_iov_bhabha = input_data[
"bhabha_all_calib"]
129 file_to_iov_hadron = input_data[
"hadron_calib"]
136 max_files_per_run_calibration = 26
137 max_files_per_run_validation = 4
138 max_events_per_run_plotting = 1
140 setMaxEventsPerCrystalCalib =
True
141 max_events_per_crystalCalib = 50000000
142 if (maxNumEventsCrystalCalib == -1):
143 setMaxEventsPerCrystalCalib =
False
144 elif (maxNumEventsCrystalCalib > 0):
145 max_events_per_crystalCalib = maxNumEventsCrystalCalib
147 print(
"max_events_per_crystalCalib = ", max_events_per_crystalCalib)
160 from prompt.utils import filter_by_select_max_events_from_files
162 reduced_file_to_iov_bhabha = filter_by_max_files_per_run(file_to_iov_bhabha, max_files_per_run_calibration)
163 input_files_bhabha = list(reduced_file_to_iov_bhabha.keys())
164 basf2.B2INFO(f
"Total number of bhabha files actually used as input for crates = {len(input_files_bhabha)}")
166 reduced_file_to_iov_bhabha_1perRun = filter_by_max_files_per_run(file_to_iov_bhabha, 1)
167 input_files_bhabha_1perRun = list(reduced_file_to_iov_bhabha_1perRun.keys())
168 basf2.B2INFO(f
"Total number of bhabha files actually used for dummy collectors = {len(input_files_bhabha_1perRun)}")
170 input_files_bhabha_full = list(file_to_iov_bhabha.keys())
171 basf2.B2INFO(f
"Total number of bhabha files as input = {len(input_files_bhabha_full)}")
173 if (setMaxEventsPerCrystalCalib):
174 temp_input_files_bhabha_full = input_files_bhabha_full.copy()
175 input_files_bhabha_crystal_maxEvents = filter_by_select_max_events_from_files(
176 temp_input_files_bhabha_full, max_events_per_crystalCalib)
177 basf2.B2INFO(
"Total number of bhabha files that could be used as input for crystal calibration ...")
178 basf2.B2INFO(f
"(ignoring payload boundaries) if a max # events is used = {len(input_files_bhabha_crystal_maxEvents)}")
180 if not input_files_bhabha_crystal_maxEvents:
181 input_files_bhabha_crystal_maxEvents = input_files_bhabha_full.copy()
182 print(
"Number of events < maximum so set the input files list equal to the full list of input bhabha files.")
184 input_files_bhabha_crystal = input_files_bhabha_full.copy()
185 if (setMaxEventsPerCrystalCalib):
186 input_files_bhabha_crystal = input_files_bhabha_crystal_maxEvents.copy()
187 print(
"List of input files slimmed for crystals.")
189 print(
"User requested max number of events filter to not be used so all bhabha input files being used for crystals")
191 basf2.B2INFO(f
"Total number of bhabha files being used for crystal calibration = {len(input_files_bhabha_crystal)}")
193 reduced_file_to_iov_hadron = filter_by_max_files_per_run(file_to_iov_hadron, max_files_per_run_validation)
194 input_files_hadron = list(reduced_file_to_iov_hadron.keys())
195 basf2.B2INFO(f
"Total number of hadron files actually used as input = {len(input_files_hadron)}")
200 reduced_file_to_iov_plotting = filter_by_max_events_per_run(file_to_iov_bhabha, max_events_per_run_plotting)
201 input_files_plotting = list(reduced_file_to_iov_plotting.keys())
204 intermediate_iov = IoV(0, 0, -1, -1)
205 requested_iov = kwargs.get(
"requested_iov",
None)
206 output_iov = IoV(requested_iov.exp_low, requested_iov.run_low, -1, -1)
209 from basf2
import register_module, create_path
210 from ROOT
import Belle2
211 from caf.framework
import Collection
215 print(
"Set up the base for the collectors for the calibrations")
217 root_input = register_module(
'RootInput')
218 rec_path_bhabha = create_path()
219 rec_path_bhabha.add_module(root_input)
220 if 'Gearbox' not in rec_path_bhabha:
221 rec_path_bhabha.add_module(
'Gearbox')
222 if 'Geometry' not in rec_path_bhabha:
223 rec_path_bhabha.add_module(
'Geometry', useDB=
True)
225 prepare_cdst_analysis(rec_path_bhabha, components=[
'SVD',
'CDC',
'ECL',
'KLM'])
229 t0BiasCorrection = t0_bhabhaToHadron_correction
232 col_bhabha = register_module(
'ECLBhabhaTCollector')
233 col_bhabha.param(
'timeAbsMax', 250)
234 col_bhabha.param(
'minCrystal', 1)
235 col_bhabha.param(
'maxCrystal', 8736)
236 col_bhabha.param(
'saveTree',
False)
237 col_bhabha.param(
'skipTrgSel',
False)
238 col_bhabha.param(
'hadronEventT0_TO_bhabhaEventT0_correction', t0BiasCorrection)
241 input_files=input_files_bhabha,
242 pre_collector_path=rec_path_bhabha)
244 eclTCol_crys =
Collection(collector=col_bhabha,
245 input_files=input_files_bhabha_crystal,
246 pre_collector_path=rec_path_bhabha)
250 print(
"Set up the base for the crate calibration algorithm")
257 eclTAlgCrates.cellIDLo = 3
258 eclTAlgCrates.cellIDHi = 2
259 eclTAlgCrates.debugOutput =
True
260 eclTAlgCrates.meanCleanRebinFactor = 3
261 eclTAlgCrates.meanCleanCutMinFactor = 0.3
262 eclTAlgCrates.debugFilenameBase =
"eclBhabhaTAlgorithm"
266 print(
"Set up the base for the crystal calibration algorithm")
273 eclTAlgCrystals.crateIDLo = 3
274 eclTAlgCrystals.crateIDHi = 2
275 eclTAlgCrystals.debugOutput =
True
276 eclTAlgCrystals.meanCleanRebinFactor = 3
277 eclTAlgCrystals.meanCleanCutMinFactor = 0.3
278 eclTAlgCrystals.debugFilenameBase =
"eclBhabhaTAlgorithm"
284 eclTAlgCrystals_saveNotReadPrevPayload = copy.deepcopy(eclTAlgCrystals)
285 eclTAlgCrystals_readNotSavePrevPayload = copy.deepcopy(eclTAlgCrystals)
287 eclTAlgCrystals_saveNotReadPrevPayload.savePrevCrysPayload =
True
288 eclTAlgCrystals_saveNotReadPrevPayload.readPrevCrysPayload =
False
290 eclTAlgCrystals_readNotSavePrevPayload.savePrevCrysPayload =
False
291 eclTAlgCrystals_readNotSavePrevPayload.readPrevCrysPayload =
True
295 print(
"Set up the base for the crystal merger algorithm")
298 merging_alg.readPrevCrysPayload =
True
307 if numCrysCrateIterations <= 0:
308 print(
"numCrysCrateIterations NEEDS TO BE > 0 !!!")
309 elif numCrysCrateIterations > 0:
313 from caf.framework
import Calibration
314 print(
"Performing ", numCrysCrateIterations,
" iterations of crate and crystal calibrations.")
316 crysCalibBaseName =
"ECLcrystalTimeCalibration_physics_"
317 crateCalibBaseName =
"ECLcrateTimeCalibration_physics_"
318 mergeCalibBaseName =
"ecl_t_merge_"
326 for i
in range(numCrysCrateIterations):
327 crysCalibName = crysCalibBaseName + str(i)
328 crateCalibName = crateCalibBaseName + str(i)
329 mergeCalibName = mergeCalibBaseName + str(i)
331 print(
"iteration = ", i)
332 print(
"crysCalibName = ", crysCalibName)
333 print(
"crateCalibName = ", crateCalibName)
338 cal_crates_i.add_collection(name=
"bhabha", collection=eclTCol)
339 cal_crates_i.algorithms = [eclTAlgCrates]
340 cal_crates_i.save_payloads =
False
341 cal_crates_i.strategies = SimpleRunByRun
342 cal_crates_i.backend_args = {
"request_memory":
"4 GB"}
348 cal_crystals_i.add_collection(name=
"bhabha", collection=eclTCol_crys)
349 cal_crystals_i.backend_args = {
"request_memory":
"4 GB"}
355 cal_crystals_i.algorithms = [eclTAlgCrystals_saveNotReadPrevPayload]
356 print(
"crystal algorithm: save previous payload for comparison purposes but do not read it")
357 print(
"eclTAlgCrystals_saveNotReadPrevPayload.savePrevCrysPayload = ",
358 eclTAlgCrystals_saveNotReadPrevPayload.savePrevCrysPayload)
359 print(
"eclTAlgCrystals_saveNotReadPrevPayload.readPrevCrysPayload = ",
360 eclTAlgCrystals_saveNotReadPrevPayload.readPrevCrysPayload)
362 cal_crystals_i.algorithms = [eclTAlgCrystals_readNotSavePrevPayload]
363 print(
"crystal algorithm: do not save previous payload but do read it in for comparison purposes")
364 print(
"eclTAlgCrystals_readNotSavePrevPayload.savePrevCrysPayload = ",
365 eclTAlgCrystals_readNotSavePrevPayload.savePrevCrysPayload)
366 print(
"eclTAlgCrystals_readNotSavePrevPayload.readPrevCrysPayload = ",
367 eclTAlgCrystals_readNotSavePrevPayload.readPrevCrysPayload)
369 cal_crystals_i.save_payloads =
False
373 if payload_boundaries:
374 cal_crystals_i.strategies = SequentialBoundaries
376 cal_crystals_i.strategies = SingleIOV
381 cal_ecl_merge_i =
Calibration(name=mergeCalibName, collector=
"DummyCollector",
382 input_files=input_files_bhabha_1perRun)
385 cal_ecl_merge_i.algorithms = [merging_alg]
386 print(
"merge algorithm: read previous payload for comparison purposes")
387 print(
"merging_alg.readPrevCrysPayload = ", merging_alg.readPrevCrysPayload)
389 cal_ecl_merge_i.save_payloads =
False
390 ecl_merge_pre_path_i = basf2.create_path()
391 prepare_cdst_analysis(ecl_merge_pre_path_i, components=[
'SVD',
'CDC',
'ECL',
'KLM'])
392 ecl_merge_pre_path_i.pre_collector_path = ecl_merge_pre_path_i
396 if payload_boundaries:
397 cal_ecl_merge_i.strategies = SequentialBoundaries
399 cal_ecl_merge_i.strategies = SingleIOV
402 for algorithm
in cal_crystals_i.algorithms:
405 if i == numCrysCrateIterations - 1:
408 if payload_boundaries:
409 algorithm.params = {
"iov_coverage": output_iov,
410 "payload_boundaries": payload_boundaries}
412 print(
"Set iov for final crystals alg - SequentialBoundaries")
414 algorithm.params = {
"apply_iov": output_iov}
415 print(
"Set iov for final crystals alg - SingleIOV ")
419 if payload_boundaries:
420 algorithm.params = {
"iov_coverage": intermediate_iov,
421 "payload_boundaries": payload_boundaries}
422 print(
"Set iov for intermediate crystals alg - SequentialBoundaries")
424 algorithm.params = {
"apply_iov": intermediate_iov}
425 print(
"Set iov for intermediate crystals alg - SingleIOV ")
428 for algorithm
in cal_ecl_merge_i.algorithms:
431 if i == numCrysCrateIterations - 1:
434 if payload_boundaries:
435 algorithm.params = {
"iov_coverage": output_iov,
436 "payload_boundaries": payload_boundaries}
438 print(
"Set iov for final merging alg - SequentialBoundaries")
440 algorithm.params = {
"apply_iov": output_iov}
441 print(
"Set iov for final merging alg - SingleIOV ")
445 if payload_boundaries:
446 algorithm.params = {
"iov_coverage": intermediate_iov,
447 "payload_boundaries": payload_boundaries}
448 print(
"Set iov for intermediate merging alg - SequentialBoundaries")
450 algorithm.params = {
"apply_iov": intermediate_iov}
451 print(
"Set iov for intermediate merging alg - SingleIOV ")
454 calibs = np.append(calibs, [cal_crates_i, cal_crystals_i, cal_ecl_merge_i])
457 calibs[len(calibs) - 3].save_payloads =
True
458 calibs[len(calibs) - 1].save_payloads =
True
469 root_input = register_module(
'RootInput')
470 rec_path_bhabha_val = create_path()
471 rec_path_bhabha_val.add_module(root_input)
472 if 'Gearbox' not in rec_path_bhabha_val:
473 rec_path_bhabha_val.add_module(
'Gearbox')
474 if 'Geometry' not in rec_path_bhabha_val:
475 rec_path_bhabha_val.add_module(
'Geometry', useDB=
True)
478 prepare_user_cdst_analysis(rec_path_bhabha_val, components=[
'SVD',
'CDC',
'ECL',
'KLM'])
479 col_bhabha_val = register_module(
'eclBhabhaTimeCalibrationValidationCollector')
480 col_bhabha_val.param(
'timeAbsMax', 70)
481 col_bhabha_val.param(
'saveTree',
False)
482 col_bhabha_val.param(
'skipTrgSel',
False)
484 eclValTCol =
Collection(collector=col_bhabha_val,
485 input_files=input_files_bhabha_crystal,
486 pre_collector_path=rec_path_bhabha_val)
496 eclValTAlgBhabha.meanCleanRebinFactor = 3
497 eclValTAlgBhabha.meanCleanCutMinFactor = 0.4
498 eclValTAlgBhabha.clusterTimesFractionWindow_maxtime = 1.5
499 eclValTAlgBhabha.debugFilenameBase =
"eclBhabhaTValidationAlgorithm"
504 from caf.framework
import Calibration
506 valid_cal_bhabha =
Calibration(
"ECLcrystalTimeCalValidation_bhabhaPhysics")
507 valid_cal_bhabha.add_collection(name=
"bhabha", collection=eclValTCol)
508 valid_cal_bhabha.save_payloads =
False
509 valid_cal_bhabha.backend_args = {
"request_memory":
"4 GB"}
515 eclValTAlgBhabha_readPrevPayload = copy.deepcopy(eclValTAlgBhabha)
516 eclValTAlgBhabha_readPrevPayload.readPrevCrysPayload =
True
518 valid_cal_bhabha.algorithms = [eclValTAlgBhabha_readPrevPayload]
519 print(
"bhabha validation: read previous payload for comparison purposes")
520 print(
"eclValTAlgBhabha_readPrevPayload.readPrevCrysPayload = ",
521 eclValTAlgBhabha_readPrevPayload.readPrevCrysPayload)
525 if payload_boundaries:
526 valid_cal_bhabha.strategies = SequentialBoundaries
528 valid_cal_bhabha.strategies = SingleIOV
530 for algorithm
in valid_cal_bhabha.algorithms:
533 if payload_boundaries:
534 algorithm.params = {
"iov_coverage": output_iov,
535 "payload_boundaries": payload_boundaries}
537 print(
"Set iov for bhabha validation alg - SequentialBoundaries")
539 algorithm.params = {
"apply_iov": output_iov}
540 print(
"Set iov for bhabha validation alg - SingleIOV")
545 root_input = register_module(
'RootInput')
546 rec_path_hadron_val = create_path()
547 rec_path_hadron_val.add_module(root_input)
548 if 'Gearbox' not in rec_path_hadron_val:
549 rec_path_hadron_val.add_module(
'Gearbox')
550 if 'Geometry' not in rec_path_hadron_val:
551 rec_path_hadron_val.add_module(
'Geometry', useDB=
True)
554 prepare_user_cdst_analysis(rec_path_hadron_val, components=[
'SVD',
'CDC',
'ECL',
'KLM'])
555 col_hadron_val = register_module(
'eclHadronTimeCalibrationValidationCollector')
556 col_hadron_val.param(
'timeAbsMax', 70)
557 col_hadron_val.param(
'saveTree',
False)
559 eclValTCol =
Collection(collector=col_hadron_val,
560 input_files=input_files_hadron,
561 pre_collector_path=rec_path_hadron_val)
571 eclValTAlgHadronic.meanCleanRebinFactor = 3
572 eclValTAlgHadronic.meanCleanCutMinFactor = 0.4
573 eclValTAlgHadronic.clusterTimesFractionWindow_maxtime = 8
574 eclValTAlgHadronic.debugFilenameBase =
"eclHadronTValidationAlgorithm"
579 from caf.framework
import Calibration
581 valid_cal_hadron =
Calibration(
"ECLcrystalTimeCalValidation_hadronPhysics")
582 valid_cal_hadron.add_collection(name=
"hadron", collection=eclValTCol)
583 valid_cal_hadron.save_payloads =
False
584 valid_cal_hadron.backend_args = {
"request_memory":
"4 GB"}
588 eclValTAlgHadron_readPrevPayload = copy.deepcopy(eclValTAlgHadronic)
589 eclValTAlgHadron_readPrevPayload.readPrevCrysPayload =
True
595 valid_cal_hadron.algorithms = [eclValTAlgHadron_readPrevPayload]
596 print(
"hadron validation: read previous payload for comparison purposes")
597 print(
"eclValTAlgHadron_readPrevPayload.readPrevCrysPayload = ",
598 eclValTAlgHadron_readPrevPayload.readPrevCrysPayload)
602 if payload_boundaries:
603 valid_cal_hadron.strategies = SequentialBoundaries
605 valid_cal_hadron.strategies = SingleIOV
607 for algorithm
in valid_cal_hadron.algorithms:
610 if payload_boundaries:
611 algorithm.params = {
"iov_coverage": output_iov,
612 "payload_boundaries": payload_boundaries}
614 print(
"Set iov for hadron validation alg - SequentialBoundaries")
616 algorithm.params = {
"apply_iov": output_iov}
617 print(
"Set iov for hadron validation alg - SingleIOV")
624 root_input = register_module(
'RootInput', entrySequences=[
'0:{}'.format(1)])
626 rec_path_bhabha_plotting = create_path()
627 rec_path_bhabha_plotting.add_module(root_input)
628 if 'Gearbox' not in rec_path_bhabha_plotting:
629 rec_path_bhabha_plotting.add_module(
'Gearbox')
630 if 'Geometry' not in rec_path_bhabha_plotting:
631 rec_path_bhabha_plotting.add_module(
'Geometry', useDB=
True)
633 prepare_cdst_analysis(rec_path_bhabha_plotting, components=[
'SVD',
'CDC',
'ECL',
'KLM'])
635 col_bhabha_plotting = register_module(
'eclTimeShiftsPlottingCollector')
636 eclTCol =
Collection(collector=col_bhabha_plotting,
637 input_files=input_files_plotting,
638 pre_collector_path=rec_path_bhabha_plotting)
645 tShifts_alg.debugFilenameBase =
"eclTimeShiftsAlgorithm"
648 tShifts_alg.crysCrateShift_min = -30
649 tShifts_alg.crysCrateShift_max = 30
654 cal_ecl_timeShifts =
Calibration(name=
"ecl_t_shifts", algorithms=[tShifts_alg],
655 input_files=input_files_plotting)
656 cal_ecl_timeShifts.add_collection(name=
"bhabha", collection=eclTCol)
658 cal_ecl_timeShifts.save_payloads =
False
662 if payload_boundaries:
663 cal_ecl_timeShifts.strategies = SequentialBoundaries
665 cal_ecl_timeShifts.strategies = SingleIOV
667 for algorithm
in cal_ecl_timeShifts.algorithms:
670 if payload_boundaries:
671 algorithm.params = {
"iov_coverage": output_iov,
672 "payload_boundaries": payload_boundaries}
674 print(
"Set iov for crate time plotting alg - SequentialBoundaries")
676 algorithm.params = {
"apply_iov": output_iov}
677 print(
"Set iov for crate time plotting alg - SingleIOV")
687 for i
in range(len(calibs) - 1):
688 calibs[i + 1].depends_on(calibs[i])
692 valid_cal_bhabha.depends_on(calibs[len(calibs) - 1])
693 valid_cal_hadron.depends_on(calibs[len(calibs) - 1])
694 cal_ecl_timeShifts.depends_on(calibs[len(calibs) - 1])
699 calibs = np.append(calibs, [valid_cal_bhabha, valid_cal_hadron, cal_ecl_timeShifts])
701 print(
"##############")
702 print(
"List of calibrations:")
704 print(
" ", c.name,
" depends on ", c.dependencies,
", save payloads = ", c.save_payloads)
705 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.