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/Vector2D.h>
16#include <tracking/trackingUtilities/numerics/EigenView.h>
20#include <Math/Functor.h>
21#include <Math/BrentMinimizer1D.h>
24using namespace TrackFindingCDC;
25using namespace TrackingUtilities;
30 Vector2D getCenterForwardDirection(
const Matrix<double, N, 3>& xyl)
33 Vector2D coordinate(xyl(N - 1, 0) - xyl(0, 0), xyl(N - 1, 1) - xyl(0, 1));
34 return coordinate.unit();
38 Vector2D getTangentialForwardDirection(
const Matrix<double, N, 3>& xyl)
41 Vector2D fromPos(xyl(0, 0), xyl(0, 1));
42 double fromL = xyl(0, 2);
44 Vector2D toPos(xyl(N - 1, 0), xyl(N - 1, 1));
45 double toL = xyl(N - 1, 2);
49 return coordinate.
unit();
53 void rotate(
Vector2D 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();
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 Vector2D coordinate = getTangentialForwardDirection(xylIn);
114 if (coordinate.
hasNAN()) {
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 Vector2D tangential(phiVec(0), phiVec(1));
153 double n0 = averages(2) - averages(0) * n12.
x() - averages(1) * n12.
y();
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 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.
static ParameterLine2D touchingCircles(const Vector2D &fromCenter, double fromSignedRadius, const Vector2D &toCenter, double toSignedRadius)
Constructs a line touching two circles in one point each.
const Vector2D & tangential() const
Gives the tangential vector of the line.
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 Vector2D &by)
Moves the coordinate system by the vector by.
A two dimensional vector which is equipped with functions for correct handling of orientation relate...
Vector2D flippedSecond() const
Makes a copy of the vector with the second coordinate flipped (no difference between active and passi...
static Vector2D average(const Vector2D &one, const Vector2D &two)
Constructs the average of two vectors.
double x() const
Getter for the x coordinate.
Vector2D orthogonal() const
Orthogonal vector to the counterclockwise direction.
bool hasNAN() const
Checks if one of the coordinates is NAN.
double y() const
Getter for the y coordinate.
Vector2D unit() const
Returns a unit vector colaligned with this.
Vector2D passiveRotatedBy(const Vector2D &phiVec) const
Returns a transformed vector version rotated by the given vector.
Namespace to hide the contained enum constants.
Abstract base class for different kinds of events.