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 ps_bhabhaskim = reco_path.add_module("Prescale", prescale=0.80)
250 ps_bhabhaskim.if_value("==0", basf2.Path(), basf2.AfterConditionPath.END)
251
252 elif (name == "cosedge"):
253 trg_bhabhaskim = reco_path.add_module(
254 "TriggerSkim",
255 triggerLines=[
256 "software_trigger_cut&skim&accept_bhabha",
257 "software_trigger_cut&filter&ee_flat_90_180",
258 "software_trigger_cut&filter&ee_flat_0_19"])
259 trg_bhabhaskim.if_value("==0", basf2.Path(), basf2.AfterConditionPath.END)
260 else:
261 trg_bhabhaskim = reco_path.add_module("TriggerSkim", triggerLines=["software_trigger_cut&skim&accept_bhabha"])
262 trg_bhabhaskim.if_value("==0", basf2.Path(), basf2.AfterConditionPath.END)
263
264 recon.prepare_cdst_analysis(path=reco_path, components=['CDC', 'ECL', 'KLM'])
265
266 reco_path.add_module(
267 'CDCDedxCorrection',
268 relativeCorrections=False,
269 scaleCor=True,
270 runGain=True,
271 timeGain=True,
272 cosineCor=True,
273 wireGain=True,
274 twoDCell=True,
275 oneDCell=True)
276 return reco_path
277
278# Collector setup
279
280
281def collector(granularity='all', name=''):
282 """
283 Create a cdcdedx calibration collector
284 Parameters:
285 name : name of calibration
286 granularity : granularity : all or run
287 Returns:
288 collector : collector module
289 """
290
291 from basf2 import register_module
292 if name == "validation":
293 col = register_module('ElectronValCollector', cleanupCuts=True)
294 return col
295
296 else:
297 col = register_module('CDCDedxElectronCollector', cleanupCuts=True)
298 if name == "timegain":
299 CollParam = {
300 'isRun': True,
301 'isInjTime': True,
302 'isRadee': True,
303 'isBhabha': False,
304 'isTrgSel': True,
305 'granularity': 'run'
306 }
307
308 elif name == "coslayer":
309 CollParam = {'isCharge': True, 'isCosth': True, 'islLayer': True, 'islDedx': True, 'granularity': granularity}
310
311 elif name == "coscorr" or name == "cosedge":
312 CollParam = {'isCharge': True, 'isCosth': True, 'granularity': granularity}
313
314 elif name == "badwire":
315 isHit = True
316 CollParam = {'isWire': True, 'isDedxhit': isHit, 'isADCcorr': not isHit, 'granularity': granularity}
317
318 elif name == "wiregain":
319 CollParam = {'isWire': True, 'isDedxhit': True, 'isCosth': True, 'granularity': granularity}
320
321 elif name == "onedcell":
322 CollParam = {
323 'isPt': True,
324 'isCosth': True,
325 'isLayer': True,
326 'isDedxhit': True,
327 'isEntaRS': True,
328 'isRadee': True,
329 'isBhabha': False,
330 'isTrgSel': True,
331 'granularity': granularity}
332
333 else:
334 CollParam = {'isRun': True, 'granularity': 'run'}
335
336 col.param(CollParam)
337 return col
338
339# Rungain Algorithm setup
340
341
342def rungain_algo(name, adjustment):
343 """
344 Create a rungain calibration algorithm.
345 Returns:
346 algo : rungain algorithm
347 """
348 algo = CDCDedxRunGainAlgorithm()
349 algo.setMonitoringPlots(True)
350 if name == "rungain2":
351 algo.setAdjustment(adjustment)
352 return algo
353
354# Injection Algorithm setup
355
356
357def injection_time_algo():
358 """
359 Create a injection time calibration algorithm.
360 Returns:
361 algo : injection time algorithm
362 """
363 algo = CDCDedxInjectTimeAlgorithm()
364 algo.setMonitoringPlots(True)
365 return algo
366
367# Cosine layer dependent Algorithm setup
368
369
370def coslayer_algo():
371 """
372 Create a cosine calibration algorithm.
373 Returns:
374 algo : cosine algorithm
375 """
376 algo = CDCDedxCosLayerAlgorithm()
377 algo.setMonitoringPlots(True)
378 return algo
379
380
381# Cosine Algorithm setup
382
383
384def cos_algo():
385 """
386 Create a cosine calibration algorithm.
387 Returns:
388 algo : cosine algorithm
389 """
390 algo = CDCDedxCosineAlgorithm()
391 algo.setMonitoringPlots(True)
392 return algo
393
394# CosineEdge Algorithm setup
395
396
397def cosedge_algo():
398 """
399 Create a cosine edge calibration algorithm.
400 Returns:
401 algo : cosine edge algorithm
402 """
403 algo = CDCDedxCosEdgeAlgorithm()
404 algo.setMonitoringPlots(True)
405 return algo
406
407# Badwire Algorithm setup
408
409
410def badwire_algo():
411 """
412 Create a badwire calibration algorithm.
413 Returns:
414 algo : badwire algorithm
415 """
416 algo = CDCDedxBadWireAlgorithm()
417 # threshold (mean and rms) pars for dedx
418 algo.setHighFracThres(0.2)
419 algo.setMeanThres(0.4)
420 algo.setRMSThres(0.4)
421 algo.setHistPars(150, 0, 5)
422 algo.setMonitoringPlots(True)
423 return algo
424
425# WireGain Algorithm setup
426
427
428def wiregain_algo():
429 """
430 Create a wire gain calibration algorithm.
431 Returns:
432 algo : wiregain algorithm
433 """
434 algo = CDCDedxWireGainAlgorithm()
435 algo.enableExtraPlots(True)
436 return algo
437
438
439def onedcell_algo():
440 """
441 Create oned cell calibration algorithim.
442 Returns:
443 algo : oned cell correction algorithm
444 """
445 algo = CDCDedx1DCellAlgorithm()
446 algo.enableExtraPlots(True)
447 algo.setMergePayload(True)
448 return algo
449
450
451def validation_algo():
452 """
453 Create validation algorithm
454 Returns:
455 algo : validation algorithm
456 """
457 algo = CDCDedxValidationAlgorithm()
458 return algo
459
460
461class CDCDedxCalibration(Calibration):
462 '''
463 CDCDedxCalibration is a specialized calibration for cdcdedx.
464 '''
465
466 def __init__(self,
467 name,
468 algorithms,
469 input_file_dict,
470 max_iterations=5,
471 dependencies=None,
472 collector_granularity='All'):
473 '''
474 parameters:
475 name: name of calibration
476 algorithims: algorithm of calibration
477 input_file_dict: input files list
478 max_iterations: maximum number of iterations
479 dependenices: depends on the previous calibration
480 collector_granularity: granularity : all or run
481 '''
482 super().__init__(name=name,
483 algorithms=algorithms
484 )
485
486 from caf.framework import Collection
487 cal_name = ''.join([i for i in name if not i.isdigit()])
488 if cal_name == "badwire" or cal_name == "wiregain":
489 collection = Collection(collector=collector(granularity=collector_granularity, name=cal_name),
490 input_files=input_file_dict[2],
491 pre_collector_path=pre_collector(cal_name)
492 )
493 elif cal_name == "coscorr" or cal_name == "cosedge" or cal_name == "onedcell":
494 collection = Collection(collector=collector(granularity=collector_granularity, name=cal_name),
495 input_files=input_file_dict[1],
496 pre_collector_path=pre_collector(cal_name)
497 )
498 else:
499 collection = Collection(collector=collector(granularity=collector_granularity, name=cal_name),
500 input_files=input_file_dict[0],
501 pre_collector_path=pre_collector(cal_name)
502 )
503 self.add_collection(name=cal_name, collection=collection)
504
505
506 self.max_iterations = max_iterations
507
508 if dependencies is not None:
509 for dep in dependencies:
510 self.depends_on(dep)
__init__(self, name, algorithms, input_file_dict, max_iterations=5, dependencies=None, collector_granularity='All')