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