8#include <tracking/trackFindingCDC/fitting/KarimakisMethod.h>
10#include <tracking/trackFindingCDC/fitting/EigenObservationMatrix.h>
11#include <tracking/trackFindingCDC/fitting/CDCObservations2D.h>
13#include <tracking/trackingUtilities/eventdata/trajectories/CDCTrajectory2D.h>
15#include <tracking/trackingUtilities/geometry/UncertainPerigeeCircle.h>
16#include <tracking/trackingUtilities/geometry/PerigeeParameters.h>
18#include <Math/Vector2D.h>
23using namespace TrackFindingCDC;
24using namespace TrackingUtilities;
34 size_t nObservations = observations2D.
size();
36 if (not nObservations)
return;
43 double frontX = observations2D.
getX(0);
44 double frontY = observations2D.
getY(0);
45 ROOT::Math::XYVector frontPos(frontX, frontY);
47 double backX = observations2D.
getX(nObservations - 1);
48 double backY = observations2D.
getY(nObservations - 1);
49 ROOT::Math::XYVector backPos(backX, backY);
51 ROOT::Math::XYVector overPos(0, 0);
68 constexpr size_t iW = 0;
69 constexpr size_t iX = 1;
70 constexpr size_t iY = 2;
71 constexpr size_t iR2 = 3;
75 const Eigen::Matrix< double, 4, 1 >& a,
76 const Eigen::Matrix< double, 4, 4 >& c,
77 bool lineConstrained =
false)
80 if (lineConstrained) {
82 q2 = c(iX, iX) - c(iY, iY);
84 q1 = c(iX, iY) * c(iR2, iR2) - c(iX, iR2) * c(iY, iR2);
85 q2 = (c(iX, iX) - c(iY, iY)) * c(iR2, iR2) - c(iX, iR2) * c(iX, iR2) + c(iY, iR2) * c(iY, iR2);
88 double phi = 0.5 * atan2(2. * q1, q2);
90 double sinphi = sin(phi);
91 double cosphi = cos(phi);
94 if (lineConstrained) {
96 I = sinphi * a(iX) - cosphi * a(iY);
99 double kappa = (sinphi * c(iX, iR2) - cosphi * c(iY, iR2)) / c(iR2, iR2);
100 double delta = -kappa * a(iR2) + sinphi * a(iX) - cosphi * a(iY);
101 curv = 2. * kappa /
sqrt(1. - 4. * delta * kappa);
102 I = 2. * delta / (1. +
sqrt(1. - 4. * delta * kappa));
107 phi += phi > 0 ? -M_PI : M_PI;
108 return UncertainPerigeeCircle(curv, phi, I);
117 double calcChi2Karimaki(
const PerigeeCircle& parameters,
119 const Eigen::Matrix< double, 4, 4 >& c,
120 bool lineConstrained =
false)
123 const ROOT::Math::XYVector vecPhi = -parameters.tangential();
125 const double cosphi = vecPhi.x();
126 const double sinphi = vecPhi.y();
128 if (lineConstrained) {
129 double chi2 = sw * (sinphi * sinphi * c(iX, iX) - 2. * sinphi * cosphi * c(iX, iY) + cosphi * cosphi * c(iY, iY));
133 const double rho = parameters.curvature();
134 const double d = parameters.impact();
136 const double u = 1 + d * rho;
137 const double kappa = 0.5 * rho / u;
139 double chi2 = sw * u * u * (sinphi * sinphi * c(iX, iX) - 2. * sinphi * cosphi * c(iX, iY) + cosphi * cosphi * c(iY,
140 iY) - kappa * kappa * c(iR2, iR2));
148 PerigeePrecision calcPrecisionKarimaki(
const PerigeeCircle& parameters,
149 const Eigen::Matrix< double, 4, 4 >& s,
150 bool lineConstrained =
false)
152 PerigeePrecision perigeePrecision;
154 const double curv = parameters.curvature();
155 const double I = parameters.impact();
158 const ROOT::Math::XYVector vecPhi = -parameters.tangential();
161 const double cosphi = vecPhi.x();
162 const double sinphi = vecPhi.y();
164 const double ssphi = sinphi * sinphi;
165 const double scphi = sinphi * cosphi;
166 const double ccphi = cosphi * cosphi;
168 const double rho = curv;
171 const double u = 1. + rho * d;
173 using namespace NPerigeeParameterIndices;
174 if (lineConstrained) {
175 perigeePrecision(c_Curv, c_Curv) = 0.;
176 perigeePrecision(c_Curv, c_Phi0) = 0.;
177 perigeePrecision(c_Curv, c_I) = 0.;
178 perigeePrecision(c_Phi0, c_Curv) = 0.;
179 perigeePrecision(c_I, c_Curv) = 0.;
181 perigeePrecision(c_Phi0, c_Phi0) = ccphi * s(iX, iX) + 2. * scphi * s(iX, iY) + ssphi * s(iY, iY);
182 perigeePrecision(c_Phi0, c_I) = -(cosphi * s(iX) + sinphi * s(iY));
183 perigeePrecision(c_I, c_Phi0) = perigeePrecision(c_Phi0, c_I);
184 perigeePrecision(c_I, c_I) = s(iW);
187 double sa = sinphi * s(iX) - cosphi * s(iY);
188 double sb = cosphi * s(iX) + sinphi * s(iY);
189 double sc = (ssphi - ccphi) * s(iX, iY) + scphi * (s(iX, iX) - s(iY, iY));
191 double sd = sinphi * s(iX, iR2) - cosphi * s(iY, iR2);
193 double saa = ssphi * s(iX, iX) - 2. * scphi * s(iX, iY) + ccphi * s(iY, iY);
196 double se = cosphi * s(iX, iR2) + sinphi * s(iY, iR2);
197 double sbb = ccphi * s(iX, iX) + 2. * scphi * s(iX, iY) + ssphi * s(iY, iY);
199 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))));
200 perigeePrecision(c_Curv, c_Phi0) = - u * (0.5 * se - d * (sc - 0.5 * d * sb));
201 perigeePrecision(c_Phi0, c_Curv) = perigeePrecision(c_Curv, c_Phi0);
202 perigeePrecision(c_Phi0, c_Phi0) = u * u * sbb;
204 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));
205 perigeePrecision(c_I, c_Curv) = perigeePrecision(c_Curv, c_I);
206 perigeePrecision(c_Phi0, c_I) = u * (rho * sc - u * sb);
207 perigeePrecision(c_I, c_Phi0) = perigeePrecision(c_Phi0, c_I);
208 perigeePrecision(c_I, c_I) = rho * (rho * saa - 2 * u * sa) + u * u * s(iW);
210 return perigeePrecision;
219 Eigen::Matrix< double, 4, 4> sNoL = getWXYRSumMatrix(observations2D);
222 Eigen::Matrix<double, 4, 4> aNoL = sNoL / sNoL(iW);
225 Eigen::Matrix<double, 4, 1> meansNoL = aNoL.row(iW);
228 Eigen::Matrix<double, 4, 4> cNoL = aNoL - meansNoL * meansNoL.transpose();
231 size_t ndf = observations2D.
size() - 2;
239 double chi2 = calcChi2Karimaki(resultCircle, sNoL(iW), cNoL);
241 PerigeePrecision perigeePrecision = calcPrecisionKarimaki(resultCircle, sNoL,
isLineConstrained());
244 PerigeeCovariance perigeeCovariance = PerigeeUtil::covarianceFromPrecision(perigeePrecision);
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.
void passiveMoveBy(const ROOT::Math::XYVector &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.
ROOT::Math::XYVector getCentralPoint() const
Extracts the observation center that is at the index in the middle.
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.
void setLocalCircle(const UncertainPerigeeCircle &localPerigeeCircle)
Setter for the generalized circle that describes the trajectory.
double setLocalOrigin(const ROOT::Math::XYVector &localOrigin)
Setter for the origin of the local coordinate system.
void clear()
Clears all information from this trajectory.
double arcLengthBetween(const ROOT::Math::XYVector &from, const ROOT::Math::XYVector &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.
double sqrt(double a)
sqrt for double
Abstract base class for different kinds of events.