Belle II Software development
caf_ecl_E.py
1
8
9"""ECL single crystal energy calibration using three control samples."""
10
11from prompt import CalibrationSettings, INPUT_DATA_FILTERS
12
13# --------------------------------------------------------------
14# ..Tell the automated script some required details
15settings = CalibrationSettings(
16 name="ecl_energy",
17 expert_username="hearty",
18 description=__doc__,
19 input_data_formats=["cdst"],
20 input_data_names=[
21 "bhabha_all_calib",
22 "gamma_gamma_calib",
23 "mumu_tight_or_highm_calib"],
24 input_data_filters={
25 "bhabha_all_calib": [
26 INPUT_DATA_FILTERS["Data Tag"]["bhabha_all_calib"],
27 INPUT_DATA_FILTERS["Data Quality Tag"]["Good Or Recoverable"],
28 INPUT_DATA_FILTERS["Beam Energy"]["4S"],
29 INPUT_DATA_FILTERS["Run Type"]["physics"],
30 INPUT_DATA_FILTERS["Magnet"]["On"]],
31 "gamma_gamma_calib": [
32 INPUT_DATA_FILTERS["Data Tag"]["gamma_gamma_calib"],
33 INPUT_DATA_FILTERS["Data Quality Tag"]["Good Or Recoverable"],
34 INPUT_DATA_FILTERS["Beam Energy"]["4S"],
35 INPUT_DATA_FILTERS["Run Type"]["physics"],
36 INPUT_DATA_FILTERS["Magnet"]["On"]],
37 "mumu_tight_or_highm_calib": [
38 INPUT_DATA_FILTERS["Data Tag"]["mumu_tight_or_highm_calib"],
39 INPUT_DATA_FILTERS["Data Quality Tag"]["Good Or Recoverable"],
40 INPUT_DATA_FILTERS["Beam Energy"]["4S"],
41 INPUT_DATA_FILTERS["Run Type"]["physics"],
42 INPUT_DATA_FILTERS["Magnet"]["On"]]},
43 depends_on=[],
44 expert_config={"ee5x5_min_entries": 100})
45
46# --------------------------------------------------------------
47# ..Raise clustering seed threshold in ECLCRFinder
48
49
50def touch_CRFinder(path, new_seed):
51 import basf2
52 """
53 Speed up ECL clustering by increasing seed threshold
54 """
55 new_path = basf2.create_path()
56 found = False
57 for m in path.modules():
58 if str(m) != "ECLCRFinder": # search module by name
59 new_path.add_module(m)
60 else:
61 crfinder = basf2.register_module('ECLCRFinder')
62 crfinder.param('energyCut0', new_seed)
63 basf2.print_params(crfinder)
64 new_path.add_module(crfinder)
65 found = True
66 if not found:
67 raise KeyError("Could not find ECLCRFinder in path")
68 return new_path
69
70# --------------------------------------------------------------
71# ..Raise threshold in ECLWaveformFit
72
73
74def touch_WaveformFit(path, energy_threshold):
75 import basf2
76 """
77 Speed up ECL reconstruction by increasing energy threshold
78 """
79 new_path = basf2.create_path()
80 found = False
81 for m in path.modules():
82 if str(m) != "ECLWaveformFit": # search module by name
83 new_path.add_module(m)
84 else:
85 waveformfit = basf2.register_module('ECLWaveformFit')
86 waveformfit.param('EnergyThreshold', energy_threshold)
87 basf2.print_params(waveformfit)
88 new_path.add_module(waveformfit)
89 found = True
90 if not found:
91 raise KeyError("Could not find ECLWaveformFit in path")
92 return new_path
93
94# --------------------------------------------------------------
95# ..The calibration functions
96
97
98def get_calibrations(input_data, **kwargs):
99 import basf2
100 from ROOT import Belle2
101 from caf.utils import IoV
102 from caf.framework import Calibration
103 from reconstruction import prepare_cdst_analysis
104
105 # --------------------------------------------------------------
106 # ..Bhabha
107
108 # ..Input data
109 file_to_iov_bhabha = input_data["bhabha_all_calib"]
110 input_files_bhabha = list(file_to_iov_bhabha.keys())
111
112 # ..Algorithm
113 algo_ee5x5 = Belle2.ECL.eclee5x5Algorithm()
114 expert_config = kwargs.get("expert_config")
115 ee5x5minEntries = expert_config["ee5x5_min_entries"]
116 algo_ee5x5.setMinEntries(ee5x5minEntries)
117 algo_ee5x5.setPayloadName("ECLCrystalEnergy5x5")
118 algo_ee5x5.setStoreConst(True)
119
120 # ..The calibration
121 eclee5x5_collector = basf2.register_module("eclee5x5Collector")
122 eclee5x5_collector.param("thetaLabMinDeg", 17.)
123 eclee5x5_collector.param("thetaLabMaxDeg", 150.)
124 eclee5x5_collector.param("minE0", 0.45)
125 eclee5x5_collector.param("minE1", 0.40)
126 eclee5x5_collector.param("maxdThetaSum", 2.)
127 eclee5x5_collector.param("dPhiScale", 1.)
128 eclee5x5_collector.param("maxTime", 10.)
129 eclee5x5_collector.param("useCalDigits", False)
130 eclee5x5_collector.param("requireL1", False)
131 eclee5x5_collector.param("granularity", "all")
132 cal_ecl_ee5x5 = Calibration("ecl_ee5x5",
133 collector=eclee5x5_collector,
134 algorithms=[algo_ee5x5],
135 input_files=input_files_bhabha
136 )
137 cal_ecl_ee5x5.backend_args = {"request_memory": "4 GB"}
138
139 # ..Add prepare_cdst_analysis to pre_collector_path
140 ee5x5_pre_path = basf2.create_path()
141 prepare_cdst_analysis(ee5x5_pre_path, components=['ECL'])
142 new_threshold = 1.0 # GeV
143 ee5x5_pre_path = touch_CRFinder(ee5x5_pre_path, new_threshold)
144 waveform_threshold = 99. # GeV
145 ee5x5_pre_path = touch_WaveformFit(ee5x5_pre_path, waveform_threshold)
146 cal_ecl_ee5x5.pre_collector_path = ee5x5_pre_path
147
148 # --------------------------------------------------------------
149 # ..gamma gamma
150
151 # ..Input data
152 file_to_iov_gamma_gamma = input_data["gamma_gamma_calib"]
153 input_files_gamma_gamma = list(file_to_iov_gamma_gamma.keys())
154
155 # ..Algorithm
156 algo_gamma_gamma = Belle2.ECL.eclGammaGammaEAlgorithm()
157 algo_gamma_gamma.setOutputName("eclGammaGammaE_algorithm.root")
158 algo_gamma_gamma.setCellIDLo(1)
159 algo_gamma_gamma.setCellIDHi(8736)
160 algo_gamma_gamma.setMinEntries(150)
161 algo_gamma_gamma.setMaxIterations(10)
162 algo_gamma_gamma.setTRatioMin(0.45)
163 algo_gamma_gamma.setTRatioMax(0.70)
164 algo_gamma_gamma.setTRatioMinHiStat(0.70)
165 algo_gamma_gamma.setTRatioMaxHiStat(0.95)
166 algo_gamma_gamma.setUpperEdgeThresh(0.02)
167 algo_gamma_gamma.setPerformFits(True)
168 algo_gamma_gamma.setFindExpValues(False)
169 algo_gamma_gamma.setStoreConst(0)
170
171 # ..The calibration
172 eclGammaGamma_collector = basf2.register_module("eclGammaGammaECollector")
173 eclGammaGamma_collector.param("granularity", "all")
174 eclGammaGamma_collector.param("thetaLabMinDeg", 0.)
175 eclGammaGamma_collector.param("thetaLabMaxDeg", 180.)
176 eclGammaGamma_collector.param("minPairMass", 9.)
177 eclGammaGamma_collector.param("mindPhi", 179.)
178 eclGammaGamma_collector.param("maxTime", 999.)
179 eclGammaGamma_collector.param("measureTrueEnergy", False)
180 eclGammaGamma_collector.param("requireL1", False)
181 cal_ecl_gamma_gamma = Calibration("ecl_gamma_gamma",
182 collector=eclGammaGamma_collector,
183 algorithms=[algo_gamma_gamma],
184 input_files=input_files_gamma_gamma
185 )
186
187 # ..Add prepare_cdst_analysis to pre_collector_path
188 gamma_gamma_pre_path = basf2.create_path()
189 prepare_cdst_analysis(gamma_gamma_pre_path, components=['ECL'])
190 new_threshold = 1.0 # GeV
191 gamma_gamma_pre_path = touch_CRFinder(gamma_gamma_pre_path, new_threshold)
192 waveform_threshold = 99. # GeV
193 gamma_gamma_pre_path = touch_WaveformFit(gamma_gamma_pre_path, waveform_threshold)
194 cal_ecl_gamma_gamma.pre_collector_path = gamma_gamma_pre_path
195
196 # --------------------------------------------------------------
197 # ..muon pair
198
199 # ..Input data
200 file_to_iov_mu_mu = input_data["mumu_tight_or_highm_calib"]
201 input_files_mu_mu = list(file_to_iov_mu_mu.keys())
202
203 # ..Algorithm
204 algo_mu_mu = Belle2.ECL.eclMuMuEAlgorithm()
205 algo_mu_mu.cellIDLo = 1
206 algo_mu_mu.cellIDHi = 8736
207 algo_mu_mu.minEntries = 150
208 algo_mu_mu.nToRebin = 1000
209 algo_mu_mu.tRatioMin = 0.05
210 algo_mu_mu.tRatioMax = 0.40
211 algo_mu_mu.lowerEdgeThresh = 0.10
212 algo_mu_mu.performFits = True
213 algo_mu_mu.findExpValues = False
214 algo_mu_mu.storeConst = 0
215
216 # ..The calibration
217 eclmumu_collector = basf2.register_module("eclMuMuECollector")
218 eclmumu_collector.param("granularity", "all")
219 eclmumu_collector.param("minPairMass", 9.0)
220 eclmumu_collector.param("minTrackLength", 30.)
221 eclmumu_collector.param("MaxNeighbourE", 0.010)
222 eclmumu_collector.param("thetaLabMinDeg", 17.)
223 eclmumu_collector.param("thetaLabMaxDeg", 150.)
224 eclmumu_collector.param("measureTrueEnergy", False)
225 eclmumu_collector.param("requireL1", False)
226 cal_ecl_mu_mu = Calibration(name="ecl_mu_mu", collector=eclmumu_collector, algorithms=algo_mu_mu, input_files=input_files_mu_mu)
227
228 # ..Need to include track extrapolation in the path before collector
229 ext_path = basf2.create_path()
230 prepare_cdst_analysis(ext_path, components=['ECL'])
231 ext_path.add_module("Ext", pdgCodes=[13])
232 new_threshold = 0.1 # GeV
233 ext_path = touch_CRFinder(ext_path, new_threshold)
234 waveform_threshold = 99. # GeV
235 ext_path = touch_WaveformFit(ext_path, waveform_threshold)
236 cal_ecl_mu_mu.pre_collector_path = ext_path
237
238 # --------------------------------------------------------------
239 # Include a merging Calibration that doesn't require input data but instead creates the final
240 # payload from the previous calibration payloads.
241
242 # We use a dummy collector that barely outputs any data and we set the input files to a single file so
243 # we spawn only one very fast job.
244 # It doesn't matter which input file we choose as the output is never used.
245
247 cal_ecl_merge = Calibration(name="ecl_merge", collector="DummyCollector", algorithms=[merging_alg],
248 input_files=input_files_mu_mu[:1])
249
250 # The important part is that we depend on all 3 previous calibrations
251 cal_ecl_merge.depends_on(cal_ecl_ee5x5)
252 cal_ecl_merge.depends_on(cal_ecl_gamma_gamma)
253 cal_ecl_merge.depends_on(cal_ecl_mu_mu)
254
255 # ..Uses cdst data so it requires prepare_cdst_analysis
256 ecl_merge_pre_path = basf2.create_path()
257 prepare_cdst_analysis(ecl_merge_pre_path, components=['ECL'])
258 new_threshold = 0.15 # GeV
259 ecl_merge_pre_path = touch_CRFinder(ecl_merge_pre_path, new_threshold)
260 waveform_threshold = 99. # GeV
261 ecl_merge_pre_path = touch_WaveformFit(ecl_merge_pre_path, waveform_threshold)
262 ecl_merge_pre_path.pre_collector_path = ecl_merge_pre_path
263
264 # --------------------------------------------------------------
265 # ..Force the output iovs to be open
266 requested_iov = kwargs.get("requested_iov", None)
267 output_iov = IoV(requested_iov.exp_low, requested_iov.run_low, -1, -1)
268 for algorithm in cal_ecl_ee5x5.algorithms:
269 algorithm.params = {"apply_iov": output_iov}
270 for algorithm in cal_ecl_gamma_gamma.algorithms:
271 algorithm.params = {"apply_iov": output_iov}
272 for algorithm in cal_ecl_mu_mu.algorithms:
273 algorithm.params = {"apply_iov": output_iov}
274 for algorithm in cal_ecl_merge.algorithms:
275 algorithm.params = {"apply_iov": output_iov}
276
277 # --------------------------------------------------------------
278 # ..Return the calibrations
279 return [cal_ecl_ee5x5, cal_ecl_gamma_gamma, cal_ecl_mu_mu, cal_ecl_merge]
Calibrate ecl crystals using gamma pair events.
Calibrate ecl crystals using previously created payloads.
Calibrate ecl crystals using muon pair events.
Calibrate ecl crystals using Bhabha events.