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