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