Belle II Software  release-05-02-19
caf_ecl_time_crystalCrate.py
1 # -*- coding: utf-8 -*-
2 
3 
10 
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."""
14 
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
18 import copy
19 
20 
27 
28 
32 settings = CalibrationSettings(
33  name="ECL crystal and crate time calibrations and validations",
34  expert_username="ehill",
35  description=__doc__,
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"]]},
52  depends_on=[],
53  expert_config={"numCrysCrateIterations": 2, "payload_boundaries": [], "t0_bhabhaToHadron_correction": 0})
54 
55 
56 
65 
66 
67 def get_calibrations(input_data, **kwargs):
68  """
69  Parameters:
70  input_data (dict): Should contain every name from the 'input_data_names' variable as a key.
71  Each value is a dictionary with {"/path/to/file_e1_r5.root": IoV(1,5,1,5), ...}. Useful for
72  assigning to calibration.files_to_iov
73 
74  **kwargs: Configuration options to be sent in. Since this may change we use kwargs as a way to help prevent
75  backwards compatibility problems. But you could use the correct arguments in b2caf-prompt-run for this
76  release explicitly if you want to.
77 
78  Currently only kwargs["output_iov"] is used. This is the output IoV range that your payloads should
79  correspond to. Generally your highest ExpRun payload should be open ended e.g. IoV(3,4,-1,-1)
80 
81  Returns:
82  list(caf.framework.Calibration): All of the calibration objects we want to assign to the CAF process
83  """
84  import basf2
85  # Set up config options
86 
87  from caf.strategies import SimpleRunByRun, SingleIOV, SequentialBoundaries
88  import numpy as np
89 
90  # In this script we want to use one sources of input data.
91  # Get the input files from the input_data variable
92  # The input data should be the bhabha skim for the calibrations
93  # and the hadron skim for the validations.
94  file_to_iov_bhabha = input_data["bhabha_all_calib"]
95  file_to_iov_hadron = input_data["hadron_calib"]
96 
97  # Set the maximum limits on the number of files/events per run.
98  # If I decided to remove the limit on the number of files per run, it is just easier
99  # to set it to a large number in case we want to introduce it later.
100  # Also, keeping it allows the crystal calibrations code to look like the
101  # crates calibration code even though they don't use the same list of input files.
102  max_files_per_run_calibration = 26
103  max_files_per_run_validation = 4
104  max_events_per_run_plotting = 1
105 
106  # We filter addition files if there are more than [max_files_per_run] files per run.
107  # The input data files are sorted alphabetically by b2caf-prompt-run
108  # already. This procedure respects that ordering
109  from prompt.utils import filter_by_max_files_per_run
110 
111  # We filter addition files if there are more than [max_events_per_run] events per run.
112  # For plotting after the calibrations
113  from prompt.utils import filter_by_max_events_per_run
114 
115  reduced_file_to_iov_bhabha = filter_by_max_files_per_run(file_to_iov_bhabha, max_files_per_run_calibration)
116  input_files_bhabha = list(reduced_file_to_iov_bhabha.keys())
117  basf2.B2INFO(f"Total number of bhabha files actually used as input for crates = {len(input_files_bhabha)}")
118 
119  reduced_file_to_iov_bhabha_1perRun = filter_by_max_files_per_run(file_to_iov_bhabha, 1)
120  input_files_bhabha_1perRun = list(reduced_file_to_iov_bhabha_1perRun.keys())
121  basf2.B2INFO(f"Total number of bhabha files actually used for dummy collectors = {len(input_files_bhabha_1perRun)}")
122 
123  input_files_bhabha_full = list(file_to_iov_bhabha.keys())
124  basf2.B2INFO(f"Total number of bhabha files as input for crystals = {len(input_files_bhabha_full)}")
125 
126  reduced_file_to_iov_hadron = filter_by_max_files_per_run(file_to_iov_hadron, max_files_per_run_validation)
127  input_files_hadron = list(reduced_file_to_iov_hadron.keys())
128  basf2.B2INFO(f"Total number of hadron files actually used as input = {len(input_files_hadron)}")
129 
130  # For plotting the sum of the crate and crystal calibration
131  # constants after the calibrations are made. To be used to
132  # monitor crate time jumps.
133  reduced_file_to_iov_plotting = filter_by_max_events_per_run(file_to_iov_bhabha, max_events_per_run_plotting)
134  input_files_plotting = list(reduced_file_to_iov_plotting.keys())
135 
136  # Determine how many iterations of the crystal calibrations and
137  # crate calibrations to perform.
138  expert_config = kwargs.get("expert_config")
139  numCrysCrateIterations = expert_config["numCrysCrateIterations"]
140  print("expert_config: numCrysCrateIterations = ", numCrysCrateIterations)
141 
142  # Determine how large of an offset should be applied to correct for
143  # differences in the CDC event t0 in bhabha and hadronic events
144  t0_bhabhaToHadron_correction = expert_config["t0_bhabhaToHadron_correction"]
145  print("expert_config: t0_bhabhaToHadron_correction = ", t0_bhabhaToHadron_correction)
146 
147  # Interval of validity for the calibrations
148  intermediate_iov = IoV(0, 0, -1, -1)
149  requested_iov = kwargs.get("requested_iov", None)
150  output_iov = IoV(requested_iov.exp_low, requested_iov.run_low, -1, -1)
151 
152  # Determine the user defined calibration boundaries. Most useful
153  # for when multiple experiments are processed at the same time.
154  # Useful for the crystal calibrations but not for the crate
155  # calibrations, which are done run-by-run.
156  payload_boundaries = [] # Introduce empty list of payload boundaries.
157  payload_boundaries.extend([ExpRun(*boundary) for boundary in expert_config["payload_boundaries"]])
158  basf2.B2INFO(f"Expert set payload boundaries are: {expert_config['payload_boundaries']}")
159  print("payload_boundaries = ", payload_boundaries)
160 
161 
162  from basf2 import register_module, create_path
163  import ROOT
164  from ROOT import Belle2
165  from ROOT.Belle2 import TestCalibrationAlgorithm
166  from caf.framework import Collection
167 
168 
170  print("Set up the base for the collectors for the calibrations")
171 
172  root_input = register_module('RootInput')
173  rec_path_bhabha = create_path()
174  rec_path_bhabha.add_module(root_input)
175  if 'Gearbox' not in rec_path_bhabha:
176  rec_path_bhabha.add_module('Gearbox')
177  if 'Geometry' not in rec_path_bhabha:
178  rec_path_bhabha.add_module('Geometry', useDB=True)
179 
180  prepare_cdst_analysis(rec_path_bhabha) # for new 2020 cdst format
181 
182  # ====================================================
183  # t0BiasCorrection = -0.9 # Correct for the CDC t0 bias in ns
184  t0BiasCorrection = t0_bhabhaToHadron_correction # Correct for the CDC t0 bias in ns
185  # ====================================================
186 
187  col_bhabha = register_module('ECLBhabhaTCollector')
188  col_bhabha.param('timeAbsMax', 250)
189  col_bhabha.param('minCrystal', 1)
190  col_bhabha.param('maxCrystal', 8736)
191  col_bhabha.param('saveTree', False)
192  col_bhabha.param('hadronEventT0_TO_bhabhaEventT0_correction', t0BiasCorrection)
193 
194  eclTCol = Collection(collector=col_bhabha,
195  input_files=input_files_bhabha,
196  pre_collector_path=rec_path_bhabha)
197 
198  eclTCol_crys = Collection(collector=col_bhabha,
199  input_files=input_files_bhabha_full,
200  pre_collector_path=rec_path_bhabha)
201 
202 
204  print("Set up the base for the crate calibration algorithm")
205 
206  eclTAlgCrates = Belle2.ECL.eclBhabhaTAlgorithm()
207 
208  # Define the CAF algorithm arguments
209  # Set the cellIDLo to be larger than cellIDHi so that no crystal
210  # calibrations will be performed.
211  eclTAlgCrates.cellIDLo = 3
212  eclTAlgCrates.cellIDHi = 2
213  eclTAlgCrates.debugOutput = True
214  eclTAlgCrates.meanCleanRebinFactor = 3
215  eclTAlgCrates.meanCleanCutMinFactor = 0.3
216  eclTAlgCrates.debugFilenameBase = "eclBhabhaTAlgorithm"
217 
218 
220  print("Set up the base for the crystal calibration algorithm")
221 
222  eclTAlgCrystals = Belle2.ECL.eclBhabhaTAlgorithm()
223 
224  # Define the CAF algorithm arguments
225  # Set the crateIDLo to be larger than crateIDHi so that no crate
226  # calibrations will be performed. More variables set later in code....
227  eclTAlgCrystals.crateIDLo = 3
228  eclTAlgCrystals.crateIDHi = 2
229  eclTAlgCrystals.debugOutput = True
230  eclTAlgCrystals.meanCleanRebinFactor = 3
231  eclTAlgCrystals.meanCleanCutMinFactor = 0.3
232  eclTAlgCrystals.debugFilenameBase = "eclBhabhaTAlgorithm"
233 
234  # Make two versions of these algorithms that differ only in whether
235  # or not the previous bucket's payload information is saved
236  # to a temporary payload for comparison purposes at each
237  # iteration.
238  eclTAlgCrystals_saveNotReadPrevPayload = copy.deepcopy(eclTAlgCrystals)
239  eclTAlgCrystals_readNotSavePrevPayload = copy.deepcopy(eclTAlgCrystals)
240 
241  eclTAlgCrystals_saveNotReadPrevPayload.savePrevCrysPayload = True
242  eclTAlgCrystals_saveNotReadPrevPayload.readPrevCrysPayload = False
243 
244  eclTAlgCrystals_readNotSavePrevPayload.savePrevCrysPayload = False
245  eclTAlgCrystals_readNotSavePrevPayload.readPrevCrysPayload = True
246 
247 
249  print("Set up the base for the crystal merger algorithm")
250 
252  if numCrysCrateIterations == 1:
253  merging_alg.readPrevCrysPayload = False
254  else:
255  merging_alg.readPrevCrysPayload = True
256 
257 
263 
264  if numCrysCrateIterations > 0:
265 
267 
268  from caf.framework import Calibration
269  print("Performing ", numCrysCrateIterations, " iterations of crate and crystal calibrations.")
270 
271  crysCalibBaseName = "ECLcrystalTimeCalibration_physics_"
272  crateCalibBaseName = "ECLcrateTimeCalibration_physics_"
273  mergeCalibBaseName = "ecl_t_merge_"
274 
275  calibs = []
276 
277  # --------------------------------------------------------------
278  # Loop over all the iterations to set up the crate and crystal
279  # calibrations.
280 
281  for i in range(numCrysCrateIterations):
282  crysCalibName = crysCalibBaseName + str(i)
283  crateCalibName = crateCalibBaseName + str(i)
284  mergeCalibName = mergeCalibBaseName + str(i)
285 
286  print("iteration = ", i)
287  print("crysCalibName = ", crysCalibName)
288  print("crateCalibName = ", crateCalibName)
289 
290 
292  cal_crates_i = Calibration(crateCalibName)
293  cal_crates_i.add_collection(name="bhabha", collection=eclTCol)
294  cal_crates_i.algorithms = [eclTAlgCrates]
295  cal_crates_i.save_payloads = False
296  cal_crates_i.strategies = SimpleRunByRun
297  cal_crates_i.backend_args = {"request_memory": "4 GB"}
298 
299 
301 
302  cal_crystals_i = Calibration(crysCalibName)
303  cal_crystals_i.add_collection(name="bhabha", collection=eclTCol_crys)
304  cal_crystals_i.backend_args = {"request_memory": "4 GB"}
305 
306  # If this is the first iteration then save the previous crystal payload
307  # values to a temporary storage payload. If this is not the first iteration
308  # then read in the previous stored payload and plot the change in the crystal
309  if i == 0 and numCrysCrateIterations > 1:
310  cal_crystals_i.algorithms = [eclTAlgCrystals_saveNotReadPrevPayload]
311  print("crystal algorithm: save previous payload for comparison purposes but do not read it")
312  print("eclTAlgCrystals_saveNotReadPrevPayload.savePrevCrysPayload = ",
313  eclTAlgCrystals_saveNotReadPrevPayload.savePrevCrysPayload)
314  print("eclTAlgCrystals_saveNotReadPrevPayload.readPrevCrysPayload = ",
315  eclTAlgCrystals_saveNotReadPrevPayload.readPrevCrysPayload)
316  elif i == 0 and numCrysCrateIterations == 1:
317  cal_crystals_i.algorithms = [eclTAlgCrystals]
318  print("crystal algorithm: do not save or read any previous payloads for comparison purposes")
319  print("eclTAlgCrystals.savePrevCrysPayload = ", eclTAlgCrystals.savePrevCrysPayload)
320  print("eclTAlgCrystals.readPrevCrysPayload = ", eclTAlgCrystals.readPrevCrysPayload)
321  else:
322  cal_crystals_i.algorithms = [eclTAlgCrystals_readNotSavePrevPayload]
323  print("crystal algorithm: do not save previous payload but do read it in for comparison purposes")
324  print("eclTAlgCrystals_readNotSavePrevPayload.savePrevCrysPayload = ",
325  eclTAlgCrystals_readNotSavePrevPayload.savePrevCrysPayload)
326  print("eclTAlgCrystals_readNotSavePrevPayload.readPrevCrysPayload = ",
327  eclTAlgCrystals_readNotSavePrevPayload.readPrevCrysPayload)
328 
329  cal_crystals_i.save_payloads = False
330 
331  # If payload boundaries are set use SequentialBoundaries
332  # otherwise use SingleIOV
333  if payload_boundaries:
334  cal_crystals_i.strategies = SequentialBoundaries
335  else:
336  cal_crystals_i.strategies = SingleIOV
337 
338 
340 
341  cal_ecl_merge_i = Calibration(name=mergeCalibName, collector="DummyCollector",
342  input_files=input_files_bhabha_1perRun)
343 
344  # If there is not only one iteration then read in the previous stored payload
345  # and plot the change in the crystal ts
346  if i == 0 and numCrysCrateIterations == 1:
347  cal_ecl_merge_i.algorithms = [merging_alg]
348  print("merge algorithm: do not read previous payload")
349  print("merging_alg.readPrevCrysPayload = ", merging_alg.readPrevCrysPayload)
350  else:
351  cal_ecl_merge_i.algorithms = [merging_alg]
352  print("merge algorithm: read previous payload for comparison purposes")
353  print("merging_alg.readPrevCrysPayload = ", merging_alg.readPrevCrysPayload)
354 
355  cal_ecl_merge_i.save_payloads = False
356  ecl_merge_pre_path_i = basf2.create_path()
357  prepare_cdst_analysis(ecl_merge_pre_path_i)
358  ecl_merge_pre_path_i.pre_collector_path = ecl_merge_pre_path_i
359 
360  # If payload boundaries are set use SequentialBoundaries
361  # otherwise use SingleIOV
362  if payload_boundaries:
363  cal_ecl_merge_i.strategies = SequentialBoundaries
364  else:
365  cal_ecl_merge_i.strategies = SingleIOV
366 
367  # Modify the iov for each of the calibration algorithms
368  for algorithm in cal_crystals_i.algorithms:
369  # The payload of the final crystal calibration iteration
370  # is given the user's iov.
371  if i == numCrysCrateIterations - 1:
372  # Set payload iov information for SequentialBoundaries
373  # and SingleIOV strategies.
374  if payload_boundaries:
375  algorithm.params = {"iov_coverage": output_iov,
376  "payload_boundaries": payload_boundaries}
377 
378  print("Set iov for final crystals alg - SequentialBoundaries")
379  else:
380  algorithm.params = {"apply_iov": output_iov}
381  print("Set iov for final crystals alg - SingleIOV ")
382  # Force the output iovs to be open for the intermediate
383  # step calibrations.
384  else:
385  if payload_boundaries:
386  algorithm.params = {"iov_coverage": intermediate_iov,
387  "payload_boundaries": payload_boundaries}
388  print("Set iov for intermediate crystals alg - SequentialBoundaries")
389  else:
390  algorithm.params = {"apply_iov": intermediate_iov}
391  print("Set iov for intermediate crystals alg - SingleIOV ")
392 
393  # Modify the iov for each of the payload merging algorithms
394  for algorithm in cal_ecl_merge_i.algorithms:
395  # The payload of the final crystal calibration iteration
396  # is given the user's iov.
397  if i == numCrysCrateIterations - 1:
398  # Set payload iov information for SequentialBoundaries
399  # and SingleIOV strategies.
400  if payload_boundaries:
401  algorithm.params = {"iov_coverage": output_iov,
402  "payload_boundaries": payload_boundaries}
403 
404  print("Set iov for final merging alg - SequentialBoundaries")
405  else:
406  algorithm.params = {"apply_iov": output_iov}
407  print("Set iov for final merging alg - SingleIOV ")
408  # Force the output iovs to be open for the intermediate
409  # step calibrations.
410  else:
411  if payload_boundaries:
412  algorithm.params = {"iov_coverage": intermediate_iov,
413  "payload_boundaries": payload_boundaries}
414  print("Set iov for intermediate merging alg - SequentialBoundaries")
415  else:
416  algorithm.params = {"apply_iov": intermediate_iov}
417  print("Set iov for intermediate merging alg - SingleIOV ")
418 
419  # Fill the calibs array with all the "calibrations" that will be run
420  calibs = np.append(calibs, [cal_crates_i, cal_crystals_i, cal_ecl_merge_i])
421 
422  # Make sure that the final paylaods get saved.
423  calibs[len(calibs) - 3].save_payloads = True # crates
424  calibs[len(calibs) - 1].save_payloads = True # crystals
425 
426 
429  root_input = register_module('RootInput')
430  rec_path_bhabha_val = create_path()
431  rec_path_bhabha_val.add_module(root_input)
432  if 'Gearbox' not in rec_path_bhabha_val:
433  rec_path_bhabha_val.add_module('Gearbox')
434  if 'Geometry' not in rec_path_bhabha_val:
435  rec_path_bhabha_val.add_module('Geometry', useDB=True)
436 
437  prepare_user_cdst_analysis(rec_path_bhabha_val) # for new 2020 cdst format
438 
439  col_bhabha_val = register_module('eclBhabhaTimeCalibrationValidationCollector')
440  col_bhabha_val.param('timeAbsMax', 70)
441  col_bhabha_val.param('saveTree', False)
442 
443  eclValTCol = Collection(collector=col_bhabha_val,
444  input_files=input_files_bhabha,
445  pre_collector_path=rec_path_bhabha_val)
446 
447 
449 
450  # Give the collector name to the algorithm since one algorithm
451  # is used to analyse the results from several possible collectors
452  eclValTAlgBhabha = Belle2.ECL.eclTValidationAlgorithm("eclBhabhaTimeCalibrationValidationCollector")
453 
454  # Define the CAF algorithm arguments
455  eclValTAlgBhabha.meanCleanRebinFactor = 3
456  eclValTAlgBhabha.meanCleanCutMinFactor = 0.4
457  eclValTAlgBhabha.clusterTimesFractionWindow_maxtime = 1.5
458  eclValTAlgBhabha.debugFilenameBase = "eclBhabhaTValidationAlgorithm"
459 
460 
462 
463  from caf.framework import Calibration
464 
465  valid_cal_bhabha = Calibration("ECLcrystalTimeCalValidation_bhabhaPhysics")
466  valid_cal_bhabha.add_collection(name="bhabha", collection=eclValTCol)
467  valid_cal_bhabha.save_payloads = False
468  valid_cal_bhabha.backend_args = {"request_memory": "4 GB"}
469 
470  # Make a second version of this algorithm that differs only in
471  # that it is instructed to read the previous crystal payload
472  eclValTAlgBhabha_readPrevPayload = copy.deepcopy(eclValTAlgBhabha)
473  eclValTAlgBhabha_readPrevPayload.readPrevCrysPayload = True
474 
475  # If there is just one iteration then don't read a non-existant payload
476  if numCrysCrateIterations > 1:
477  valid_cal_bhabha.algorithms = [eclValTAlgBhabha_readPrevPayload]
478  print("bhabha validation: read previous payload for comparison purposes")
479  print("eclValTAlgBhabha_readPrevPayload.readPrevCrysPayload = ",
480  eclValTAlgBhabha_readPrevPayload.readPrevCrysPayload)
481  else:
482  valid_cal_bhabha.algorithms = [eclValTAlgBhabha]
483  print("bhabha validation: do not read previous payload for comparison purposes")
484  print("eclValTAlgBhabha.readPrevCrysPayload = ", eclValTAlgBhabha.readPrevCrysPayload)
485 
486  # If payload boundaries are set use SequentialBoundaries
487  # otherwise use SingleIOV
488  if payload_boundaries:
489  valid_cal_bhabha.strategies = SequentialBoundaries
490  else:
491  valid_cal_bhabha.strategies = SingleIOV
492 
493  for algorithm in valid_cal_bhabha.algorithms:
494  # Set payload iov information for SequentialBoundaries
495  # and SingleIOV strategies.
496  if payload_boundaries:
497  algorithm.params = {"iov_coverage": output_iov,
498  "payload_boundaries": payload_boundaries}
499 
500  print("Set iov for bhabha validation alg - SequentialBoundaries")
501  else:
502  algorithm.params = {"apply_iov": output_iov}
503  print("Set iov for bhabha validation alg - SingleIOV")
504 
505 
508  root_input = register_module('RootInput')
509  rec_path_hadron_val = create_path()
510  rec_path_hadron_val.add_module(root_input)
511  if 'Gearbox' not in rec_path_hadron_val:
512  rec_path_hadron_val.add_module('Gearbox')
513  if 'Geometry' not in rec_path_hadron_val:
514  rec_path_hadron_val.add_module('Geometry', useDB=True)
515 
516  prepare_user_cdst_analysis(rec_path_hadron_val) # for new 2020 cdst format
517 
518  col_hadron_val = register_module('eclHadronTimeCalibrationValidationCollector')
519  col_hadron_val.param('timeAbsMax', 70)
520  col_hadron_val.param('saveTree', False)
521 
522  eclValTCol = Collection(collector=col_hadron_val,
523  input_files=input_files_hadron,
524  pre_collector_path=rec_path_hadron_val)
525 
526 
528 
529  # Give the collector name to the algorithm since one algorithm
530  # is used to analyse the results from several possible collectors
531  eclValTAlgHadronic = Belle2.ECL.eclTValidationAlgorithm("eclHadronTimeCalibrationValidationCollector")
532 
533  # Define the CAF algorithm arguments
534  eclValTAlgHadronic.meanCleanRebinFactor = 3
535  eclValTAlgHadronic.meanCleanCutMinFactor = 0.4
536  eclValTAlgHadronic.clusterTimesFractionWindow_maxtime = 8
537  eclValTAlgHadronic.debugFilenameBase = "eclHadronTValidationAlgorithm"
538 
539 
541 
542  from caf.framework import Calibration
543 
544  valid_cal_hadron = Calibration("ECLcrystalTimeCalValidation_hadronPhysics")
545  valid_cal_hadron.add_collection(name="hadron", collection=eclValTCol)
546  valid_cal_hadron.save_payloads = False
547  valid_cal_hadron.backend_args = {"request_memory": "4 GB"}
548 
549  # Make a second version of this algorithm that differs only in
550  # that it is instructed to read the previous crystal payload
551  eclValTAlgHadron_readPrevPayload = copy.deepcopy(eclValTAlgHadronic)
552  eclValTAlgHadron_readPrevPayload.readPrevCrysPayload = True
553 
554  # If there is just one iteration then don't read a non-existant payload
555  if numCrysCrateIterations > 1:
556  valid_cal_hadron.algorithms = [eclValTAlgHadron_readPrevPayload]
557  print("hadron validation: read previous payload for comparison purposes")
558  print("eclValTAlgHadron_readPrevPayload.readPrevCrysPayload = ",
559  eclValTAlgHadron_readPrevPayload.readPrevCrysPayload)
560  else:
561  valid_cal_hadron.algorithms = [eclValTAlgHadronic]
562  print("hadron validation: do not read previous payload for comparison purposes")
563  print("eclValTAlgHadronic.readPrevCrysPayload = ", eclValTAlgHadronic.readPrevCrysPayload)
564 
565  # If payload boundaries are set use SequentialBoundaries
566  # otherwise use SingleIOV
567  if payload_boundaries:
568  valid_cal_hadron.strategies = SequentialBoundaries
569  else:
570  valid_cal_hadron.strategies = SingleIOV
571 
572  for algorithm in valid_cal_hadron.algorithms:
573  # Set payload iov information for SequentialBoundaries
574  # and SingleIOV strategies.
575  if payload_boundaries:
576  algorithm.params = {"iov_coverage": output_iov,
577  "payload_boundaries": payload_boundaries}
578 
579  print("Set iov for hadron validation alg - SequentialBoundaries")
580  else:
581  algorithm.params = {"apply_iov": output_iov}
582  print("Set iov for hadron validation alg - SingleIOV")
583 
584 
587 
588  # Set up the collector but with only one event per file
589  root_input = register_module('RootInput', entrySequences=['0:{}'.format(1)])
590 
591  rec_path_bhabha_plotting = create_path()
592  rec_path_bhabha_plotting.add_module(root_input)
593  if 'Gearbox' not in rec_path_bhabha_plotting:
594  rec_path_bhabha_plotting.add_module('Gearbox')
595  if 'Geometry' not in rec_path_bhabha_plotting:
596  rec_path_bhabha_plotting.add_module('Geometry', useDB=True)
597 
598  prepare_cdst_analysis(rec_path_bhabha_plotting) # for new 2020 cdst format
599 
600  col_bhabha_plotting = register_module('eclTimeShiftsPlottingCollector')
601  eclTCol = Collection(collector=col_bhabha_plotting,
602  input_files=input_files_plotting,
603  pre_collector_path=rec_path_bhabha_plotting)
604 
605  # Set up the plotting. Use the two files with the collector to
606  # determine the run range to plot. The plotting is done in the
607  # algorithm
608 
609  tShifts_alg = Belle2.ECL.eclTimeShiftsAlgorithm()
610  tShifts_alg.debugFilenameBase = "eclTimeShiftsAlgorithm"
611 
612  # +-30ns range allows for unexpectedly large jumps
613  tShifts_alg.crysCrateShift_min = -30 # in ns
614  tShifts_alg.crysCrateShift_max = 30 # in ns
615 
616  # Make the algorithm loop over the runs, not just the collector
617  # tShifts_alg.algorithmReadPayloads = True
618 
619  cal_ecl_timeShifts = Calibration(name="ecl_t_shifts", algorithms=[tShifts_alg],
620  input_files=input_files_plotting)
621  cal_ecl_timeShifts.add_collection(name="bhabha", collection=eclTCol)
622 
623  cal_ecl_timeShifts.save_payloads = False
624 
625  # If payload boundaries are set use SequentialBoundaries
626  # otherwise use SingleIOV
627  if payload_boundaries:
628  cal_ecl_timeShifts.strategies = SequentialBoundaries
629  else:
630  cal_ecl_timeShifts.strategies = SingleIOV
631 
632  for algorithm in cal_ecl_timeShifts.algorithms:
633  # Set payload iov information for SequentialBoundaries
634  # and SingleIOV strategies.
635  if payload_boundaries:
636  algorithm.params = {"iov_coverage": output_iov,
637  "payload_boundaries": payload_boundaries}
638 
639  print("Set iov for crate time plotting alg - SequentialBoundaries")
640  else:
641  algorithm.params = {"apply_iov": output_iov}
642  print("Set iov for crate time plotting alg - SingleIOV")
643 
644 
649 
650  # Make the crate and crytsal calibrations and the cerge crystal
651  # process occur in the order loaded into the array.
652  for i in range(len(calibs) - 1):
653  calibs[i + 1].depends_on(calibs[i])
654 
655  # The validations and plotting can run independently of each other
656  # but rely on the last calibration step
657  valid_cal_bhabha.depends_on(calibs[len(calibs) - 1])
658  valid_cal_hadron.depends_on(calibs[len(calibs) - 1])
659  cal_ecl_timeShifts.depends_on(calibs[len(calibs) - 1])
660 
661 
663 
664  calibs = np.append(calibs, [valid_cal_bhabha, valid_cal_hadron, cal_ecl_timeShifts])
665 
666  print("##############")
667  print("List of calibrations:")
668  for c in calibs:
669  print(" ", c.name, " depends on ", c.dependencies, ", save payloads = ", c.save_payloads)
670  print("##############")
671 
672  # You must return all calibrations you want to run in the prompt process, even if it's only one
673  # Calibrations will be executed in this order as a result of the dependencies defined by the "dependes_on(...)".
674  return calibs
675 
676  else:
677 
680 
681  print("numCrysCrateIterations value resulting in default calibration iteration set up")
682  print("Performing these calibration iterations: crate -> crystal -> crate")
683 
684 
686 
687  from caf.framework import Calibration
688 
689  cal_crates_1 = Calibration("ECLcrateTimeCalibration_physics_1")
690  cal_crates_1.add_collection(name="bhabha", collection=eclTCol)
691  cal_crates_1.algorithms = [eclTAlgCrates]
692  cal_crates_1.save_payloads = False
693  cal_crates_1.backend_args = {"request_memory": "4 GB"}
694 
695  # Here we set the AlgorithmStrategy for our algorithm
696 
697  # The SimpleRunByRun strategy executes your algorithm over runs
698  # individually to give you payloads for each one (if successful)
699  # It will not do any merging of runs which didn't contain enough data.
700  # So failure is expected if your algorithm requires a large amount of data compared to run length.
701  # You should only use granularity='run' for the collector when using this strategy.
702 
703  cal_crates_1.strategies = SimpleRunByRun
704 
705  # Most other options like database chain and backend args will be overwritten by b2caf-prompt-run.
706  # So we don't bother setting them.
707 
708 
710 
711  cal_crystals_1 = Calibration("ECLcrystalTimeCalibration_physics_1")
712  cal_crystals_1.add_collection(name="bhabha", collection=eclTCol_crys)
713  cal_crystals_1.algorithms = [eclTAlgCrystals]
714  cal_crystals_1.backend_args = {"request_memory": "4 GB"}
715 
716  # Two sets of payloads are created here:
717  # * ECLCrystalTimeOffset
718  # * ECLCrystalTimeOffsetBhabha
719  # We technically want to save ECLCrystalTimeOffsetBhabha to the GT but because we don't want
720  # ECLCrystalTimeOffset we save neither here and get the merging algorithm to save a copy
721  # of ECLCrystalTimeOffsetBhabha later.
722  cal_crystals_1.save_payloads = False
723 
724  # Here we set the AlgorithmStrategy for our algorithm
725 
726  # The default value is SingleIOV, you don't have to set this, it is done automatically.
727  # SingleIOV just takes all of the runs as one big IoV and executes the algorithm once on all of their data.
728  # You can use granularity='run' or granularity='all' for the collector when using this strategy.
729 
730  # If payload boundaries are set use SequentialBoundaries
731  # otherwise use SingleIOV
732  if payload_boundaries:
733  cal_crystals_1.strategies = SequentialBoundaries
734  else:
735  cal_crystals_1.strategies = SingleIOV
736 
737 
739  cal_crates_2 = Calibration("ECLcrateTimeCalibration_physics_2")
740  cal_crates_2.add_collection(name="bhabha", collection=eclTCol)
741  cal_crates_2.algorithms = [eclTAlgCrates]
742  cal_crates_2.strategies = SimpleRunByRun
743  cal_crates_2.backend_args = {"request_memory": "4 GB"}
744 
745 
749 
750  # We use a dummy collector that barely outputs any data and we set the input files to a single file so
751  # we spawn only one very fast job.
752  # It doesn't matter which input file we choose as the output is never used.
753 
754  cal_ecl_merge = Calibration(name="ecl_t_merge", collector="DummyCollector", algorithms=[merging_alg],
755  input_files=input_files_bhabha_1perRun)
756 
757  # The important part is that we depend on all the calibrations we previously ran
758  cal_ecl_merge.depends_on(cal_crystals_1)
759 
760  # ..Uses cdst data so it requires prepare_cdst_analysis
761  ecl_merge_pre_path = basf2.create_path()
762  prepare_cdst_analysis(ecl_merge_pre_path)
763  ecl_merge_pre_path.pre_collector_path = ecl_merge_pre_path
764 
765  # If payload boundaries are set use SequentialBoundaries
766  # otherwise use SingleIOV
767  if payload_boundaries:
768  cal_ecl_merge.strategies = SequentialBoundaries
769  else:
770  cal_ecl_merge.strategies = SingleIOV
771 
772  # Modify the iov for each of the algorithms
773  for algorithm in cal_crystals_1.algorithms:
774  if payload_boundaries:
775  algorithm.params = {"iov_coverage": intermediate_iov,
776  "payload_boundaries": payload_boundaries}
777  print("Set iov for crystals alg - SequentialBoundaries")
778  else:
779  algorithm.params = {"apply_iov": intermediate_iov}
780  print("Set iov for crystals alg - SingleIOV")
781 
782  for algorithm in cal_ecl_merge.algorithms:
783  if payload_boundaries:
784  algorithm.params = {"iov_coverage": output_iov,
785  "payload_boundaries": payload_boundaries}
786  print("Set iov for crystals merge alg - SequentialBoundaries")
787  else:
788  algorithm.params = {"apply_iov": output_iov}
789  print("Set iov for crystals merge alg - SingleIOV")
790 
791 
794  root_input = register_module('RootInput')
795  rec_path_bhabha_val = create_path()
796  rec_path_bhabha_val.add_module(root_input)
797  if 'Gearbox' not in rec_path_bhabha_val:
798  rec_path_bhabha_val.add_module('Gearbox')
799  if 'Geometry' not in rec_path_bhabha_val:
800  rec_path_bhabha_val.add_module('Geometry', useDB=True)
801 
802  prepare_user_cdst_analysis(rec_path_bhabha_val) # for new 2020 cdst format
803 
804  col_bhabha_val = register_module('eclBhabhaTimeCalibrationValidationCollector')
805  col_bhabha_val.param('timeAbsMax', 70)
806  col_bhabha_val.param('saveTree', False)
807 
808  eclValTCol = Collection(collector=col_bhabha_val,
809  input_files=input_files_bhabha,
810  pre_collector_path=rec_path_bhabha_val)
811 
812 
814 
815  # Give the collector name to the algorithm since one algorithm
816  # is used to analyse the results from several possible collectors
817  eclValTAlgBhabha = Belle2.ECL.eclTValidationAlgorithm("eclBhabhaTimeCalibrationValidationCollector")
818 
819  # Define the CAF algorithm arguments
820  eclValTAlgBhabha.meanCleanRebinFactor = 3
821  eclValTAlgBhabha.meanCleanCutMinFactor = 0.4
822  eclValTAlgBhabha.clusterTimesFractionWindow_maxtime = 1.5
823  eclValTAlgBhabha.debugFilenameBase = "eclBhabhaTValidationAlgorithm"
824 
825 
827 
828  from caf.framework import Calibration
829 
830  valid_cal_bhabha = Calibration("ECLcrystalTimeCalValidation_bhabhaPhysics")
831  valid_cal_bhabha.add_collection(name="bhabha", collection=eclValTCol)
832  valid_cal_bhabha.algorithms = [eclValTAlgBhabha]
833  valid_cal_bhabha.save_payloads = False
834  valid_cal_bhabha.backend_args = {"request_memory": "4 GB"}
835 
836  eclValTAlgBhabha.readPrevCrysPayload = True
837  print("eclValTAlgBhabha.readPrevCrysPayload = ", eclValTAlgBhabha.readPrevCrysPayload)
838 
839  # Here we set the AlgorithmStrategy for our algorithm
840 
841  # The default value is SingleIOV, you don't have to set this, it is done automatically.
842  # SingleIOV just takes all of the runs as one big IoV and executes the algorithm once on all of their data.
843  # You can use granularity='run' or granularity='all' for the collector when using this strategy.
844 
845  # If payload boundaries are set use SequentialBoundaries
846  # otherwise use SingleIOV
847  if payload_boundaries:
848  valid_cal_bhabha.strategies = SequentialBoundaries
849  else:
850  valid_cal_bhabha.strategies = SingleIOV
851 
852  for algorithm in valid_cal_bhabha.algorithms:
853  # Set payload iov information for SequentialBoundaries
854  # and SingleIOV strategies.
855  if payload_boundaries:
856  algorithm.params = {"iov_coverage": output_iov,
857  "payload_boundaries": payload_boundaries}
858 
859  print("Set iov for bhabha validation alg - SequentialBoundaries")
860  else:
861  algorithm.params = {"apply_iov": output_iov}
862  print("Set iov for bhabha validation alg - SingleIOV")
863 
864 
867  root_input = register_module('RootInput')
868  rec_path_hadron_val = create_path()
869  rec_path_hadron_val.add_module(root_input)
870  if 'Gearbox' not in rec_path_hadron_val:
871  rec_path_hadron_val.add_module('Gearbox')
872  if 'Geometry' not in rec_path_hadron_val:
873  rec_path_hadron_val.add_module('Geometry', useDB=True)
874 
875  prepare_user_cdst_analysis(rec_path_hadron_val) # for new 2020 cdst format
876 
877  col_hadron_val = register_module('eclHadronTimeCalibrationValidationCollector')
878  col_hadron_val.param('timeAbsMax', 70)
879  col_hadron_val.param('saveTree', False)
880 
881  eclValTCol = Collection(collector=col_hadron_val,
882  input_files=input_files_hadron,
883  pre_collector_path=rec_path_hadron_val)
884 
885 
887 
888  # Give the collector name to the algorithm since one algorithm
889  # is used to analyse the results from several possible collectors
890  eclValTAlgHadronic = Belle2.ECL.eclTValidationAlgorithm("eclHadronTimeCalibrationValidationCollector")
891 
892  # Define the CAF algorithm arguments
893  eclValTAlgHadronic.meanCleanRebinFactor = 3
894  eclValTAlgHadronic.meanCleanCutMinFactor = 0.4
895  eclValTAlgHadronic.clusterTimesFractionWindow_maxtime = 8
896  eclValTAlgHadronic.debugFilenameBase = "eclHadronTValidationAlgorithm"
897 
898 
900 
901  from caf.framework import Calibration
902 
903  valid_cal_hadron = Calibration("ECLcrystalTimeCalValidation_hadronPhysics")
904  valid_cal_hadron.add_collection(name="hadron", collection=eclValTCol)
905  valid_cal_hadron.algorithms = [eclValTAlgHadronic]
906  valid_cal_hadron.save_payloads = False
907  valid_cal_bhabha.backend_args = {"request_memory": "4 GB"}
908 
909  eclValTAlgHadronic.readPrevCrysPayload = True
910  print("eclValTAlgHadronic.readPrevCrysPayload = ", eclValTAlgHadronic.readPrevCrysPayload)
911 
912  # Here we set the AlgorithmStrategy for our algorithm
913 
914  # The default value is SingleIOV, you don't have to set this, it is done automatically.
915  # SingleIOV just takes all of the runs as one big IoV and executes the algorithm once on all of their data.
916  # You can use granularity='run' or granularity='all' for the collector when using this strategy.
917 
918  # If payload boundaries are set use SequentialBoundaries
919  # otherwise use SingleIOV
920  if payload_boundaries:
921  valid_cal_hadron.strategies = SequentialBoundaries
922  else:
923  valid_cal_hadron.strategies = SingleIOV
924 
925  for algorithm in valid_cal_hadron.algorithms:
926  # Set payload iov information for SequentialBoundaries
927  # and SingleIOV strategies.
928  if payload_boundaries:
929  algorithm.params = {"iov_coverage": output_iov,
930  "payload_boundaries": payload_boundaries}
931 
932  print("Set iov for hadron validation alg - SequentialBoundaries")
933  else:
934  algorithm.params = {"apply_iov": output_iov}
935  print("Set iov for hadron validation alg - SingleIOV")
936 
937 
940 
941  # Set up the collector but with only one event per file
942  root_input = register_module('RootInput', entrySequences=['0:{}'.format(1)])
943 
944  rec_path_bhabha_plotting = create_path()
945  rec_path_bhabha_plotting.add_module(root_input)
946  if 'Gearbox' not in rec_path_bhabha_plotting:
947  rec_path_bhabha_plotting.add_module('Gearbox')
948  if 'Geometry' not in rec_path_bhabha_plotting:
949  rec_path_bhabha_plotting.add_module('Geometry', useDB=True)
950 
951  prepare_cdst_analysis(rec_path_bhabha_plotting) # for new 2020 cdst format
952 
953  col_bhabha_plotting = register_module('eclTimeShiftsPlottingCollector')
954  eclTCol = Collection(collector=col_bhabha_plotting,
955  input_files=input_files_plotting,
956  pre_collector_path=rec_path_bhabha_plotting,
957  )
958 
959  # Set up the plotting. Use the two files with the collector to
960  # determine the run range to plot. The plotting is done in the
961  # algorithm
962 
963  tShifts_alg = Belle2.ECL.eclTimeShiftsAlgorithm()
964  tShifts_alg.debugFilenameBase = "eclTimeShiftsAlgorithm"
965 
966  # +-30ns range allows for unexpectedly large jumps
967  tShifts_alg.crysCrateShift_min = -30 # in ns
968  tShifts_alg.crysCrateShift_max = 30 # in ns
969 
970  # Make the algorithm loop over the runs, not just the collector
971  # tShifts_alg.algorithmReadPayloads = True
972 
973  cal_ecl_timeShifts = Calibration(name="ecl_t_shifts", algorithms=[tShifts_alg],
974  input_files=input_files_plotting)
975  cal_ecl_timeShifts.add_collection(name="bhabha", collection=eclTCol)
976 
977  cal_ecl_timeShifts.save_payloads = False
978 
979  # If payload boundaries are set use SequentialBoundaries
980  # otherwise use SingleIOV
981  if payload_boundaries:
982  cal_ecl_timeShifts.strategies = SequentialBoundaries
983  else:
984  cal_ecl_timeShifts.strategies = SingleIOV
985 
986  for algorithm in cal_ecl_timeShifts.algorithms:
987  # Set payload iov information for SequentialBoundaries
988  # and SingleIOV strategies.
989  if payload_boundaries:
990  algorithm.params = {"iov_coverage": output_iov,
991  "payload_boundaries": payload_boundaries}
992 
993  print("Set iov for crate time plotting alg - SequentialBoundaries")
994  else:
995  algorithm.params = {"apply_iov": output_iov}
996  print("Set iov for crate time plotting alg - SingleIOV")
997 
998 
1004 
1005  # cal_crates_1 depends on the crystal payload values in the global tag
1006  cal_crystals_1.depends_on(cal_crates_1)
1007  cal_ecl_merge.depends_on(cal_crystals_1)
1008  cal_crates_2.depends_on(cal_ecl_merge)
1009 
1010  # The validations can run independently of each other but rely on the
1011  # last calibration step
1012  valid_cal_bhabha.depends_on(cal_crates_2)
1013  valid_cal_hadron.depends_on(cal_crates_2)
1014 
1015  # Plotting
1016  cal_ecl_timeShifts.depends_on(cal_crates_2)
1017 
1018 
1020 
1021  # You must return all calibrations you want to run in the prompt process, even if it's only one
1022  # Calibrations will be executed in this order as a result of the dependencies defined by the "dependes_on(...)".
1023  return [cal_crates_1, cal_crystals_1, cal_ecl_merge, cal_crates_2,
1024  valid_cal_bhabha, valid_cal_hadron, cal_ecl_timeShifts]
1025 
1026 
Belle2::ECL::eclTimeShiftsAlgorithm
Calibrate ecl crystals using previously created payloads.
Definition: eclTimeShiftsAlgorithm.h:38
prompt.utils
Definition: utils.py:1
Belle2::ECL::eclTValidationAlgorithm
Validate the ecl timing calibrations using a hadronic event selection.
Definition: eclTValidationAlgorithm.h:37
Belle2::ECL::eclMergingCrystalTimingAlgorithm
Calibrate ecl crystals using previously created payloads.
Definition: eclMergingCrystalTimingAlgorithm.h:47
Collection
Definition: Collection.py:1
Belle2::ECL::eclBhabhaTAlgorithm
Calibrate ecl crystals using bhabha events.
Definition: eclBhabhaTAlgorithm.h:39
Calibration
Definition: Calibration.py:1