Belle II Software  release-08-02-06
caf_cdcdedx.py
1 
8 
9 """
10 Airflow script for automatic CDC dEdx calibration. It is currently for the electron based
11 calibration, where at present only RunGain, injection time, Cosine and WireGain are implimented.
12 The remaining two 2D and 1D will be implimented in the near future.
13 
14 Second part called "Hadron calibration" are not compitable with CAF/AirFlow
15 and will be done offline for a while.
16 """
17 
18 import ROOT
19 from ROOT import gSystem
20 from ROOT.Belle2 import CDCDedxRunGainAlgorithm, CDCDedxCosineAlgorithm, CDCDedxWireGainAlgorithm
21 from ROOT.Belle2 import CDCDedxCosEdgeAlgorithm, CDCDedxBadWireAlgorithm, CDCDedxInjectTimeAlgorithm
22 from ROOT.Belle2 import CDCDedx1DCellAlgorithm
23 
24 from caf.framework import Calibration
25 from caf.strategies import SequentialRunByRun, SequentialBoundaries
26 from prompt import CalibrationSettings, INPUT_DATA_FILTERS
27 import reconstruction as recon
28 from random import seed
29 import basf2
30 
31 gSystem.Load('libreconstruction.so')
32 ROOT.gROOT.SetBatch(True)
33 
34 settings = CalibrationSettings(
35  name="CDC dedx",
36  expert_username="renu",
37  description=__doc__,
38  input_data_formats=["cdst"],
39  input_data_names=["bhabha_all_calib"],
40  expert_config={
41  "payload_boundaries": [],
42  "calib_datamode": False,
43  "maxevt_rg": 75000,
44  "maxevt_cc": 18e6,
45  "maxevt_wg": 18e6,
46  "adjustment": 1.00798,
47  "calib_mode": "full", # manual or predefined: full or quick
48  "calibration_procedure": {"rungain0": 0, "rungain1": 0, "rungain2": 0}
49  },
50  input_data_filters={
51  "bhabha_all_calib": [
52  INPUT_DATA_FILTERS['Run Type']['physics'],
53  INPUT_DATA_FILTERS['Data Tag']['bhabha_all_calib'],
54  INPUT_DATA_FILTERS['Data Quality Tag']['Good Or Recoverable'],
55  INPUT_DATA_FILTERS['Magnet']['On'],
56  INPUT_DATA_FILTERS['Beam Energy']['4S'],
57  INPUT_DATA_FILTERS['Beam Energy']['Continuum'],
58  INPUT_DATA_FILTERS['Beam Energy']['Scan']]},
59  depends_on=[])
60 
61 
62 def get_calibrations(input_data, **kwargs):
63  """ REQUIRED FUNCTION used by b2caf-prompt-run tool
64  This function return a list of Calibration
65  objects we assign to the CAF process
66  """
67 
68  import basf2
69  file_to_iov_physics = input_data["bhabha_all_calib"]
70 
71  expert_config = kwargs.get("expert_config")
72  calib_mode = expert_config["calib_mode"]
73 
74  # extracting parameters
75  fulldataMode = expert_config["calib_datamode"]
76  adjustment = expert_config["adjustment"]
77 
78  if fulldataMode:
79  input_files_rungain = list(file_to_iov_physics.keys())
80  input_files_coscorr = list(file_to_iov_physics.keys())
81  input_files_wiregain = list(file_to_iov_physics.keys())
82  else:
83  seed(271492)
84 
85  maxevt_rg = expert_config["maxevt_rg"]
86  maxevt_cc = expert_config["maxevt_cc"]
87  maxevt_wg = expert_config["maxevt_wg"]
88 
89  from prompt.utils import filter_by_max_events_per_run, filter_by_select_max_events_from_files
90 
91  # collection for rungains
92  max_files_for_maxevents = maxevt_rg # allevents to accp bhabha event ratio = 0.60
93  reduced_file_to_iov_rungain = filter_by_max_events_per_run(file_to_iov_physics, max_files_for_maxevents, True)
94  input_files_rungain = list(reduced_file_to_iov_rungain.keys())
95  basf2.B2INFO(f"Total number of files used for rungains = {len(input_files_rungain)}")
96 
97  # collection for cosinecorr
98  input_files_coscorr = filter_by_select_max_events_from_files(list(file_to_iov_physics.keys()), maxevt_cc)
99  basf2.B2INFO(f"Total number of files used for cosine = {len(input_files_coscorr)}")
100  if not input_files_coscorr:
101  raise ValueError(
102  f"Cosine: all requested ({maxevt_cc}) events not found")
103 
104  # collection for wiregain
105  if maxevt_wg == maxevt_cc:
106  input_files_wiregain = input_files_coscorr
107  else:
108  input_files_wiregain = filter_by_select_max_events_from_files(list(file_to_iov_physics.keys()), maxevt_wg)
109 
110  basf2.B2INFO(f"Total number of files used for wiregains = {len(input_files_wiregain)}")
111  if not input_files_wiregain:
112  raise ValueError(
113  f"WireGain: all requested ({maxevt_wg}) events not found")
114 
115  requested_iov = kwargs.get("requested_iov", None)
116  from caf.utils import ExpRun, IoV
117  output_iov = IoV(requested_iov.exp_low, requested_iov.run_low, -1, -1)
118 
119  payload_boundaries = [ExpRun(output_iov.exp_low, output_iov.run_low)]
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 
123  collector_granularity = 'all'
124  if expert_config["payload_boundaries"] is not None:
125  basf2.B2INFO('Found payload_boundaries: set collector granularity to run')
126  collector_granularity = 'run'
127 
128  if calib_mode == "full":
129  calibration_procedure = {
130  "rungain0": 0, # Run Gain trail (No Payload saving and take of effect of previous rungains)
131  "timegain0": 0, # Injection time gain Pre (No payload saving)
132  "timegain1": 0, # Injection time gain
133  "rungain1": 0, # Run Gain Pre (No Payload saving)
134  "coscorr0": 0, # Cosine Corr Gain Pre (No Payload saving)
135  "cosedge0": 0, # Cosine edge Corr Gain
136  "badwire0": 0, # Bad wire
137  "wiregain0": 0, # WireGain Gain
138  "onedcell0": 0, # OneD cell correction
139  "coscorr1": 0, # Cosine Corr Gain
140  "rungain2": 0 # Final Run Gain to take Wire and Cosine correction in effect
141  }
142  elif calib_mode == "quick":
143  calibration_procedure = {
144  "rungain0": 0,
145  "timegain0": 0,
146  "rungain1": 0,
147  "coscorr0": 0,
148  "cosedge0": 0,
149  "badwire0": 0,
150  "wiregain0": 0,
151  "rungain2": 0
152  }
153  elif calib_mode == "manual":
154  calibration_procedure = expert_config["calibration_procedure"]
155  else:
156  basf2.B2FATAL(f"Calibration mode is not defined {calib_mode}, should be full, quick, or manual")
157 
158  calib_keys = list(calibration_procedure)
159  cals = [None]*len(calib_keys)
160  basf2.B2INFO(f"Run calibration mode = {calib_mode}:")
161 
162  for i in range(len(cals)):
163  max_iter = calibration_procedure[calib_keys[i]]
164  alg = None
165  data_files = [input_files_rungain, input_files_coscorr, input_files_wiregain]
166  cal_name = ''.join([i for i in calib_keys[i] if not i.isdigit()])
167  if cal_name == "rungain":
168  alg = [rungain_algo(calib_keys[i], adjustment)]
169  elif cal_name == "coscorr":
170  alg = [cos_algo()]
171  elif cal_name == "cosedge":
172  alg = [cosedge_algo()]
173  elif cal_name == "timegain":
174  alg = [injection_time_algo()]
175  elif cal_name == "badwire":
176  alg = [badwire_algo()]
177  elif cal_name == "wiregain":
178  alg = [wiregain_algo()]
179  elif cal_name == "onedcell":
180  alg = [onedcell_algo()]
181  else:
182  basf2.B2FATAL(f"The calibration is not defined, check spelling: calib {i}: {calib_keys[i]}")
183 
184  basf2.B2INFO(f"calibration for {calib_keys[i]} with number of iteration={max_iter}")
185 
186  cals[i] = CDCDedxCalibration(name=calib_keys[i],
187  algorithms=alg,
188  input_file_dict=data_files,
189  max_iterations=max_iter,
190  collector_granularity=collector_granularity,
191  dependencies=[cals[i-1]] if i > 0 else None
192  )
193  if payload_boundaries:
194  basf2.B2INFO("Found payload_boundaries: calibration strategies set to SequentialBoundaries.")
195  if cal_name == "rungain" or cal_name == "timegain":
196  cals[i].strategies = SequentialRunByRun
197  for algorithm in cals[i].algorithms:
198  algorithm.params = {"iov_coverage": output_iov}
199  if calib_keys[i] == "rungain0" or calib_keys[i] == "rungain1" or calib_keys[i] == "timegain0":
200  cals[i].save_payloads = False
201  else:
202  cals[i].strategies = SequentialBoundaries
203  for algorithm in cals[i].algorithms:
204  algorithm.params = {"iov_coverage": output_iov, "payload_boundaries": payload_boundaries}
205  if calib_keys[i] == "coscorr0":
206  cals[i].save_payloads = False
207 
208  else:
209  for algorithm in cals[i].algorithms:
210  algorithm.params = {"apply_iov": output_iov}
211 
212  return cals
213 
214 
215 # Precollector path
216 def pre_collector(name='rg'):
217  """
218  Define pre collection.
219  Parameters:
220  name : name of the calibration
221  rungain rungain0 by Default.
222  Returns:
223  path : path for pre collection
224  """
225 
226  reco_path = basf2.create_path()
227  recon.prepare_cdst_analysis(path=reco_path)
228  if (name == "timegain" or name == "onedcell"):
229  trg_bhabhaskim = reco_path.add_module("TriggerSkim", triggerLines=["software_trigger_cut&skim&accept_radee"])
230  trg_bhabhaskim.if_value("==0", basf2.Path(), basf2.AfterConditionPath.END)
231  ps_bhabhaskim = reco_path.add_module("Prescale", prescale=0.80)
232  ps_bhabhaskim.if_value("==0", basf2.Path(), basf2.AfterConditionPath.END)
233 
234  elif (name == "cosedge"):
235  trg_bhabhaskim = reco_path.add_module(
236  "TriggerSkim",
237  triggerLines=[
238  "software_trigger_cut&skim&accept_bhabha",
239  "software_trigger_cut&filter&ee_flat_90_180",
240  "software_trigger_cut&filter&ee_flat_0_19"])
241  trg_bhabhaskim.if_value("==0", basf2.Path(), basf2.AfterConditionPath.END)
242  else:
243  trg_bhabhaskim = reco_path.add_module("TriggerSkim", triggerLines=["software_trigger_cut&skim&accept_bhabha"])
244  trg_bhabhaskim.if_value("==0", basf2.Path(), basf2.AfterConditionPath.END)
245 
246  reco_path.add_module(
247  'CDCDedxCorrection',
248  relativeCorrections=False,
249  scaleCor=True,
250  runGain=True,
251  timeGain=True,
252  cosineCor=True,
253  wireGain=True,
254  twoDCell=True,
255  oneDCell=True)
256  return reco_path
257 
258 # Collector setup
259 
260 
261 def collector(granularity='all', name=''):
262  """
263  Create a cdcdedx calibration collector
264  Parameters:
265  name : name of calibration
266  granularity : granularity : all or run
267  Returns:
268  collector : collector module
269  """
270 
271  from basf2 import register_module
272  col = register_module('CDCDedxElectronCollector', cleanupCuts=True)
273  if name == "timegain":
274  CollParam = {'isRun': True, 'isInjTime': True, 'granularity': 'run'}
275 
276  elif name == "coscorr" or name == "cosedge":
277  CollParam = {'isCharge': True, 'isCosth': True, 'granularity': granularity}
278 
279  elif name == "badwire":
280  isHit = True
281  CollParam = {'isWire': True, 'isDedxhit': isHit, 'isADCcorr': not isHit, 'granularity': granularity}
282 
283  elif name == "wiregain":
284  CollParam = {'isWire': True, 'isDedxhit': True, 'granularity': granularity}
285 
286  elif name == "onedcell":
287  CollParam = {
288  'isPt': True,
289  'isCosth': True,
290  'isLayer': True,
291  'isDedxhit': True,
292  'isEntaRS': True,
293  'granularity': granularity}
294 
295  else:
296  CollParam = {'isRun': True, 'granularity': 'run'}
297 
298  col.param(CollParam)
299  return col
300 
301 # Rungain Algorithm setup
302 
303 
304 def rungain_algo(name, adjustment):
305  """
306  Create a rungain calibration algorithm.
307  Returns:
308  algo : rungain algorithm
309  """
310  algo = CDCDedxRunGainAlgorithm()
311  algo.setMonitoringPlots(True)
312  if name == "rungain2":
313  algo.setAdjustment(adjustment)
314  return algo
315 
316 # Injection Algorithm setup
317 
318 
319 def injection_time_algo():
320  """
321  Create a injection time calibration algorithm.
322  Returns:
323  algo : injection time algorithm
324  """
325  algo = CDCDedxInjectTimeAlgorithm()
326  algo.setMonitoringPlots(True)
327  return algo
328 
329 # Cosine Algorithm setup
330 
331 
332 def cos_algo():
333  """
334  Create a cosine calibration algorithm.
335  Returns:
336  algo : cosine algorithm
337  """
338  algo = CDCDedxCosineAlgorithm()
339  algo.setMonitoringPlots(True)
340  return algo
341 
342 # CosineEdge Algorithm setup
343 
344 
345 def cosedge_algo():
346  """
347  Create a cosine edge calibration algorithm.
348  Returns:
349  algo : cosine edge algorithm
350  """
351  algo = CDCDedxCosEdgeAlgorithm()
352  algo.setMonitoringPlots(True)
353  return algo
354 
355 # Badwire Algorithm setup
356 
357 
358 def badwire_algo():
359  """
360  Create a badwire calibration algorithm.
361  Returns:
362  algo : badwire algorithm
363  """
364  algo = CDCDedxBadWireAlgorithm()
365  # threshold (mean and rms) pars for dedx
366  algo.setHighFracThres(0.2)
367  algo.setMeanThres(0.4)
368  algo.setRMSThres(0.4)
369  algo.setHistPars(150, 0, 5)
370  algo.setMonitoringPlots(True)
371  return algo
372 
373 # WireGain Algorithm setup
374 
375 
376 def wiregain_algo():
377  """
378  Create a wire gain calibration algorithm.
379  Returns:
380  algo : wiregain algorithm
381  """
382  algo = CDCDedxWireGainAlgorithm()
383  algo.enableExtraPlots(True)
384  return algo
385 
386 
387 def onedcell_algo():
388  """
389  Create oned cell calibration algorithim.
390  Returns:
391  algo : oned cell correction algorithm
392  """
393  algo = CDCDedx1DCellAlgorithm()
394  algo.enableExtraPlots(True)
395  algo.setMergePayload(True)
396  return algo
397 
398 
400  '''
401  CDCDedxCalibration is a specialized calibration for cdcdedx.
402  '''
403 
404  def __init__(self,
405  name,
406  algorithms,
407  input_file_dict,
408  max_iterations=5,
409  dependencies=None,
410  collector_granularity='All'):
411  '''
412  parameters:
413  name: name of calibration
414  algorithims: algorithm of calibration
415  input_file_dict: input files list
416  max_iterations: maximum number of iterations
417  dependenices: depends on the previous calibration
418  collector_granularity: granularity : all or run
419  '''
420  super().__init__(name=name,
421  algorithms=algorithms
422  )
423 
424  from caf.framework import Collection
425  cal_name = ''.join([i for i in name if not i.isdigit()])
426  if cal_name == "badwire" or cal_name == "wiregain":
427  collection = Collection(collector=collector(granularity=collector_granularity, name=cal_name),
428  input_files=input_file_dict[2],
429  pre_collector_path=pre_collector(cal_name)
430  )
431  elif cal_name == "coscorr" or cal_name == "cosedge" or cal_name == "onedcell":
432  collection = Collection(collector=collector(granularity=collector_granularity, name=cal_name),
433  input_files=input_file_dict[1],
434  pre_collector_path=pre_collector(cal_name)
435  )
436  else:
437  collection = Collection(collector=collector(granularity=collector_granularity, name=cal_name),
438  input_files=input_file_dict[0],
439  pre_collector_path=pre_collector(cal_name)
440  )
441  self.add_collection(name=cal_name, collection=collection)
442 
443 
444  self.max_iterationsmax_iterations = max_iterations
445 
446  if dependencies is not None:
447  for dep in dependencies:
448  self.depends_on(dep)
max_iterations
maximum iterations
Definition: caf_cdcdedx.py:444
def __init__(self, name, algorithms, input_file_dict, max_iterations=5, dependencies=None, collector_granularity='All')
Definition: caf_cdcdedx.py:410