Belle II Software development
caf_cdcdedx.py
1
8
9"""
10Airflow script for automatic CDC dEdx calibration. It is currently for the electron based
11calibration, where at present only RunGain, injection time, Cosine and WireGain are implemented.
12The remaining two 2D and 1D will be implemented in the near future.
13
14Second part called "Hadron calibration" are not compatible with CAF/AirFlow
15and will be done offline for a while.
16"""
17
18import ROOT
19from ROOT import gSystem
20from ROOT.Belle2 import CDCDedxRunGainAlgorithm, CDCDedxCosineAlgorithm, CDCDedxWireGainAlgorithm
21from ROOT.Belle2 import CDCDedxCosEdgeAlgorithm, CDCDedxBadWireAlgorithm, CDCDedxInjectTimeAlgorithm
22from ROOT.Belle2 import CDCDedx1DCellAlgorithm
23
24from caf.framework import Calibration
25from caf.strategies import SequentialRunByRun, SequentialBoundaries
26from prompt import CalibrationSettings, INPUT_DATA_FILTERS
27import reconstruction as recon
28from random import seed
29import basf2
30
31gSystem.Load('libreconstruction.so')
32ROOT.gROOT.SetBatch(True)
33
34settings = CalibrationSettings(
35 name="CDC dedx",
36 expert_username="renu",
37 description=__doc__,
38 input_data_formats=["cdst"],
39 input_data_names=["bhabha_all_calib"],
40 expert_config={
41 "payload_boundaries": [],
42 "calib_datamode": False,
43 "maxevt_rg": 75000,
44 "maxevt_cc": 18e6,
45 "maxevt_wg": 18e6,
46 "adjustment": 1.00798,
47 "calib_mode": "full", # manual or predefined: full or quick
48 "calibration_procedure": {"rungain0": 0, "rungain1": 0, "rungain2": 0}
49 },
50 input_data_filters={
51 "bhabha_all_calib": [
52 INPUT_DATA_FILTERS['Run Type']['physics'],
53 INPUT_DATA_FILTERS['Data Tag']['bhabha_all_calib'],
54 INPUT_DATA_FILTERS['Data Quality Tag']['Good Or Recoverable'],
55 INPUT_DATA_FILTERS['Magnet']['On'],
56 INPUT_DATA_FILTERS['Beam Energy']['4S'],
57 INPUT_DATA_FILTERS['Beam Energy']['Continuum'],
58 INPUT_DATA_FILTERS['Beam Energy']['Scan']]},
59 depends_on=[])
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 }
142 elif calib_mode == "quick":
143 calibration_procedure = {
144 "rungain0": 0,
145 "timegain0": 0,
146 "rungain1": 0,
147 "coscorr0": 0,
148 "cosedge0": 0,
149 "badwire0": 0,
150 "wiregain0": 0,
151 "rungain2": 0
152 }
153 elif calib_mode == "manual":
154 calibration_procedure = expert_config["calibration_procedure"]
155 else:
156 basf2.B2FATAL(f"Calibration mode is not defined {calib_mode}, should be full, quick, or manual")
157
158 calib_keys = list(calibration_procedure)
159 cals = [None]*len(calib_keys)
160 basf2.B2INFO(f"Run calibration mode = {calib_mode}:")
161
162 for i in range(len(cals)):
163 max_iter = calibration_procedure[calib_keys[i]]
164 alg = None
165 data_files = [input_files_rungain, input_files_coscorr, input_files_wiregain]
166 cal_name = ''.join([i for i in calib_keys[i] if not i.isdigit()])
167 if cal_name == "rungain":
168 alg = [rungain_algo(calib_keys[i], adjustment)]
169 elif cal_name == "coscorr":
170 alg = [cos_algo()]
171 elif cal_name == "cosedge":
172 alg = [cosedge_algo()]
173 elif cal_name == "timegain":
174 alg = [injection_time_algo()]
175 elif cal_name == "badwire":
176 alg = [badwire_algo()]
177 elif cal_name == "wiregain":
178 alg = [wiregain_algo()]
179 elif cal_name == "onedcell":
180 alg = [onedcell_algo()]
181 else:
182 basf2.B2FATAL(f"The calibration is not defined, check spelling: calib {i}: {calib_keys[i]}")
183
184 basf2.B2INFO(f"calibration for {calib_keys[i]} with number of iteration={max_iter}")
185
186 cals[i] = CDCDedxCalibration(name=calib_keys[i],
187 algorithms=alg,
188 input_file_dict=data_files,
189 max_iterations=max_iter,
190 collector_granularity=collector_granularity,
191 dependencies=[cals[i-1]] if i > 0 else None
192 )
193 if payload_boundaries:
194 basf2.B2INFO("Found payload_boundaries: calibration strategies set to SequentialBoundaries.")
195 if cal_name == "rungain" or cal_name == "timegain":
196 cals[i].strategies = SequentialRunByRun
197 for algorithm in cals[i].algorithms:
198 algorithm.params = {"iov_coverage": output_iov}
199 if calib_keys[i] == "rungain0" or calib_keys[i] == "rungain1" or calib_keys[i] == "timegain0":
200 cals[i].save_payloads = False
201 else:
202 cals[i].strategies = SequentialBoundaries
203 for algorithm in cals[i].algorithms:
204 algorithm.params = {"iov_coverage": output_iov, "payload_boundaries": payload_boundaries}
205 if calib_keys[i] == "coscorr0":
206 cals[i].save_payloads = False
207
208 else:
209 for algorithm in cals[i].algorithms:
210 algorithm.params = {"apply_iov": output_iov}
211
212 return cals
213
214
215# Precollector path
216def pre_collector(name='rg'):
217 """
218 Define pre collection.
219 Parameters:
220 name : name of the calibration
221 rungain rungain0 by Default.
222 Returns:
223 path : path for pre collection
224 """
225
226 reco_path = basf2.create_path()
227 recon.prepare_cdst_analysis(path=reco_path)
228 if (name == "timegain" or name == "onedcell"):
229 trg_bhabhaskim = reco_path.add_module("TriggerSkim", triggerLines=["software_trigger_cut&skim&accept_radee"])
230 trg_bhabhaskim.if_value("==0", basf2.Path(), basf2.AfterConditionPath.END)
231 ps_bhabhaskim = reco_path.add_module("Prescale", prescale=0.80)
232 ps_bhabhaskim.if_value("==0", basf2.Path(), basf2.AfterConditionPath.END)
233
234 elif (name == "cosedge"):
235 trg_bhabhaskim = reco_path.add_module(
236 "TriggerSkim",
237 triggerLines=[
238 "software_trigger_cut&skim&accept_bhabha",
239 "software_trigger_cut&filter&ee_flat_90_180",
240 "software_trigger_cut&filter&ee_flat_0_19"])
241 trg_bhabhaskim.if_value("==0", basf2.Path(), basf2.AfterConditionPath.END)
242 else:
243 trg_bhabhaskim = reco_path.add_module("TriggerSkim", triggerLines=["software_trigger_cut&skim&accept_bhabha"])
244 trg_bhabhaskim.if_value("==0", basf2.Path(), basf2.AfterConditionPath.END)
245
246 reco_path.add_module(
247 'CDCDedxCorrection',
248 relativeCorrections=False,
249 scaleCor=True,
250 runGain=True,
251 timeGain=True,
252 cosineCor=True,
253 wireGain=True,
254 twoDCell=True,
255 oneDCell=True)
256 return reco_path
257
258# Collector setup
259
260
261def collector(granularity='all', name=''):
262 """
263 Create a cdcdedx calibration collector
264 Parameters:
265 name : name of calibration
266 granularity : granularity : all or run
267 Returns:
268 collector : collector module
269 """
270
271 from basf2 import register_module
272 col = register_module('CDCDedxElectronCollector', cleanupCuts=True)
273 if name == "timegain":
274 CollParam = {'isRun': True, 'isInjTime': True, 'granularity': 'run'}
275
276 elif name == "coscorr" or name == "cosedge":
277 CollParam = {'isCharge': True, 'isCosth': True, 'granularity': granularity}
278
279 elif name == "badwire":
280 isHit = True
281 CollParam = {'isWire': True, 'isDedxhit': isHit, 'isADCcorr': not isHit, 'granularity': granularity}
282
283 elif name == "wiregain":
284 CollParam = {'isWire': True, 'isDedxhit': True, 'granularity': granularity}
285
286 elif name == "onedcell":
287 CollParam = {
288 'isPt': True,
289 'isCosth': True,
290 'isLayer': True,
291 'isDedxhit': True,
292 'isEntaRS': True,
293 'granularity': granularity}
294
295 else:
296 CollParam = {'isRun': True, 'granularity': 'run'}
297
298 col.param(CollParam)
299 return col
300
301# Rungain Algorithm setup
302
303
304def rungain_algo(name, adjustment):
305 """
306 Create a rungain calibration algorithm.
307 Returns:
308 algo : rungain algorithm
309 """
310 algo = CDCDedxRunGainAlgorithm()
311 algo.setMonitoringPlots(True)
312 if name == "rungain2":
313 algo.setAdjustment(adjustment)
314 return algo
315
316# Injection Algorithm setup
317
318
319def injection_time_algo():
320 """
321 Create a injection time calibration algorithm.
322 Returns:
323 algo : injection time algorithm
324 """
325 algo = CDCDedxInjectTimeAlgorithm()
326 algo.setMonitoringPlots(True)
327 return algo
328
329# Cosine Algorithm setup
330
331
332def cos_algo():
333 """
334 Create a cosine calibration algorithm.
335 Returns:
336 algo : cosine algorithm
337 """
338 algo = CDCDedxCosineAlgorithm()
339 algo.setMonitoringPlots(True)
340 return algo
341
342# CosineEdge Algorithm setup
343
344
345def cosedge_algo():
346 """
347 Create a cosine edge calibration algorithm.
348 Returns:
349 algo : cosine edge algorithm
350 """
351 algo = CDCDedxCosEdgeAlgorithm()
352 algo.setMonitoringPlots(True)
353 return algo
354
355# Badwire Algorithm setup
356
357
358def badwire_algo():
359 """
360 Create a badwire calibration algorithm.
361 Returns:
362 algo : badwire algorithm
363 """
364 algo = CDCDedxBadWireAlgorithm()
365 # threshold (mean and rms) pars for dedx
366 algo.setHighFracThres(0.2)
367 algo.setMeanThres(0.4)
368 algo.setRMSThres(0.4)
369 algo.setHistPars(150, 0, 5)
370 algo.setMonitoringPlots(True)
371 return algo
372
373# WireGain Algorithm setup
374
375
376def wiregain_algo():
377 """
378 Create a wire gain calibration algorithm.
379 Returns:
380 algo : wiregain algorithm
381 """
382 algo = CDCDedxWireGainAlgorithm()
383 algo.enableExtraPlots(True)
384 return algo
385
386
387def onedcell_algo():
388 """
389 Create oned cell calibration algorithm.
390 Returns:
391 algo : oned cell correction algorithm
392 """
393 algo = CDCDedx1DCellAlgorithm()
394 algo.enableExtraPlots(True)
395 algo.setMergePayload(True)
396 return algo
397
398
400 '''
401 CDCDedxCalibration is a specialized calibration for cdcdedx.
402 '''
403
404 def __init__(self,
405 name,
406 algorithms,
407 input_file_dict,
408 max_iterations=5,
409 dependencies=None,
410 collector_granularity='All'):
411 '''
412 parameters:
413 name: name of calibration
414 algorithms: algorithm of calibration
415 input_file_dict: input files list
416 max_iterations: maximum number of iterations
417 dependencies: depends on the previous calibration
418 collector_granularity: granularity : all or run
419 '''
420 super().__init__(name=name,
421 algorithms=algorithms
422 )
423
424 from caf.framework import Collection
425 cal_name = ''.join([i for i in name if not i.isdigit()])
426 if cal_name == "badwire" or cal_name == "wiregain":
427 collection = Collection(collector=collector(granularity=collector_granularity, name=cal_name),
428 input_files=input_file_dict[2],
429 pre_collector_path=pre_collector(cal_name)
430 )
431 elif cal_name == "coscorr" or cal_name == "cosedge" or cal_name == "onedcell":
432 collection = Collection(collector=collector(granularity=collector_granularity, name=cal_name),
433 input_files=input_file_dict[1],
434 pre_collector_path=pre_collector(cal_name)
435 )
436 else:
437 collection = Collection(collector=collector(granularity=collector_granularity, name=cal_name),
438 input_files=input_file_dict[0],
439 pre_collector_path=pre_collector(cal_name)
440 )
441 self.add_collection(name=cal_name, collection=collection)
442
443
444 self.max_iterations = max_iterations
445
446 if dependencies is not None:
447 for dep in dependencies:
448 self.depends_on(dep)
max_iterations
maximum iterations
Definition: caf_cdcdedx.py:444
def __init__(self, name, algorithms, input_file_dict, max_iterations=5, dependencies=None, collector_granularity='All')
Definition: caf_cdcdedx.py:410