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