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