Belle II Software  release-08-01-10
caf_ecl_E.py
1 
8 
9 """ECL single crystal energy calibration using three control samples."""
10 
11 from prompt import CalibrationSettings, INPUT_DATA_FILTERS
12 
13 # --------------------------------------------------------------
14 # ..Tell the automated script some required details
15 settings = 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 
50 def 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 
74 def 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 
98 def 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.