Belle II Software  release-08-01-10
KarimakisMethod.cc
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 #include <tracking/trackFindingCDC/fitting/KarimakisMethod.h>
9 
10 #include <tracking/trackFindingCDC/fitting/EigenObservationMatrix.h>
11 #include <tracking/trackFindingCDC/fitting/CDCObservations2D.h>
12 
13 #include <tracking/trackFindingCDC/eventdata/trajectories/CDCTrajectory2D.h>
14 
15 #include <tracking/trackFindingCDC/geometry/UncertainPerigeeCircle.h>
16 #include <tracking/trackFindingCDC/geometry/PerigeeParameters.h>
17 #include <tracking/trackFindingCDC/geometry/Vector2D.h>
18 
19 #include <Eigen/Core>
20 
21 using namespace Belle2;
22 using namespace TrackFindingCDC;
23 
25  : m_lineConstrained(false)
26 {
27 }
28 
30  CDCObservations2D& observations2D) const
31 {
32  size_t nObservations = observations2D.size();
33  trajectory2D.clear();
34  if (not nObservations) return;
35 
36  Vector2D ref = observations2D.getCentralPoint();
37  observations2D.passiveMoveBy(ref);
38 
39  UncertainPerigeeCircle perigeeCircle = fitInternal(observations2D);
40 
41  double frontX = observations2D.getX(0);
42  double frontY = observations2D.getY(0);
43  Vector2D frontPos(frontX, frontY);
44 
45  double backX = observations2D.getX(nObservations - 1);
46  double backY = observations2D.getY(nObservations - 1);
47  Vector2D backPos(backX, backY);
48 
49  Vector2D overPos(0, 0);
50  double totalPerps = (perigeeCircle->arcLengthBetween(frontPos, overPos) +
51  perigeeCircle->arcLengthBetween(overPos, backPos));
52 
53  if (totalPerps < 0) {
54  perigeeCircle.reverse();
55  }
56 
57  trajectory2D.setLocalOrigin(ref);
58  trajectory2D.setLocalCircle(perigeeCircle);
59 }
60 
61 
62 
63 
64 namespace {
66  constexpr size_t iW = 0;
67  constexpr size_t iX = 1;
68  constexpr size_t iY = 2;
69  constexpr size_t iR2 = 3;
70 
72  UncertainPerigeeCircle fitKarimaki(const double /*sw*/,
73  const Eigen::Matrix< double, 4, 1 >& a,
74  const Eigen::Matrix< double, 4, 4 >& c,
75  bool lineConstrained = false)
76  {
77  double q1, q2 = 0.0;
78  if (lineConstrained) {
79  q1 = c(iX, iY);
80  q2 = c(iX, iX) - c(iY, iY);
81  } else {
82  q1 = c(iX, iY) * c(iR2, iR2) - c(iX, iR2) * c(iY, iR2);
83  q2 = (c(iX, iX) - c(iY, iY)) * c(iR2, iR2) - c(iX, iR2) * c(iX, iR2) + c(iY, iR2) * c(iY, iR2);
84  }
85 
86  double phi = 0.5 * atan2(2. * q1, q2);
87 
88  double sinphi = sin(phi);
89  double cosphi = cos(phi);
90 
91  double curv, I = 0.0;
92  if (lineConstrained) {
93  curv = 0.0; //line
94  I = sinphi * a(iX) - cosphi * a(iY);
95 
96  } else {
97  double kappa = (sinphi * c(iX, iR2) - cosphi * c(iY, iR2)) / c(iR2, iR2);
98  double delta = -kappa * a(iR2) + sinphi * a(iX) - cosphi * a(iY);
99  curv = 2. * kappa / sqrt(1. - 4. * delta * kappa);
100  I = 2. * delta / (1. + sqrt(1. - 4. * delta * kappa));
101 
102  }
103 
104  // Karimaki uses the opposite sign for phi in contrast to the convention of this framework !!!
105  phi += phi > 0 ? -M_PI : M_PI;
106  return UncertainPerigeeCircle(curv, phi, I);
107 
108  }
109 
110 
111 
112 
113 
115  double calcChi2Karimaki(const PerigeeCircle& parameters,
116  const double sw,
117  const Eigen::Matrix< double, 4, 4 >& c,
118  bool lineConstrained = false)
119  {
120  // Karimaki uses the opposite sign for phi in contrast to the convention of this framework !!!
121  const Vector2D vecPhi = -parameters.tangential();
122 
123  const double cosphi = vecPhi.x();
124  const double sinphi = vecPhi.y();
125 
126  if (lineConstrained) {
127  double chi2 = sw * (sinphi * sinphi * c(iX, iX) - 2. * sinphi * cosphi * c(iX, iY) + cosphi * cosphi * c(iY, iY));
128  return chi2;
129  } else {
130  // Terminology Karimaki used in the paper
131  const double rho = parameters.curvature();
132  const double d = parameters.impact();
133 
134  const double u = 1 + d * rho;
135  const double kappa = 0.5 * rho / u;
136 
137  double chi2 = sw * u * u * (sinphi * sinphi * c(iX, iX) - 2. * sinphi * cosphi * c(iX, iY) + cosphi * cosphi * c(iY,
138  iY) - kappa * kappa * c(iR2, iR2));
139  return chi2;
140  }
141 
142  }
143 
144 
145 
146  PerigeePrecision calcPrecisionKarimaki(const PerigeeCircle& parameters,
147  const Eigen::Matrix< double, 4, 4 >& s,
148  bool lineConstrained = false)
149  {
150  PerigeePrecision perigeePrecision;
151 
152  const double curv = parameters.curvature();
153  const double I = parameters.impact();
154 
155  // Karimaki uses the opposite sign for phi in contrast to the convention of this framework !!!
156  const Vector2D vecPhi = -parameters.tangential();
157 
158  // Ternminology Karimaki using in the paper
159  const double cosphi = vecPhi.x();
160  const double sinphi = vecPhi.y();
161 
162  const double ssphi = sinphi * sinphi;
163  const double scphi = sinphi * cosphi;
164  const double ccphi = cosphi * cosphi;
165 
166  const double rho = curv;
167  const double d = I;
168 
169  const double u = 1. + rho * d;
170 
171  using namespace NPerigeeParameterIndices;
172  if (lineConstrained) {
173  perigeePrecision(c_Curv, c_Curv) = 0.;
174  perigeePrecision(c_Curv, c_Phi0) = 0.;
175  perigeePrecision(c_Curv, c_I) = 0.;
176  perigeePrecision(c_Phi0, c_Curv) = 0.;
177  perigeePrecision(c_I, c_Curv) = 0.;
178 
179  perigeePrecision(c_Phi0, c_Phi0) = ccphi * s(iX, iX) + 2. * scphi * s(iX, iY) + ssphi * s(iY, iY);
180  perigeePrecision(c_Phi0, c_I) = -(cosphi * s(iX) + sinphi * s(iY));
181  perigeePrecision(c_I, c_Phi0) = perigeePrecision(c_Phi0, c_I);
182  perigeePrecision(c_I, c_I) = s(iW);
183 
184  } else {
185  double sa = sinphi * s(iX) - cosphi * s(iY);
186  double sb = cosphi * s(iX) + sinphi * s(iY);
187  double sc = (ssphi - ccphi) * s(iX, iY) + scphi * (s(iX, iX) - s(iY, iY));
188 
189  double sd = sinphi * s(iX, iR2) - cosphi * s(iY, iR2);
190 
191  double saa = ssphi * s(iX, iX) - 2. * scphi * s(iX, iY) + ccphi * s(iY, iY);
192 
193  // Not in the Karimaki paper, but factors a similar term.
194  double se = cosphi * s(iX, iR2) + sinphi * s(iY, iR2);
195  double sbb = ccphi * s(iX, iX) + 2. * scphi * s(iX, iY) + ssphi * s(iY, iY);
196 
197  perigeePrecision(c_Curv, c_Curv) = 0.25 * s(iR2, iR2) - d * (sd - d * (saa + 0.5 * s(iR2) - d * (sa - 0.25 * d * s(iW))));
198  perigeePrecision(c_Curv, c_Phi0) = - u * (0.5 * se - d * (sc - 0.5 * d * sb));
199  perigeePrecision(c_Phi0, c_Curv) = perigeePrecision(c_Curv, c_Phi0);
200  perigeePrecision(c_Phi0, c_Phi0) = u * u * sbb;
201 
202  perigeePrecision(c_Curv, c_I) = rho * (-0.5 * sd + d * saa) + 0.5 * u * s(iR2) - 0.5 * d * ((2 * u + rho * d) * sa - u * d * s(iW));
203  perigeePrecision(c_I, c_Curv) = perigeePrecision(c_Curv, c_I);
204  perigeePrecision(c_Phi0, c_I) = u * (rho * sc - u * sb);
205  perigeePrecision(c_I, c_Phi0) = perigeePrecision(c_Phi0, c_I);
206  perigeePrecision(c_I, c_I) = rho * (rho * saa - 2 * u * sa) + u * u * s(iW);
207  }
208  return perigeePrecision;
209  }
210 }
211 
212 
213 
215 {
216  // Matrix of weighted sums
217  Eigen::Matrix< double, 4, 4> sNoL = getWXYRSumMatrix(observations2D);
218 
219  // Matrix of averages
220  Eigen::Matrix<double, 4, 4> aNoL = sNoL / sNoL(iW);
221 
222  // Measurement means
223  Eigen::Matrix<double, 4, 1> meansNoL = aNoL.row(iW);
224 
225  // Covariance matrix
226  Eigen::Matrix<double, 4, 4> cNoL = aNoL - meansNoL * meansNoL.transpose();
227 
228  // Determine NDF : Circle fit eats up to 3 degrees of freedom debpending on the constraints
229  size_t ndf = observations2D.size() - 2;
230 
231  if (not isLineConstrained()) {
232  --ndf;
233  }
234 
235  // Parameters to be fitted
236  UncertainPerigeeCircle resultCircle = fitKarimaki(sNoL(iW), meansNoL, cNoL, isLineConstrained());
237  double chi2 = calcChi2Karimaki(resultCircle, sNoL(iW), cNoL);
238 
239  PerigeePrecision perigeePrecision = calcPrecisionKarimaki(resultCircle, sNoL, isLineConstrained());
240 
241  // Use in pivotingin caset the matrix is not full rank as is for the constrained cases-
242  PerigeeCovariance perigeeCovariance = PerigeeUtil::covarianceFromPrecision(perigeePrecision);
243 
244  resultCircle.setChi2(chi2);
245  resultCircle.setNDF(ndf);
246  resultCircle.setPerigeeCovariance(perigeeCovariance);
247  return resultCircle;
248 }
Class serving as a storage of observed drift circles to present to the Riemann fitter.
double getX(int iObservation) const
Getter for the x value of the observation at the given index.
double getY(int iObservation) const
Getter for the y value of the observation at the given index.
Vector2D getCentralPoint() const
Extracts the observation center that is at the index in the middle.
void passiveMoveBy(const Vector2D &origin)
Moves all observations passively such that the given vector becomes to origin of the new coordinate s...
std::size_t size() const
Returns the number of observations stored.
Particle trajectory as it is seen in xy projection represented as a circle.
double setLocalOrigin(const Vector2D &localOrigin)
Setter for the origin of the local coordinate system.
void setLocalCircle(const UncertainPerigeeCircle &localPerigeeCircle)
Setter for the generalized circle that describes the trajectory.
void clear()
Clears all information from this trajectoy.
KarimakisMethod()
Constructor setting the default constraints.
bool isLineConstrained() const
Getter for the indictor that lines should be fitted by this fitter.
UncertainPerigeeCircle fitInternal(CDCObservations2D &observations2D) const
Internal method doing the heavy work.
void update(CDCTrajectory2D &trajectory2D, CDCObservations2D &observations2D) const
Executes the fit and updates the trajectory parameters. This may render the information in the observ...
Extension of the generalized circle also caching the perigee coordinates.
Definition: PerigeeCircle.h:36
double arcLengthBetween(const Vector2D &from, const Vector2D &to) const
Calculates the arc length between two points of closest approach on the circle.
A matrix implementation to be used as an interface typ through out the track finder.
Definition: PlainMatrix.h:40
Adds an uncertainty matrix to the circle in perigee parameterisation.
void reverse()
Flips the orientation of the circle in place.
void setPerigeeCovariance(const PerigeeCovariance &perigeeCovariance)
Setter for the whole covariance matrix of the perigee parameters.
void setNDF(std::size_t ndf)
Setter for the number of degrees of freediom used in the circle fit.
void setChi2(const double chi2)
Setter for the chi square value of the circle fit.
A two dimensional vector which is equipped with functions for correct handeling of orientation relat...
Definition: Vector2D.h:35
double x() const
Getter for the x coordinate.
Definition: Vector2D.h:607
double y() const
Getter for the y coordinate.
Definition: Vector2D.h:617
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
@ c_I
Constant to address the impact parameter.
@ c_Phi0
Constant to address the azimuth angle of the direction of flight at the perigee.
@ c_Curv
Constant to address the curvature.
Abstract base class for different kinds of events.
static CovarianceMatrix covarianceFromPrecision(const PrecisionMatrix &prec)
Convert the precision matrix to the corresponding covariance matrix.