Belle II Software  release-05-02-19
simulation.py
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3 
4 from basf2 import *
5 from geometry import check_components
6 from ROOT import Belle2
7 from pxd import add_pxd_simulation
8 from svd import add_svd_simulation
9 from svd import add_svd_reconstruction
10 from tracking import add_tracking_for_PXDDataReduction_simulation
11 
12 
13 def check_simulation(path):
14  """Check if the minimum number of modules required for simulation are in
15  the path and in the correct order"""
16  required = ['Gearbox', 'Geometry', 'FullSim']
17  found = []
18 
19  # make a list of all required modules in the path
20  for module in path.modules():
21  module_type = module.type()
22  # if required add to list of found modules
23  if module_type in required:
24  # unless it is already in there
25  if module_type in found:
26  B2ERROR("Duplicate module in path: %s" % module_type)
27  else:
28  found.append(module.type())
29 
30  if len(required) != len(found):
31  # Apparently at least one module is missing
32  for r in required:
33  if r not in found:
34  B2ERROR("No '%s' module found but needed for simulation" % r)
35  # We have all modules but do they have the correct order?
36  elif required != found:
37  B2ERROR("Simulation modules in wrong order. Should be '%s' but is '%s'"
38  % (", ".join(required), ", ".join(found)))
39 
40 
41 def add_PXDDataReduction(path, components, pxd_unfiltered_digits='pxd_unfiltered_digits',
42  doCleanup=True, overrideDB=False, usePXDDataReduction=True):
43  """
44  This function adds the standard simulation modules to a path.
45  @param pxd_unfiltered_digits: the name of the StoreArray containing the input PXDDigits
46  @param overrideDB: override settings from the DB with the value set in 'usePXDDataReduction'
47  @param usePXDDataReduction: if 'overrideDB==True', override settings from the DB
48  @param doCleanup: if 'doCleanup=True' temporary datastore objects are emptied
49  """
50 
51  # SVD reconstruction
52  svd_cluster = '__ROIsvdClusters'
53  add_svd_reconstruction(path, isROIsimulation=True)
54 
55  # SVD tracking
56  svd_reco_tracks = '__ROIsvdRecoTracks'
57 
58  add_tracking_for_PXDDataReduction_simulation(path, components, svd_cluster='__ROIsvdClusters')
59 
60  add_roiFinder(path, svd_reco_tracks)
61 
62  # Filtering of PXDDigits
63  pxd_digifilter = register_module('PXDdigiFilter')
64  pxd_digifilter.param('ROIidsName', 'ROIs')
65  pxd_digifilter.param('PXDDigitsName', pxd_unfiltered_digits)
66  pxd_digifilter.param('PXDDigitsInsideROIName', 'PXDDigits')
67  pxd_digifilter.param('overrideDB', overrideDB)
68  pxd_digifilter.param('usePXDDataReduction', usePXDDataReduction) # only used for overrideDB=True
69  path.add_module(pxd_digifilter)
70 
71  # empty the StoreArrays which were used for the PXDDatareduction as those are not needed anymore
72  if doCleanup:
73  datastore_cleaner = register_module('PruneDataStore')
74  datastore_cleaner.param('keepMatchedEntries', False)
75  datastore_cleaner.param('matchEntries', ['ROIs', '__ROIsvdRecoDigits', '__ROIsvdClusters', '__ROIsvdRecoTracks',
76  'SPTrackCands__ROI', 'SpacePoints__ROI', pxd_unfiltered_digits,
77  # till here it are StoreArrays, the following are relations and Datastore objects
78  'SegmentNetwork__ROI', 'PXDInterceptsToROIs',
79  'RecoHitInformationsTo__ROIsvdClusters',
80  'SpacePoints__ROITo__ROIsvdClusters', '__ROIsvdClustersToMCParticles',
81  '__ROIsvdRecoDigitsToMCParticles',
82  '__ROIsvdClustersTo__ROIsvdRecoDigits', '__ROIsvdClustersToSVDTrueHits',
83  '__ROIsvdClustersTo__ROIsvdRecoTracks', '__ROIsvdRecoTracksToPXDIntercepts',
84  '__ROIsvdRecoTracksToRecoHitInformations',
85  '__ROIsvdRecoTracksToSPTrackCands__ROI'])
86  path.add_module(datastore_cleaner)
87 
88 
89 def add_roiFinder(path, reco_tracks):
90  """
91  Add the ROI finding to the path creating ROIs out of reco tracks by extrapolating them to the PXD volume.
92  :param path: Where to add the module to.
93  :param reco_tracks: Which tracks to use in the extrapolation step.
94  """
95 
96  pxdDataRed = register_module('PXDROIFinder')
97  param_pxdDataRed = {
98  'recoTrackListName': reco_tracks,
99  'PXDInterceptListName': 'PXDIntercepts',
100  'ROIListName': 'ROIs',
101  'tolerancePhi': 0.15,
102  'toleranceZ': 0.5,
103  'sigmaSystU': 0.02,
104  'sigmaSystV': 0.02,
105  'numSigmaTotU': 10,
106  'numSigmaTotV': 10,
107  'maxWidthU': 0.5,
108  'maxWidthV': 0.5,
109  }
110  pxdDataRed.param(param_pxdDataRed)
111  path.add_module(pxdDataRed)
112 
113 
114 def add_simulation(
115  path,
116  components=None,
117  bkgfiles=None,
118  bkgOverlay=True,
119  forceSetPXDDataReduction=False,
120  usePXDDataReduction=True,
121  cleanupPXDDataReduction=True,
122  generate_2nd_cdc_hits=False,
123  simulateT0jitter=False,
124  usePXDGatedMode=False):
125  """
126  This function adds the standard simulation modules to a path.
127  @param forceSetPXDDataReduction: override settings from the DB with the value set in 'usePXDDataReduction'
128  @param usePXDDataReduction: if 'forceSetPXDDataReduction==True', override settings from the DB
129  @param cleanupPXDDataReduction: if True the datastore objects used by PXDDataReduction are emptied
130  """
131 
132  # Check compoments.
133  check_components(components)
134 
135  # background mixing or overlay input before process forking
136  if bkgfiles is not None:
137  if bkgOverlay:
138  bkginput = register_module('BGOverlayInput')
139  bkginput.param('inputFileNames', bkgfiles)
140  path.add_module(bkginput)
141  else:
142  bkgmixer = register_module('BeamBkgMixer')
143  bkgmixer.param('backgroundFiles', bkgfiles)
144  if components:
145  bkgmixer.param('components', components)
146  path.add_module(bkgmixer)
147  if usePXDGatedMode:
148  if components is None or 'PXD' in components:
149  # PXD is sensitive to hits in intervall -20us to +20us
150  bkgmixer.param('minTimePXD', -20000.0)
151  bkgmixer.param('maxTimePXD', 20000.0)
152  # Emulate injection vetos for PXD
153  pxd_veto_emulator = register_module('PXDInjectionVetoEmulator')
154  path.add_module(pxd_veto_emulator)
155 
156  # geometry parameter database
157  if 'Gearbox' not in path:
158  gearbox = register_module('Gearbox')
159  path.add_module(gearbox)
160 
161  # detector geometry
162  if 'Geometry' not in path:
163  path.add_module('Geometry', useDB=True)
164  if components is not None:
165  B2WARNING("Custom detector components specified: Will still build full geometry")
166 
167  # event T0 jitter simulation
168  if simulateT0jitter and 'EventT0Generator' not in path:
169  eventt0 = register_module('EventT0Generator')
170  path.add_module(eventt0)
171 
172  # detector simulation
173  if 'FullSim' not in path:
174  g4sim = register_module('FullSim')
175  path.add_module(g4sim)
176 
177  check_simulation(path)
178 
179  # no checks are performed for BeamBkgMixer and the Digitizers as they are
180  # not necessary for running simulation jobs and it should be possible to
181  # have them in the path more than once
182 
183  # SVD digitization
184  if components is None or 'SVD' in components:
185  add_svd_simulation(path)
186 
187  # CDC digitization
188  if components is None or 'CDC' in components:
189  cdc_digitizer = register_module('CDCDigitizer')
190  cdc_digitizer.param("Output2ndHit", generate_2nd_cdc_hits)
191  path.add_module(cdc_digitizer)
192 
193  # PXD digitization
194  pxd_digits_name = ''
195  if components is None or 'PXD' in components:
196  if forceSetPXDDataReduction:
197  if usePXDDataReduction:
198  pxd_digits_name = 'pxd_unfiltered_digits'
199  add_pxd_simulation(path, digitsName=pxd_digits_name)
200  else:
201  # use DB conditional module to decide whether ROI finding should be activated
202  path_disableROI_Sim = create_path()
203  path_enableROI_Sim = create_path()
204 
205  add_pxd_simulation(path_disableROI_Sim, digitsName='PXDDigits')
206  add_pxd_simulation(path_enableROI_Sim, digitsName='pxd_unfiltered_digits')
207 
208  roi_condition_module_Sim = path.add_module("ROIfindingConditionFromDB")
209  roi_condition_module_Sim.if_true(path_enableROI_Sim, AfterConditionPath.CONTINUE)
210  roi_condition_module_Sim.if_false(path_disableROI_Sim, AfterConditionPath.CONTINUE)
211 
212  # TOP digitization
213  if components is None or 'TOP' in components:
214  top_digitizer = register_module('TOPDigitizer')
215  path.add_module(top_digitizer)
216 
217  # ARICH digitization
218  if components is None or 'ARICH' in components:
219  arich_digitizer = register_module('ARICHDigitizer')
220  path.add_module(arich_digitizer)
221 
222  # ECL digitization
223  if components is None or 'ECL' in components:
224  ecl_digitizer = register_module('ECLDigitizer')
225  if bkgfiles is not None:
226  ecl_digitizer.param('Background', 1)
227  path.add_module(ecl_digitizer)
228 
229  # KLM digitization
230  if components is None or 'KLM' in components:
231  klm_digitizer = register_module('KLMDigitizer')
232  path.add_module(klm_digitizer)
233 
234  # background overlay executor - after all digitizers
235  if bkgfiles is not None and bkgOverlay:
236  if forceSetPXDDataReduction:
237  path.add_module('BGOverlayExecutor', PXDDigitsName=pxd_digits_name)
238 
239  if components is None or 'PXD' in components:
240  path.add_module("PXDDigitSorter", digits=pxd_digits_name)
241 
242  # sort SVDShaperDigits before PXD data reduction
243  if components is None or 'SVD' in components:
244  path.add_module("SVDShaperDigitSorter")
245  else:
246  path_disableROI_Bkg = create_path()
247  path_enableROI_Bkg = create_path()
248 
249  path_disableROI_Bkg.add_module('BGOverlayExecutor', PXDDigitsName='PXDDigits')
250  if components is None or 'PXD' in components:
251  path_disableROI_Bkg.add_module("PXDDigitSorter", digits='PXDDigits')
252  if components is None or 'SVD' in components:
253  path_disableROI_Bkg.add_module("SVDShaperDigitSorter")
254 
255  path_enableROI_Bkg.add_module('BGOverlayExecutor', PXDDigitsName='pxd_unfiltered_digits')
256  if components is None or 'PXD' in components:
257  path_enableROI_Bkg.add_module("PXDDigitSorter", digits='pxd_unfiltered_digits')
258  if components is None or 'SVD' in components:
259  path_enableROI_Bkg.add_module("SVDShaperDigitSorter")
260 
261  roi_condition_module_Bkg = path.add_module("ROIfindingConditionFromDB")
262  roi_condition_module_Bkg.if_true(path_enableROI_Bkg, AfterConditionPath.CONTINUE)
263  roi_condition_module_Bkg.if_false(path_disableROI_Bkg, AfterConditionPath.CONTINUE)
264 
265  # PXD data reduction - after background overlay executor
266  if components is None or 'PXD' in components:
267  if forceSetPXDDataReduction:
268  if usePXDDataReduction:
269  add_PXDDataReduction(path, components, pxd_digits_name, doCleanup=cleanupPXDDataReduction,
270  overrideDB=forceSetPXDDataReduction, usePXDDataReduction=usePXDDataReduction)
271  else:
272  path_enableROI_Red = create_path()
273  add_PXDDataReduction(
274  path_enableROI_Red,
275  components,
276  pxd_unfiltered_digits='pxd_unfiltered_digits',
277  doCleanup=cleanupPXDDataReduction)
278 
279  roi_condition_module_Red = path.add_module("ROIfindingConditionFromDB")
280  roi_condition_module_Red.if_true(path_enableROI_Red, AfterConditionPath.CONTINUE)
281 
282  # statistics summary
283  path.add_module('StatisticsSummary').set_name('Sum_Simulation')