Belle II Software  release-05-02-19
caf_svd_time.py
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3 '''
4 Script to perform the svd time calibration with the CoG6, CoG3 and ELS3 algorithms
5 '''
6 
7 import sys
8 import datetime
9 import random
10 
11 from ROOT.Belle2 import SVDCoGTimeCalibrationAlgorithm
12 from ROOT.Belle2 import SVD3SampleCoGTimeCalibrationAlgorithm
13 from ROOT.Belle2 import SVD3SampleELSTimeCalibrationAlgorithm
14 from ROOT.Belle2 import SVDTimeValidationAlgorithm
15 
16 import basf2 as b2
17 
18 import rawdata as raw
19 from softwaretrigger.constants import HLT_INPUT_OBJECTS
20 from tracking import add_tracking_reconstruction
21 
22 from caf.framework import Calibration
23 from caf import strategies
24 from caf.utils import IoV
25 from prompt import CalibrationSettings, input_data_filters
26 from prompt.utils import filter_by_max_events_per_run
27 
28 b2.set_log_level(b2.LogLevel.INFO)
29 
30 random.seed(42)
31 
32 now = datetime.datetime.now()
33 
34 settings = CalibrationSettings(name="caf_svd_time",
35  expert_username="gdujany",
36  description=__doc__,
37  input_data_formats=["raw"],
38  input_data_names=["hadron_calib"],
39  input_data_filters={"hadron_calib": [input_data_filters["Data Tag"]["hadron_calib"],
40  input_data_filters["Beam Energy"]["4S"],
41  input_data_filters["Beam Energy"]["Continuum"],
42  input_data_filters["Run Type"]["physics"],
43  input_data_filters["Magnet"]["On"]]},
44  depends_on=[],
45  expert_config={
46  "max_events_per_run": 10000,
47  "isMC": False,
48  })
49 
50 
52 
53 
54 def remove_module(path, name):
55 
56  new_path = b2.create_path()
57  for m in path.modules():
58  if name != m.name():
59  new_path.add_module(m)
60  return new_path
61 
62 
63 
64 NEW_RECO_DIGITS_NAME = "SVDRecoDigitsFromTracks"
65 NEW_SHAPER_DIGITS_NAME = "SVDShaperDigitsFromTracks"
66 
67 
68 def create_collector(name="SVDTimeCalibrationCollector",
69  clusters="SVDClustersFromTracks",
70  event_info="SVDEventInfo",
71  event_t0="EventT0",
72  granularity="run"):
73  """
74  Simply creates a SVDTimeCalibrationCollector module with some options.
75 
76  Returns:
77  pybasf2.Module
78  """
79 
80  collector = b2.register_module("SVDTimeCalibrationCollector")
81  collector.set_name(name)
82  collector.param("SVDClustersFromTracksName", clusters)
83  collector.param("SVDEventInfoName", event_info)
84  collector.param("EventT0Name", event_t0)
85  collector.param("granularity", granularity)
86 
87  return collector
88 
89 
90 def create_validation_collector(name="SVDTimeValidationCollector",
91  clusters="SVDClusters",
92  clusters_onTracks="SVDClustersOnTracks",
93  event_info="SVDEventInfo",
94  event_t0="EventT0",
95  granularity="run"):
96  """
97  Simply creates a SVDTimeCalibrationCollector module with some options.
98 
99  Returns:
100  pybasf2.Module
101  """
102 
103  collector = b2.register_module("SVDTimeValidationCollector")
104  collector.set_name(name)
105  collector.param("SVDClustersName", clusters)
106  collector.param("SVDClustersOnTracksName", clusters_onTracks)
107  collector.param("SVDEventInfoName", event_info)
108  collector.param("EventT0Name", event_t0)
109  collector.param("granularity", granularity)
110 
111  return collector
112 
113 
114 def create_algorithm(unique_id, prefix="", min_entries=10000):
115  """
116  Simply creates a SVDCoGTimeCalibrationAlgorithm class with some options.
117 
118  Returns:
119  ROOT.Belle2.SVDCoGTimeCalibrationAlgorithm
120  """
121  if "CoG6" in prefix:
122  algorithm = SVDCoGTimeCalibrationAlgorithm(unique_id)
123  if "CoG3" in prefix:
124  algorithm = SVD3SampleCoGTimeCalibrationAlgorithm(unique_id)
125  if "ELS3" in prefix:
126  algorithm = SVD3SampleELSTimeCalibrationAlgorithm(unique_id)
127  if prefix:
128  algorithm.setPrefix(prefix)
129  algorithm.setMinEntries(min_entries)
130 
131  return algorithm
132 
133 
134 def create_validation_algorithm(prefix="", min_entries=10000):
135  """
136  Simply creates a SVDCoGTimeValidationAlgorithm class with some options.
137 
138  Returns:
139  ROOT.Belle2.SVDCoGTimeValidationAlgorithm
140  """
141  algorithm = SVDTimeValidationAlgorithm()
142  if prefix:
143  algorithm.setPrefix(prefix)
144  algorithm.setMinEntries(min_entries)
145 
146  return algorithm
147 
148 
149 def create_svd_clusterizer(name="ClusterReconstruction",
150  clusters="SVDClustersFromTracks",
151  reco_digits=None,
152  shaper_digits=None,
153  time_algorithm=0,
154  get_3sample_raw_time=False):
155  """
156  Simply creates a SVDSimpleClusterizer module with some options.
157 
158  Returns:
159  pybasf2.Module
160  """
161 
162  cluster = b2.register_module("SVDSimpleClusterizer")
163  cluster.set_name(name)
164  cluster.param("Clusters", clusters)
165  if reco_digits is not None:
166  cluster.param("RecoDigits", reco_digits)
167  if shaper_digits is not None:
168  cluster.param("ShaperDigits", shaper_digits)
169  cluster.param("timeAlgorithm", time_algorithm)
170  if get_3sample_raw_time:
171  cluster.param("Calibrate3SampleWithEventT0", False)
172  return cluster
173 
174 
175 def create_pre_collector_path(clusterizers, isMC=False, is_validation=False):
176  """
177  Create a basf2 path that runs a common reconstruction path and also runs several SVDSimpleClusterizer
178  modules with different configurations. This way they re-use the same reconstructed objects.
179 
180  Parameters:
181  clusterizers (list[pybasf2.Module]): All the differently configured SVDSimpleClusterizer modules.
182  They should output to different datastore objects.
183 
184  returns:
185  pybasf2.Path
186  """
187  # Set-up re-processing path
188  path = b2.create_path()
189 
190  # Read from file only what is needed
191  path.add_module("RootInput", branchNames=HLT_INPUT_OBJECTS)
192 
193  # unpack raw data to do the tracking
194  if not isMC:
195  raw.add_unpackers(path, components=['PXD', 'SVD', 'CDC'])
196  else:
197  path.add_module("Gearbox")
198  path.add_module("Geometry")
199 
200  # proceed only if we acquired 6-sample strips
201  skim6SampleEvents = b2.register_module("SVD6SampleEventSkim")
202  path.add_module(skim6SampleEvents)
203  emptypath = b2.create_path()
204  skim6SampleEvents.if_false(emptypath)
205 
206  # run tracking reconstruction
207  add_tracking_reconstruction(path)
208  path = remove_module(path, "V0Finder")
209  if not is_validation:
210  b2.set_module_parameters(path, 'SVDCoGTimeEstimator', CalibrationWithEventT0=False)
211 
212  # repeat svd reconstruction using only SVDShaperDigitsFromTracks
213  path.add_module("SVDShaperDigitsFromTracks")
214 
215  cog = b2.register_module("SVDCoGTimeEstimator")
216  cog.set_name("CoGReconstruction")
217  path.add_module(cog)
218  b2.set_module_parameters(path, 'CoGReconstruction',
219  ShaperDigits=NEW_SHAPER_DIGITS_NAME,
220  RecoDigits=NEW_RECO_DIGITS_NAME,
221  CalibrationWithEventT0=is_validation)
222 
223  for cluster in clusterizers:
224  path.add_module(cluster)
225 
226  path = remove_module(path, "SVDMissingAPVsClusterCreator")
227 
228  return path
229 
230 
231 def get_calibrations(input_data, **kwargs):
232 
233  file_to_iov_physics = input_data["hadron_calib"]
234  expert_config = kwargs.get("expert_config")
235  max_events_per_run = expert_config["max_events_per_run"] # Maximum number of events selected per each run
236  isMC = expert_config["isMC"]
237 
238  reduced_file_to_iov_physics = filter_by_max_events_per_run(file_to_iov_physics,
239  max_events_per_run, random_select=True)
240  good_input_files = list(reduced_file_to_iov_physics.keys())
241 
242  b2.B2INFO(f"Total number of files used as input = {len(good_input_files)}")
243 
244  exps = [i.exp_low for i in reduced_file_to_iov_physics.values()]
245  runs = sorted([i.run_low for i in reduced_file_to_iov_physics.values()])
246 
247  firstRun = runs[0]
248  lastRun = runs[-1]
249  expNum = exps[0]
250 
251  if not len(good_input_files):
252  print("No good input files found! Check that the input files have entries != 0!")
253  sys.exit(1)
254 
255  cog6_suffix = "_CoG6"
256  cog3_suffix = "_CoG3"
257  els3_suffix = "_ELS3"
258 
259  calType = "Prompt"
260  if isMC:
261  calType = "MC"
262  unique_id_cog6 = f"SVDCoGTimeCalibrations_{calType}_{now.isoformat()}_INFO:_3rdOrderPol_TBindep_" \
263  f"Exp{expNum}_runsFrom{firstRun}to{lastRun}"
264  print(f"\nUniqueID_CoG6:\n{unique_id_cog6}")
265 
266  unique_id_cog3 = f"SVD3SampleCoGTimeCalibrations_{calType}_{now.isoformat()}_INFO:_3rdOrderPol_TBindep_" \
267  f"Exp{expNum}_runsFrom{firstRun}to{lastRun}"
268  print(f"\nUniqueID_CoG3:\n{unique_id_cog3}")
269 
270  unique_id_els3 = f"SVD3SampleELSTimeCalibrations_{calType}_{now.isoformat()}_INFO:_TBindep_" \
271  f"Exp{expNum}_runsFrom{firstRun}to{lastRun}"
272  print(f"\nUniqueID_ELS3:\n{unique_id_els3}")
273 
274  requested_iov = kwargs.get("requested_iov", None)
275  output_iov = IoV(requested_iov.exp_low, requested_iov.run_low, -1, -1)
276 
277 
280 
281  cog6 = create_svd_clusterizer(
282  name=f"ClusterReconstruction{cog6_suffix}",
283  clusters=f"SVDClustersFromTracks{cog6_suffix}",
284  reco_digits=NEW_RECO_DIGITS_NAME,
285  shaper_digits=NEW_SHAPER_DIGITS_NAME,
286  time_algorithm=0,
287  get_3sample_raw_time=True)
288 
289  cog3 = create_svd_clusterizer(
290  name=f"ClusterReconstruction{cog3_suffix}",
291  clusters=f"SVDClustersFromTracks{cog3_suffix}",
292  reco_digits=NEW_RECO_DIGITS_NAME,
293  shaper_digits=NEW_SHAPER_DIGITS_NAME,
294  time_algorithm=1,
295  get_3sample_raw_time=True)
296 
297  els3 = create_svd_clusterizer(
298  name=f"ClusterReconstruction{els3_suffix}",
299  clusters=f"SVDClustersFromTracks{els3_suffix}",
300  reco_digits=NEW_RECO_DIGITS_NAME,
301  shaper_digits=NEW_SHAPER_DIGITS_NAME,
302  time_algorithm=2,
303  get_3sample_raw_time=True)
304 
305 
308  eventInfo = "SVDEventInfo"
309  if isMC:
310  eventInfo = "SVDEventInfoSim"
311 
312  coll_cog6 = create_collector(
313  name=f"SVDTimeCalibrationCollector{cog6_suffix}",
314  clusters=f"SVDClustersFromTracks{cog6_suffix}",
315  event_info=eventInfo,
316  event_t0="EventT0")
317 
318  algo_cog6 = create_algorithm(
319  unique_id_cog6,
320  prefix=coll_cog6.name(),
321  min_entries=10000)
322 
323  coll_cog3 = create_collector(
324  name=f"SVDTimeCalibrationCollector{cog3_suffix}",
325  clusters=f"SVDClustersFromTracks{cog3_suffix}",
326  event_info=eventInfo,
327  event_t0="EventT0")
328 
329  algo_cog3 = create_algorithm(
330  unique_id_cog3,
331  prefix=coll_cog3.name(),
332  min_entries=10000)
333 
334  coll_els3 = create_collector(
335  name=f"SVDTimeCalibrationCollector{els3_suffix}",
336  clusters=f"SVDClustersFromTracks{els3_suffix}",
337  event_info=eventInfo,
338  event_t0="EventT0")
339 
340  algo_els3 = create_algorithm(
341  unique_id_els3,
342  prefix=coll_els3.name(),
343  min_entries=10000)
344 
345 
349 
350  pre_collector_path = create_pre_collector_path(
351  clusterizers=[cog6, cog3, els3],
352  isMC=isMC)
353  pre_collector_path.add_module(coll_cog6)
354  pre_collector_path.add_module(coll_cog3)
355  # We leave the coll_els3 to be the one "managed" by the CAF
356 
357  # calibration setup
358  calibration = Calibration("SVDTime",
359  collector=coll_els3, # The other collectors are in the pre_collector_path itself
360  algorithms=[algo_cog3, algo_cog6, algo_els3],
361  input_files=good_input_files,
362  pre_collector_path=pre_collector_path)
363 
364  calibration.strategies = strategies.SequentialBoundaries
365 
366  for algorithm in calibration.algorithms:
367  algorithm.params = {"iov_coverage": output_iov}
368 
369 
372 
373  val_cog6 = create_svd_clusterizer(
374  name=f"ClusterReconstruction{cog6_suffix}",
375  clusters=f"SVDClusters{cog6_suffix}",
376  time_algorithm=0)
377 
378  val_cog6_onTracks = create_svd_clusterizer(
379  name=f"ClusterReconstruction{cog6_suffix}_onTracks",
380  clusters=f"SVDClusters{cog6_suffix}_onTracks",
381  reco_digits=NEW_RECO_DIGITS_NAME,
382  shaper_digits=NEW_SHAPER_DIGITS_NAME,
383  time_algorithm=0)
384 
385  val_cog3 = create_svd_clusterizer(
386  name=f"ClusterReconstruction{cog3_suffix}",
387  clusters=f"SVDClusters{cog3_suffix}",
388  time_algorithm=1)
389 
390  val_cog3_onTracks = create_svd_clusterizer(
391  name=f"ClusterReconstruction{cog3_suffix}_onTracks",
392  clusters=f"SVDClusters{cog3_suffix}_onTracks",
393  reco_digits=NEW_RECO_DIGITS_NAME,
394  shaper_digits=NEW_SHAPER_DIGITS_NAME,
395  time_algorithm=1)
396 
397  val_els3 = create_svd_clusterizer(
398  name=f"ClusterReconstruction{els3_suffix}",
399  clusters=f"SVDClusters{els3_suffix}",
400  time_algorithm=2)
401 
402  val_els3_onTracks = create_svd_clusterizer(
403  name=f"ClusterReconstruction{els3_suffix}_onTracks",
404  clusters=f"SVDClusters{els3_suffix}_onTracks",
405  reco_digits=NEW_RECO_DIGITS_NAME,
406  shaper_digits=NEW_SHAPER_DIGITS_NAME,
407  time_algorithm=2)
408 
409  val_coll_cog6 = create_validation_collector(
410  name=f"SVDTimeValidationCollector{cog6_suffix}",
411  clusters=f"SVDClusters{cog6_suffix}",
412  clusters_onTracks=f"SVDClusters{cog6_suffix}_onTracks",
413  event_info=eventInfo,
414  event_t0="EventT0")
415 
416  val_algo_cog6 = create_validation_algorithm(
417  prefix=val_coll_cog6.name(),
418  min_entries=10000)
419 
420  val_coll_cog3 = create_validation_collector(
421  name=f"SVDTimeValidationCollector{cog3_suffix}",
422  clusters=f"SVDClusters{cog3_suffix}",
423  clusters_onTracks=f"SVDClusters{cog3_suffix}_onTracks",
424  event_info=eventInfo,
425  event_t0="EventT0")
426 
427  val_algo_cog3 = create_validation_algorithm(
428  prefix=val_coll_cog3.name(),
429  min_entries=10000)
430 
431  val_coll_els3 = create_validation_collector(
432  name=f"SVDTimeValidationCollector{els3_suffix}",
433  clusters=f"SVDClusters{els3_suffix}",
434  clusters_onTracks=f"SVDClusters{els3_suffix}_onTracks",
435  event_info=eventInfo,
436  event_t0="EventT0")
437 
438  val_algo_els3 = create_validation_algorithm(
439  prefix=val_coll_els3.name(),
440  min_entries=10000)
441 
442  val_pre_collector_path = create_pre_collector_path(
443  clusterizers=[val_cog6, val_cog6_onTracks,
444  val_cog3, val_cog3_onTracks,
445  val_els3, val_els3_onTracks],
446  isMC=isMC, is_validation=True)
447  val_pre_collector_path.add_module(val_coll_cog6)
448  val_pre_collector_path.add_module(val_coll_cog3)
449 
450  val_calibration = Calibration("SVDTimeValidation",
451  collector=val_coll_els3,
452  algorithms=[val_algo_cog3, val_algo_cog6,
453  val_algo_els3],
454  input_files=good_input_files,
455  pre_collector_path=val_pre_collector_path)
456 
457  val_calibration.strategies = strategies.SequentialRunByRun
458 
459  for algorithm in val_calibration.algorithms:
460  algorithm.params = {"iov_coverage": output_iov}
461 
462  val_calibration.depends_on(calibration)
463 
464  return [calibration, val_calibration]
prompt.utils
Definition: utils.py:1
strategies.SequentialRunByRun
Definition: strategies.py:251
softwaretrigger.constants
Definition: constants.py:1
strategies.SequentialBoundaries
Definition: strategies.py:647
Calibration
Definition: Calibration.py:1