17#include "GaudiKernel/MsgStream.h"
18#include "GaudiKernel/SystemOfUnits.h"
31 const ToolHandle<IIntersector>& intersector,
32 std::vector<FitMeasurement*>& measurements,
FitParameters* parameters,
33 const ToolHandle<IIntersector>& rungeKuttaIntersector,
34 const ToolHandle<IPropagator>& stepPropagator,
int useStepPropagator)
62 m_x0(parameters->position().
x()),
63 m_y0(parameters->position().
y()),
64 m_z0(parameters->position().
z())
70 int numberPositionMeas = 0;
85 if (m->isPositionMeasurement())
92 if (!m->isEnergyDeposit() || !
m_parameters->fitMomentum())
95 if (numberPositionMeas < 5) {
162 const double cotTheta =
164 sinTheta = 1. / std::sqrt(1. + cotTheta * cotTheta);
166 sinTheta * cotTheta);
178 if (m->isCluster()) {
180 }
else if (m->isDrift() || m->isPerigee() ||
187 driftDirection = driftDirection.unit();
188 m->minimizationDirection(driftDirection);
190 }
else if (m->isVertex()) {
195 minimizationDirection = minimizationDirection.unit();
196 m->minimizationDirection(minimizationDirection);
198 m->weight() * (
m_cosPhi0 * m->minimizationDirection().y() -
199 m_sinPhi0 * m->minimizationDirection().x()));
200 if (m->is2Dimensional())
201 m->derivative2(
Z0, m->weight2() * m->sensorDirection().z());
202 }
else if (!m->numberDoF()) {
204 }
else if (m->isScatterer()) {
205 unsigned param = m->lastParameter() - 2;
209 m->derivative2(++param, m->weight());
210 }
else if (m->isAlignment()) {
211 unsigned param = m->firstParameter();
212 m->derivative(param, m->weight());
213 m->derivative2(++param, m->weight2());
214 }
else if (m->isEnergyDeposit()) {
217 const double weight = m->weight();
251 const double floor = 0.000000030;
252 const double fraction = 0.0001;
297 if (!(*m).numberDoF())
301 if (!m->isPositionMeasurement()) {
302 if (m->isScatterer())
304 const double phiResidual =
307 m->residual(phiResidual);
308 const double thetaResidual =
310 (*m).residual2(thetaResidual);
312 }
else if ((*m).isAlignment())
314 (*m).residual(-m->weight() *
317 (*m).residual2(-m->weight2() *
321 }
else if (m->isEnergyDeposit()) {
325 const double residual = m->weight() * (E0 - E1 - m->energyLoss());
326 m->residual(residual);
334 const Amg::Vector3D& minimizationDirection = m->minimizationDirection();
338 double residual = m->weight() * minimizationDirection.dot(offset);
339 if (m->alignmentParameter()) {
341 unsigned param = m->alignmentParameter() - 1;
345 m_parameters->alignmentAngle(param) * m->derivative(deriv) +
346 m_parameters->alignmentOffset(param) * m->derivative(deriv + 1);
348 if (m->alignmentParameter2()) {
350 param = m->alignmentParameter2() - 1;
354 m_parameters->alignmentAngle(param) * m->derivative(deriv) +
355 m_parameters->alignmentOffset(param) * m->derivative(deriv + 1);
358 m->residual(residual);
359 if (!m->is2Dimensional())
361 const double residual2 = m->weight2() * m->sensorDirection().dot(offset);
362 m->residual2(residual2);
363 }
else if (m->isDrift() ||
366 double residual = m->weight() * (minimizationDirection.dot(offset) +
367 m->signedDriftDistance());
368 if (m->alignmentParameter()) {
370 unsigned param = m->alignmentParameter() - 1;
374 m_parameters->alignmentAngle(param) * m->derivative(deriv) +
375 m_parameters->alignmentOffset(param) * m->derivative(deriv + 1);
378 if (m->alignmentParameter2()) {
380 param = m->alignmentParameter2() - 1;
384 m_parameters->alignmentAngle(param) * m->derivative(deriv) +
385 m_parameters->alignmentOffset(param) * m->derivative(deriv + 1);
388 m->residual(residual);
392 }
else if (m->isPseudo())
394 const double residual = m->weight() * minimizationDirection.dot(offset);
395 m->residual(residual);
396 if (!m->is2Dimensional())
398 const double residual2 = m->weight2() * m->sensorDirection().dot(offset);
399 m->residual2(residual2);
400 }
else if (m->isVertex()) {
401 const double residual = m->weight() *
402 (minimizationDirection.x() * offset.x() +
403 minimizationDirection.y() * offset.y()) /
404 minimizationDirection.perp();
405 m->residual(residual);
406 if (!m->is2Dimensional())
408 const double residual2 = m->weight2() * m->sensorDirection().dot(offset);
409 m->residual2(residual2);
440 if (startDirection.z() == 0. || endDirection.z() == 0.)
443 const double deflectionPhi = startDirection.x() * endDirection.y() -
444 startDirection.y() * endDirection.x();
445 const double deflectionTheta = startDirection.perp() * endDirection.z() -
446 startDirection.z() * endDirection.perp();
449 const double shiftPhi0 = std::sqrt(covariance(2, 2));
455 sinTheta = 1. / std::sqrt(1. + cotTheta * cotTheta);
456 startDirection =
Amg::Vector3D(sinTheta * cosPhi, sinTheta * sinPhi,
457 sinTheta * cotTheta);
463 const double deltaPhi = startDirection.x() * endDirection.y() -
464 startDirection.y() * endDirection.x() - deflectionPhi;
465 const double deltaTheta = startDirection.perp() * endDirection.z() -
466 startDirection.z() * endDirection.perp() -
468 covariance(3, 3) += deltaTheta * deltaTheta;
469 if (std::abs(deflectionTheta) > 0.0001) {
470 const double deltaQOverP =
471 (deltaTheta / deflectionTheta) *
m_parameters->qOverP();
472 covariance(4, 4) += deltaQOverP * deltaQOverP;
474 if (log.level() < MSG::DEBUG) {
475 log << MSG::VERBOSE << std::setiosflags(std::ios::fixed)
476 <<
" fieldIntegralUncertainty: "
477 <<
" shiftPhi0 " << std::setw(8) << std::setprecision(3) << shiftPhi0
478 <<
" deflection (phi,theta) " << std::setw(8) << std::setprecision(4)
479 << deflectionPhi << std::setw(8) << std::setprecision(4)
480 << deflectionTheta <<
" diff " << std::setw(8)
481 << std::setprecision(4) <<
deltaPhi << std::setw(8)
482 << std::setprecision(4) << deltaTheta <<
endmsg;
487 double shiftD0 = std::sqrt(covariance(0, 0));
488 double shiftZ0 = std::sqrt(covariance(1, 1));
497 const double dPhi = covariance(0, 2) / shiftD0;
501 sinTheta = 1. / std::sqrt(1. + cotTheta * cotTheta);
502 cotTheta -= covariance(1, 3) / (shiftZ0 * sinTheta * sinTheta);
503 startDirection =
Amg::Vector3D(sinTheta * cosPhi, sinTheta * sinPhi,
504 sinTheta * cotTheta);
510 const double deltaPhi = startDirection.x() * endDirection.y() -
511 startDirection.y() * endDirection.x() - deflectionPhi;
512 const double deltaTheta = startDirection.perp() * endDirection.z() -
513 startDirection.z() * endDirection.perp() -
517 covariance(3, 3) += deltaTheta * deltaTheta;
518 if (std::abs(deflectionTheta) > 0.0001) {
519 const double deltaQOverP =
520 (deltaTheta / deflectionTheta) *
m_parameters->qOverP();
521 covariance(4, 4) += deltaQOverP * deltaQOverP;
524 if (log.level() < MSG::DEBUG) {
525 log << MSG::VERBOSE << std::setiosflags(std::ios::fixed)
526 <<
" fieldIntegralUncertainty: "
527 <<
" shiftD0 " << std::setw(8) << std::setprecision(1) << shiftD0
528 <<
" shiftZ0 " << std::setw(8) << std::setprecision(1) << shiftZ0
529 <<
" deflection (phi,theta) " << std::setw(8) << std::setprecision(4)
530 << deflectionPhi << std::setw(8) << std::setprecision(4)
531 << deflectionTheta <<
" diff " << std::setw(8)
532 << std::setprecision(4) <<
deltaPhi << std::setw(8)
533 << std::setprecision(4) << deltaTheta <<
endmsg;
543 if (!m->isPositionMeasurement() || m->numberDoF() > 1)
545 int derivativeFlag = 0;
546 if (m->numberDoF()) {
552 if (m->isCluster()) {
554 }
else if (m->isDrift() || m->isPerigee() || m->isPseudo()) {
564 double weight = measurement.
weight();
581 if (derivativeFlag != 0) {
597 weight * sensorDirection.cross(
intersection.direction()) /
613 measurement.
derivative(
Phi0, weight * minimizationDirection.dot(offset) /
623 yDistance * weightedProjection.x());
628 unsigned param =
m_parameters->firstScatteringParameter();
629 std::vector<FitMeasurement*>::const_iterator s =
m_scatterers.begin();
633 const double xDistScat =
635 const double yDistScat =
637 const double rDistScat = -(scatteringCentre.
direction().
x() * xDistScat +
638 scatteringCentre.
direction().y() * yDistScat) /
641 measurement.
derivative(param, xDistScat * weightedProjection.y() -
642 yDistScat * weightedProjection.x());
643 measurement.
derivative(++param, weightedProjection.z() * rDistScat);
660 measurement.
derivative(param, weight * distance);
661 measurement.
derivative(++param, weight * projection);
672 measurement.
derivative(param, weight * distance);
673 measurement.
derivative(++param, weight * projection);
680 if (derivativeFlag == 1)
682 weight = measurement.
weight2();
700 -weight * minimizationDirection.cross(
intersection.direction()) /
725 yDistance * weightedProjection.x());
730 unsigned param =
m_parameters->firstScatteringParameter();
731 std::vector<FitMeasurement*>::const_iterator s =
m_scatterers.begin();
735 const double xDistScat =
737 const double yDistScat =
739 const double rDistScat = -(scatteringCentre.
direction().
x() * xDistScat +
740 scatteringCentre.
direction().y() * yDistScat) /
743 measurement.
derivative2(param, xDistScat * weightedProjection.y() -
744 yDistScat * weightedProjection.x());
745 measurement.
derivative2(++param, weightedProjection.z() * rDistScat);
762 if (derivativeFlag != 0) {
763 const double weight = measurement.
weight();
765 const double xDrift = driftDirection.x();
766 const double yDrift = driftDirection.y();
812 Phi0, weight * (xDistance * yDrift - yDistance * xDrift));
815 measurement.
derivative(
Z0, weight * driftDirection.z());
820 unsigned param =
m_parameters->firstScatteringParameter();
821 std::vector<FitMeasurement*>::const_iterator s =
m_scatterers.begin();
825 const double xDistScat =
827 const double yDistScat =
829 const double rDistScat = -(scatteringCentre.
direction().
x() * xDistScat +
830 scatteringCentre.
direction().y() * yDistScat) /
834 param, weight * (xDistScat * yDrift - yDistScat * xDrift));
835 measurement.
derivative(++param, weight * driftDirection.z() * rDistScat);
853 double rDistance = -(alignmentCentre.
direction().
x() * xDistance +
854 alignmentCentre.
direction().y() * yDistance) /
857 measurement.
derivative(param, weight * driftDirection.z() * rDistance);
861 double projection = 0;
863 if (std::abs(surface.
normal().z()) > 0.5) {
864 projection = (driftDirection.x() * surface.
center().x() +
865 driftDirection.y() * surface.
center().y()) /
868 projection = driftDirection.z();
870 measurement.
derivative(++param, weight * projection);
885 rDistance = -(alignmentCentre.
direction().
x() * xDistance +
886 alignmentCentre.
direction().y() * yDistance) /
889 measurement.
derivative(param, weight * driftDirection.z() * rDistance);
894 if (surface.
normal().dot(surface.
center().unit()) < 0.5) {
895 projection = driftDirection.z();
897 projection = (driftDirection.x() * surface.
center().x() +
898 driftDirection.y() * surface.
center().y()) /
901 measurement.
derivative(++param, weight * projection);
907 if (derivativeFlag == 1)
909 const double weight = measurement.
weight2();
911 const double xWire = wireDirection.x();
912 const double yWire = wireDirection.y();
946 weight * (xDistance * yWire - yDistance * xWire));
954 unsigned param =
m_parameters->firstScatteringParameter();
955 std::vector<FitMeasurement*>::const_iterator s =
m_scatterers.begin();
959 const double xDistScat =
961 const double yDistScat =
963 const double rDistScat = -(scatteringCentre.
direction().
x() * xDistScat +
964 scatteringCentre.
direction().y() * yDistScat) /
968 weight * (xDistScat * yWire - yDistScat * xWire));
969 measurement.
derivative2(++param, weight * wireDirection.z() * rDistScat);
979 const Surface* surface =
nullptr;
980 const EventContext& ctx = Gaudi::Hive::currentContext();
982 std::vector<FitMeasurement*>::iterator m =
m_measurements.begin();
983 if ((**m).isVertex()) {
985 std::optional<TrackSurfaceIntersection> newIntersectionSTEP =
990 if (newIntersectionSTEP)
992 (newIntersectionSTEP->position() -
intersection->position()).mag();
995 if (newIntersectionSTEP) {
998 (newIntersectionSTEP->position() -
intersection->position()).mag();
999 std::cout <<
" iMeasProc 1 distance STEP and Intersector " << dist
1000 <<
" ex dist " << exdist << std::endl;
1002 std::cout <<
" iMeasProc 1 ALARM distance STEP and Intersector "
1003 << dist <<
" ex dist " << exdist << std::endl;
1006 std::cout <<
" iMeasProc 1 ALARM STEP did not intersect! "
1017 surface = (**m).surface();
1028 if ((**m).afterCalo()) {
1034 if ((**m).numberDoF() && (**m).isScatterer())
1040 if ((**m).surface() != surface) {
1042 std::optional<TrackSurfaceIntersection> newIntersectionSTEP =
1047 if (newIntersectionSTEP)
1048 exdist = (newIntersectionSTEP->position() -
intersection->position())
1053 if (newIntersectionSTEP) {
1054 const double dist = 1000. * (newIntersectionSTEP->position() -
1057 std::cout <<
" iMeasProc 2 distance STEP and Intersector " << dist
1058 <<
" ex dist " << exdist << std::endl;
1060 std::cout <<
" iMeasProc 2 ALARM distance STEP and Intersector "
1061 << dist <<
" ex dist " << exdist << std::endl;
1064 std::cout <<
" iMeasProc 2 ALARM STEP did not intersect! "
1075 surface = (**m).surface();
1084 if ((**m).isEnergyDeposit() || (**m).isScatterer()) {
1086 if ((**m).numberDoF()) {
1087 if ((**m).isEnergyDeposit())
1105 if ((**m).isScatterer())
1108 const double sinDeltaPhi = std::sin(
m_parameters->scattererPhi(nScat));
1109 const double cosDeltaPhi = std::sqrt(1. - sinDeltaPhi * sinDeltaPhi);
1110 const double sinDeltaTheta = std::sin(
m_parameters->scattererTheta(nScat));
1111 double tanDeltaTheta = sinDeltaTheta;
1112 if (std::abs(sinDeltaTheta) < 1.)
1113 tanDeltaTheta /= std::sqrt(1. - sinDeltaTheta * sinDeltaTheta);
1115 trackDirection /= trackDirection.perp();
1116 const double cosPhi = trackDirection.x() * cosDeltaPhi -
1117 trackDirection.y() * sinDeltaPhi;
1118 const double sinPhi = trackDirection.y() * cosDeltaPhi +
1119 trackDirection.x() * sinDeltaPhi;
1120 const double cotTheta = (trackDirection.z() - tanDeltaTheta) /
1121 (1. + trackDirection.z() * tanDeltaTheta);
1123 trackDirection = trackDirection.unit();
1136 const double loss = (**m).energyLoss() * std::abs(
qOverP);
1137 qOverP *= 1. + loss + loss * loss + loss * loss * loss;
1139 double momentum = 1. /
qOverP;
1140 if (momentum > 0.) {
1141 momentum -= (**m).energyLoss();
1143 momentum += (**m).energyLoss();
Scalar perp2() const
perp2 method - perpendicular length squared
Scalar deltaPhi(const MatrixBase< Derived > &vec) const
double derivative(int param) const
const Amg::Vector3D & sensorDirection(void) const
bool afterCalo(void) const
const TrackSurfaceIntersection & intersection(ExtrapolationType type) const
double weight(void) const
unsigned alignmentParameter(void) const
double weight2(void) const
bool numericalDerivative(void) const
unsigned alignmentParameter2(void) const
unsigned lastParameter(void) const
const Amg::Vector3D & minimizationDirection(void) const
const Amg::Vector3D & normal(void) const
double derivative2(int param) const
bool isPseudo(void) const
const Surface * surface(void) const
magnetic field properties to steer the behavior of the extrapolation
bool calculateFittedTrajectory(int iteration)
const ToolHandle< IIntersector > & m_rungeKuttaIntersector
std::vector< FitMeasurement * > m_alignments
TrackSurfaceIntersection m_vertexIntersect
~MeasurementProcessor(void)
void propagationDerivatives(void)
FitParameters * m_parameters
const ToolHandle< IPropagator > & m_stepPropagator
bool calculateDerivatives(void)
void clusterDerivatives(int derivativeFlag, FitMeasurement &measurement)
double m_delta[ExtrapolationTypes]
TrackSurfaceIntersection m_intersectStartingValue
Trk::MagneticFieldProperties m_stepField
std::vector< FitMeasurement * > m_scatterers
void fieldIntegralUncertainty(MsgStream &log, Amg::MatrixX &covariance)
MeasurementProcessor(bool asymmetricCaloEnergy, Amg::MatrixX &derivativeMatrix, const ToolHandle< IIntersector > &intersector, std::vector< FitMeasurement * > &measurements, FitParameters *parameters, const ToolHandle< IIntersector > &rungeKuttaIntersector, const ToolHandle< IPropagator > &stepPropagator, int useStepPropagator)
double m_qOverP[ExtrapolationTypes]
void driftDerivatives(int derivativeFlag, FitMeasurement &measurement)
double m_qOverPbeforeCalo
void calculateResiduals(void)
bool extrapolateToMeasurements(ExtrapolationType type)
FitMeasurement * m_caloEnergyMeasurement
int m_firstScatteringParameter
std::vector< FitMeasurement * > & m_measurements
const ToolHandle< IIntersector > & m_intersector
bool m_asymmetricCaloEnergy
bool m_numericDerivatives
Abstract Base Class for tracking surfaces.
virtual const Amg::Vector3D & normal() const
Returns the normal vector of the Surface (i.e.
const Amg::Vector3D & center() const
Returns the center position of the Surface.
An intersection with a Surface is given by.
const Amg::Vector3D & direction() const
Method to retrieve the direction at the Intersection.
const Amg::Vector3D & position() const
Method to retrieve the position of the Intersection.
std::vector< std::string > intersection(std::vector< std::string > &v1, std::vector< std::string > &v2)
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic Matrix - dynamic allocation.
bool hasPositiveOrZeroDiagElems(const AmgSymMatrix(N) &mat)
Returns true if all diagonal elements of the covariance matrix are finite aka sane in the above defin...
Eigen::Matrix< double, 3, 1 > Vector3D
=============================================================================
Ensure that the ATLAS eigen extensions are properly loaded.
@ FastField
call the fast field access method of the FieldSvc
@ FullField
Field is set to be realistic, but within a given Volume.
@ z
global position (cartesian)