Belle II Software  release-05-01-25
path_utils.py
1 from pybasf2 import B2WARNING
2 
3 from basf2 import register_module, create_path
4 from ckf.path_functions import add_pxd_ckf, add_ckf_based_merger, add_svd_ckf, add_cosmics_svd_ckf, add_cosmics_pxd_ckf
5 from pxd import add_pxd_reconstruction
6 from svd import add_svd_reconstruction
7 from tracking.adjustments import adjust_module
8 
9 from iov_conditional import phase_2_conditional
10 
11 
12 def use_local_sectormap(path, pathToLocalSM):
13  """
14  Helper function that sets up the SectorMapBootstrapModule in that way that a local sectormap will be
15  loaded instead the one from the DB. Has to be applied on the path after the SectorMapBootstrap was
16  put into the path (usually in add_reconstructin)
17 
18  :param path: The path the SectorMapBootstrapModule is in.
19  :param pathToLocalSM: the local storage position of the sectormap (including the name)
20 
21  """
22  B2WARNING("Warning will load local SectorMap from: " + pathToLocalSM)
23  adjust_module(path, 'SectorMapBootstrap', **{"ReadSecMapFromDB": False,
24  "ReadSectorMap": True, "SectorMapsInputFile": pathToLocalSM})
25 
26 
27 def add_geometry_modules(path, components=None):
28  """
29  Helper function to add the geometry related modules needed for tracking
30  to the path.
31 
32  :param path: The path to add the tracking reconstruction modules to
33  :param components: the list of geometry components in use or None for all components.
34  """
35  # check for detector geometry, necessary for track extrapolation in genfit
36  if 'Geometry' not in path:
37  path.add_module('Geometry', useDB=True)
38  if components is not None:
39  B2WARNING("Custom detector components specified: Will still build full geometry")
40 
41  # Material effects for all track extrapolations
42  if 'SetupGenfitExtrapolation' not in path:
43  path.add_module('SetupGenfitExtrapolation',
44  energyLossBrems=False, noiseBrems=False)
45 
46 
47 def add_hit_preparation_modules(path, components=None):
48  """
49  Helper fucntion to prepare the hit information to be used by tracking.
50  """
51 
52  # Preparation of the SVD clusters
53  if is_svd_used(components):
54  add_svd_reconstruction(path)
55 
56  # Preparation of the PXD clusters
57  if is_pxd_used(components):
58  add_pxd_reconstruction(path)
59 
60 
61 def add_track_fit_and_track_creator(path, components=None, pruneTracks=False, trackFitHypotheses=None,
62  reco_tracks="RecoTracks", add_mva_quality_indicator=False):
63  """
64  Helper function to add the modules performing the
65  track fit, the V0 fit and the Belle2 track creation to the path.
66 
67  :param path: The path to add the tracking reconstruction modules to
68  :param components: the list of geometry components in use or None for all components.
69  :param pruneTracks: Delete all hits expect the first and the last from the found tracks.
70  :param reco_tracks: Name of the StoreArray where the reco tracks should be stored
71  :param add_mva_quality_indicator: If true, add the MVA track quality estimation
72  to the path that sets the quality indicator property of the found tracks.
73  """
74  # Correct time seed
75  path.add_module("IPTrackTimeEstimator",
76  recoTracksStoreArrayName=reco_tracks, useFittedInformation=False)
77  # track fitting
78  path.add_module("DAFRecoFitter", recoTracksStoreArrayName=reco_tracks).set_name(
79  "Combined_DAFRecoFitter")
80  # Add MVA classifier that uses information not included in the calculation of the fit p-value
81  # to add a track quality indicator for classification of fake vs. MC-matched tracks
82  if add_mva_quality_indicator:
83  path.add_module("TrackQualityEstimatorMVA", collectEventFeatures=True)
84  # create Belle2 Tracks from the genfit Tracks
85  # The following particle hypothesis will be fitted: Pion, Kaon and Proton
86  # Muon fit is working but gives very similar as the Pion due to the closeness of masses
87  # -> therefore not in the default fit list
88  # Electron fit has as systematic bias and therefore not done here. Therefore, pion fits
89  # will be used for electrons which gives a better result as GenFit's current electron
90  # implementation.
91  path.add_module('TrackCreator', recoTrackColName=reco_tracks,
92  pdgCodes=[211, 321, 2212] if not trackFitHypotheses else trackFitHypotheses)
93 
94  # V0 finding
95  path.add_module('V0Finder', RecoTracks=reco_tracks, v0FitterMode=1)
96 
97  # prune genfit tracks
98  if pruneTracks:
99  add_prune_tracks(path, components=components, reco_tracks=reco_tracks)
100 
101 
102 def add_cr_track_fit_and_track_creator(path, components=None,
103  data_taking_period='early_phase3', top_in_counter=False,
104  prune_tracks=False, event_timing_extraction=True,
105  reco_tracks="RecoTracks", tracks=""):
106  """
107  Helper function to add the modules performing the cdc cr track fit
108  and track creation to the path.
109 
110  :param path: The path to which to add the tracking reconstruction modules
111  :param data_taking_period: The cosmics generation will be added using the
112  parameters, that where used in this period of data taking. The periods can be found in cdc/cr/__init__.py.
113 
114  :param components: the list of geometry components in use or None for all components.
115  :param reco_tracks: The name of the reco tracks to use
116  :param tracks: the name of the output Belle tracks
117  :param prune_tracks: Delete all hits expect the first and the last from the found tracks.
118  :param event_timing_extraction: extract the event time
119  :param top_in_counter: time of propagation from the hit point to the PMT in the trigger counter is subtracted
120  (assuming PMT is put at -z of the counter).
121  """
122 
123  if data_taking_period not in ["phase2", "phase3", "early_phase3"]:
124  import cdc.cr as cosmics_setup
125 
126  cosmics_setup.set_cdc_cr_parameters(data_taking_period)
127 
128  # Time seed
129  path.add_module("PlaneTriggerTrackTimeEstimator",
130  recoTracksStoreArrayName=reco_tracks,
131  pdgCodeToUseForEstimation=13,
132  triggerPlanePosition=cosmics_setup.triggerPos,
133  triggerPlaneDirection=cosmics_setup.normTriggerPlaneDirection,
134  useFittedInformation=False)
135 
136  # Initial track fitting
137  path.add_module("DAFRecoFitter",
138  recoTracksStoreArrayName=reco_tracks,
139  probCut=0.00001,
140  pdgCodesToUseForFitting=13,
141  )
142 
143  # Correct time seed
144  path.add_module("PlaneTriggerTrackTimeEstimator",
145  recoTracksStoreArrayName=reco_tracks,
146  pdgCodeToUseForEstimation=13,
147  triggerPlanePosition=cosmics_setup.triggerPos,
148  triggerPlaneDirection=cosmics_setup.normTriggerPlaneDirection,
149  useFittedInformation=True,
150  useReadoutPosition=top_in_counter,
151  readoutPosition=cosmics_setup.readOutPos,
152  readoutPositionPropagationSpeed=cosmics_setup.lightPropSpeed
153  )
154  else:
155  path.add_module("IPTrackTimeEstimator",
156  recoTracksStoreArrayName=reco_tracks, useFittedInformation=False)
157 
158  # Track fitting
159  path.add_module("DAFRecoFitter",
160  recoTracksStoreArrayName=reco_tracks,
161  pdgCodesToUseForFitting=13,
162  )
163 
164  if event_timing_extraction:
165  # Extract the time
166  path.add_module("FullGridChi2TrackTimeExtractor",
167  RecoTracksStoreArrayName=reco_tracks,
168  GridMaximalT0Value=40,
169  GridMinimalT0Value=-40,
170  GridGridSteps=6
171  )
172 
173  # Track fitting
174  path.add_module("DAFRecoFitter",
175  # probCut=0.00001,
176  recoTracksStoreArrayName=reco_tracks,
177  pdgCodesToUseForFitting=13,
178  )
179 
180  # Create Belle2 Tracks from the genfit Tracks
181  path.add_module('TrackCreator',
182  pdgCodes=[13],
183  recoTrackColName=reco_tracks,
184  trackColName=tracks,
185  useClosestHitToIP=True,
186  useBFieldAtHit=True
187  )
188 
189  # Prune genfit tracks
190  if prune_tracks:
191  add_prune_tracks(path=path, components=components,
192  reco_tracks=reco_tracks)
193 
194 
195 def add_mc_matcher(path, components=None, mc_reco_tracks="MCRecoTracks",
196  reco_tracks="RecoTracks", use_second_cdc_hits=False,
197  split_after_delta_t=-1.0):
198  """
199  Match the tracks to the MC truth. The matching works based on
200  the output of the TrackFinderMCTruthRecoTracks.
201 
202  :param path: The path to add the tracking reconstruction modules to
203  :param components: the list of geometry components in use or None for all components.
204  :param mc_reco_tracks: Name of the StoreArray where the mc reco tracks will be stored
205  :param reco_tracks: Name of the StoreArray where the reco tracks should be stored
206  :param use_second_cdc_hits: If true, the second hit information will be used in the CDC track finding.
207  :param split_after_delta_t: If positive, split MCRecoTrack into multiple MCRecoTracks if the time
208  distance between two adjecent SimHits is more than the given value
209  """
210  path.add_module('TrackFinderMCTruthRecoTracks',
211  RecoTracksStoreArrayName=mc_reco_tracks,
212  WhichParticles=[],
213  UseSecondCDCHits=use_second_cdc_hits,
214  UsePXDHits=is_pxd_used(components),
215  UseSVDHits=is_svd_used(components),
216  UseCDCHits=is_cdc_used(components),
217  SplitAfterDeltaT=split_after_delta_t)
218 
219  path.add_module('MCRecoTracksMatcher',
220  mcRecoTracksStoreArrayName=mc_reco_tracks,
221  prRecoTracksStoreArrayName=reco_tracks,
222  UsePXDHits=is_pxd_used(components),
223  UseSVDHits=is_svd_used(components),
224  UseCDCHits=is_cdc_used(components))
225 
226 
227 def add_prune_tracks(path, components=None, reco_tracks="RecoTracks"):
228  """
229  Adds removal of the intermediate states at each measurement from the fitted tracks.
230 
231  :param path: The path to add the tracking reconstruction modules to
232  :param components: the list of geometry components in use or None for all components.
233  :param reco_tracks: Name of the StoreArray where the reco tracks should be stored
234  """
235 
236  # do not add any pruning, if no tracking detectors are in the components
237  if components and not ('SVD' in components or 'CDC' in components):
238  return
239 
240  path.add_module('PruneRecoTracks', storeArrayName=reco_tracks)
241  path.add_module("PruneGenfitTracks")
242 
243 
244 def add_pxd_track_finding(path, components, input_reco_tracks, output_reco_tracks, use_mc_truth=False,
245  add_both_directions=False, temporary_reco_tracks="PXDRecoTracks", **kwargs):
246  """Add the pxd track finding to the path"""
247  if not is_pxd_used(components):
248  return
249 
250  if use_mc_truth:
251  # MC CKF needs MC matching information
252  path.add_module("MCRecoTracksMatcher", UsePXDHits=False,
253  UseSVDHits=is_svd_used(components), UseCDCHits=is_cdc_used(components),
254  mcRecoTracksStoreArrayName="MCRecoTracks",
255  prRecoTracksStoreArrayName=input_reco_tracks)
256 
257  add_pxd_ckf(path, svd_cdc_reco_tracks=input_reco_tracks, pxd_reco_tracks=temporary_reco_tracks,
258  direction="backward", use_mc_truth=use_mc_truth, **kwargs)
259 
260  if add_both_directions:
261  add_pxd_ckf(path, svd_cdc_reco_tracks=input_reco_tracks, pxd_reco_tracks=temporary_reco_tracks,
262  direction="forward", use_mc_truth=use_mc_truth, **kwargs)
263 
264  path.add_module("RelatedTracksCombiner", CDCRecoTracksStoreArrayName=input_reco_tracks,
265  VXDRecoTracksStoreArrayName=temporary_reco_tracks, recoTracksStoreArrayName=output_reco_tracks)
266 
267 
268 def add_pxd_cr_track_finding(path, components, input_reco_tracks, output_reco_tracks, use_mc_truth=False,
269  add_both_directions=False, temporary_reco_tracks="PXDRecoTracks", **kwargs):
270  """Add the pxd track finding to the path"""
271  if not is_pxd_used(components):
272  return
273 
274  if use_mc_truth:
275  # MC CKF needs MC matching information
276  path.add_module("MCRecoTracksMatcher", UsePXDHits=False,
277  UseSVDHits=is_svd_used(components), UseCDCHits=is_cdc_used(components),
278  mcRecoTracksStoreArrayName="MCRecoTracks",
279  prRecoTracksStoreArrayName=input_reco_tracks)
280 
281  add_cosmics_pxd_ckf(path, svd_cdc_reco_tracks=input_reco_tracks, pxd_reco_tracks=temporary_reco_tracks,
282  direction="backward", use_mc_truth=use_mc_truth, **kwargs)
283 
284  if add_both_directions:
285  add_cosmics_pxd_ckf(path, svd_cdc_reco_tracks=input_reco_tracks, pxd_reco_tracks=temporary_reco_tracks,
286  direction="forward", use_mc_truth=use_mc_truth, **kwargs)
287 
288  path.add_module("RelatedTracksCombiner", CDCRecoTracksStoreArrayName=input_reco_tracks,
289  VXDRecoTracksStoreArrayName=temporary_reco_tracks, recoTracksStoreArrayName=output_reco_tracks)
290 
291 
292 def add_svd_track_finding(
293  path,
294  components,
295  input_reco_tracks,
296  output_reco_tracks,
297  svd_ckf_mode="VXDTF2_after",
298  use_mc_truth=False,
299  add_both_directions=True,
300  temporary_reco_tracks="SVDRecoTracks",
301  temporary_svd_cdc_reco_tracks="SVDPlusCDCStandaloneRecoTracks",
302  use_svd_to_cdc_ckf=True,
303  prune_temporary_tracks=True,
304  add_mva_quality_indicator=False,
305  **kwargs,
306 ):
307  """
308  Add SVD track finding to the path.
309 
310  :param path: The path to add the tracking reconstruction modules to
311  :param components: The list of geometry components in use or None for all components.
312  :param input_reco_tracks: Name of the StoreArray with the input reco tracks (usually from CDC) that are used in the
313  CKF track finding and are merged with the newly found SVD tracks into the ``output_reco_tracks``.
314  :param output_reco_tracks: Name of the StoreArray where the reco tracks outputted by the SVD track finding should be
315  stored.
316  :param svd_ckf_mode: String designating the mode of the CDC-to-SVD CKF, that is how it is combined with the VXDTF2
317  standalone track finding. One of "VXDTF2_after", "VXDTF2_before", "VXDTF2_before_with_second_ckf",
318  "only_ckf", "VXDTF2_alone", "cosmics".
319  :param use_mc_truth: Add mc matching and use the MC information in the CKF (but not in the VXDTF2)
320  :param add_both_directions: Whether to add the CKF with both forward and backward extrapolation directions instead
321  of just one.
322  :param temporary_reco_tracks: Intermediate store array where the SVD tracks from the VXDTF2 standalone track finding
323  are stored, before they are merged with CDC tracks and extended via the CKF tracking.
324  :param temporary_svd_cdc_reco_tracks: Intermediate store array where the combination of ``temporary_reco_tracks``
325  (from SVD) and ``input_reco_tracks`` (from CDC standalone) is stored, before the CKF is applied.
326  It is only used if ``use_svd_to_cdc_ckf`` is true. Otherwise, the combination is stored directly in
327  ``output_reco_tracks``.
328  :param use_svd_to_cdc_ckf: Whether to enable the CKF extrapolation from the SVD into the CDC.
329  That CKF application is not affected by ``svd_ckf_mode``.
330  :param prune_temporary_tracks: Delete all hits expect the first and last from intermediate track objects.
331  :param add_mva_quality_indicator: Add the VVXDQualityEstimatorMVA module to set the quality indicator
332  property for tracks from VXDTF2 standalone tracking
333  (ATTENTION: Standard triplet QI of VXDTF2 is replaced in this case
334  -> setting this option to 'True' will have some influence on the final track collection)
335  """
336 
337  if not is_svd_used(components):
338  return
339 
340  if not input_reco_tracks:
341  # We do not have an input track store array. So lets just add vxdtf track finding
342  add_vxd_track_finding_vxdtf2(path, components=["SVD"], reco_tracks=output_reco_tracks,
343  add_mva_quality_indicator=add_mva_quality_indicator)
344  return
345 
346  if use_mc_truth:
347  # MC CKF needs MC matching information
348  path.add_module("MCRecoTracksMatcher", UsePXDHits=False, UseSVDHits=False,
349  UseCDCHits=is_cdc_used(components),
350  mcRecoTracksStoreArrayName="MCRecoTracks",
351  prRecoTracksStoreArrayName=input_reco_tracks)
352 
353  if svd_ckf_mode == "VXDTF2_before":
354  add_vxd_track_finding_vxdtf2(path, components=["SVD"], reco_tracks=temporary_reco_tracks,
355  add_mva_quality_indicator=add_mva_quality_indicator)
356  add_ckf_based_merger(path, cdc_reco_tracks=input_reco_tracks, svd_reco_tracks=temporary_reco_tracks,
357  use_mc_truth=use_mc_truth, direction="backward", **kwargs)
358  if add_both_directions:
359  add_ckf_based_merger(path, cdc_reco_tracks=input_reco_tracks, svd_reco_tracks=temporary_reco_tracks,
360  use_mc_truth=use_mc_truth, direction="forward", **kwargs)
361 
362  elif svd_ckf_mode == "VXDTF2_before_with_second_ckf":
363  add_vxd_track_finding_vxdtf2(path, components=["SVD"], reco_tracks=temporary_reco_tracks,
364  add_mva_quality_indicator=add_mva_quality_indicator)
365  add_ckf_based_merger(path, cdc_reco_tracks=input_reco_tracks, svd_reco_tracks=temporary_reco_tracks,
366  use_mc_truth=use_mc_truth, direction="backward", **kwargs)
367  if add_both_directions:
368  add_ckf_based_merger(path, cdc_reco_tracks=input_reco_tracks, svd_reco_tracks=temporary_reco_tracks,
369  use_mc_truth=use_mc_truth, direction="forward", **kwargs)
370  add_svd_ckf(path, cdc_reco_tracks=input_reco_tracks, svd_reco_tracks=temporary_reco_tracks,
371  use_mc_truth=use_mc_truth, direction="backward", **kwargs)
372  if add_both_directions:
373  add_svd_ckf(path, cdc_reco_tracks=input_reco_tracks, svd_reco_tracks=temporary_reco_tracks,
374  use_mc_truth=use_mc_truth, direction="forward", filter_cut=0.01, **kwargs)
375 
376  elif svd_ckf_mode == "only_ckf":
377  add_svd_ckf(path, cdc_reco_tracks=input_reco_tracks, svd_reco_tracks=temporary_reco_tracks,
378  use_mc_truth=use_mc_truth, direction="backward", **kwargs)
379  if add_both_directions:
380  add_svd_ckf(path, cdc_reco_tracks=input_reco_tracks, svd_reco_tracks=temporary_reco_tracks,
381  use_mc_truth=use_mc_truth, direction="forward", filter_cut=0.01, **kwargs)
382 
383  elif svd_ckf_mode == "VXDTF2_after":
384  add_svd_ckf(path, cdc_reco_tracks=input_reco_tracks, svd_reco_tracks=temporary_reco_tracks,
385  use_mc_truth=use_mc_truth, direction="backward", **kwargs)
386  if add_both_directions:
387  add_svd_ckf(path, cdc_reco_tracks=input_reco_tracks, svd_reco_tracks=temporary_reco_tracks,
388  use_mc_truth=use_mc_truth, direction="forward", filter_cut=0.01, **kwargs)
389 
390  add_vxd_track_finding_vxdtf2(path, components=["SVD"], reco_tracks=temporary_reco_tracks,
391  add_mva_quality_indicator=add_mva_quality_indicator)
392  add_ckf_based_merger(path, cdc_reco_tracks=input_reco_tracks, svd_reco_tracks=temporary_reco_tracks,
393  use_mc_truth=use_mc_truth, direction="backward", **kwargs)
394  if add_both_directions:
395  add_ckf_based_merger(path, cdc_reco_tracks=input_reco_tracks, svd_reco_tracks=temporary_reco_tracks,
396  use_mc_truth=use_mc_truth, direction="forward", **kwargs)
397 
398  elif svd_ckf_mode == "VXDTF2_alone":
399  add_vxd_track_finding_vxdtf2(path, components=["SVD"], reco_tracks=temporary_reco_tracks,
400  add_mva_quality_indicator=add_mva_quality_indicator)
401  path.add_module('VXDCDCTrackMerger',
402  CDCRecoTrackColName=input_reco_tracks,
403  VXDRecoTrackColName=temporary_reco_tracks)
404 
405  elif svd_ckf_mode == "cosmics":
406  add_cosmics_svd_ckf(path, cdc_reco_tracks=input_reco_tracks, svd_reco_tracks=temporary_reco_tracks,
407  use_mc_truth=use_mc_truth, direction="backward", **kwargs)
408  if add_both_directions:
409  add_cosmics_svd_ckf(path, cdc_reco_tracks=input_reco_tracks, svd_reco_tracks=temporary_reco_tracks,
410  use_mc_truth=use_mc_truth, direction="forward", **kwargs)
411 
412  else:
413  raise ValueError(f"Do not understand the svd_ckf_mode {svd_ckf_mode}")
414 
415  if use_svd_to_cdc_ckf:
416  combined_svd_cdc_standalone_tracks = temporary_svd_cdc_reco_tracks
417  else:
418  combined_svd_cdc_standalone_tracks = output_reco_tracks
419 
420  # Write out the combinations of tracks
421  path.add_module("RelatedTracksCombiner", VXDRecoTracksStoreArrayName=temporary_reco_tracks,
422  CDCRecoTracksStoreArrayName=input_reco_tracks,
423  recoTracksStoreArrayName=combined_svd_cdc_standalone_tracks)
424 
425  if use_svd_to_cdc_ckf:
426  path.add_module("ToCDCCKF",
427  inputWireHits="CDCWireHitVector",
428  inputRecoTrackStoreArrayName=combined_svd_cdc_standalone_tracks,
429  relatedRecoTrackStoreArrayName="CKFCDCRecoTracks",
430  relationCheckForDirection="backward",
431  ignoreTracksWithCDChits=True,
432  outputRecoTrackStoreArrayName="CKFCDCRecoTracks",
433  outputRelationRecoTrackStoreArrayName=combined_svd_cdc_standalone_tracks,
434  writeOutDirection="backward",
435  stateBasicFilterParameters={"maximalHitDistance": 0.15},
436  pathFilter="arc_length",
437  maximalLayerJump=4)
438 
439  path.add_module("CDCCKFTracksCombiner",
440  CDCRecoTracksStoreArrayName="CKFCDCRecoTracks",
441  VXDRecoTracksStoreArrayName=combined_svd_cdc_standalone_tracks,
442  recoTracksStoreArrayName=output_reco_tracks)
443 
444  if prune_temporary_tracks:
445  for temp_reco_track in [combined_svd_cdc_standalone_tracks, "CKFCDCRecoTracks"]:
446  path.add_module('PruneRecoTracks', storeArrayName=temp_reco_track)
447 
448 
449 def add_cdc_track_finding(path, output_reco_tracks="RecoTracks", with_ca=False,
450  use_second_hits=False, add_mva_quality_indicator=True,
451  reattach_hits=False):
452  """
453  Convenience function for adding all cdc track finder modules
454  to the path.
455 
456  The result is a StoreArray with name @param reco_tracks full of RecoTracks (not TrackCands any more!).
457  Use the GenfitTrackCandidatesCreator Module to convert back.
458 
459  :param path: basf2 path
460  :param output_reco_tracks: Name of the output RecoTracks. Defaults to RecoTracks.
461  :param use_second_hits: If true, the second hit information will be used in the CDC track finding.
462  :param add_mva_quality_indicator: Add the TFCDC_TrackQualityEstimator module to set the CDC quality
463  indicator property of the CDC ``output_reco_tracks``
464  :param cdc_quality_estimator_weightfile: Weightfile identifier for the TFCDC_TrackQualityEstimator
465  :param reattach_hits: if true, use the ReattachCDCWireHitsToRecoTracks module at the end of the CDC track finding
466  to readd hits with bad ADC or TOT rejected by the TFCDC_WireHitPreparer module.
467  """
468  # add EventLevelTrackinginfo for logging errors
469  if 'RegisterEventLevelTrackingInfo' not in path:
470  path.add_module('RegisterEventLevelTrackingInfo')
471 
472  # Init the geometry for cdc tracking and the hits and cut low ADC hits
473  path.add_module("TFCDC_WireHitPreparer",
474  wirePosition="aligned",
475  useSecondHits=use_second_hits,
476  flightTimeEstimation="outwards",
477  filter="cuts_from_DB")
478 
479  # Constructs clusters
480  path.add_module("TFCDC_ClusterPreparer",
481  ClusterFilter="all",
482  ClusterFilterParameters={})
483 
484  # Find segments within the clusters
485  path.add_module("TFCDC_SegmentFinderFacetAutomaton")
486 
487  # Find axial tracks
488  path.add_module("TFCDC_AxialTrackFinderLegendre")
489 
490  # Improve the quality of the axial tracks
491  path.add_module("TFCDC_TrackQualityAsserter",
492  corrections=["B2B"])
493 
494  # Find the stereo hits to those axial tracks
495  path.add_module('TFCDC_StereoHitFinder')
496 
497  # Combine segments with axial tracks
498  path.add_module('TFCDC_SegmentTrackCombiner',
499  segmentTrackFilter="mva",
500  segmentTrackFilterParameters={"cut": 0.74},
501  trackFilter="mva",
502  trackFilterParameters={"cut": 0.1})
503 
504  output_tracks = "CDCTrackVector"
505 
506  if with_ca:
507  output_tracks = "CombinedCDCTrackVector"
508  path.add_module("TFCDC_TrackFinderSegmentPairAutomaton",
509  tracks="CDCTrackVector2")
510 
511  # Overwrites the origin CDCTrackVector
512  path.add_module("TFCDC_TrackCombiner",
513  inputTracks="CDCTrackVector",
514  secondaryInputTracks="CDCTrackVector2",
515  tracks=output_tracks)
516 
517  # Improve the quality of all tracks and output
518  path.add_module("TFCDC_TrackQualityAsserter",
519  inputTracks=output_tracks,
520  corrections=[
521  "LayerBreak",
522  "OneSuperlayer",
523  "Small",
524  ])
525 
526  if with_ca:
527  # Add curlers in the axial inner most superlayer
528  path.add_module("TFCDC_TrackCreatorSingleSegments",
529  inputTracks=output_tracks,
530  MinimalHitsBySuperLayerId={0: 15})
531 
532  if add_mva_quality_indicator:
533  # Add CDC-specific mva method to set the quality indicator for the CDC tracks
534  path.add_module(
535  "TFCDC_TrackQualityEstimator",
536  inputTracks=output_tracks,
537  filter='mva',
538  filterParameters={"cut": 0.7},
539  deleteTracks=True,
540  resetTakenFlag=True
541  )
542 
543  # Export CDCTracks to RecoTracks representation
544  path.add_module("TFCDC_TrackExporter",
545  inputTracks=output_tracks,
546  RecoTracksStoreArrayName="CDCRecoTracksBeforeReattaching" if reattach_hits else output_reco_tracks)
547 
548  if reattach_hits:
549  # The ReattachCDCWireHitsToRecoTracks module (below) requires the SetupGenfitExtrapolation module
550  if 'SetupGenfitExtrapolation' not in path:
551  # Prepare Genfit extrapolation
552  path.add_module('SetupGenfitExtrapolation')
553 
554  # Loop over low-ADC/TOT CDCWireHits and RecoTracks and reattach the hits to the tracks if they are close enough
555  path.add_module("ReattachCDCWireHitsToRecoTracks",
556  inputRecoTracksStoreArrayName="CDCRecoTracksBeforeReattaching",
557  outputRecoTracksStoreArrayName=output_reco_tracks)
558 
559  # Correct time seed (only necessary for the CDC tracks)
560  path.add_module("IPTrackTimeEstimator",
561  useFittedInformation=False,
562  recoTracksStoreArrayName=output_reco_tracks)
563 
564  # run fast t0 estimation from CDC hits only
565  path.add_module("CDCHitBasedT0Extraction")
566 
567  # prepare mdst event level info
568  path.add_module("CDCTrackingEventLevelMdstInfoFiller")
569 
570 
571 def add_eclcdc_track_finding(path, components, output_reco_tracks="RecoTracks", prune_temporary_tracks=True):
572  """
573  Convenience function for adding all track finder modules to the path that are based on ecl seeds.
574 
575  The result is a StoreArray with name @param reco_tracks full of RecoTracks.
576  Use the GenfitTrackCandidatesCreator Module to convert back.
577 
578  :param path: basf2 path
579  :param components: the list of geometry components in use or None for all components.
580  :param output_reco_tracks: Name of the output RecoTracks. Defaults to RecoTracks.
581  :param pruneTracks: Delete all hits expect the first and the last from the found tracks.
582  """
583  if not is_cdc_used(components) or not is_ecl_used(components):
584  return
585 
586  ecl_cdc_reco_tracks = "ECLCDCRecoTracks"
587 
588  if not is_svd_used(components):
589  ecl_cdc_reco_tracks = output_reco_tracks
590 
591  # collections that will be pruned
592  temporary_reco_track_list = []
593 
594  path.add_module("ToCDCFromEclCKF",
595  inputWireHits="CDCWireHitVector",
596  minimalEnRequirementCluster=0.3,
597  eclSeedRecoTrackStoreArrayName='EclSeedRecoTracks',
598  hitFindingDirection="backward",
599  outputRecoTrackStoreArrayName="CDCRecoTracksFromEcl",
600  outputRelationRecoTrackStoreArrayName="EclSeedRecoTracks",
601  writeOutDirection="forward",
602  stateBasicFilterParameters={"maximalHitDistance": 7.5, "maximalHitDistanceEclSeed": 75.0},
603  stateExtrapolationFilterParameters={"direction": "backward"},
604  pathFilter="arc_length_fromEcl",
605  inputECLshowersStoreArrayName="ECLShowers",
606  trackFindingDirection="backward",
607  setTakenFlag=False,
608  seedComponent="ECL"
609  )
610 
611  path.add_module("ToCDCCKF",
612  inputWireHits="CDCWireHitVector",
613  inputRecoTrackStoreArrayName="CDCRecoTracksFromEcl",
614  relatedRecoTrackStoreArrayName=ecl_cdc_reco_tracks,
615  relationCheckForDirection="backward",
616  outputRecoTrackStoreArrayName=ecl_cdc_reco_tracks,
617  outputRelationRecoTrackStoreArrayName="CDCRecoTracksFromEcl",
618  writeOutDirection="backward",
619  stateBasicFilterParameters={"maximalHitDistance": 0.75},
620  stateExtrapolationFilterParameters={"direction": "forward"},
621  pathFilter="arc_length",
622  seedComponent="ECL"
623  )
624  # "EclSeedRecoTracks" don't have to be added to the list as these do not contain any hits
625  temporary_reco_track_list.append('CDCRecoTracksFromEcl')
626 
627  # Do the following modules have to be added as these are executed already after
628  # the CDC standalone?
629  # If so: they also have to be included in the new SVD->CDC CKF (see add_svd_track_finding(..) above)
630 
631  # Correct time seed (only necessary for the CDC tracks)
632  # path.add_module("IPTrackTimeEstimator",
633  # useFittedInformation=False,
634  # recoTracksStoreArrayName=ecl_cdc_reco_tracks)
635 
636  # run fast t0 estimation from CDC hits only
637  # path.add_module("CDCHitBasedT0Extraction")
638 
639  # prepare mdst event level info
640  # path.add_module("CDCTrackingEventLevelMdstInfoFiller")
641 
642  if is_svd_used(components):
643  add_svd_track_finding(path, components=components, input_reco_tracks=ecl_cdc_reco_tracks,
644  output_reco_tracks=output_reco_tracks, use_mc_truth=False,
645  svd_ckf_mode="only_ckf", add_both_directions=False,
646  temporary_reco_tracks="ECLSVDRecoTracks", use_svd_to_cdc_ckf=False,
647  prune_temporary_tracks=prune_temporary_tracks)
648  temporary_reco_track_list.append(ecl_cdc_reco_tracks)
649  temporary_reco_track_list.append('ECLSVDRecoTracks')
650 
651  if prune_temporary_tracks:
652  for temporary_reco_track_name in temporary_reco_track_list:
653  if temporary_reco_track_name != output_reco_tracks:
654  path.add_module('PruneRecoTracks', storeArrayName=temporary_reco_track_name)
655 
656 
657 def add_cdc_cr_track_finding(path, output_reco_tracks="RecoTracks", trigger_point=(0, 0, 0), merge_tracks=True,
658  use_second_cdc_hits=False):
659  """
660  Convenience function for adding all cdc track finder modules currently dedicated for the CDC-TOP testbeam
661  to the path.
662 
663  The result is a StoreArray with name @param reco_tracks full of RecoTracks (not TrackCands any more!).
664 
665  Arguments
666  ---------
667  path: basf2.Path
668  The path to be filled
669  output_reco_tracks: str
670  Name of the output RecoTracks. Defaults to RecoTracks.
671  merge_tracks: bool
672  The upper and lower half of the tracks should be merged together in one track
673  use_second_hits: bool
674  If true, the second hit information will be used in the CDC track finding.
675  """
676 
677  # Init the geometry for cdc tracking and the hits
678  path.add_module("TFCDC_WireHitPreparer",
679  useSecondHits=use_second_cdc_hits,
680  flightTimeEstimation="downwards",
681  triggerPoint=trigger_point)
682 
683  # Constructs clusters and reduce background hits
684  path.add_module("TFCDC_ClusterPreparer",
685  ClusterFilter="mva_bkg",
686  ClusterFilterParameters={"cut": 0.2})
687 
688  # Find segments within the clusters
689  path.add_module("TFCDC_SegmentFinderFacetAutomaton",
690  SegmentOrientation="downwards")
691 
692  # Find axial tracks
693  path.add_module("TFCDC_AxialTrackFinderLegendre")
694 
695  # Improve the quality of the axial tracks
696  path.add_module("TFCDC_TrackQualityAsserter",
697  corrections=["B2B"])
698 
699  # Find the stereo hits to those axial tracks
700  path.add_module('TFCDC_StereoHitFinder')
701 
702  # Combine segments with axial tracks
703  path.add_module('TFCDC_SegmentTrackCombiner',
704  segmentTrackFilter="mva",
705  segmentTrackFilterParameters={"cut": 0.74},
706  trackFilter="mva",
707  trackFilterParameters={"cut": 0.1})
708 
709  # Improve the quality of all tracks and output
710  path.add_module("TFCDC_TrackQualityAsserter",
711  corrections=["LayerBreak", "OneSuperlayer", "Small"],
712  )
713 
714  # Flip track orientation to always point downwards
715  path.add_module("TFCDC_TrackOrienter",
716  inputTracks="CDCTrackVector",
717  tracks="OrientedCDCTrackVector",
718  TrackOrientation="downwards",
719  )
720 
721  output_tracks = "OrientedCDCTrackVector"
722 
723  if merge_tracks:
724  # Merge tracks together if needed
725  path.add_module("TFCDC_TrackLinker",
726  inputTracks="OrientedCDCTrackVector",
727  tracks="MergedCDCTrackVector",
728  filter="phi",
729  )
730  output_tracks = "MergedCDCTrackVector"
731 
732  # However, we also want to export the non merged tracks
733  # Correct time seed - assumes velocity near light speed
734  path.add_module("TFCDC_TrackFlightTimeAdjuster",
735  inputTracks="OrientedCDCTrackVector",
736  )
737 
738  # Export CDCTracks to RecoTracks representation
739  path.add_module("TFCDC_TrackExporter",
740  inputTracks="OrientedCDCTrackVector",
741  RecoTracksStoreArrayName="NonMergedRecoTracks")
742 
743  # Correct time seed - assumes velocity near light speed
744  path.add_module("TFCDC_TrackFlightTimeAdjuster",
745  inputTracks=output_tracks,
746  )
747 
748  # Export CDCTracks to RecoTracks representation
749  path.add_module("TFCDC_TrackExporter",
750  inputTracks=output_tracks,
751  RecoTracksStoreArrayName=output_reco_tracks)
752 
753  # run fast t0 estimation from CDC hits only
754  path.add_module("CDCHitBasedT0Extraction")
755 
756 
757 def add_vxd_track_finding_vxdtf2(
758  path,
759  svd_clusters="",
760  reco_tracks="RecoTracks",
761  components=None,
762  suffix="",
763  useTwoStepSelection=True,
764  PXDminSVDSPs=3,
765  sectormap_file=None,
766  custom_setup_name=None,
767  min_SPTC_quality=0.,
768  filter_overlapping=True,
769  add_mva_quality_indicator=False,
770 ):
771  """
772  Convenience function for adding all vxd track finder Version 2 modules
773  to the path.
774 
775  The result is a StoreArray with name @param reco_tracks full of RecoTracks (not TrackCands any more!).
776  Use the GenfitTrackCandidatesCreator Module to convert back.
777 
778  :param path: basf2 path
779  :param svd_clusters: SVDCluster collection name
780  :param reco_tracks: Name of the output RecoTracks, Defaults to RecoTracks.
781  :param components: List of the detector components to be used in the reconstruction. Defaults to None which means
782  all components.
783  :param suffix: all names of intermediate Storearrays will have the suffix appended. Useful in cases someone needs to
784  put several instances of track finding in one path.
785  :param useTwoStepSelection: if True Families will be defined during path creation and will be used to create only
786  the best candidate per family.
787  :param PXDminSVDSPs: When using PXD require at least this number of SVD SPs for the SPTCs
788  :param sectormap_file: if set to a finite value, a file will be used instead of the sectormap in the database.
789  :param custom_setup_name: Set a custom setup name for the tree in the sector map.
790  :param min_SPTC_quality: minimal qualityIndicator value to keeps SPTCs after the QualityEstimation.
791  0 means no cut. Default: 0
792  :param filter_overlapping: Whether to use SVDOverlapResolver, Default: True
793  :param add_mva_quality_indicator: Whether to use the MVA Quality Estimator module for VXDTF2 tracks to set the
794  quality_indicator property of the found ``reco_tracks``. Default: False.
795  """
796 
799 
800  # setting different for pxd and svd:
801  if is_pxd_used(components):
802  setup_name = "SVDPXDDefault"
803  db_sec_map_file = "VXDSectorMap_v000.root"
804  use_pxd = True
805  else:
806  setup_name = "SVDOnlyDefault"
807  db_sec_map_file = "SVDSectorMap_v000.root"
808  use_pxd = False
809 
810 
814 
815  # setup the event level tracking info to log errors and stuff
816  nameTrackingInfoModule = "RegisterEventLevelTrackingInfo" + suffix
817  nameEventTrackingInfo = "EventLevelTrackingInfo" + suffix
818  if nameTrackingInfoModule not in path:
819  # Use modified name of module and created StoreObj as module might be added twice (PXDDataReduction)
820  registerEventlevelTrackingInfo = register_module('RegisterEventLevelTrackingInfo')
821  registerEventlevelTrackingInfo.set_name(nameTrackingInfoModule)
822  registerEventlevelTrackingInfo.param('EventLevelTrackingInfoName', nameEventTrackingInfo)
823  path.add_module(registerEventlevelTrackingInfo)
824 
825  nameSPs = 'SpacePoints' + suffix
826 
827  pxdSPCreatorName = 'PXDSpacePointCreator' + suffix
828  if pxdSPCreatorName not in [e.name() for e in path.modules()]:
829  if use_pxd:
830  spCreatorPXD = register_module('PXDSpacePointCreator')
831  spCreatorPXD.set_name(pxdSPCreatorName)
832  spCreatorPXD.param('NameOfInstance', 'PXDSpacePoints')
833  spCreatorPXD.param('SpacePoints', "PXD" + nameSPs)
834  path.add_module(spCreatorPXD)
835 
836  # SecMap Bootstrap
837  secMapBootStrap = register_module('SectorMapBootstrap')
838  secMapBootStrap.param('ReadSectorMap', sectormap_file is not None) # read from file
839  secMapBootStrap.param('ReadSecMapFromDB', sectormap_file is None) # this will override ReadSectorMap
840  secMapBootStrap.param('SectorMapsInputFile', sectormap_file or db_sec_map_file)
841  secMapBootStrap.param('SetupToRead', custom_setup_name or setup_name)
842  secMapBootStrap.param('WriteSectorMap', False)
843  path.add_module(secMapBootStrap)
844 
845 
849 
850  spacePointArrayNames = ["SVD" + nameSPs]
851  if use_pxd:
852  spacePointArrayNames += ["PXD" + nameSPs]
853 
854  nameSegNet = 'SegmentNetwork' + suffix
855 
856  segNetProducer = register_module('SegmentNetworkProducer')
857  segNetProducer.param('NetworkOutputName', nameSegNet)
858  segNetProducer.param('SpacePointsArrayNames', spacePointArrayNames)
859  segNetProducer.param('sectorMapName', custom_setup_name or setup_name)
860  segNetProducer.param('EventLevelTrackingInfoName', nameEventTrackingInfo)
861  path.add_module(segNetProducer)
862 
863 
867 
868  # append a suffix to the storearray name
869  nameSPTCs = 'SPTrackCands' + suffix
870 
871  trackFinder = register_module('TrackFinderVXDCellOMat')
872  trackFinder.param('NetworkName', nameSegNet)
873  trackFinder.param('SpacePointTrackCandArrayName', nameSPTCs)
874  trackFinder.param('printNetworks', False)
875  trackFinder.param('setFamilies', useTwoStepSelection)
876  trackFinder.param('selectBestPerFamily', useTwoStepSelection)
877  trackFinder.param('xBestPerFamily', 30)
878  trackFinder.param('EventLevelTrackingInfoName', nameEventTrackingInfo)
879  path.add_module(trackFinder)
880 
881  if useTwoStepSelection:
882  subSetModule = register_module('AddVXDTrackCandidateSubSets')
883  subSetModule.param('NameSpacePointTrackCands', nameSPTCs)
884  path.add_module(subSetModule)
885 
886 
890 
891  # When using PXD require at least PXDminSVDSPs SVD SPs for the SPTCs
892  if use_pxd:
893  pxdSVDCut = register_module('PXDSVDCut')
894  pxdSVDCut.param('minSVDSPs', PXDminSVDSPs)
895  pxdSVDCut.param('SpacePointTrackCandsStoreArrayName', nameSPTCs)
896  path.add_module(pxdSVDCut)
897 
898  if add_mva_quality_indicator:
899  path.add_module(
900  "VXDQualityEstimatorMVA",
901  SpacePointTrackCandsStoreArrayName=nameSPTCs,
902  )
903  else:
904  path.add_module(
905  'QualityEstimatorVXD',
906  EstimationMethod='tripletFit',
907  SpacePointTrackCandsStoreArrayName=nameSPTCs,
908  )
909 
910  if min_SPTC_quality > 0.:
911  qualityIndicatorCutter = register_module('VXDTrackCandidatesQualityIndicatorCutter')
912  qualityIndicatorCutter.param('minRequiredQuality', min_SPTC_quality)
913  qualityIndicatorCutter.param('NameSpacePointTrackCands', nameSPTCs)
914  path.add_module(qualityIndicatorCutter)
915 
916  # will discard track candidates (with low quality estimators) if the number of TC is above threshold
917  maxCandidateSelection = register_module('BestVXDTrackCandidatesSelector')
918  maxCandidateSelection.param('NameSpacePointTrackCands', nameSPTCs)
919  maxCandidateSelection.param('NewNameSpacePointTrackCands', nameSPTCs)
920  maxCandidateSelection.param('SubsetCreation', False)
921  path.add_module(maxCandidateSelection)
922 
923  # Properties
924  vIPRemover = register_module('SPTCvirtualIPRemover')
925  vIPRemover.param('tcArrayName', nameSPTCs)
926  # want to remove virtualIP for any track length
927  vIPRemover.param('maxTCLengthForVIPKeeping', 0)
928  path.add_module(vIPRemover)
929 
930 
934 
935  if filter_overlapping:
936  overlapResolver = register_module('SVDOverlapResolver')
937  overlapResolver.param('NameSpacePointTrackCands', nameSPTCs)
938  overlapResolver.param('ResolveMethod', 'greedy') # other option is 'hopfield'
939  overlapResolver.param('NameSVDClusters', svd_clusters)
940  path.add_module(overlapResolver)
941 
942 
946 
947  momSeedRetriever = register_module('SPTCmomentumSeedRetriever')
948  momSeedRetriever.param('tcArrayName', nameSPTCs)
949  path.add_module(momSeedRetriever)
950 
951  converter = register_module('SPTC2RTConverter')
952  converter.param('recoTracksStoreArrayName', reco_tracks)
953  converter.param('spacePointsTCsStoreArrayName', nameSPTCs)
954  converter.param('svdClustersName', svd_clusters)
955  converter.param('svdHitsStoreArrayName', svd_clusters)
956  path.add_module(converter)
957 
958 
959 def is_svd_used(components):
960  """Return true, if the SVD is present in the components list"""
961  return components is None or 'SVD' in components
962 
963 
964 def is_pxd_used(components):
965  """Return true, if the PXD is present in the components list"""
966  return components is None or 'PXD' in components
967 
968 
969 def is_cdc_used(components):
970  """Return true, if the CDC is present in the components list"""
971  return components is None or 'CDC' in components
972 
973 
974 def is_ecl_used(components):
975  """Return true, if the ECL is present in the components list"""
976  return components is None or 'ECL' in components
tracking.adjustments
Definition: adjustments.py:1
ckf.path_functions
Definition: path_functions.py:1
cr