Belle II Software development
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/trackingUtilities/eventdata/trajectories/CDCTrajectory2D.h>
14
15#include <tracking/trackingUtilities/geometry/UncertainPerigeeCircle.h>
16#include <tracking/trackingUtilities/geometry/PerigeeParameters.h>
17#include <tracking/trackingUtilities/geometry/Vector2D.h>
18
19#include <Eigen/Core>
20
21using namespace Belle2;
22using namespace TrackFindingCDC;
23using namespace TrackingUtilities;
24
29
31 CDCObservations2D& observations2D) const
32{
33 size_t nObservations = observations2D.size();
34 trajectory2D.clear();
35 if (not nObservations) return;
36
37 Vector2D ref = observations2D.getCentralPoint();
38 observations2D.passiveMoveBy(ref);
39
40 UncertainPerigeeCircle perigeeCircle = fitInternal(observations2D);
41
42 double frontX = observations2D.getX(0);
43 double frontY = observations2D.getY(0);
44 Vector2D frontPos(frontX, frontY);
45
46 double backX = observations2D.getX(nObservations - 1);
47 double backY = observations2D.getY(nObservations - 1);
48 Vector2D backPos(backX, backY);
49
50 Vector2D overPos(0, 0);
51 double totalPerps = (perigeeCircle->arcLengthBetween(frontPos, overPos) +
52 perigeeCircle->arcLengthBetween(overPos, backPos));
53
54 if (totalPerps < 0) {
55 perigeeCircle.reverse();
56 }
57
58 trajectory2D.setLocalOrigin(ref);
59 trajectory2D.setLocalCircle(perigeeCircle);
60}
61
62
63
64
65namespace {
67 constexpr size_t iW = 0;
68 constexpr size_t iX = 1;
69 constexpr size_t iY = 2;
70 constexpr size_t iR2 = 3;
71
73 UncertainPerigeeCircle fitKarimaki(const double /*sw*/,
74 const Eigen::Matrix< double, 4, 1 >& a,
75 const Eigen::Matrix< double, 4, 4 >& c,
76 bool lineConstrained = false)
77 {
78 double q1, q2 = 0.0;
79 if (lineConstrained) {
80 q1 = c(iX, iY);
81 q2 = c(iX, iX) - c(iY, iY);
82 } else {
83 q1 = c(iX, iY) * c(iR2, iR2) - c(iX, iR2) * c(iY, iR2);
84 q2 = (c(iX, iX) - c(iY, iY)) * c(iR2, iR2) - c(iX, iR2) * c(iX, iR2) + c(iY, iR2) * c(iY, iR2);
85 }
86
87 double phi = 0.5 * atan2(2. * q1, q2);
88
89 double sinphi = sin(phi);
90 double cosphi = cos(phi);
91
92 double curv, I = 0.0;
93 if (lineConstrained) {
94 curv = 0.0; //line
95 I = sinphi * a(iX) - cosphi * a(iY);
96
97 } else {
98 double kappa = (sinphi * c(iX, iR2) - cosphi * c(iY, iR2)) / c(iR2, iR2);
99 double delta = -kappa * a(iR2) + sinphi * a(iX) - cosphi * a(iY);
100 curv = 2. * kappa / sqrt(1. - 4. * delta * kappa);
101 I = 2. * delta / (1. + sqrt(1. - 4. * delta * kappa));
102
103 }
104
105 // Karimaki uses the opposite sign for phi in contrast to the convention of this framework !!!
106 phi += phi > 0 ? -M_PI : M_PI;
107 return UncertainPerigeeCircle(curv, phi, I);
108
109 }
110
111
112
113
114
116 double calcChi2Karimaki(const PerigeeCircle& parameters,
117 const double sw,
118 const Eigen::Matrix< double, 4, 4 >& c,
119 bool lineConstrained = false)
120 {
121 // Karimaki uses the opposite sign for phi in contrast to the convention of this framework !!!
122 const Vector2D vecPhi = -parameters.tangential();
123
124 const double cosphi = vecPhi.x();
125 const double sinphi = vecPhi.y();
126
127 if (lineConstrained) {
128 double chi2 = sw * (sinphi * sinphi * c(iX, iX) - 2. * sinphi * cosphi * c(iX, iY) + cosphi * cosphi * c(iY, iY));
129 return chi2;
130 } else {
131 // Terminology Karimaki used in the paper
132 const double rho = parameters.curvature();
133 const double d = parameters.impact();
134
135 const double u = 1 + d * rho;
136 const double kappa = 0.5 * rho / u;
137
138 double chi2 = sw * u * u * (sinphi * sinphi * c(iX, iX) - 2. * sinphi * cosphi * c(iX, iY) + cosphi * cosphi * c(iY,
139 iY) - kappa * kappa * c(iR2, iR2));
140 return chi2;
141 }
142
143 }
144
145
146
147 PerigeePrecision calcPrecisionKarimaki(const PerigeeCircle& parameters,
148 const Eigen::Matrix< double, 4, 4 >& s,
149 bool lineConstrained = false)
150 {
151 PerigeePrecision perigeePrecision;
152
153 const double curv = parameters.curvature();
154 const double I = parameters.impact();
155
156 // Karimaki uses the opposite sign for phi in contrast to the convention of this framework !!!
157 const Vector2D vecPhi = -parameters.tangential();
158
159 // Ternminology Karimaki using in the paper
160 const double cosphi = vecPhi.x();
161 const double sinphi = vecPhi.y();
162
163 const double ssphi = sinphi * sinphi;
164 const double scphi = sinphi * cosphi;
165 const double ccphi = cosphi * cosphi;
166
167 const double rho = curv;
168 const double d = I;
169
170 const double u = 1. + rho * d;
171
172 using namespace NPerigeeParameterIndices;
173 if (lineConstrained) {
174 perigeePrecision(c_Curv, c_Curv) = 0.;
175 perigeePrecision(c_Curv, c_Phi0) = 0.;
176 perigeePrecision(c_Curv, c_I) = 0.;
177 perigeePrecision(c_Phi0, c_Curv) = 0.;
178 perigeePrecision(c_I, c_Curv) = 0.;
179
180 perigeePrecision(c_Phi0, c_Phi0) = ccphi * s(iX, iX) + 2. * scphi * s(iX, iY) + ssphi * s(iY, iY);
181 perigeePrecision(c_Phi0, c_I) = -(cosphi * s(iX) + sinphi * s(iY));
182 perigeePrecision(c_I, c_Phi0) = perigeePrecision(c_Phi0, c_I);
183 perigeePrecision(c_I, c_I) = s(iW);
184
185 } else {
186 double sa = sinphi * s(iX) - cosphi * s(iY);
187 double sb = cosphi * s(iX) + sinphi * s(iY);
188 double sc = (ssphi - ccphi) * s(iX, iY) + scphi * (s(iX, iX) - s(iY, iY));
189
190 double sd = sinphi * s(iX, iR2) - cosphi * s(iY, iR2);
191
192 double saa = ssphi * s(iX, iX) - 2. * scphi * s(iX, iY) + ccphi * s(iY, iY);
193
194 // Not in the Karimaki paper, but factors a similar term.
195 double se = cosphi * s(iX, iR2) + sinphi * s(iY, iR2);
196 double sbb = ccphi * s(iX, iX) + 2. * scphi * s(iX, iY) + ssphi * s(iY, iY);
197
198 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))));
199 perigeePrecision(c_Curv, c_Phi0) = - u * (0.5 * se - d * (sc - 0.5 * d * sb));
200 perigeePrecision(c_Phi0, c_Curv) = perigeePrecision(c_Curv, c_Phi0);
201 perigeePrecision(c_Phi0, c_Phi0) = u * u * sbb;
202
203 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));
204 perigeePrecision(c_I, c_Curv) = perigeePrecision(c_Curv, c_I);
205 perigeePrecision(c_Phi0, c_I) = u * (rho * sc - u * sb);
206 perigeePrecision(c_I, c_Phi0) = perigeePrecision(c_Phi0, c_I);
207 perigeePrecision(c_I, c_I) = rho * (rho * saa - 2 * u * sa) + u * u * s(iW);
208 }
209 return perigeePrecision;
210 }
211}
212
213
214
216{
217 // Matrix of weighted sums
218 Eigen::Matrix< double, 4, 4> sNoL = getWXYRSumMatrix(observations2D);
219
220 // Matrix of averages
221 Eigen::Matrix<double, 4, 4> aNoL = sNoL / sNoL(iW);
222
223 // Measurement means
224 Eigen::Matrix<double, 4, 1> meansNoL = aNoL.row(iW);
225
226 // Covariance matrix
227 Eigen::Matrix<double, 4, 4> cNoL = aNoL - meansNoL * meansNoL.transpose();
228
229 // Determine NDF : Circle fit eats up to 3 degrees of freedom debpending on the constraints
230 size_t ndf = observations2D.size() - 2;
231
232 if (not isLineConstrained()) {
233 --ndf;
234 }
235
236 // Parameters to be fitted
237 UncertainPerigeeCircle resultCircle = fitKarimaki(sNoL(iW), meansNoL, cNoL, isLineConstrained());
238 double chi2 = calcChi2Karimaki(resultCircle, sNoL(iW), cNoL);
239
240 PerigeePrecision perigeePrecision = calcPrecisionKarimaki(resultCircle, sNoL, isLineConstrained());
241
242 // Use in pivotingin caset the matrix is not full rank as is for the constrained cases-
243 PerigeeCovariance perigeeCovariance = PerigeeUtil::covarianceFromPrecision(perigeePrecision);
244
245 resultCircle.setChi2(chi2);
246 resultCircle.setNDF(ndf);
247 resultCircle.setPerigeeCovariance(perigeeCovariance);
248 return resultCircle;
249}
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.
TrackingUtilities::Vector2D getCentralPoint() const
Extracts the observation center that is at the index in the middle.
void passiveMoveBy(const TrackingUtilities::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.
KarimakisMethod()
Constructor setting the default constraints.
void update(TrackingUtilities::CDCTrajectory2D &trajectory2D, CDCObservations2D &observations2D) const
Executes the fit and updates the trajectory parameters. This may render the information in the observ...
bool isLineConstrained() const
Getter for the indicator that lines should be fitted by this fitter.
TrackingUtilities::UncertainPerigeeCircle fitInternal(CDCObservations2D &observations2D) const
Internal method doing the heavy work.
bool m_lineConstrained
Memory for the flag indicating that lines should be fitted.
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 trajectory.
double arcLengthBetween(const Vector2D &from, const Vector2D &to) const
Calculates the arc length between two points of closest approach on the circle.
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 handling of orientation relate...
Definition Vector2D.h:36
double x() const
Getter for the x coordinate.
Definition Vector2D.h:626
double y() const
Getter for the y coordinate.
Definition Vector2D.h:641
double sqrt(double a)
sqrt for double
Definition beamHelpers.h:28
Abstract base class for different kinds of events.