8#include <tracking/trackFindingCDC/fitting/FacetFitter.h>
10#include <tracking/trackingUtilities/eventdata/hits/CDCFacet.h>
11#include <tracking/trackingUtilities/eventdata/hits/CDCWireHit.h>
12#include <tracking/trackingUtilities/geometry/UncertainParameterLine2D.h>
13#include <tracking/trackingUtilities/geometry/ParameterLine2D.h>
14#include <tracking/trackingUtilities/geometry/VectorUtil.h>
15#include <tracking/trackingUtilities/numerics/EigenView.h>
19#include <Math/Vector2D.h>
20#include <Math/Functor.h>
21#include <Math/BrentMinimizer1D.h>
24using namespace TrackFindingCDC;
25using namespace TrackingUtilities;
30 ROOT::Math::XYVector getCenterForwardDirection(
const Matrix<double, N, 3>& xyl)
33 ROOT::Math::XYVector coordinate(xyl(N - 1, 0) - xyl(0, 0), xyl(N - 1, 1) - xyl(0, 1));
34 return VectorUtil::unit(coordinate);
38 ROOT::Math::XYVector getTangentialForwardDirection(
const Matrix<double, N, 3>& xyl)
41 ROOT::Math::XYVector fromPos(xyl(0, 0), xyl(0, 1));
42 double fromL = xyl(0, 2);
44 ROOT::Math::XYVector toPos(xyl(N - 1, 0), xyl(N - 1, 1));
45 double toL = xyl(N - 1, 2);
48 ROOT::Math::XYVector coordinate = tangentLine.
tangential();
49 return VectorUtil::unit(coordinate);
53 void rotate(ROOT::Math::XYVector coordinate, Matrix<double, N, 3>& xyl)
56 rot(0, 0) = coordinate.x();
57 rot(0, 1) = -coordinate.y();
58 rot(1, 0) = coordinate.y();
59 rot(1, 1) = coordinate.x();
64 void unrotate(ROOT::Math::XYVector coordinate, ROOT::Math::XYVector& vec)
68 vec = VectorUtil::passiveRotatedBy(vec, ROOT::Math::XYVector(coordinate.X(), -coordinate.Y()));
71 Eigen::Vector2d fitPhiVecZeroSteps(
const Eigen::Matrix<double, 3, 3>& xylCov,
double& chi2)
73 chi2 = xylCov(1, 1) + 2 * xylCov(1, 2) + xylCov(2, 2);
74 return Eigen::Vector2d(1, 0);
77 Eigen::Vector2d fitPhiVecOneStep(
const Eigen::Matrix<double, 3, 3>& xylCov,
double& chi2)
79 const double phi = (xylCov(0, 1) + xylCov(0, 2)) / xylCov(0, 0);
80 chi2 = xylCov(1, 1) + 2 * xylCov(1, 2) + xylCov(2, 2) - phi * (xylCov(0, 1) + xylCov(0, 2));
81 return Eigen::Vector2d(std::cos(phi), std::sin(phi));
84 Eigen::Vector2d fitPhiVecBrent(
const Eigen::Matrix<double, 3, 3>& xylCov,
int nIter,
double& chi2)
86 const Eigen::Matrix< double, 2, 2> A = xylCov.topLeftCorner<2, 2>();
87 const Eigen::Matrix< double, 2, 1> b = xylCov.topRightCorner<2, 1>();
88 const double c = xylCov(2, 2);
90 auto calcReducedChi2 = [&A, &b](
double phi) ->
double {
91 Eigen::Matrix<double, 2, 1> normal(std::sin(phi), -std::cos(phi));
92 return ((normal.transpose() * A - 2 * b.transpose()) * normal)[0];
95 ROOT::Math::Functor1D functor(calcReducedChi2);
96 ROOT::Math::BrentMinimizer1D bm;
97 bm.SetFunction(functor, -M_PI / 2, M_PI / 2);
100 chi2 = bm.FValMinimum() + c;
101 const double phi = bm.XMinimum();
102 return Eigen::Vector2d(std::cos(phi), std::sin(phi));
107 Matrix<double, N, 1> wIn,
111 ROOT::Math::XYVector coordinate = getTangentialForwardDirection(xylIn);
114 if (VectorUtil::hasNAN(coordinate)) {
115 coordinate = getCenterForwardDirection(xylIn);
118 rotate(coordinate, xylIn);
120 auto xyl = mapToEigen(xylIn);
121 auto w = mapToEigen(wIn).array();
123 Eigen::Array< double, 1, 3> averages = (xyl.array().colwise() * w).colwise().sum() / w.sum();
124 Eigen::Matrix< double, N, 3> deltas = xyl.array().rowwise() - averages;
125 Eigen::Matrix< double, N, 3> weightedDeltas = deltas.array().colwise() * w;
126 Eigen::Matrix< double, 3, 3> covariances = deltas.transpose() * weightedDeltas / w.sum();
128 Eigen::Vector2d phiVec;
131 phiVec = fitPhiVecZeroSteps(covariances, chi2);
132 }
else if (nSteps == 1) {
133 phiVec = fitPhiVecOneStep(covariances, chi2);
135 phiVec = fitPhiVecBrent(covariances, nSteps, chi2);
139 double meanArcLength = averages.topLeftCorner<1, 2>().matrix() * phiVec;
140 double varArcLength = phiVec.transpose() * covariances.topLeftCorner<2, 2>() * phiVec;
144 LinePrecision linePrecision;
145 linePrecision(c_Phi0, c_Phi0) = p * (varArcLength + meanArcLength * meanArcLength);
146 linePrecision(c_Phi0, c_I) = p * meanArcLength;
147 linePrecision(c_I, c_Phi0) = p * meanArcLength;
148 linePrecision(c_I, c_I) = p;
149 LineCovariance lineCovariance = LineUtil::covarianceFromFullPrecision(linePrecision);
151 ROOT::Math::XYVector tangential(phiVec(0), phiVec(1));
152 ROOT::Math::XYVector n12 = VectorUtil::Orthogonal(tangential, ERotation::c_Clockwise);
153 double n0 = averages(2) - averages(0) * n12.x() - averages(1) * n12.y();
154 ROOT::Math::XYVector support = -n12 * n0;
157 unrotate(coordinate, support);
158 unrotate(coordinate, tangential);
183 xyl(0, 0) = startWirePos2D.x() - support.x();
184 xyl(0, 1) = startWirePos2D.y() - support.y();
186 w(0) = 1.0 / startDriftLengthVar;
190 xyl(1, 0) = middleWirePos2D.x() - support.x();
191 xyl(1, 1) = middleWirePos2D.y() - support.y();
193 w(1) = 1.0 / middleDriftLengthVar;
197 xyl(2, 0) = endWirePos2D.x() - support.x();
198 xyl(2, 1) = endWirePos2D.y() - support.y();
200 w(2) = 1.0 / endDriftLengthVar;
205 return fitLine.chi2();
228 xyl(0, 0) = startWirePos2D.x() - support.x();
229 xyl(0, 1) = startWirePos2D.y() - support.y();
231 w(0) = 1.0 / startDriftLengthVar;
235 xyl(1, 0) = middleWirePos2D.x() - support.x();
236 xyl(1, 1) = middleWirePos2D.y() - support.y();
238 w(1) = 1.0 / middleDriftLengthVar;
242 xyl(2, 0) = endWirePos2D.x() - support.x();
243 xyl(2, 1) = endWirePos2D.y() - support.y();
245 w(2) = 1.0 / endDriftLengthVar;
255 xyl(3, 0) = startWirePos2D.x() - support.x();
256 xyl(3, 1) = startWirePos2D.y() - support.y();
258 w(3) = 1.0 / startDriftLengthVar;
262 xyl(4, 0) = middleWirePos2D.x() - support.x();
263 xyl(4, 1) = middleWirePos2D.y() - support.y();
265 w(4) = 1.0 / middleDriftLengthVar;
269 xyl(5, 0) = endWirePos2D.x() - support.x();
270 xyl(5, 1) = endWirePos2D.y() - support.y();
272 w(5) = 1.0 / endDriftLengthVar;
282 TrackingUtilities::Matrix<double, 3, 1> w,
285 return ::fit(std::move(xyl), std::move(w), nSteps);
static double fit(const TrackingUtilities::CDCFacet &facet, int nSteps=100)
Fits a proper line to facet and returns the chi2.
Class representing a triple of neighboring oriented wire with additional trajectory information.
void setFitLine(const UncertainParameterLine2D &fitLine) const
Setter for the contained line fit information.
const CDCWireHit & getMiddleWireHit() const
Getter for the hit wire of the second oriented wire hit.
CDCRLWireHit & getStartRLWireHit()
Getter for the first oriented wire hit.
CDCRLWireHit & getEndRLWireHit()
Getter for the third oriented wire hit.
CDCRLWireHit & getMiddleRLWireHit()
Getter for the second oriented wire hit.
Class representing an oriented hit wire including a hypotheses whether the causing track passes left ...
const CDCWireHit & getWireHit() const
Getter for the wire hit associated with the oriented hit.
double getRefDriftLengthVariance() const
Getter for the variance of the drift length at the reference position of the wire.
double getSignedRefDriftLength() const
Getter for the drift length at the reference position of the wire.
const ROOT::Math::XYVector & getRefPos2D() const
The two dimensional reference position (z=0) of the underlying wire.
A line with a support point and tangential vector.
const ROOT::Math::XYVector & tangential() const
Gives the tangential vector of the line.
static ParameterLine2D touchingCircles(const ROOT::Math::XYVector &fromCenter, double fromSignedRadius, const ROOT::Math::XYVector &toCenter, double toSignedRadius)
Constructs a line touching two circles in one point each.
static PlainMatrix< T, M, N > Identity()
Construct an identity matrix.
static PlainMatrix< T, M, N > Zero()
Construct a matrix initialized with zeros.
A parameter line including including an line covariance matrix which is interpreted as located in the...
void passiveMoveBy(const ROOT::Math::XYVector &by)
Moves the coordinate system by the vector by.
Namespace to hide the contained enum constants.
Abstract base class for different kinds of events.