8#include <tracking/trackFindingCDC/fitting/ExtendedRiemannsMethod.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 <tracking/trackingUtilities/numerics/EigenView.h>
20#include <framework/logging/Logger.h>
22#include <Math/Vector2D.h>
28using namespace TrackFindingCDC;
29using namespace TrackingUtilities;
40 size_t nObservations = observations2D.
size();
42 if (not nObservations)
return;
44 ROOT::Math::XYVector origin = ROOT::Math::XYVector(0.0, 0.0);
52 double frontX = observations2D.
getX(0);
53 double frontY = observations2D.
getY(0);
54 ROOT::Math::XYVector frontPos(frontX, frontY);
56 double backX = observations2D.
getX(nObservations - 1);
57 double backY = observations2D.
getY(nObservations - 1);
58 ROOT::Math::XYVector backPos(backX, backY);
60 ROOT::Math::XYVector overPos(0, 0);
76 enum EParabolicIndices {
85 PerigeeCircle fit(
const Eigen::Matrix< double, 5, 5 >& sumMatrix,
86 bool lineConstrained =
false,
87 bool originConstrained =
false)
91 if (lineConstrained) {
92 if (originConstrained) {
93 Eigen::Matrix< double, 2, 2> X = sumMatrix.block<2, 2>(1, 1);
94 Eigen::Matrix< double, 2, 1> y = sumMatrix.block<2, 1>(1, iL);
95 Eigen::Matrix< double, 2, 1> n = X.ldlt().solve(y);
99 Eigen::Matrix< double, 3, 3> X = sumMatrix.block<3, 3>(0, 0);
100 Eigen::Matrix< double, 3, 1> y = sumMatrix.block<3, 1>(0, iL);
101 Eigen::Matrix< double, 3, 1> n = X.ldlt().solve(y);
107 if (originConstrained) {
108 Eigen::Matrix< double, 3, 3> X = sumMatrix.block<3, 3>(1, 1);
109 Eigen::Matrix< double, 3, 1> y = sumMatrix.block<3, 1>(1, iL);
110 Eigen::Matrix< double, 3, 1> n = X.ldlt().solve(y);
114 Eigen::Matrix< double, 4, 4> X = sumMatrix.block<4, 4>(0, 0);
115 Eigen::Matrix< double, 4, 1> y = sumMatrix.block<4, 1>(0, iL);
116 Eigen::Matrix< double, 4, 1> n = X.ldlt().solve(y);
125 PerigeeCircle fit(Eigen::Matrix< double, 4, 4 > sumMatrix,
126 bool lineConstrained =
false,
127 bool originConstrained =
false)
132 using namespace NParabolicParameterIndices;
133 if (lineConstrained) {
134 if (originConstrained) {
135 Eigen::Matrix< double, 2, 2> X = sumMatrix.block<2, 2>(1, 1);
136 Eigen::SelfAdjointEigenSolver< Eigen::Matrix<double, 2, 2> > eigensolver(X);
137 Eigen::Matrix<double, 2, 1> n = eigensolver.eigenvectors().col(0);
138 if (eigensolver.info() != Eigen::Success) {
139 B2WARNING(
"SelfAdjointEigenSolver could not compute the eigen values of the observation matrix");
144 Eigen::Matrix< double, 3, 3> X = sumMatrix.block<3, 3>(0, 0);
145 Eigen::SelfAdjointEigenSolver< Eigen::Matrix<double, 3, 3> > eigensolver(X);
146 Eigen::Matrix<double, 3, 1> n = eigensolver.eigenvectors().col(0);
147 if (eigensolver.info() != Eigen::Success) {
148 B2WARNING(
"Eigen::SelfAdjointEigenSolver could not compute the eigen values of the observation matrix");
154 if (originConstrained) {
155 Eigen::Matrix< double, 3, 3> X = sumMatrix.block<3, 3>(1, 1);
156 Eigen::SelfAdjointEigenSolver< Eigen::Matrix<double, 3, 3> > eigensolver(X);
157 Eigen::Matrix<double, 3, 1> n = eigensolver.eigenvectors().col(0);
158 if (eigensolver.info() != Eigen::Success) {
159 B2WARNING(
"Eigen::SelfAdjointEigenSolver could not compute the eigen values of the observation matrix");
164 Eigen::Matrix< double, 4, 4 > X = sumMatrix.block<4, 4>(0, 0);
165 Eigen::SelfAdjointEigenSolver< Eigen::Matrix<double, 4, 4> > eigensolver(X);
166 Eigen::Matrix<double, 4, 1> n = eigensolver.eigenvectors().col(0);
167 if (eigensolver.info() != Eigen::Success) {
168 B2WARNING(
"Eigen::SelfAdjointEigenSolver could not compute the eigen values of the observation matrix");
177 PerigeeCircle fitSeperateOffset(Eigen::Matrix< double, 4, 1 > means,
178 Eigen::Matrix< double, 4, 4 > c,
179 bool lineConstrained =
false)
184 using namespace NParabolicParameterIndices;
185 if (lineConstrained) {
186 Eigen::Matrix< double, 2, 2> X = c.block<2, 2>(1, 1);
187 Eigen::SelfAdjointEigenSolver< Eigen::Matrix<double, 2, 2> > eigensolver(X);
188 if (eigensolver.info() != Eigen::Success) {
189 B2WARNING(
"Eigen::SelfAdjointEigenSolver could not compute the eigen values of the observation matrix");
194 Eigen::Matrix<double, 4, 1> n;
195 n.middleRows<2>(iX) = eigensolver.eigenvectors().col(0);
196 n(iW) = -means.middleRows<2>(iX).transpose() * n.middleRows<2>(iX);
201 Eigen::Matrix< double, 3, 3> X = c.block<3, 3>(1, 1);
202 Eigen::SelfAdjointEigenSolver< Eigen::Matrix<double, 3, 3> > eigensolver(X);
203 if (eigensolver.info() != Eigen::Success) {
204 B2WARNING(
"Eigen::SelfAdjointEigenSolver could not compute the eigen values of the observation matrix");
209 Eigen::Matrix<double, 4, 1> n;
210 n.middleRows<3>(iX) = eigensolver.eigenvectors().col(0);
211 n(iW) = -means.middleRows<3>(iX).transpose() * n.middleRows<3>(iX);
219 double calcChi2(
const PerigeeCircle& parameters,
220 const Eigen::Matrix< double, 5, 5 >& s)
222 Eigen::Matrix<double, 5, 1> n;
223 n(0) = parameters.n0();
224 n(1) = parameters.n1();
225 n(2) = parameters.n2();
226 n(3) = parameters.n3();
229 double chi2 = n.transpose() * s * n;
235 double calcChi2(
const PerigeeCircle& parameters,
236 const Eigen::Matrix< double, 4, 4 >& s)
238 Eigen::Matrix<double, 4, 1> n;
239 n(0) = parameters.n0();
240 n(1) = parameters.n1();
241 n(2) = parameters.n2();
242 n(3) = parameters.n3();
244 double chi2 = n.transpose() * s * n;
249 PerigeePrecision calcPrecision(
const PerigeeCircle& parameters,
250 const Eigen::Matrix< double, 4, 4 >& s,
251 bool lineConstrained =
false,
252 bool originConstrained =
false)
254 const double impact = parameters.impact();
255 const ROOT::Math::XYVector& phi0Vec = parameters.tangential();
256 const double curvature = parameters.curvature();
258 using namespace NPerigeeParameterIndices;
259 Eigen::Matrix<double, 4, 3> ambiguity = Eigen::Matrix<double, 4, 3> ::Zero();
261 ambiguity(0, c_Curv) = impact * impact / 2;
262 ambiguity(1, c_Curv) = phi0Vec.y() * impact;
263 ambiguity(2, c_Curv) = -phi0Vec.x() * impact;
264 ambiguity(3, c_Curv) = 1.0 / 2.0;
266 ambiguity(0, c_Phi0) = 0;
267 ambiguity(1, c_Phi0) = phi0Vec.x() * (1 + curvature * impact);
268 ambiguity(2, c_Phi0) = phi0Vec.y() * (1 + curvature * impact);
269 ambiguity(3, c_Phi0) = 0;
271 ambiguity(0, c_I) = 1 + curvature * impact;
272 ambiguity(1, c_I) = phi0Vec.y() * curvature;
273 ambiguity(2, c_I) = -phi0Vec.x() * curvature;
274 ambiguity(3, c_I) = 0;
276 Eigen::Matrix<double, 3, 3> perigeePrecision = ambiguity.transpose() * s * ambiguity;
278 if (lineConstrained) {
279 perigeePrecision.row(c_Curv) = Eigen::Matrix<double, 1, 3>::Zero();
280 perigeePrecision.col(c_Curv) = Eigen::Matrix<double, 3, 1>::Zero();
283 if (originConstrained) {
284 perigeePrecision.row(c_I) = Eigen::Matrix<double, 1, 3>::Zero();
285 perigeePrecision.col(c_I) = Eigen::Matrix<double, 3, 1>::Zero();
288 PerigeePrecision result;
289 mapToEigen(result) = perigeePrecision;
302 Eigen::Matrix< double, 5, 5 > s = getWXYRLSumMatrix(observations2D);
305 Eigen::Matrix<double, 4, 4> sNoL = s.block<4, 4>(0, 0);
308 size_t ndf = observations2D.
size() - 1;
323 if (nObservationsWithDriftRadius > 0) {
325 chi2 = calcChi2(resultCircle, s);
331 Eigen::Matrix< double, 4, 4> aNoL = sNoL / sNoL(iW);
334 Eigen::Matrix< double, 4, 1> meansNoL = aNoL.row(iW);
337 Eigen::Matrix< double, 4, 4> cNoL = aNoL - meansNoL * meansNoL.transpose();
345 chi2 = calcChi2(resultCircle, sNoL);
349 PerigeePrecision perigeePrecision =
353 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.
std::size_t getNObservationsWithDriftRadius() const
Returns the number of observations having a drift radius radius.
ROOT::Math::XYVector getCentralPoint() const
Extracts the observation center that is at the index in the middle.
void update(TrackingUtilities::CDCTrajectory2D &trajectory2D, CDCObservations2D &observations2D) const
Executes the fit and updates the trajectory parameters This may render the information in the observa...
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_originConstrained
Memory for the flag indicating that curves through the origin shall be fitter.
ExtendedRiemannsMethod()
Constructor setting the default constraints.
bool m_lineConstrained
Memory for the flag indicating that lines should be fitted.
bool isOriginConstrained() const
Getter for the indicator that curves through the origin should be fitted by this fitter.
Particle trajectory as it is seen in xy projection represented as a circle.
void clear()
Clears all information from this trajectory.
Extension of the generalized circle also caching the perigee coordinates.
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.
static PerigeeCircle fromN(double n0, double n1, double n2, double n3=0)
Constructor with the four parameters of the generalized 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.
Abstract base class for different kinds of events.
Namespace to hide the contained enum constants.