Belle II Software development
caf_cdcdedx_electron.py
1
8
9"""
10Airflow script for automatic CDC dEdx calibration. It is the electron based
11calibration, where at present only RunGain, injection time, Cosine, WireGain and 1D are implemented.
12The remaining two 2D will be implemented in the near future.
13"""
14
15import ROOT
16from ROOT import gSystem
17from ROOT.Belle2 import CDCDedxRunGainAlgorithm, CDCDedxCosineAlgorithm, CDCDedxWireGainAlgorithm
18from ROOT.Belle2 import CDCDedxCosEdgeAlgorithm, CDCDedxBadWireAlgorithm, CDCDedxInjectTimeAlgorithm
19from ROOT.Belle2 import CDCDedx1DCellAlgorithm, CDCDedxValidationAlgorithm, CDCDedxCosLayerAlgorithm
20
21from caf.framework import Calibration
22from caf.strategies import SingleIOV, SequentialRunByRun, SequentialBoundaries
23from prompt import CalibrationSettings, INPUT_DATA_FILTERS
24import reconstruction as recon
25from random import seed
26import basf2
27
28gSystem.Load('libreconstruction.so')
29ROOT.gROOT.SetBatch(True)
30
31settings = CalibrationSettings(
32 name="CDC dedx",
33 expert_username="renu92garg",
34 subsystem="cdc",
35 description=__doc__,
36 input_data_formats=["cdst"],
37 input_data_names=["bhabha_combined_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_combined_calib": [
50 INPUT_DATA_FILTERS['Run Type']['physics'],
51 INPUT_DATA_FILTERS['Data Tag']['bhabha_combined_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 produced_payloads=["CDCDedxInjectionTime", "CDCDedxCosineEdge", "CDCDedxBadWires",
59 "CDCDedxWireGain", "CDCDedx1DCell", "CDCDedxCosineCor", "CDCDedxRunGain"])
60
61
62def 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_combined_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 "wiregain0": 0, # WireGain Gain Pre (No Payload saving)
132 "timegain0": 0, # Injection time gain Pre (No payload saving)
133 "timegain1": 0, # Injection time gain
134 "rungain1": 0, # Run Gain Pre (No Payload saving)
135 "coslayer0": 0, # Cosine Corr Gain layer dependent (No Payload saving)
136 "coscorr0": 0, # Cosine Corr Gain Pre (No Payload saving)
137 "cosedge0": 0, # Cosine edge Corr Gain
138 "badwire0": 0, # Bad wire
139 "wiregain1": 0, # WireGain Gain
140 "onedcell0": 0, # OneD cell correction Pre (No payload saving)
141 "onedcell1": 0, # OneD cell correction
142 "coslayer1": 0, # Cosine Corr Gain layer dependent (No Payload saving)
143 "coscorr1": 0, # Cosine Corr Gain
144 "rungain2": 0, # Final Run Gain to take Wire and Cosine correction in effect
145 "validation0": 0 # get data for validation
146 }
147 elif calib_mode == "quick":
148 calibration_procedure = {
149 "rungain0": 0,
150 "timegain1": 0,
151 "rungain1": 0,
152 "coslayer1": 0,
153 "coscorr1": 0,
154 "cosedge0": 0,
155 "badwire0": 0,
156 "wiregain1": 0,
157 "rungain2": 0,
158 "validation0": 0
159 }
160 elif calib_mode == "manual":
161 calibration_procedure = expert_config["calibration_procedure"]
162 else:
163 basf2.B2FATAL(f"Calibration mode is not defined {calib_mode}, should be full, quick, or manual")
164
165 calib_keys = list(calibration_procedure)
166 cals = [None]*len(calib_keys)
167 basf2.B2INFO(f"Run calibration mode = {calib_mode}:")
168
169 for i in range(len(cals)):
170 max_iter = calibration_procedure[calib_keys[i]]
171 alg = None
172 data_files = [input_files_rungain, input_files_coscorr, input_files_wiregain]
173 cal_name = ''.join([i for i in calib_keys[i] if not i.isdigit()])
174 if cal_name == "rungain":
175 alg = [rungain_algo(calib_keys[i], adjustment)]
176 elif cal_name == "coslayer":
177 alg = [coslayer_algo()]
178 elif cal_name == "coscorr":
179 alg = [cos_algo()]
180 elif cal_name == "cosedge":
181 alg = [cosedge_algo()]
182 elif cal_name == "timegain":
183 alg = [injection_time_algo()]
184 elif cal_name == "badwire":
185 alg = [badwire_algo()]
186 elif cal_name == "wiregain":
187 alg = [wiregain_algo()]
188 elif cal_name == "onedcell":
189 alg = [onedcell_algo()]
190 elif cal_name == "validation":
191 alg = [validation_algo()]
192 else:
193 basf2.B2FATAL(f"The calibration is not defined, check spelling: calib {i}: {calib_keys[i]}")
194
195 basf2.B2INFO(f"calibration for {calib_keys[i]} with number of iteration={max_iter}")
196
197 cals[i] = CDCDedxCalibration(name=calib_keys[i],
198 algorithms=alg,
199 input_file_dict=data_files,
200 max_iterations=max_iter,
201 collector_granularity=collector_granularity,
202 dependencies=[cals[i-1]] if i > 0 else None
203 )
204 if payload_boundaries:
205 basf2.B2INFO("Found payload_boundaries: calibration strategies set to SequentialBoundaries.")
206 if cal_name == "rungain" or cal_name == "timegain":
207 cals[i].strategies = SequentialRunByRun
208 for algorithm in cals[i].algorithms:
209 algorithm.params = {"iov_coverage": output_iov}
210 if calib_keys[i] == "rungain0" or calib_keys[i] == "rungain1" or calib_keys[i] == "timegain0":
211 cals[i].save_payloads = False
212 elif cal_name == "onedcell":
213 cals[i].strategies = SingleIOV
214 for algorithm in cals[i].algorithms:
215 algorithm.params = {"apply_iov": output_iov}
216 if calib_keys[i] == "onedcell0":
217 cals[i].save_payloads = False
218 else:
219 cals[i].strategies = SequentialBoundaries
220 for algorithm in cals[i].algorithms:
221 algorithm.params = {"iov_coverage": output_iov, "payload_boundaries": payload_boundaries}
222 if (calib_keys[i] == "coscorr0" or calib_keys[i] == "coslayer0" or calib_keys[i] == "coslayer1"
223 or calib_keys[i] == "wiregain0"):
224 cals[i].save_payloads = False
225
226 else:
227 for algorithm in cals[i].algorithms:
228 algorithm.params = {"apply_iov": output_iov}
229
230 return cals
231
232
233# Precollector path
234def pre_collector(name='rg'):
235 """
236 Define pre collection.
237 Parameters:
238 name : name of the calibration
239 rungain rungain0 by Default.
240 Returns:
241 path : path for pre collection
242 """
243
244 reco_path = basf2.create_path()
245
246 if (name == "validation"):
247 basf2.B2INFO("no trigger skim")
248 elif (name == "timegain" or name == "onedcell"):
249 trg_bhabhaskim = reco_path.add_module(
250 "TriggerSkim",
251 triggerLines=["software_trigger_cut&skim&accept_bhabha_cdc"])
252 trg_bhabhaskim.if_value("==0", basf2.Path(), basf2.AfterConditionPath.END)
253 ps_bhabhaskim = reco_path.add_module("Prescale", prescale=0.80)
254 ps_bhabhaskim.if_value("==0", basf2.Path(), basf2.AfterConditionPath.END)
255
256 elif (name == "cosedge"):
257 trg_bhabhaskim = reco_path.add_module(
258 "TriggerSkim",
259 triggerLines=[
260 "software_trigger_cut&skim&accept_bhabha",
261 "software_trigger_cut&filter&ee_flat_90_180",
262 "software_trigger_cut&filter&ee_flat_0_19"])
263 trg_bhabhaskim.if_value("==0", basf2.Path(), basf2.AfterConditionPath.END)
264 else:
265 trg_bhabhaskim = reco_path.add_module("TriggerSkim", triggerLines=["software_trigger_cut&skim&accept_bhabha"])
266 trg_bhabhaskim.if_value("==0", basf2.Path(), basf2.AfterConditionPath.END)
267
268 recon.prepare_cdst_analysis(path=reco_path)
269
270 reco_path.add_module(
271 'CDCDedxCorrection',
272 relativeCorrections=False,
273 scaleCor=True,
274 runGain=True,
275 timeGain=True,
276 cosineCor=True,
277 wireGain=True,
278 twoDCell=True,
279 oneDCell=True)
280 return reco_path
281
282# Collector setup
283
284
285def collector(granularity='all', name=''):
286 """
287 Create a cdcdedx calibration collector
288 Parameters:
289 name : name of calibration
290 granularity : granularity : all or run
291 Returns:
292 collector : collector module
293 """
294
295 from basf2 import register_module
296 if name == "validation":
297 col = register_module('ElectronValCollector', cleanupCuts=True)
298 return col
299
300 else:
301 col = register_module('CDCDedxElectronCollector', cleanupCuts=True)
302 if name == "timegain":
303 CollParam = {'isRun': True, 'isInjTime': True, 'isRadee': True, 'granularity': 'run'}
304
305 elif name == "coslayer":
306 CollParam = {'isCharge': True, 'isCosth': True, 'islLayer': True, 'islDedx': True, 'granularity': granularity}
307
308 elif name == "coscorr" or name == "cosedge":
309 CollParam = {'isCharge': True, 'isCosth': True, 'granularity': granularity}
310
311 elif name == "badwire":
312 isHit = True
313 CollParam = {'isWire': True, 'isDedxhit': isHit, 'isADCcorr': not isHit, 'granularity': granularity}
314
315 elif name == "wiregain":
316 CollParam = {'isWire': True, 'isDedxhit': True, 'isCosth': True, 'granularity': granularity}
317
318 elif name == "onedcell":
319 CollParam = {
320 'isPt': True,
321 'isCosth': True,
322 'isLayer': True,
323 'isDedxhit': True,
324 'isEntaRS': True,
325 'isRadee': True,
326 'granularity': granularity}
327
328 else:
329 CollParam = {'isRun': True, 'granularity': 'run'}
330
331 col.param(CollParam)
332 return col
333
334# Rungain Algorithm setup
335
336
337def rungain_algo(name, adjustment):
338 """
339 Create a rungain calibration algorithm.
340 Returns:
341 algo : rungain algorithm
342 """
343 algo = CDCDedxRunGainAlgorithm()
344 algo.setMonitoringPlots(True)
345 if name == "rungain2":
346 algo.setAdjustment(adjustment)
347 return algo
348
349# Injection Algorithm setup
350
351
352def injection_time_algo():
353 """
354 Create a injection time calibration algorithm.
355 Returns:
356 algo : injection time algorithm
357 """
358 algo = CDCDedxInjectTimeAlgorithm()
359 algo.setMonitoringPlots(True)
360 return algo
361
362# Cosine layer dependent Algorithm setup
363
364
365def coslayer_algo():
366 """
367 Create a cosine calibration algorithm.
368 Returns:
369 algo : cosine algorithm
370 """
371 algo = CDCDedxCosLayerAlgorithm()
372 algo.setMonitoringPlots(True)
373 return algo
374
375
376# Cosine Algorithm setup
377
378
379def cos_algo():
380 """
381 Create a cosine calibration algorithm.
382 Returns:
383 algo : cosine algorithm
384 """
385 algo = CDCDedxCosineAlgorithm()
386 algo.setMonitoringPlots(True)
387 return algo
388
389# CosineEdge Algorithm setup
390
391
392def cosedge_algo():
393 """
394 Create a cosine edge calibration algorithm.
395 Returns:
396 algo : cosine edge algorithm
397 """
398 algo = CDCDedxCosEdgeAlgorithm()
399 algo.setMonitoringPlots(True)
400 return algo
401
402# Badwire Algorithm setup
403
404
405def badwire_algo():
406 """
407 Create a badwire calibration algorithm.
408 Returns:
409 algo : badwire algorithm
410 """
411 algo = CDCDedxBadWireAlgorithm()
412 # threshold (mean and rms) pars for dedx
413 algo.setHighFracThres(0.2)
414 algo.setMeanThres(0.4)
415 algo.setRMSThres(0.4)
416 algo.setHistPars(150, 0, 5)
417 algo.setMonitoringPlots(True)
418 return algo
419
420# WireGain Algorithm setup
421
422
423def wiregain_algo():
424 """
425 Create a wire gain calibration algorithm.
426 Returns:
427 algo : wiregain algorithm
428 """
429 algo = CDCDedxWireGainAlgorithm()
430 algo.enableExtraPlots(True)
431 return algo
432
433
434def onedcell_algo():
435 """
436 Create oned cell calibration algorithim.
437 Returns:
438 algo : oned cell correction algorithm
439 """
440 algo = CDCDedx1DCellAlgorithm()
441 algo.enableExtraPlots(True)
442 algo.setMergePayload(True)
443 return algo
444
445
446def validation_algo():
447 """
448 Create validation algorithm
449 Returns:
450 algo : validation algorithm
451 """
452 algo = CDCDedxValidationAlgorithm()
453 return algo
454
455
456class CDCDedxCalibration(Calibration):
457 '''
458 CDCDedxCalibration is a specialized calibration for cdcdedx.
459 '''
460
461 def __init__(self,
462 name,
463 algorithms,
464 input_file_dict,
465 max_iterations=5,
466 dependencies=None,
467 collector_granularity='All'):
468 '''
469 parameters:
470 name: name of calibration
471 algorithims: algorithm of calibration
472 input_file_dict: input files list
473 max_iterations: maximum number of iterations
474 dependenices: depends on the previous calibration
475 collector_granularity: granularity : all or run
476 '''
477 super().__init__(name=name,
478 algorithms=algorithms
479 )
480
481 from caf.framework import Collection
482 cal_name = ''.join([i for i in name if not i.isdigit()])
483 if cal_name == "badwire" or cal_name == "wiregain":
484 collection = Collection(collector=collector(granularity=collector_granularity, name=cal_name),
485 input_files=input_file_dict[2],
486 pre_collector_path=pre_collector(cal_name)
487 )
488 elif cal_name == "coscorr" or cal_name == "cosedge" or cal_name == "onedcell":
489 collection = Collection(collector=collector(granularity=collector_granularity, name=cal_name),
490 input_files=input_file_dict[1],
491 pre_collector_path=pre_collector(cal_name)
492 )
493 else:
494 collection = Collection(collector=collector(granularity=collector_granularity, name=cal_name),
495 input_files=input_file_dict[0],
496 pre_collector_path=pre_collector(cal_name)
497 )
498 self.add_collection(name=cal_name, collection=collection)
499
500
501 self.max_iterations = max_iterations
502
503 if dependencies is not None:
504 for dep in dependencies:
505 self.depends_on(dep)
__init__(self, name, algorithms, input_file_dict, max_iterations=5, dependencies=None, collector_granularity='All')