Belle II Software development
caf_cdcdedx_hadron.py
1
8
9
10"""
11Airflow script for automatic CDC dEdx calibration. It is the hadron based
12calibration, where Hadron saturation and beta gamma curve and resolution calibration implemented.
13"""
14
15from prompt import CalibrationSettings, INPUT_DATA_FILTERS
16from caf.framework import Calibration, Collection
17from caf.strategies import SequentialBoundaries
18from ROOT.Belle2 import CDCDedxHadSatAlgorithm, CDCDedxHadBGAlgorithm
19from basf2 import create_path, register_module
20from cdcdedx_calibration_utils import make_pion_kaon_collection, make_proton_collection
21from cdcdedx_calibration_utils import make_muon_collection, make_electron_collection
22
23from prompt.calibrations.caf_cdcdedx_electron import settings as cdc_dedx_electron
24from prompt.calibrations.caf_top import settings as top
25
26
27quality_flags = [INPUT_DATA_FILTERS["Run Type"]["physics"],
28 INPUT_DATA_FILTERS["Data Quality Tag"]["Good Or Recoverable"],
29 INPUT_DATA_FILTERS["Magnet"]["On"],
30 INPUT_DATA_FILTERS['Beam Energy']['4S'],
31 INPUT_DATA_FILTERS['Beam Energy']['Continuum'],
32 INPUT_DATA_FILTERS['Beam Energy']['Scan']]
33
34collection = ["pion_kaon", "electron", "muon", "proton"]
35
36
37settings = CalibrationSettings(
38 name="CDC dedx Hadron Calibrations",
39 expert_username="renu92garg",
40 subsystem="cdc",
41 description=__doc__,
42 input_data_formats=["cdst"],
43 input_data_names=["hadron_calib", "bhabha_all_calib", "radmumu_calib"],
44 input_data_filters={
45 "hadron_calib": [INPUT_DATA_FILTERS["Data Tag"]["hadron_calib"]] + quality_flags,
46 "bhabha_all_calib": [INPUT_DATA_FILTERS['Data Tag']['bhabha_all_calib']] + quality_flags,
47 "radmumu_calib": [INPUT_DATA_FILTERS['Data Tag']['radmumu_calib']] + quality_flags
48 },
49 expert_config={"payload_boundaries": [],
50 "proton_minCut": 0.5,
51 "proton_maxCut": 1.2,
52 "maxevt": 2e6,
53 "sat_bgpar": {"muon": [8, 2.83, 28.83], "proton": [6, 0.44, 0.85]},
54 "bgpar": {"muon": [12, 2.85, 28.85], "proton": [20, 0.33, 0.85]},
55 "cosbins": {"muon": 24, "proton": 20},
56 },
57 depends_on=[cdc_dedx_electron, top],
58 produced_payloads=["CDCDedxHadronCor", "CDCDedxMeanPars", "CDCDedxSigmaPars"])
59
60
61
62
63def get_calibrations(input_data, **kwargs):
64 """
65 Parameters:
66 input_data (dict): Should contain every name from the 'input_data_names' variable as a key.
67 Each value is a dictionary with {"/path/to/file_e1_r5.root": IoV(1,5,1,5), ...}. Useful for
68 assigning to calibration.files_to_iov
69
70 **kwargs: Configuration options to be sent in. Since this may change we use kwargs as a way to help prevent
71 backwards compatibility problems. But you could use the correct arguments in b2caf-prompt-run for this
72 release explicitly if you want to.
73
74 Currently only kwargs["output_iov"] is used. This is the output IoV range that your payloads should
75 correspond to. Generally your highest ExpRun payload should be open ended e.g. IoV(3,4,-1,-1)
76
77 Returns:
78 list(caf.framework.Calibration): All of the calibration objects we want to assign to the CAF process
79 """
80 import basf2
81
82 # Set up config options
83 # In this script we want to use one sources of input data.
84 # Get the input files from the input_data variable
85 file_to_iov_muon = input_data["radmumu_calib"]
86 file_to_iov_electron = input_data["bhabha_all_calib"]
87 file_to_iov_hadron = input_data["hadron_calib"]
88
89 expert_config = kwargs.get("expert_config")
90 maxevt = expert_config["maxevt"]
91
92 from prompt.utils import filter_by_select_max_events_from_files
93
94 input_files_muon = list(file_to_iov_muon.keys())
95
96 input_files_electron = filter_by_select_max_events_from_files(list(file_to_iov_electron.keys()), maxevt)
97 if not input_files_electron:
98 raise ValueError(f"Electron: all requested ({maxevt}) events not found")
99
100 input_files_hadron = list(file_to_iov_hadron.keys())
101
102 basf2.B2INFO(f"Total number of files actually used as input for muon = {len(input_files_muon)}")
103 basf2.B2INFO(f"Total number of files actually used as input for electron = {len(input_files_electron)}")
104 basf2.B2INFO(f"Total number of files actually used as input for hadron = {len(input_files_hadron)}")
105
106 # Get the overall IoV we our process should cover. Includes the end values that we may want to ignore since our output
107 # IoV should be open ended. We could also use this as part of the input data selection in some way.
108 requested_iov = kwargs.get("requested_iov", None)
109
110 from caf.utils import ExpRun, IoV
111 # The actual value our output IoV payload should have. Notice that we've set it open ended.
112 output_iov = IoV(requested_iov.exp_low, requested_iov.run_low, -1, -1)
113
114 payload_boundaries = [ExpRun(output_iov.exp_low, output_iov.run_low)]
115 payload_boundaries.extend([ExpRun(*boundary) for boundary in expert_config["payload_boundaries"]])
116 basf2.B2INFO(f"Expert set payload boundaries are: {expert_config['payload_boundaries']}")
117
118 # extracting parameters
119 proton_minCut = expert_config["proton_minCut"]
120 proton_maxCut = expert_config["proton_maxCut"]
121 bgpar = expert_config["bgpar"]
122 sat_bgpar = expert_config["sat_bgpar"]
123 cosbins = expert_config["cosbins"]
124
125
127
128 root_input = register_module("RootInput")
129
130 #
131 # pion kaon collection
132 #
133 rec_path_pion_kaon = create_path()
134 rec_path_pion_kaon.add_module(root_input)
135
136 pion_kaon_list = []
137 pion_kaon_list = make_pion_kaon_collection(rec_path_pion_kaon)
138
139 collector_pion_kaon = register_module('CDCDedxHadronCollector')
140 collector_pion_kaon.param("particleLists", pion_kaon_list)
141
142 collection_pion_kaon = Collection(collector=collector_pion_kaon,
143 input_files=input_files_hadron,
144 pre_collector_path=rec_path_pion_kaon, max_collector_jobs=400)
145
146 #
147 # proton collection
148 #
149 rec_path_proton = create_path()
150 rec_path_proton.add_module(root_input)
151 proton_list = make_proton_collection(rec_path_proton)
152
153 collector_proton = register_module('CDCDedxHadronCollector', particleLists=proton_list)
154 collector_proton.param("maxcut", proton_maxCut)
155 collector_proton.param("mincut", proton_minCut)
156
157 collection_proton = Collection(collector=collector_proton,
158 input_files=input_files_hadron,
159 pre_collector_path=rec_path_proton,
160 max_collector_jobs=400
161 )
162
163 #
164 # muon collection
165 #
166 rec_path_muon = create_path()
167 rec_path_muon.add_module(root_input)
168 muon_list = make_muon_collection(rec_path_muon)
169
170 collector_muon = register_module('CDCDedxHadronCollector', particleLists=muon_list)
171
172 collection_muon = Collection(collector=collector_muon,
173 input_files=input_files_muon,
174 pre_collector_path=rec_path_muon
175 )
176
177 #
178 # electron collection
179 #
180 rec_path_electron = create_path()
181 rec_path_electron.add_module(root_input)
182 electron_list = make_electron_collection(rec_path_electron)
183 collector_electron = register_module('CDCDedxHadronCollector', particleLists=electron_list)
184
185 collection_electron = Collection(collector=collector_electron,
186 input_files=input_files_electron,
187 pre_collector_path=rec_path_electron
188 )
189
190 # set algorithim
191 algorithm_sat = CDCDedxHadSatAlgorithm()
192 algorithm_sat.setProtonCut(proton_minCut)
193 for key, value in sat_bgpar.items():
194 algorithm_sat.setBGPars(key, value[0], value[1], value[2])
195
196 algorithm_bg = CDCDedxHadBGAlgorithm()
197 algorithm_bg.setProtonCut(proton_minCut)
198
199 for key, value in bgpar.items():
200 algorithm_bg.setBGPars(key, value[0], value[1], value[2])
201
202 for key, value in cosbins.items():
203 algorithm_bg.setCosBin(key, value)
204
205 # set calibration
206 cal = Calibration("Hadron_saturation")
207 cal.add_collection(name="pion_kaon", collection=collection_pion_kaon)
208 cal.add_collection(name="proton", collection=collection_proton)
209 cal.add_collection(name="muon", collection=collection_muon)
210 cal.add_collection(name="electron", collection=collection_electron)
211
212 cal.algorithms = [algorithm_sat, algorithm_bg]
213
214 if payload_boundaries:
215 basf2.B2INFO("Found payload_boundaries: calibration strategies set to SequentialBoundaries.")
216 cal.strategies = SequentialBoundaries
217 for algorithm in cal.algorithms:
218 algorithm.params = {"iov_coverage": output_iov, "payload_boundaries": payload_boundaries}
219 else:
220 for algorithm in cal.algorithms:
221 algorithm.params = {"iov_coverage": output_iov}
222
223 # You must return all calibrations you want to run in the prompt process, even if it's only one
224 return [cal]
225
226