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
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="renu",
34 description=__doc__,
35 input_data_formats=["cdst"],
36 input_data_names=["bhabha_all_calib"],
37 expert_config={
38 "payload_boundaries": [],
39 "calib_datamode": False,
40 "maxevt_rg": 75000,
41 "maxevt_cc": 18e6,
42 "maxevt_wg": 18e6,
43 "adjustment": 1.00798,
44 "calib_mode": "full", # manual or predefined: full or quick
45 "calibration_procedure": {"rungain0": 0, "rungain1": 0, "rungain2": 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
59def 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
71 # extracting parameters
72 fulldataMode = expert_config["calib_datamode"]
73 adjustment = expert_config["adjustment"]
74
75 if fulldataMode:
76 input_files_rungain = list(file_to_iov_physics.keys())
77 input_files_coscorr = list(file_to_iov_physics.keys())
78 input_files_wiregain = list(file_to_iov_physics.keys())
79 else:
80 seed(271492)
81
82 maxevt_rg = expert_config["maxevt_rg"]
83 maxevt_cc = expert_config["maxevt_cc"]
84 maxevt_wg = expert_config["maxevt_wg"]
85
86 from prompt.utils import filter_by_max_events_per_run, filter_by_select_max_events_from_files
87
88 # collection for rungains
89 max_files_for_maxevents = maxevt_rg # allevents to accp bhabha event ratio = 0.60
90 reduced_file_to_iov_rungain = filter_by_max_events_per_run(file_to_iov_physics, max_files_for_maxevents, True)
91 input_files_rungain = list(reduced_file_to_iov_rungain.keys())
92 basf2.B2INFO(f"Total number of files used for rungains = {len(input_files_rungain)}")
93
94 # collection for cosinecorr
95 input_files_coscorr = filter_by_select_max_events_from_files(list(file_to_iov_physics.keys()), maxevt_cc)
96 basf2.B2INFO(f"Total number of files used for cosine = {len(input_files_coscorr)}")
97 if not input_files_coscorr:
98 raise ValueError(
99 f"Cosine: all requested ({maxevt_cc}) events not found")
100
101 # collection for wiregain
102 if maxevt_wg == maxevt_cc:
103 input_files_wiregain = input_files_coscorr
104 else:
105 input_files_wiregain = filter_by_select_max_events_from_files(list(file_to_iov_physics.keys()), maxevt_wg)
106
107 basf2.B2INFO(f"Total number of files used for wiregains = {len(input_files_wiregain)}")
108 if not input_files_wiregain:
109 raise ValueError(
110 f"WireGain: all requested ({maxevt_wg}) events not found")
111
112 requested_iov = kwargs.get("requested_iov", None)
113 from caf.utils import ExpRun, IoV
114 output_iov = IoV(requested_iov.exp_low, requested_iov.run_low, -1, -1)
115
116 payload_boundaries = [ExpRun(output_iov.exp_low, output_iov.run_low)]
117 payload_boundaries.extend([ExpRun(*boundary) for boundary in expert_config["payload_boundaries"]])
118 basf2.B2INFO(f"Expert set payload boundaries are: {expert_config['payload_boundaries']}")
119
120 collector_granularity = 'all'
121 if expert_config["payload_boundaries"] is not None:
122 basf2.B2INFO('Found payload_boundaries: set collector granularity to run')
123 collector_granularity = 'run'
124
125 if calib_mode == "full":
126 calibration_procedure = {
127 "rungain0": 0, # Run Gain trail (No Payload saving and take of effect of previous rungains)
128 "timegain0": 0, # Injection time gain Pre (No payload saving)
129 "timegain1": 0, # Injection time gain
130 "rungain1": 0, # Run Gain Pre (No Payload saving)
131 "coscorr0": 0, # Cosine Corr Gain Pre (No Payload saving)
132 "cosedge0": 0, # Cosine edge Corr Gain
133 "badwire0": 0, # Bad wire
134 "wiregain0": 0, # WireGain Gain
135 "onedcell0": 0, # OneD cell correction
136 "coscorr1": 0, # Cosine Corr Gain
137 "rungain2": 0 # Final Run Gain to take Wire and Cosine correction in effect
138 }
139 elif calib_mode == "quick":
140 calibration_procedure = {
141 "rungain0": 0,
142 "timegain0": 0,
143 "rungain1": 0,
144 "coscorr0": 0,
145 "cosedge0": 0,
146 "badwire0": 0,
147 "wiregain0": 0,
148 "rungain2": 0
149 }
150 elif calib_mode == "manual":
151 calibration_procedure = expert_config["calibration_procedure"]
152 else:
153 basf2.B2FATAL(f"Calibration mode is not defined {calib_mode}, should be full, quick, or manual")
154
155 calib_keys = list(calibration_procedure)
156 cals = [None]*len(calib_keys)
157 basf2.B2INFO(f"Run calibration mode = {calib_mode}:")
158
159 for i in range(len(cals)):
160 max_iter = calibration_procedure[calib_keys[i]]
161 alg = None
162 data_files = [input_files_rungain, input_files_coscorr, input_files_wiregain]
163 cal_name = ''.join([i for i in calib_keys[i] if not i.isdigit()])
164 if cal_name == "rungain":
165 alg = [rungain_algo(calib_keys[i], adjustment)]
166 elif cal_name == "coscorr":
167 alg = [cos_algo()]
168 elif cal_name == "cosedge":
169 alg = [cosedge_algo()]
170 elif cal_name == "timegain":
171 alg = [injection_time_algo()]
172 elif cal_name == "badwire":
173 alg = [badwire_algo()]
174 elif cal_name == "wiregain":
175 alg = [wiregain_algo()]
176 elif cal_name == "onedcell":
177 alg = [onedcell_algo()]
178 else:
179 basf2.B2FATAL(f"The calibration is not defined, check spelling: calib {i}: {calib_keys[i]}")
180
181 basf2.B2INFO(f"calibration for {calib_keys[i]} with number of iteration={max_iter}")
182
183 cals[i] = CDCDedxCalibration(name=calib_keys[i],
184 algorithms=alg,
185 input_file_dict=data_files,
186 max_iterations=max_iter,
187 collector_granularity=collector_granularity,
188 dependencies=[cals[i-1]] if i > 0 else None
189 )
190 if payload_boundaries:
191 basf2.B2INFO("Found payload_boundaries: calibration strategies set to SequentialBoundaries.")
192 if cal_name == "rungain" or cal_name == "timegain":
193 cals[i].strategies = SequentialRunByRun
194 for algorithm in cals[i].algorithms:
195 algorithm.params = {"iov_coverage": output_iov}
196 if calib_keys[i] == "rungain0" or calib_keys[i] == "rungain1" or calib_keys[i] == "timegain0":
197 cals[i].save_payloads = False
198 else:
199 cals[i].strategies = SequentialBoundaries
200 for algorithm in cals[i].algorithms:
201 algorithm.params = {"iov_coverage": output_iov, "payload_boundaries": payload_boundaries}
202 if calib_keys[i] == "coscorr0":
203 cals[i].save_payloads = False
204
205 else:
206 for algorithm in cals[i].algorithms:
207 algorithm.params = {"apply_iov": output_iov}
208
209 return cals
210
211
212# Precollector path
213def pre_collector(name='rg'):
214 """
215 Define pre collection.
216 Parameters:
217 name : name of the calibration
218 rungain rungain0 by Default.
219 Returns:
220 path : path for pre collection
221 """
222
223 reco_path = basf2.create_path()
224 recon.prepare_cdst_analysis(path=reco_path)
225 if (name == "timegain" or name == "onedcell"):
226 trg_bhabhaskim = reco_path.add_module("TriggerSkim", triggerLines=["software_trigger_cut&skim&accept_radee"])
227 trg_bhabhaskim.if_value("==0", basf2.Path(), basf2.AfterConditionPath.END)
228 ps_bhabhaskim = reco_path.add_module("Prescale", prescale=0.80)
229 ps_bhabhaskim.if_value("==0", basf2.Path(), basf2.AfterConditionPath.END)
230
231 elif (name == "cosedge"):
232 trg_bhabhaskim = reco_path.add_module(
233 "TriggerSkim",
234 triggerLines=[
235 "software_trigger_cut&skim&accept_bhabha",
236 "software_trigger_cut&filter&ee_flat_90_180",
237 "software_trigger_cut&filter&ee_flat_0_19"])
238 trg_bhabhaskim.if_value("==0", basf2.Path(), basf2.AfterConditionPath.END)
239 else:
240 trg_bhabhaskim = reco_path.add_module("TriggerSkim", triggerLines=["software_trigger_cut&skim&accept_bhabha"])
241 trg_bhabhaskim.if_value("==0", basf2.Path(), basf2.AfterConditionPath.END)
242
243 reco_path.add_module(
244 'CDCDedxCorrection',
245 relativeCorrections=False,
246 scaleCor=True,
247 runGain=True,
248 timeGain=True,
249 cosineCor=True,
250 wireGain=True,
251 twoDCell=True,
252 oneDCell=True)
253 return reco_path
254
255# Collector setup
256
257
258def collector(granularity='all', name=''):
259 """
260 Create a cdcdedx calibration collector
261 Parameters:
262 name : name of calibration
263 granularity : granularity : all or run
264 Returns:
265 collector : collector module
266 """
267
268 from basf2 import register_module
269 col = register_module('CDCDedxElectronCollector', cleanupCuts=True)
270 if name == "timegain":
271 CollParam = {'isRun': True, 'isInjTime': True, 'granularity': 'run'}
272
273 elif name == "coscorr" or name == "cosedge":
274 CollParam = {'isCharge': True, 'isCosth': True, 'granularity': granularity}
275
276 elif name == "badwire":
277 isHit = True
278 CollParam = {'isWire': True, 'isDedxhit': isHit, 'isADCcorr': not isHit, 'granularity': granularity}
279
280 elif name == "wiregain":
281 CollParam = {'isWire': True, 'isDedxhit': True, 'granularity': granularity}
282
283 elif name == "onedcell":
284 CollParam = {
285 'isPt': True,
286 'isCosth': True,
287 'isLayer': True,
288 'isDedxhit': True,
289 'isEntaRS': True,
290 'granularity': granularity}
291
292 else:
293 CollParam = {'isRun': True, 'granularity': 'run'}
294
295 col.param(CollParam)
296 return col
297
298# Rungain Algorithm setup
299
300
301def rungain_algo(name, adjustment):
302 """
303 Create a rungain calibration algorithm.
304 Returns:
305 algo : rungain algorithm
306 """
307 algo = CDCDedxRunGainAlgorithm()
308 algo.setMonitoringPlots(True)
309 if name == "rungain2":
310 algo.setAdjustment(adjustment)
311 return algo
312
313# Injection Algorithm setup
314
315
316def injection_time_algo():
317 """
318 Create a injection time calibration algorithm.
319 Returns:
320 algo : injection time algorithm
321 """
322 algo = CDCDedxInjectTimeAlgorithm()
323 algo.setMonitoringPlots(True)
324 return algo
325
326# Cosine Algorithm setup
327
328
329def cos_algo():
330 """
331 Create a cosine calibration algorithm.
332 Returns:
333 algo : cosine algorithm
334 """
335 algo = CDCDedxCosineAlgorithm()
336 algo.setMonitoringPlots(True)
337 return algo
338
339# CosineEdge Algorithm setup
340
341
342def cosedge_algo():
343 """
344 Create a cosine edge calibration algorithm.
345 Returns:
346 algo : cosine edge algorithm
347 """
348 algo = CDCDedxCosEdgeAlgorithm()
349 algo.setMonitoringPlots(True)
350 return algo
351
352# Badwire Algorithm setup
353
354
355def badwire_algo():
356 """
357 Create a badwire calibration algorithm.
358 Returns:
359 algo : badwire algorithm
360 """
361 algo = CDCDedxBadWireAlgorithm()
362 # threshold (mean and rms) pars for dedx
363 algo.setHighFracThres(0.2)
364 algo.setMeanThres(0.4)
365 algo.setRMSThres(0.4)
366 algo.setHistPars(150, 0, 5)
367 algo.setMonitoringPlots(True)
368 return algo
369
370# WireGain Algorithm setup
371
372
373def wiregain_algo():
374 """
375 Create a wire gain calibration algorithm.
376 Returns:
377 algo : wiregain algorithm
378 """
379 algo = CDCDedxWireGainAlgorithm()
380 algo.enableExtraPlots(True)
381 return algo
382
383
384def onedcell_algo():
385 """
386 Create oned cell calibration algorithm.
387 Returns:
388 algo : oned cell correction algorithm
389 """
390 algo = CDCDedx1DCellAlgorithm()
391 algo.enableExtraPlots(True)
392 algo.setMergePayload(True)
393 return algo
394
395
397 '''
398 CDCDedxCalibration is a specialized calibration for cdcdedx.
399 '''
400
401 def __init__(self,
402 name,
403 algorithms,
404 input_file_dict,
405 max_iterations=5,
406 dependencies=None,
407 collector_granularity='All'):
408 '''
409 parameters:
410 name: name of calibration
411 algorithms: algorithm of calibration
412 input_file_dict: input files list
413 max_iterations: maximum number of iterations
414 dependencies: depends on the previous calibration
415 collector_granularity: granularity : all or run
416 '''
417 super().__init__(name=name,
418 algorithms=algorithms
419 )
420
421 from caf.framework import Collection
422 cal_name = ''.join([i for i in name if not i.isdigit()])
423 if cal_name == "badwire" or cal_name == "wiregain":
424 collection = Collection(collector=collector(granularity=collector_granularity, name=cal_name),
425 input_files=input_file_dict[2],
426 pre_collector_path=pre_collector(cal_name)
427 )
428 elif cal_name == "coscorr" or cal_name == "cosedge" or cal_name == "onedcell":
429 collection = Collection(collector=collector(granularity=collector_granularity, name=cal_name),
430 input_files=input_file_dict[1],
431 pre_collector_path=pre_collector(cal_name)
432 )
433 else:
434 collection = Collection(collector=collector(granularity=collector_granularity, name=cal_name),
435 input_files=input_file_dict[0],
436 pre_collector_path=pre_collector(cal_name)
437 )
438 self.add_collection(name=cal_name, collection=collection)
439
440
441 self.max_iterations = max_iterations
442
443 if dependencies is not None:
444 for dep in dependencies:
445 self.depends_on(dep)
def __init__(self, name, algorithms, input_file_dict, max_iterations=5, dependencies=None, collector_granularity='All')