Belle II Software  release-08-01-10
caf_ecl_time_crystalCrate.py
1 
8 
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."""
12 
13 from prompt import CalibrationSettings, INPUT_DATA_FILTERS
14 from reconstruction import prepare_cdst_analysis, prepare_user_cdst_analysis
15 from caf.utils import IoV, ExpRun
16 import copy
17 
18 
25 
26 
30 settings = CalibrationSettings(
31  name="ECL crystal and crate time calibrations and validations",
32  expert_username="hearty",
33  description=__doc__,
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"]]},
50  depends_on=[],
51  expert_config={"numCrysCrateIterations": 1,
52  "maxNumberEvents": 50000000,
53  "payload_boundaries": [],
54  "t0_bhabhaToHadron_correction": 0})
55 
56 
57 
66 
67 
68 def get_calibrations(input_data, **kwargs):
69  """
70  Parameters:
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
74 
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.
78 
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)
81 
82  Returns:
83  list(caf.framework.Calibration): All of the calibration objects we want to assign to the CAF process
84  """
85  import basf2
86  # Set up config options
87 
88  # Extract expert config variables input from command line (or from
89  # the calibrations submission website via the command line).
90  expert_config = kwargs.get("expert_config")
91 
92  # Determine how many iterations of the crystal calibrations and
93  # crate calibrations to perform.
94  numCrysCrateIterations = expert_config["numCrysCrateIterations"]
95  print("expert_config: numCrysCrateIterations = ", numCrysCrateIterations)
96 
97  # Set the maximum number of events to include per crystal calibration
98  # NOTE: THIS IS NOT QUITE RIGHT SINCE THIS MAXIMUM DOESN'T WORK WITH
99  # THE sequentialBoundaries SET UP FOR SEPARATE RUN NUMBER REGIONS FOR
100  # CRYSTAL CALIBRATIONS !! BUT THIS WILL WORK WELL IF THERE IS ONLY ONE
101  # RUN RANGE REGION FOR THE CRYSTAL CALIBRATIONS.
102  maxNumEventsCrystalCalib = expert_config["maxNumberEvents"]
103  print("expert_config: maxNumEventsCrystalCalib = ", maxNumEventsCrystalCalib)
104 
105  # Determine how large of an offset should be applied to correct for
106  # differences in the CDC event t0 in bhabha and hadronic events
107  t0_bhabhaToHadron_correction = expert_config["t0_bhabhaToHadron_correction"]
108  print("expert_config: t0_bhabhaToHadron_correction = ", t0_bhabhaToHadron_correction)
109 
110  from caf.strategies import SimpleRunByRun, SingleIOV, SequentialBoundaries
111  import numpy as np
112 
113  # Determine the user defined calibration boundaries. Most useful
114  # for when multiple experiments are processed at the same time.
115  # Useful for the crystal calibrations but not for the crate
116  # calibrations, which are done run-by-run.
117  payload_boundaries = [] # Introduce empty list of 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)
121 
122  # In this script we want to use one sources of input data.
123  # Get the input files from the input_data variable
124  # The input data should be the bhabha skim for the calibrations
125  # and the hadron skim for the validations.
126  file_to_iov_bhabha = input_data["bhabha_all_calib"]
127  file_to_iov_hadron = input_data["hadron_calib"]
128 
129  # Set the maximum limits on the number of files/events per run.
130  # If I decided to remove the limit on the number of files per run, it is just easier
131  # to set it to a large number in case we want to introduce it later.
132  # Also, keeping it allows the crystal calibrations code to look like the
133  # crates calibration code even though they don't use the same list of input files.
134  max_files_per_run_calibration = 26
135  max_files_per_run_validation = 4
136  max_events_per_run_plotting = 1
137 
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
144 
145  print("max_events_per_crystalCalib = ", max_events_per_crystalCalib)
146 
147  # We filter addition files if there are more than [max_files_per_run] files per run.
148  # The input data files are sorted alphabetically by b2caf-prompt-run
149  # already. This procedure respects that ordering
150  from prompt.utils import filter_by_max_files_per_run
151 
152  # We filter addition files if there are more than [max_events_per_run] events per run.
153  # For plotting after the calibrations
154  from prompt.utils import filter_by_max_events_per_run
155 
156  # We filter addition files if there are more than [max_events_per_calibration] events per crystal calibration.
157  # For doing the crystal calibrations
158  from prompt.utils import filter_by_select_max_events_from_files
159 
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)}")
163 
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)}")
167 
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)}")
170 
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)}")
177 
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.")
181 
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.")
186  else:
187  print("User requested max number of events filter to not be used so all bhabha input files being used for crystals")
188 
189  basf2.B2INFO(f"Total number of bhabha files being used for crystal calibration = {len(input_files_bhabha_crystal)}")
190 
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)}")
194 
195  # For plotting the sum of the crate and crystal calibration
196  # constants after the calibrations are made. To be used to
197  # monitor crate time jumps.
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())
200 
201  # Interval of validity for the calibrations
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)
205 
206 
207  from basf2 import register_module, create_path
208  from ROOT import Belle2
209  from caf.framework import Collection
210 
211 
213  print("Set up the base for the collectors for the calibrations")
214 
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)
222 
223  prepare_cdst_analysis(rec_path_bhabha, components=['SVD', 'CDC', 'ECL', 'KLM'])
224 
225  # ====================================================
226  # t0BiasCorrection = -0.9 # Correct for the CDC t0 bias in ns
227  t0BiasCorrection = t0_bhabhaToHadron_correction # Correct for the CDC t0 bias in ns
228  # ====================================================
229 
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)
237 
238  eclTCol = Collection(collector=col_bhabha,
239  input_files=input_files_bhabha,
240  pre_collector_path=rec_path_bhabha)
241 
242  eclTCol_crys = Collection(collector=col_bhabha,
243  input_files=input_files_bhabha_crystal,
244  pre_collector_path=rec_path_bhabha)
245 
246 
248  print("Set up the base for the crate calibration algorithm")
249 
250  eclTAlgCrates = Belle2.ECL.eclBhabhaTAlgorithm()
251 
252  # Define the CAF algorithm arguments
253  # Set the cellIDLo to be larger than cellIDHi so that no crystal
254  # calibrations will be performed.
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"
261 
262 
264  print("Set up the base for the crystal calibration algorithm")
265 
266  eclTAlgCrystals = Belle2.ECL.eclBhabhaTAlgorithm()
267 
268  # Define the CAF algorithm arguments
269  # Set the crateIDLo to be larger than crateIDHi so that no crate
270  # calibrations will be performed. More variables set later in code....
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"
277 
278  # Make two versions of these algorithms that differ only in whether
279  # or not the previous bucket's payload information is saved
280  # to a temporary payload for comparison purposes at each
281  # iteration.
282  eclTAlgCrystals_saveNotReadPrevPayload = copy.deepcopy(eclTAlgCrystals)
283  eclTAlgCrystals_readNotSavePrevPayload = copy.deepcopy(eclTAlgCrystals)
284 
285  eclTAlgCrystals_saveNotReadPrevPayload.savePrevCrysPayload = True
286  eclTAlgCrystals_saveNotReadPrevPayload.readPrevCrysPayload = False
287 
288  eclTAlgCrystals_readNotSavePrevPayload.savePrevCrysPayload = False
289  eclTAlgCrystals_readNotSavePrevPayload.readPrevCrysPayload = True
290 
291 
293  print("Set up the base for the crystal merger algorithm")
294 
296  merging_alg.readPrevCrysPayload = True
297 
298 
304 
305  if numCrysCrateIterations <= 0:
306  print("numCrysCrateIterations NEEDS TO BE > 0 !!!")
307  elif numCrysCrateIterations > 0:
308 
310 
311  from caf.framework import Calibration
312  print("Performing ", numCrysCrateIterations, " iterations of crate and crystal calibrations.")
313 
314  crysCalibBaseName = "ECLcrystalTimeCalibration_physics_"
315  crateCalibBaseName = "ECLcrateTimeCalibration_physics_"
316  mergeCalibBaseName = "ecl_t_merge_"
317 
318  calibs = []
319 
320  # --------------------------------------------------------------
321  # Loop over all the iterations to set up the crate and crystal
322  # calibrations.
323 
324  for i in range(numCrysCrateIterations):
325  crysCalibName = crysCalibBaseName + str(i)
326  crateCalibName = crateCalibBaseName + str(i)
327  mergeCalibName = mergeCalibBaseName + str(i)
328 
329  print("iteration = ", i)
330  print("crysCalibName = ", crysCalibName)
331  print("crateCalibName = ", crateCalibName)
332 
333 
335  cal_crates_i = Calibration(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"}
341 
342 
344 
345  cal_crystals_i = Calibration(crysCalibName)
346  cal_crystals_i.add_collection(name="bhabha", collection=eclTCol_crys)
347  cal_crystals_i.backend_args = {"request_memory": "4 GB"}
348 
349  # If this is the first iteration then save the previous crystal payload
350  # values to a temporary storage payload. If this is not the first iteration
351  # then read in the previous stored payload and plot the change in the crystal
352  if i == 0:
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)
359  else:
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)
366 
367  cal_crystals_i.save_payloads = False
368 
369  # If payload boundaries are set use SequentialBoundaries
370  # otherwise use SingleIOV
371  if payload_boundaries:
372  cal_crystals_i.strategies = SequentialBoundaries
373  else:
374  cal_crystals_i.strategies = SingleIOV
375 
376 
378 
379  cal_ecl_merge_i = Calibration(name=mergeCalibName, collector="DummyCollector",
380  input_files=input_files_bhabha_1perRun)
381 
382  # Read in the previous crystal payload values for comparision
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)
386 
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
391 
392  # If payload boundaries are set use SequentialBoundaries
393  # otherwise use SingleIOV
394  if payload_boundaries:
395  cal_ecl_merge_i.strategies = SequentialBoundaries
396  else:
397  cal_ecl_merge_i.strategies = SingleIOV
398 
399  # Modify the iov for each of the calibration algorithms
400  for algorithm in cal_crystals_i.algorithms:
401  # The payload of the final crystal calibration iteration
402  # is given the user's iov.
403  if i == numCrysCrateIterations - 1:
404  # Set payload iov information for SequentialBoundaries
405  # and SingleIOV strategies.
406  if payload_boundaries:
407  algorithm.params = {"iov_coverage": output_iov,
408  "payload_boundaries": payload_boundaries}
409 
410  print("Set iov for final crystals alg - SequentialBoundaries")
411  else:
412  algorithm.params = {"apply_iov": output_iov}
413  print("Set iov for final crystals alg - SingleIOV ")
414  # Force the output iovs to be open for the intermediate
415  # step calibrations.
416  else:
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")
421  else:
422  algorithm.params = {"apply_iov": intermediate_iov}
423  print("Set iov for intermediate crystals alg - SingleIOV ")
424 
425  # Modify the iov for each of the payload merging algorithms
426  for algorithm in cal_ecl_merge_i.algorithms:
427  # The payload of the final crystal calibration iteration
428  # is given the user's iov.
429  if i == numCrysCrateIterations - 1:
430  # Set payload iov information for SequentialBoundaries
431  # and SingleIOV strategies.
432  if payload_boundaries:
433  algorithm.params = {"iov_coverage": output_iov,
434  "payload_boundaries": payload_boundaries}
435 
436  print("Set iov for final merging alg - SequentialBoundaries")
437  else:
438  algorithm.params = {"apply_iov": output_iov}
439  print("Set iov for final merging alg - SingleIOV ")
440  # Force the output iovs to be open for the intermediate
441  # step calibrations.
442  else:
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")
447  else:
448  algorithm.params = {"apply_iov": intermediate_iov}
449  print("Set iov for intermediate merging alg - SingleIOV ")
450 
451  # Fill the calibs array with all the "calibrations" that will be run
452  calibs = np.append(calibs, [cal_crates_i, cal_crystals_i, cal_ecl_merge_i])
453 
454  # Make sure that the final paylaods get saved.
455  calibs[len(calibs) - 3].save_payloads = True # crates
456  calibs[len(calibs) - 1].save_payloads = True # crystals
457 
458 
463 
464 
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)
474 
475  # exclude PXD and PID, so only CDC and ECL used for eventT0
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)
481 
482  eclValTCol = Collection(collector=col_bhabha_val,
483  input_files=input_files_bhabha_crystal,
484  pre_collector_path=rec_path_bhabha_val)
485 
486 
488 
489  # Give the collector name to the algorithm since one algorithm
490  # is used to analyse the results from several possible collectors
491  eclValTAlgBhabha = Belle2.ECL.eclTValidationAlgorithm("eclBhabhaTimeCalibrationValidationCollector")
492 
493  # Define the CAF algorithm arguments
494  eclValTAlgBhabha.meanCleanRebinFactor = 3
495  eclValTAlgBhabha.meanCleanCutMinFactor = 0.4
496  eclValTAlgBhabha.clusterTimesFractionWindow_maxtime = 1.5
497  eclValTAlgBhabha.debugFilenameBase = "eclBhabhaTValidationAlgorithm"
498 
499 
501 
502  from caf.framework import Calibration
503 
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"}
508 
509  # Make a second version of this algorithm that differs only in
510  # that it is instructed to read the previous crystal payload.
511  # The version where we don't read in the previous payload
512  # is left over from a previous code version
513  eclValTAlgBhabha_readPrevPayload = copy.deepcopy(eclValTAlgBhabha)
514  eclValTAlgBhabha_readPrevPayload.readPrevCrysPayload = True
515 
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)
520 
521  # If payload boundaries are set use SequentialBoundaries
522  # otherwise use SingleIOV
523  if payload_boundaries:
524  valid_cal_bhabha.strategies = SequentialBoundaries
525  else:
526  valid_cal_bhabha.strategies = SingleIOV
527 
528  for algorithm in valid_cal_bhabha.algorithms:
529  # Set payload iov information for SequentialBoundaries
530  # and SingleIOV strategies.
531  if payload_boundaries:
532  algorithm.params = {"iov_coverage": output_iov,
533  "payload_boundaries": payload_boundaries}
534 
535  print("Set iov for bhabha validation alg - SequentialBoundaries")
536  else:
537  algorithm.params = {"apply_iov": output_iov}
538  print("Set iov for bhabha validation alg - SingleIOV")
539 
540 
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)
550 
551  # exclude PXD and PID, so only CDC and ECL used for eventT0
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)
556 
557  eclValTCol = Collection(collector=col_hadron_val,
558  input_files=input_files_hadron,
559  pre_collector_path=rec_path_hadron_val)
560 
561 
563 
564  # Give the collector name to the algorithm since one algorithm
565  # is used to analyse the results from several possible collectors
566  eclValTAlgHadronic = Belle2.ECL.eclTValidationAlgorithm("eclHadronTimeCalibrationValidationCollector")
567 
568  # Define the CAF algorithm arguments
569  eclValTAlgHadronic.meanCleanRebinFactor = 3
570  eclValTAlgHadronic.meanCleanCutMinFactor = 0.4
571  eclValTAlgHadronic.clusterTimesFractionWindow_maxtime = 8
572  eclValTAlgHadronic.debugFilenameBase = "eclHadronTValidationAlgorithm"
573 
574 
576 
577  from caf.framework import Calibration
578 
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"}
583 
584  # Make a second version of this algorithm that differs only in
585  # that it is instructed to read the previous crystal payload
586  eclValTAlgHadron_readPrevPayload = copy.deepcopy(eclValTAlgHadronic)
587  eclValTAlgHadron_readPrevPayload.readPrevCrysPayload = True
588 
589  # Make a second version of this algorithm that differs only in
590  # that it is instructed to read the previous crystal payload.
591  # The version where we don't read in the previous payload
592  # is left over from a previous code version
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)
597 
598  # If payload boundaries are set use SequentialBoundaries
599  # otherwise use SingleIOV
600  if payload_boundaries:
601  valid_cal_hadron.strategies = SequentialBoundaries
602  else:
603  valid_cal_hadron.strategies = SingleIOV
604 
605  for algorithm in valid_cal_hadron.algorithms:
606  # Set payload iov information for SequentialBoundaries
607  # and SingleIOV strategies.
608  if payload_boundaries:
609  algorithm.params = {"iov_coverage": output_iov,
610  "payload_boundaries": payload_boundaries}
611 
612  print("Set iov for hadron validation alg - SequentialBoundaries")
613  else:
614  algorithm.params = {"apply_iov": output_iov}
615  print("Set iov for hadron validation alg - SingleIOV")
616 
617 
620 
621  # Set up the collector but with only one event per file
622  root_input = register_module('RootInput', entrySequences=['0:{}'.format(1)])
623 
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)
630 
631  prepare_cdst_analysis(rec_path_bhabha_plotting, components=['SVD', 'CDC', 'ECL', 'KLM'])
632 
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)
637 
638  # Set up the plotting. Use the two files with the collector to
639  # determine the run range to plot. The plotting is done in the
640  # algorithm
641 
642  tShifts_alg = Belle2.ECL.eclTimeShiftsAlgorithm()
643  tShifts_alg.debugFilenameBase = "eclTimeShiftsAlgorithm"
644 
645  # +-30ns range allows for unexpectedly large jumps
646  tShifts_alg.crysCrateShift_min = -30 # in ns
647  tShifts_alg.crysCrateShift_max = 30 # in ns
648 
649  # Make the algorithm loop over the runs, not just the collector
650  # tShifts_alg.algorithmReadPayloads = True
651 
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)
655 
656  cal_ecl_timeShifts.save_payloads = False
657 
658  # If payload boundaries are set use SequentialBoundaries
659  # otherwise use SingleIOV
660  if payload_boundaries:
661  cal_ecl_timeShifts.strategies = SequentialBoundaries
662  else:
663  cal_ecl_timeShifts.strategies = SingleIOV
664 
665  for algorithm in cal_ecl_timeShifts.algorithms:
666  # Set payload iov information for SequentialBoundaries
667  # and SingleIOV strategies.
668  if payload_boundaries:
669  algorithm.params = {"iov_coverage": output_iov,
670  "payload_boundaries": payload_boundaries}
671 
672  print("Set iov for crate time plotting alg - SequentialBoundaries")
673  else:
674  algorithm.params = {"apply_iov": output_iov}
675  print("Set iov for crate time plotting alg - SingleIOV")
676 
677 
682 
683  # Make the crate and crytsal calibrations and the cerge crystal
684  # process occur in the order loaded into the array.
685  for i in range(len(calibs) - 1):
686  calibs[i + 1].depends_on(calibs[i])
687 
688  # The validations and plotting can run independently of each other
689  # but rely on the last calibration step
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])
693 
694 
696 
697  calibs = np.append(calibs, [valid_cal_bhabha, valid_cal_hadron, cal_ecl_timeShifts])
698 
699  print("##############")
700  print("List of calibrations:")
701  for c in calibs:
702  print(" ", c.name, " depends on ", c.dependencies, ", save payloads = ", c.save_payloads)
703  print("##############")
704 
705  # You must return all calibrations you want to run in the prompt process, even if it's only one
706  # Calibrations will be executed in this order as a result of the dependencies defined by the "dependes_on(...)".
707  return calibs
708 
709 
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.