8#include <tracking/trackFindingCDC/fitting/FacetFitter.h>
10#include <tracking/trackFindingCDC/eventdata/hits/CDCFacet.h>
11#include <tracking/trackFindingCDC/eventdata/hits/CDCWireHit.h>
12#include <tracking/trackFindingCDC/geometry/UncertainParameterLine2D.h>
13#include <tracking/trackFindingCDC/geometry/ParameterLine2D.h>
14#include <tracking/trackFindingCDC/geometry/Vector2D.h>
16#include <tracking/trackFindingCDC/numerics/EigenView.h>
20#include <Math/Functor.h>
21#include <Math/BrentMinimizer1D.h>
24using namespace TrackFindingCDC;
29 Vector2D getCenterForwardDirection(
const Matrix<double, N, 3>& xyl)
32 Vector2D coordinate(xyl(N - 1, 0) - xyl(0, 0), xyl(N - 1, 1) - xyl(0, 1));
33 return coordinate.unit();
37 Vector2D getTangentialForwardDirection(
const Matrix<double, N, 3>& xyl)
40 Vector2D fromPos(xyl(0, 0), xyl(0, 1));
41 double fromL = xyl(0, 2);
43 Vector2D toPos(xyl(N - 1, 0), xyl(N - 1, 1));
44 double toL = xyl(N - 1, 2);
48 return coordinate.
unit();
52 void rotate(
Vector2D coordinate, Matrix<double, N, 3>& xyl)
55 rot(0, 0) = coordinate.
x();
56 rot(0, 1) = -coordinate.
y();
57 rot(1, 0) = coordinate.
y();
58 rot(1, 1) = coordinate.
x();
70 Eigen::Vector2d fitPhiVecZeroSteps(
const Eigen::Matrix<double, 3, 3>& xylCov,
double& chi2)
72 chi2 = xylCov(1, 1) + 2 * xylCov(1, 2) + xylCov(2, 2);
73 return Eigen::Vector2d(1, 0);
76 Eigen::Vector2d fitPhiVecOneStep(
const Eigen::Matrix<double, 3, 3>& xylCov,
double& chi2)
78 const double phi = (xylCov(0, 1) + xylCov(0, 2)) / xylCov(0, 0);
79 chi2 = xylCov(1, 1) + 2 * xylCov(1, 2) + xylCov(2, 2) - phi * (xylCov(0, 1) + xylCov(0, 2));
80 return Eigen::Vector2d(std::cos(phi), std::sin(phi));
83 Eigen::Vector2d fitPhiVecBrent(
const Eigen::Matrix<double, 3, 3>& xylCov,
int nIter,
double& chi2)
85 const Eigen::Matrix< double, 2, 2> A = xylCov.topLeftCorner<2, 2>();
86 const Eigen::Matrix< double, 2, 1> b = xylCov.topRightCorner<2, 1>();
87 const double c = xylCov(2, 2);
89 auto calcReducedChi2 = [&A, &b](
double phi) ->
double {
90 Eigen::Matrix<double, 2, 1> normal(std::sin(phi), -std::cos(phi));
91 return ((normal.transpose() * A - 2 * b.transpose()) * normal)[0];
94 ROOT::Math::Functor1D functor(calcReducedChi2);
95 ROOT::Math::BrentMinimizer1D bm;
96 bm.SetFunction(functor, -M_PI / 2, M_PI / 2);
99 chi2 = bm.FValMinimum() + c;
100 const double phi = bm.XMinimum();
101 return Eigen::Vector2d(std::cos(phi), std::sin(phi));
106 Matrix<double, N, 1> wIn,
110 Vector2D coordinate = getTangentialForwardDirection(xylIn);
113 if (coordinate.
hasNAN()) {
114 coordinate = getCenterForwardDirection(xylIn);
117 rotate(coordinate, xylIn);
119 auto xyl = mapToEigen(xylIn);
120 auto w = mapToEigen(wIn).array();
122 Eigen::Array< double, 1, 3> averages = (xyl.array().colwise() * w).colwise().sum() / w.sum();
123 Eigen::Matrix< double, N, 3> deltas = xyl.array().rowwise() - averages;
124 Eigen::Matrix< double, N, 3> weightedDeltas = deltas.array().colwise() * w;
125 Eigen::Matrix< double, 3, 3> covariances = deltas.transpose() * weightedDeltas / w.sum();
127 Eigen::Vector2d phiVec;
130 phiVec = fitPhiVecZeroSteps(covariances, chi2);
131 }
else if (nSteps == 1) {
132 phiVec = fitPhiVecOneStep(covariances, chi2);
134 phiVec = fitPhiVecBrent(covariances, nSteps, chi2);
138 double meanArcLength = averages.topLeftCorner<1, 2>().matrix() * phiVec;
139 double varArcLength = phiVec.transpose() * covariances.topLeftCorner<2, 2>() * phiVec;
142 using namespace NLineParameterIndices;
144 linePrecision(c_Phi0, c_Phi0) = p * (varArcLength + meanArcLength * meanArcLength);
145 linePrecision(c_Phi0, c_I) = p * meanArcLength;
146 linePrecision(c_I, c_Phi0) = p * meanArcLength;
147 linePrecision(c_I, c_I) = p;
148 LineCovariance lineCovariance = LineUtil::covarianceFromFullPrecision(linePrecision);
150 Vector2D tangential(phiVec(0), phiVec(1));
152 double n0 = averages(2) - averages(0) * n12.
x() - averages(1) * n12.
y();
156 unrotate(coordinate, support);
157 unrotate(coordinate, tangential);
182 xyl(0, 0) = startWirePos2D.
x() - support.
x();
183 xyl(0, 1) = startWirePos2D.
y() - support.
y();
185 w(0) = 1.0 / startDriftLengthVar;
189 xyl(1, 0) = middleWirePos2D.
x() - support.
x();
190 xyl(1, 1) = middleWirePos2D.
y() - support.
y();
192 w(1) = 1.0 / middleDriftLengthVar;
196 xyl(2, 0) = endWirePos2D.
x() - support.
x();
197 xyl(2, 1) = endWirePos2D.
y() - support.
y();
199 w(2) = 1.0 / endDriftLengthVar;
202 fitLine.passiveMoveBy(-support);
204 return fitLine.chi2();
227 xyl(0, 0) = startWirePos2D.
x() - support.
x();
228 xyl(0, 1) = startWirePos2D.
y() - support.
y();
230 w(0) = 1.0 / startDriftLengthVar;
234 xyl(1, 0) = middleWirePos2D.
x() - support.
x();
235 xyl(1, 1) = middleWirePos2D.
y() - support.
y();
237 w(1) = 1.0 / middleDriftLengthVar;
241 xyl(2, 0) = endWirePos2D.
x() - support.
x();
242 xyl(2, 1) = endWirePos2D.
y() - support.
y();
244 w(2) = 1.0 / endDriftLengthVar;
254 xyl(3, 0) = startWirePos2D.
x() - support.
x();
255 xyl(3, 1) = startWirePos2D.
y() - support.
y();
257 w(3) = 1.0 / startDriftLengthVar;
261 xyl(4, 0) = middleWirePos2D.
x() - support.
x();
262 xyl(4, 1) = middleWirePos2D.
y() - support.
y();
264 w(4) = 1.0 / middleDriftLengthVar;
268 xyl(5, 0) = endWirePos2D.
x() - support.
x();
269 xyl(5, 1) = endWirePos2D.
y() - support.
y();
271 w(5) = 1.0 / endDriftLengthVar;
275 fitLine.passiveMoveBy(-support);
284 return ::fit(std::move(xyl), std::move(w), nSteps);
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 Vector2D & getRefPos2D() const
The two dimensional reference position (z=0) of the underlying wire.
static double fit(const CDCFacet &facet, int nSteps=100)
Fits a proper line to facet and returns the chi2.
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.
A matrix implementation to be used as an interface typ through out the track finder.
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...
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.
Abstract base class for different kinds of events.