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 implimented.
12The remaining two 2D and 1D will be implimented in the near future.
13
14Second part called "Hadron calibration" are not compitable 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 caf.framework import Calibration
23from caf.strategies import SequentialRunByRun, SequentialBoundaries
24from prompt import CalibrationSettings, INPUT_DATA_FILTERS
25import reconstruction as recon
26from random import seed
27import basf2
28
29gSystem.Load('libreconstruction.so')
30ROOT.gROOT.SetBatch(True)
31
32settings = CalibrationSettings(
33 name="CDC dedx",
34 expert_username="renu",
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
59
60def get_calibrations(input_data, **kwargs):
61 """ REQUIRED FUNCTION used by b2caf-prompt-run tool
62 This function return a list of Calibration
63 objects we assign to the CAF process
64 """
65
66 import basf2
67 file_to_iov_physics = input_data["bhabha_all_calib"]
68
69 expert_config = kwargs.get("expert_config")
70 calib_mode = expert_config["calib_mode"]
71
72 # extracting parameters
73 fulldataMode = expert_config["calib_datamode"]
74 adjustment = expert_config["adjustment"]
75
76 if fulldataMode:
77 input_files_rungain = list(file_to_iov_physics.keys())
78 input_files_coscorr = list(file_to_iov_physics.keys())
79 input_files_wiregain = list(file_to_iov_physics.keys())
80 else:
81 seed(271492)
82
83 maxevt_rg = expert_config["maxevt_rg"]
84 maxevt_cc = expert_config["maxevt_cc"]
85 maxevt_wg = expert_config["maxevt_wg"]
86
87 from prompt.utils import filter_by_max_events_per_run, filter_by_select_max_events_from_files
88
89 # collection for rungains
90 max_files_for_maxevents = maxevt_rg # allevents to accp bhabha event ratio = 0.60
91 reduced_file_to_iov_rungain = filter_by_max_events_per_run(file_to_iov_physics, max_files_for_maxevents, True)
92 input_files_rungain = list(reduced_file_to_iov_rungain.keys())
93 basf2.B2INFO(f"Total number of files used for rungains = {len(input_files_rungain)}")
94
95 # collection for cosinecorr
96 input_files_coscorr = filter_by_select_max_events_from_files(list(file_to_iov_physics.keys()), maxevt_cc)
97 basf2.B2INFO(f"Total number of files used for cosine = {len(input_files_coscorr)}")
98 if not input_files_coscorr:
99 raise ValueError(
100 f"Cosine: all requested ({maxevt_cc}) events not found")
101
102 # collection for wiregain
103 if maxevt_wg == maxevt_cc:
104 input_files_wiregain = input_files_coscorr
105 else:
106 input_files_wiregain = filter_by_select_max_events_from_files(list(file_to_iov_physics.keys()), maxevt_wg)
107
108 basf2.B2INFO(f"Total number of files used for wiregains = {len(input_files_wiregain)}")
109 if not input_files_wiregain:
110 raise ValueError(
111 f"WireGain: all requested ({maxevt_wg}) events not found")
112
113 requested_iov = kwargs.get("requested_iov", None)
114 from caf.utils import ExpRun, IoV
115 output_iov = IoV(requested_iov.exp_low, requested_iov.run_low, -1, -1)
116
117 payload_boundaries = [ExpRun(output_iov.exp_low, output_iov.run_low)]
118 payload_boundaries.extend([ExpRun(*boundary) for boundary in expert_config["payload_boundaries"]])
119 basf2.B2INFO(f"Expert set payload boundaries are: {expert_config['payload_boundaries']}")
120
121 collector_granularity = 'all'
122 if expert_config["payload_boundaries"] is not None:
123 basf2.B2INFO('Found payload_boundaries: set collector granularity to run')
124 collector_granularity = 'run'
125
126 if calib_mode == "full":
127 calibration_procedure = {
128 "rungain0": 0, # Run Gain trail (No Payload saving and take of effect of previous rungains)
129 "timegain0": 0, # Injection time gain Pre (No payload saving)
130 "timegain1": 0, # Injection time gain
131 "rungain1": 0, # Run Gain Pre (No Payload saving)
132 "coscorr0": 0, # Cosine Corr Gain Pre (No Payload saving)
133 "coscorr1": 0, # Cosine Corr Gain
134 "cosedge0": 0, # Cosine edge Corr Gain
135 "badwire0": 0, # Bad wire
136 "wiregain0": 0, # WireGain 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 else:
177 basf2.B2FATAL(f"The calibration is not defined, check spelling: calib {i}: {calib_keys[i]}")
178
179 basf2.B2INFO(f"calibration for {calib_keys[i]} with number of iteration={max_iter}")
180
181 cals[i] = CDCDedxCalibration(name=calib_keys[i],
182 algorithms=alg,
183 input_file_dict=data_files,
184 max_iterations=max_iter,
185 collector_granularity=collector_granularity,
186 dependencies=[cals[i-1]] if i > 0 else None
187 )
188 if payload_boundaries:
189 basf2.B2INFO("Found payload_boundaries: calibration strategies set to SequentialBoundaries.")
190 if cal_name == "rungain" or cal_name == "timegain":
191 cals[i].strategies = SequentialRunByRun
192 for algorithm in cals[i].algorithms:
193 algorithm.params = {"iov_coverage": output_iov}
194 if calib_keys[i] == "rungain0" or calib_keys[i] == "rungain1" or calib_keys[i] == "timegain0":
195 cals[i].save_payloads = False
196 else:
197 cals[i].strategies = SequentialBoundaries
198 for algorithm in cals[i].algorithms:
199 algorithm.params = {"iov_coverage": output_iov, "payload_boundaries": payload_boundaries}
200 if calib_keys[i] == "coscorr0":
201 cals[i].save_payloads = False
202
203 else:
204 for algorithm in cals[i].algorithms:
205 algorithm.params = {"apply_iov": output_iov}
206
207 return cals
208
209
210# Precollector path
211def pre_collector(name='rg'):
212 """
213 Define pre collection.
214 Parameters:
215 name : name of the calibration
216 rungain rungain0 by Default.
217 Returns:
218 path : path for pre collection
219 """
220
221 reco_path = basf2.create_path()
222 recon.prepare_cdst_analysis(path=reco_path)
223 if (name == "timegain"):
224 trg_bhabhaskim = reco_path.add_module("TriggerSkim", triggerLines=["software_trigger_cut&skim&accept_radee"])
225 trg_bhabhaskim.if_value("==0", basf2.Path(), basf2.AfterConditionPath.END)
226 # ps_bhabhaskim = reco_path.add_module("Prescale", prescale=0.80)
227 # ps_bhabhaskim.if_value("==0", basf2.Path(), basf2.AfterConditionPath.END)
228
229 elif (name == "cosedge"):
230 trg_bhabhaskim = reco_path.add_module(
231 "TriggerSkim",
232 triggerLines=[
233 "software_trigger_cut&skim&accept_bhabha",
234 "software_trigger_cut&filter&ee_flat_90_180",
235 "software_trigger_cut&filter&ee_flat_0_19"])
236 trg_bhabhaskim.if_value("==0", basf2.Path(), basf2.AfterConditionPath.END)
237 else:
238 trg_bhabhaskim = reco_path.add_module("TriggerSkim", triggerLines=["software_trigger_cut&skim&accept_bhabha"])
239 trg_bhabhaskim.if_value("==0", basf2.Path(), basf2.AfterConditionPath.END)
240
241 reco_path.add_module(
242 'CDCDedxCorrection',
243 relativeCorrections=False,
244 scaleCor=True,
245 runGain=True,
246 timeGain=True,
247 cosineCor=True,
248 wireGain=True,
249 twoDCell=True,
250 oneDCell=True)
251 return reco_path
252
253# Collector setup
254
255
256def collector(granularity='all', name=''):
257 """
258 Create a cdcdedx calibration collector
259 Parameters:
260 name : name of calibration
261 granularity : granularity : all or run
262 Returns:
263 collector : collector module
264 """
265
266 from basf2 import register_module
267 col = register_module('CDCDedxElectronCollector', cleanupCuts=True)
268 if name == "timegain":
269 CollParam = {'isRun': True, 'isInjTime': True, 'granularity': 'run'}
270
271 elif name == "coscorr" or name == "cosedge":
272 CollParam = {'isCharge': True, 'isCosth': True, 'granularity': granularity}
273
274 elif name == "badwire":
275 isHit = True
276 CollParam = {'isWire': True, 'isDedxhit': isHit, 'isADCcorr': not isHit, 'granularity': granularity}
277
278 elif name == "wiregain":
279 CollParam = {'isWire': True, 'isDedxhit': True, 'granularity': granularity}
280
281 else:
282 CollParam = {'isRun': True, 'granularity': 'run'}
283
284 col.param(CollParam)
285 return col
286
287# Rungain Algorithm setup
288
289
290def rungain_algo(name, adjustment):
291 """
292 Create a rungain calibration algorithm.
293 Returns:
294 algo : rungain algorithm
295 """
296 algo = CDCDedxRunGainAlgorithm()
297 algo.setMonitoringPlots(True)
298 if name == "rungain2":
299 algo.setAdjustment(adjustment)
300 return algo
301
302# Injection Algorithm setup
303
304
305def injection_time_algo():
306 """
307 Create a injection time calibration algorithm.
308 Returns:
309 algo : injection time algorithm
310 """
311 algo = CDCDedxInjectTimeAlgorithm()
312 algo.setMonitoringPlots(True)
313 return algo
314
315# Cosine Algorithm setup
316
317
318def cos_algo():
319 """
320 Create a cosine calibration algorithm.
321 Returns:
322 algo : cosine algorithm
323 """
324 algo = CDCDedxCosineAlgorithm()
325 algo.setMonitoringPlots(True)
326 return algo
327
328# CosineEdge Algorithm setup
329
330
331def cosedge_algo():
332 """
333 Create a cosine edge calibration algorithm.
334 Returns:
335 algo : cosine edge algorithm
336 """
337 algo = CDCDedxCosEdgeAlgorithm()
338 algo.setMonitoringPlots(True)
339 return algo
340
341# Badwire Algorithm setup
342
343
344def badwire_algo():
345 """
346 Create a badwire calibration algorithm.
347 Returns:
348 algo : badwire algorithm
349 """
350 algo = CDCDedxBadWireAlgorithm()
351 # threshold (mean and rms) pars for dedx
352 algo.setHighFracThres(0.2)
353 algo.setMeanThres(0.4)
354 algo.setRMSThres(0.4)
355 algo.setHistPars(150, 0, 5)
356 algo.setMonitoringPlots(True)
357 return algo
358
359# WireGain Algorithm setup
360
361
362def wiregain_algo():
363 """
364 Create a wire gain calibration algorithm.
365 Returns:
366 algo : wiregain algorithm
367 """
368 algo = CDCDedxWireGainAlgorithm()
369 algo.enableExtraPlots(True)
370 return algo
371
372
374 '''
375 CDCDedxCalibration is a specialized calibration for cdcdedx.
376 '''
377
378 def __init__(self,
379 name,
380 algorithms,
381 input_file_dict,
382 max_iterations=5,
383 dependencies=None,
384 collector_granularity='All'):
385 '''
386 parameters:
387 name: name of calibration
388 algorithims: algorithm of calibration
389 input_file_dict: input files list
390 max_iterations: maximum number of iterations
391 dependenices: depends on the previous calibration
392 collector_granularity: granularity : all or run
393 '''
394 super().__init__(name=name,
395 algorithms=algorithms
396 )
397
398 from caf.framework import Collection
399 cal_name = ''.join([i for i in name if not i.isdigit()])
400 if cal_name == "badwire" or cal_name == "wiregain":
401 collection = Collection(collector=collector(granularity=collector_granularity, name=cal_name),
402 input_files=input_file_dict[2],
403 pre_collector_path=pre_collector(cal_name)
404 )
405 elif cal_name == "coscorr" or cal_name == "cosedge":
406 collection = Collection(collector=collector(granularity=collector_granularity, name=cal_name),
407 input_files=input_file_dict[1],
408 pre_collector_path=pre_collector(cal_name)
409 )
410 else:
411 collection = Collection(collector=collector(granularity=collector_granularity, name=cal_name),
412 input_files=input_file_dict[0],
413 pre_collector_path=pre_collector(cal_name)
414 )
415 self.add_collection(name=cal_name, collection=collection)
416
417
418 self.max_iterations = max_iterations
419
420 if dependencies is not None:
421 for dep in dependencies:
422 self.depends_on(dep)
max_iterations
maximum iterations
Definition: caf_cdcdedx.py:418
def __init__(self, name, algorithms, input_file_dict, max_iterations=5, dependencies=None, collector_granularity='All')
Definition: caf_cdcdedx.py:384