Belle II Software  release-06-01-15
ThreeHitFilters.h
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 #pragma once
10 
11 #include <TVector3.h>
12 #include "tracking/vxdCaTracking/TwoHitFilters.h"
13 #include "tracking/vxdCaTracking/FilterExceptions.h"
14 #include <framework/logging/Logger.h>
15 
16 namespace Belle2 {
24  public:
25 
29  m_radiusCalculated(false),
30  m_radius(0.),
31  m_x2(0.),
32  m_y2(0.),
33  m_z2(0.)
34  {
35  m_hitA.SetXYZ(0., 0., 0.);
36  m_hitB.SetXYZ(0., 0., 0.);
37  m_hitC.SetXYZ(0., 0., 0.);
38  m_vecAB.SetXYZ(0., 0., 0.);
39  m_vecBC.SetXYZ(0., 0., 0.);
40  resetMagneticField(1.5);
41  }
42 
44  ThreeHitFilters(const TVector3& outerHit, const TVector3& centerHit, const TVector3& innerHit,
45  const double magneticFieldStrength = 1.5):
47  m_radiusCalculated(false),
48  m_radius(0.),
49  m_hitA(outerHit),
50  m_hitB(centerHit),
51  m_hitC(innerHit),
52  m_vecAB(outerHit - centerHit),
53  m_vecBC(centerHit - innerHit)
54  {
55  m_x2 = m_vecAB[0] * m_vecBC[0];
56  m_y2 = m_vecAB[1] * m_vecBC[1];
57  m_z2 = m_vecAB[2] * m_vecBC[2];
58  resetMagneticField(magneticFieldStrength);
59  }
60 
61 
64 
66  void resetValues(const TVector3& outerHit, const TVector3& centerHit, const TVector3& innerHit)
67  {
68  m_radiusCalculated = false;
70  m_radius = 0.;
71  m_hitA = outerHit;
72  m_hitB = centerHit;
73  m_hitC = innerHit;
74  m_vecAB = outerHit - centerHit;
75  m_vecBC = centerHit - innerHit;
76 
77  m_x2 = m_vecAB[0] * m_vecBC[0];
78  m_y2 = m_vecAB[1] * m_vecBC[1];
79  m_z2 = m_vecAB[2] * m_vecBC[2];
80  }
81 
82 
83 
89  void resetMagneticField(const double magneticFieldStrength = 1.5) { m_magneticFieldFactor = magneticFieldStrength * 0.00299710; }
90 
91 
92 
94  double getMagneticField() { return m_magneticFieldFactor / 0.00299710; }
95 
96 
97 
99  double filterNan(double value) { return m_twoHitFilter.filterNan(value); }
100 
101 
102 
104  double calcAngle3D()
105  {
106  double angle = ((m_x2 + m_y2 + m_z2) / (m_vecAB.Mag2() *
107  m_vecBC.Mag2())); // fullCalc would be acos(m_vecAB.Dot(m_vecBC) / m_vecAB.Mag()*m_vecBC.Mag())
108  return filterNan(angle);
109  } // return unit: none (calculation for degrees is incomplete, if you want readable numbers, use fullAngle3D instead)
110 
111 
112 
114  double fullAngle3D()
115  {
116  double angle = acos(m_vecAB.Dot(m_vecBC) / (m_vecAB.Mag() * m_vecBC.Mag())); // 0-pi
117  angle = (angle * (180. / M_PI));
118  return filterNan(angle);
119  } // return unit: ° (0 - 180°)
120 
121 
122 
124  double calcAngleXY()
125  {
126  double angle = ((m_x2 + m_y2) / (m_vecAB.Perp2() * m_vecBC.Perp2())); // fullAngle:
127  return filterNan(angle);
128  } // return unit: none (calculation for degrees is incomplete, if you want readable numbers, use fullAngleXY instead)
129 
130 
131 
133  double fullAngleXY()
134  {
135  double angle = fullAngle2D(m_vecAB, m_vecBC); // 0-pi
136  angle = (angle * (180. / M_PI));
137  return filterNan(angle);
138  } // return unit: ° (0 - 180°)
139 
140 
141 
143  double calcAngleRZ()
144  {
145  TVector3 rzVecAB(m_vecAB.Perp(), m_vecAB[2], 0.);
146  TVector3 rzVecBC(m_vecBC.Perp(), m_vecBC[2], 0.);
147  return calcAngle2D(rzVecAB, rzVecBC);
148  } // return unit: none (calculation for degrees is incomplete, if you want readable numbers, use fullAngleRZ instead)
149 
150 
151 
153  double fullAngleRZ()
154  {
155  TVector3 rzVecAB(m_vecAB.Perp(), m_vecAB[2], 0.);
156  TVector3 rzVecBC(m_vecBC.Perp(), m_vecBC[2], 0.);
157  double angle = fullAngle2D(rzVecAB, rzVecBC); // 0-pi
158  angle = (angle * (180. / M_PI));
159  return filterNan(angle);
160  } // return unit: ° (0 - 180°)
161 
162 
163 
166  {
167  checkCalcRadius();
168 
169  return (fabs(m_centerABC.Perp() - m_radius)); // distance of closest approach of circle to the IP
170  } // return unit: cm
171 
172 
173 
175  double calcPt()
176  {
177  checkCalcRadius();
178 
179  return calcPt(m_radius);
180  } // return unit: GeV/c
181 
182 
183 
185  double calcPt(double radius)
186  {
187  sanityCheckRadius(radius);
188 
189  return (m_magneticFieldFactor * radius);
190  } // return unit: GeV/c
191 
192 
193 
196  {
198  double slopeAB = m_twoHitFilter.calcSlopeRZ();
200  double slopeBC = m_twoHitFilter.calcSlopeRZ();
201 
202  return filterNan(slopeBC - slopeAB);
203  } // return unit: none
204 
205 
206 
212  {
214 
215  TVector3 points2hitA = m_hitA - m_centerABC;
216  TVector3 points2hitB = m_hitB - m_centerABC;
217  TVector3 points2hitC = m_hitC - m_centerABC;
218  double alfaAB = fullAngle2D(points2hitA, points2hitB);
219  double alfaBC = fullAngle2D(points2hitB, points2hitC);
220  //return filterNan( (alfaAB * m_vecBC[2]) - (alfaBC *m_vecAB[2]) );
221  return (alfaAB * m_vecBC[2]) - (alfaBC *
222  m_vecAB[2]); // equals to alfaAB/dZAB and alfaBC/dZBC, but this solution here can not produce a division by zero
223  } // return unit: radians*cm
224 
225 
226 
229  {
230  checkCalcRadius();
231 
232  TVector3 points2hitA = m_hitA - m_centerABC;
233  TVector3 points2hitB = m_hitB - m_centerABC;
234  TVector3 points2hitC = m_hitC - m_centerABC;
235  double alfaABr = fullAngle2D(points2hitA, points2hitB) * m_radius;
236  double alfaBCr = fullAngle2D(points2hitB, points2hitC) * m_radius;
237 
238  return filterNan((asin(m_vecAB[2] / alfaABr)) - asin(m_vecBC[2] / alfaBCr)); // Beware of z>r!
239  }
240 
241 
242 
245  {
247  TVector3 points2hitA = m_hitA - m_centerABC;
248  TVector3 points2hitB = m_hitB - m_centerABC;
249  TVector3 points2hitC = m_hitC - m_centerABC;
250  double alfaAB = calcAngle2D(points2hitA, points2hitB);
251  double alfaBC = calcAngle2D(points2hitB, points2hitC);
252  // real calculation: ratio is (m_vecij[2] = deltaZ): alfaAB/deltaZab : alfaBC/deltaZbc, the following equation saves two times '/'
253  return filterNan((alfaAB * m_vecBC[2]) / (alfaBC * m_vecAB[2]));
254  } // return unit: none
255 
256 
257 
259  double calcHelixFit() { return calcHelixParameterFit(); }
260 
261 
262 
264  double calcAngle2D(const TVector3& vecA, const TVector3& vecB)
265  {
266  double angle = ((vecA[0] * vecB[0] + vecA[1] * vecB[1]) / sqrt(vecA.Perp2() * vecB.Perp2()));
267  return filterNan(angle);
268  }
269 
273  double fullAngle2D(const TVector3& vecA, const TVector3& vecB)
274  {
275  return acos(calcAngle2D(vecA, vecB));
276  //return filterNan(angle);
277  }
278 
279 
280 
282  double calcRadius(const TVector3& a, const TVector3& b, const TVector3& c, const TVector3& circleCenter)
283  {
284  return ((circleCenter - a).Perp() + (circleCenter - b).Perp() + (circleCenter - c).Perp()) /
285  3.; // = radius in [cm], sign here not needed. normally: signKappaAB/normAB1
286  } // used by calcPt() and calcCircleDist2IP()
287 
288 
289 
291  void calcCircleCenter(const TVector3& a, const TVector3& b, const TVector3& c, TVector3& circleCenter)
292  {
293  // calculates the intersection point using Cramer's rule.
294  // x_1+s*n_1==x_2+t*n_2 --> n_1 *s - n_2 *t == x_2 - x_1 --> http://en.wikipedia.org/wiki/Cramer%27s_rule
295  double inX = b[0] - c[0]; // x value of the normal vector of the inner segment (b-c)
296  double inY = b[1] - c[1]; // y value of the normal vector of the inner segment (b-c)
297  double outX = a[0] - b[0]; // x value of the normal vector of the outer segment (a-b)
298  double outY = a[1] - b[1]; // y value of the normal vector of the outer segment (a-b)
299 
300  //searching solution for Ax = b, aij are the matrix elements of A, bi are elements of b
301  double a11 = inY;
302  double a12 = -inX;
303  double a21 = -outY;
304  double a22 = outX;
305  double b1 = b[0] + outX * 0.5 - (c[0] + inX * 0.5);
306  double b2 = b[1] + outY * 0.5 - (c[1] + inY * 0.5);
307 
308  if (a11 * a22 == a12 * a21) { throw FilterExceptions::Straight_Line(); }
309 
310  double s = (b1 * a22 - b2 * a21) / (a11 * a22 - a12 * a21); //the determinant is zero iff the three hits are on a line in (x,y).
311 
312  circleCenter.SetXYZ(c[0] + inX * 0.5 + s * inY, c[1] + inY * 0.5 - s * inX, 0.);
313  }
314 
315 
316 
318  int calcSign(const TVector3& a, const TVector3& b, const TVector3& c);
319 
320 
321 
323  int calcSign(const TVector3& a, const TVector3& b, const TVector3& c, const TVector3& sigma_a, const TVector3& sigma_b,
324  const TVector3& sigma_c)
325  {
326  TVector3 c2b = b - c; c2b.SetZ(0.);
327  TVector3 b2a = a - b; b2a.SetZ(0.);
328  double angle = atan2(b2a[0], b2a[1]) - atan2(c2b[0], c2b[1]);
329  double sigmaan = (sigma_a.Mag() + sigma_b.Mag() + sigma_c.Mag()) / (3.*(c2b.Mag() +
330  b2a.Mag())); //TODO 1/3...mean of the sigmas. Possible improvement: Use a parameter instead, and determine with simulated events.
331  if (angle < (-sigmaan)) { return -1; }
332  else if (angle > sigmaan) {return 1; }
333  else { return 0; }
334  }
335 
336 
337 
338  protected:
339 
340 
343  {
344  if (m_circleCenterCalculated == false) {
347  }
348  }
349 
350 
353  {
355  if (m_radiusCalculated == false) {
358  m_radiusCalculated = true;
359  }
360  }
361 
362 
364  void sanityCheckRadius(double radius)
365  {
366  if (fabs(radius) <
367  0.0000001) { // WARNING hardcoded value, is there a quasi-global value for such cases (this case, minimal accepted radius)
368  m_radiusCalculated = false;
369  m_circleCenterCalculated = false;
370  m_radius = 0.;
371  B2ERROR("sanityCheckRadius: given radius is " << radius << ", which is below threshold of " << 0.0000001 << ", throwing exception");
372  throw FilterExceptions::Circle_too_small();
373  }
374  }
375 
376 
377 
382  double m_radius;
383  double m_x2;
384  double m_y2;
385  double m_z2;
387  TVector3 m_centerABC;
388  TVector3 m_hitA;
389  TVector3 m_hitB;
390  TVector3 m_hitC;
391  TVector3 m_vecAB;
392  TVector3 m_vecBC;
394  }; //end class ThreeHitFilters
396 } //end namespace Belle2
The class 'ThreeHitFilters' bundles filter methods using 3 hits which are stored in TVector3s.
~ThreeHitFilters()
Destructor.
double calcAngle3D()
calculates the angle between the hits/vectors (3D), returning unit: none (calculation for degrees is ...
int calcSign(const TVector3 &a, const TVector3 &b, const TVector3 &c, const TVector3 &sigma_a, const TVector3 &sigma_b, const TVector3 &sigma_c)
calculates calculates the sign of the curvature of given 3-hit-tracklet.
double calcDeltaSOverZ()
calculates the helixparameter describing the deviation in arc length per unit in z.
double fullAngle3D()
calculates the angle between the hits/vectors (3D), returning unit: angle in degrees
bool m_circleCenterCalculated
initially set to false, will be set true if calcCircleCenter() is used at least once
double m_radius
radius[cm] of a circle in r-phi-plane formed by the 3 hits
double calcPt()
calculates the estimation of the transverse momentum of the 3-hit-tracklet, returning unit: GeV/c
double calcHelixFit()
reverse compatibility, calls calcHelixParameterFit
double fullAngleRZ()
calculates the angle between the hits/vectors (RZ), returning unit: angle in degrees
double m_x2
internal intermediate value storing x^2, no enduser-relevance
TVector3 m_hitC
inner hit (position relevant for useful filter calculation) used for the filter calculation
bool m_radiusCalculated
initially set to false, will be set true if calcInvCurvature() is used at least once
double calcRadius(const TVector3 &a, const TVector3 &b, const TVector3 &c, const TVector3 &circleCenter)
calculates an estimation of the radius of given hits and existing estimation of circleCenter,...
void checkCalcCircleCenter()
checks whether the calcCircleCenter()-Member has been executed already and executes it if not
double filterNan(double value)
returns zero if value is nan or inf
double calcDeltaSlopeRZ()
calculates deviations in the slope of the inner segment and the outer segment, returning unit: none
TVector3 m_vecBC
vector pointing from inner hit to center hit (inner segment)
double fullAngle2D(const TVector3 &vecA, const TVector3 &vecB)
calculates the angle between the hits/vectors (2D), generalized, returning unit: angle in radians WAR...
double getMagneticField()
returns the set value of the magnetic field in Tesla
double m_y2
internal intermediate value storing y^2, no enduser-relevance
double calcAngleRZ()
calculates the angle between the hits/vectors (RZ), returning unit: none (calculation for degrees is ...
double fullAngleXY()
calculates the angle between the hits/vectors (XY), returning unit: angle in degrees
void sanityCheckRadius(double radius)
check Radius for bad values and throw exception if the value is bad
double calcDeltaSlopeZOverS()
compares the "slopes" z over arc length.
void calcCircleCenter(const TVector3 &a, const TVector3 &b, const TVector3 &c, TVector3 &circleCenter)
calculates an estimation of circleCenter position, result is written into the 4th input-parameter
void resetValues(const TVector3 &outerHit, const TVector3 &centerHit, const TVector3 &innerHit)
Overrides Constructor-Setup.
double calcCircleDist2IP()
calculates the distance of the point of closest approach of circle to the IP, returning unit: cm
ThreeHitFilters(const TVector3 &outerHit, const TVector3 &centerHit, const TVector3 &innerHit, const double magneticFieldStrength=1.5)
Constructor.
void resetMagneticField(const double magneticFieldStrength=1.5)
Overrides Constructor-Setup for magnetic field.
TVector3 m_vecAB
vector pointing from center hit to outer hit (outer segment)
double m_z2
internal intermediate value storing z^2, no enduser-relevance
double calcPt(double radius)
calculates the estimation of the transverse momentum of given radius using defined strength of magnet...
double calcAngle2D(const TVector3 &vecA, const TVector3 &vecB)
calculates the angle between the hits/vectors (2D), generalized, returning unit: none.
TwoHitFilters m_twoHitFilter
instance of TwoHitFilters-class used for some internal calculations
double calcHelixParameterFit()
calculates the helixparameter describing the deviation in z per unit angle, returning unit: none
void checkCalcRadius()
checks whether the calcRadius()-Member has been executed already and executes it if not
double m_magneticFieldFactor
is factor containing speed of light (c), the magnetic field (b) and the scaling factor s for conversi...
double calcAngleXY()
calculates the angle between the hits/vectors (XY), returning unit: none (calculation for degrees is ...
int calcSign(const TVector3 &a, const TVector3 &b, const TVector3 &c)
calculates calculates the sign of the curvature of given 3-hit-tracklet.
TVector3 m_hitA
outer hit (position relevant for useful filter calculation) used for the filter calculation
TVector3 m_centerABC
center position of a circle in r-phi-plane formed by the 3 hits
TVector3 m_hitB
center hit (position relevant for useful filter calculation) used for the filter calculation
ThreeHitFilters()
Empty constructor.
The class 'TwoHitFilters' bundles filter methods using 2 hits which are stored in TVector3s.
Definition: TwoHitFilters.h:22
void resetValues(const TVector3 &outerHit, const TVector3 &innerHit)
Overrides Constructor-Setup.
Definition: TwoHitFilters.h:46
double filterNan(double value) const
nice little nanChecker returns 0 if value was nan or inf, else returns value itself
double calcSlopeRZ() const
calculates the angle of the slope of the hits in RZ, returnValue = theta = atan(r/z)
Definition: TwoHitFilters.h:70
Abstract base class for different kinds of events.