Belle II Software development
utilities.py
1
8
9import basf2 # Import basf2 to make the Belle2 namespace available # noqa
10import ROOT
11from ROOT import Belle2
12
13import numpy as np
14import math
15
16# Vectorised version of the error function for numpy arrays
17try:
18 from scipy.special import erf
19except 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
36prob = np.frompyfunc(ROOT.TMath.Prob, 2, 1)
37
38
39def 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
50def 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
61def 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
77def 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 |= {(det_id, hit.getArrayIndex()) for hit in hits}
106
107 return det_hit_ids
108
109
110def 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
131def 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
161def 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
171def 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
A Class to store the Monte Carlo particle information.
Definition: MCParticle.h:32
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