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