Belle II Software  release-08-01-10
utilities.py
1 
8 
9 import basf2 # Import basf2 to make the Belle2 namespace available # noqa
10 import ROOT
11 from ROOT import Belle2
12 
13 import numpy as np
14 import math
15 
16 # Vectorised version of the error function for numpy arrays
17 try:
18  from scipy.special import erf
19 except ImportError:
20  # Minimal workaround that only relies on numpy and python 2.7
21  # erf as a vectorized function
22  # Will convert the incoming nparray to dtype 'object', if nan
23  # values are contained
24  # use numpy.asfarray(...) to convert back
25  erf_ufunc = np.frompyfunc(math.erf, 1, 1)
26 
27  def erf(*args):
28  result = erf_ufunc(*args)
29  return np.asfarray(result)
30 
31 
32 # Vectorised version of the Prob function as known from TMath for numpy arrays
33 
34 # Minimal workaround that only relies on numpy and python 2.7
35 # prob as a vectorized function
36 prob = np.frompyfunc(ROOT.TMath.Prob, 2, 1)
37 
38 
39 def is_primary(mc_particle):
40  """Indicates if the given MCParticle is primary.
41 
42  Parameters
43  ----------
44  mc_particle : Belle2.MCParticle
45  MCParticle to be checked"""
46 
47  return mc_particle.hasStatus(Belle2.MCParticle.c_PrimaryParticle)
48 
49 
50 def is_stable_in_generator(mc_particle):
51  """Indicates if the given MCParticle is stable in the generator
52 
53  Parameters
54  ----------
55  mc_particle : Belle2.MCParticle
56  MCParticle to be checked"""
57 
58  return mc_particle.hasStatus(Belle2.MCParticle.c_StableInGenerator)
59 
60 
61 def getObjectList(pointerVec):
62  """ This is a temporary work-around for the new externals v01-10-00
63  A direct iteration on a vector of pointers creates significant memory leak
64  This can be avoid by a range based loop
65 
66  Parameters
67  ----------
68  pointerVec : pointerVec
69  A vector of pointers
70  """
71  objList = []
72  for i in range(len(pointerVec)):
73  objList.append(pointerVec[i])
74  return objList
75 
76 
77 def get_det_hit_ids(reco_track, det_ids=[Belle2.Const.PXD, Belle2.Const.SVD, Belle2.Const.CDC]):
78  """Retrieves the hit ids contained in the track for the given detector ids
79 
80  Parameters
81  ----------
82  reco_track : RecoTrack
83  Track
84  det_ids : list(int)
85  List of the detector ids for which the hit ids should be retrieved
86 
87  Returns
88  -------
89  set( (int, int) )
90  A set of pairs like (det_id, hit_id) representing the hit content of the track
91  """
92  det_hit_ids = set()
93  for det_id in det_ids:
94  if det_id == Belle2.Const.CDC:
95  hits = getObjectList(reco_track.getCDCHitList())
96  elif det_id == Belle2.Const.SVD:
97  hits = getObjectList(reco_track.getSVDHitList())
98  elif det_id == Belle2.Const.PXD:
99  hits = getObjectList(reco_track.getPXDHitList())
100  else:
101  raise ValueError("DET ID not known.")
102 
103  # Working around a bug in ROOT where you should not access empty std::vectors
104  if len(hits) != 0:
105  det_hit_ids |= set((det_id, hit.getArrayIndex()) for hit in hits)
106 
107  return det_hit_ids
108 
109 
110 def calc_ndf_from_det_hit_ids(det_hit_ids,
111  ndf_by_det_id={Belle2.Const.PXD: 2,
112  Belle2.Const.SVD: 1,
113  Belle2.Const.CDC: 1}):
114  """For a set of detector and hit ids calculate the total number of degrees of freedom
115 
116  Parameters
117  ----------
118  det_hit_ids : set( (int, int) )
119  A set of pairs like (det_id, hit_id) representing the hit content of a track
120  ndf_by_det_ids : dict(int=int)
121  A map from detector ids to the number of degrees of freedom one hit in this detector represents.
122 
123  Returns
124  -------
125  int
126  Total number of degrees of freedom represented by the hit set
127  """
128  return sum(ndf_by_det_id[det_id] for det_id, hit_id in det_hit_ids)
129 
130 
131 def calc_hit_efficiency(det_hit_ids,
132  mc_det_hit_ids,
133  ndf_by_det_id={Belle2.Const.PXD: 2,
134  Belle2.Const.SVD: 1,
135  Belle2.Const.CDC: 1}):
136  """Calculates the fraction of detector and hits ids in a reference (MC) set that are also
137  present in a reconstructed (PR) set.
138 
139  The ratio is given in terms of degrees of freedom the hits represent
140 
141  Parameters
142  ----------
143  det_hit_ids : set( (int, int) )
144  A set of pairs like (det_id, hit_id) representing the hit content of a reconstructed (PR) track
145  mc_det_hit_ids : set( (int, int) )
146  A set of pairs like (det_id, hit_id) representing the hit content of a reference (MC) track
147  ndf_by_det_ids : dict(int=int)
148  A map from detector ids to the number of degrees of freedom one hit in this detector represents.
149 
150  Returns
151  -------
152  float
153  Fraction of hits in the reference (MC) track that are also present in the reconstructed (PR) track
154  in terms of number of degrees of freedom.
155  """
156  common_det_hit_ids = det_hit_ids & mc_det_hit_ids
157  return np.divide(1.0 * calc_ndf_from_det_hit_ids(common_det_hit_ids),
158  calc_ndf_from_det_hit_ids(mc_det_hit_ids))
159 
160 
161 def getHelixFromMCParticle(mc_particle):
162  position = mc_particle.getVertex()
163  momentum = mc_particle.getMomentum()
164  charge_sign = (-1 if mc_particle.getCharge() < 0 else 1)
165  b_field = Belle2.BFieldManager.getField(position).Z() / Belle2.Unit.T
166 
167  seed_helix = Belle2.Helix(position, momentum, charge_sign, b_field)
168  return seed_helix
169 
170 
171 def getSeedTrackFitResult(reco_track):
172  position = reco_track.getPositionSeed()
173  momentum = reco_track.getMomentumSeed()
174  cartesian_covariance = reco_track.getSeedCovariance()
175  charge_sign = (-1 if reco_track.getChargeSeed() < 0 else 1)
176  # It does not matter, which particle we put in here, so we just use a pion
177  particle_type = Belle2.Const.pion
178  p_value = float('nan')
179  b_field = Belle2.BFieldManager.getField(ROOT.Math.XYZVector(position)).Z() / Belle2.Unit.T
180  cdc_hit_pattern = 0
181  svd_hit_pattern = 0
182  # the value 0xFFFF will cause the TrackFitResult::getNDF() to return -1
183  ndf = 0xFFFF
184 
185  track_fit_result = Belle2.TrackFitResult(
186  position,
187  momentum,
188  cartesian_covariance,
189  charge_sign,
190  particle_type,
191  p_value,
192  b_field,
193  cdc_hit_pattern,
194  svd_hit_pattern,
195  ndf
196  )
197 
198  return track_fit_result
Helix parameter class.
Definition: Helix.h:48
Values of the result of a track fit with a given particle hypothesis.
static void getField(const double *pos, double *field)
return the magnetic field at a given position.
Definition: BFieldManager.h:91