17 #include "GaudiKernel/MsgStream.h"
18 #include "GaudiKernel/SystemOfUnits.h"
31 const ToolHandle<IIntersector>& intersector,
33 const ToolHandle<IIntersector>& rungeKuttaIntersector,
34 const ToolHandle<IPropagator>& stepPropagator,
int useStepPropagator)
35 : m_asymmetricCaloEnergy(asymmetricCaloEnergy),
36 m_caloEnergyMeasurement(nullptr),
42 m_firstScatteringParameter(
parameters->firstScatteringParameter()),
44 m_intersector(intersector),
46 m_largeDeltaPhi0(0.05),
48 m_measurements(measurements),
49 m_numericDerivatives(false),
51 m_phiInstability(false),
52 m_qOverPbeforeCalo(0.),
53 m_qOverPafterCalo(0.),
54 m_rungeKuttaIntersector(rungeKuttaIntersector),
55 m_stepPropagator(stepPropagator),
56 m_useStepPropagator(useStepPropagator),
61 m_intersectStartingValue(),
70 int numberPositionMeas = 0;
85 if (
m->isPositionMeasurement())
95 if (numberPositionMeas < 5) {
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() -
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()) {
251 double floor = 0.000000030;
252 double fraction = 0.0001;
297 if (!(*m).numberDoF())
301 if (!
m->isPositionMeasurement()) {
302 if (
m->isScatterer())
307 m->residual(phiResidual);
308 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 double residual =
m->weight() * (E0 - E1 -
m->energyLoss());
334 const Amg::Vector3D& minimizationDirection =
m->minimizationDirection();
339 if (
m->alignmentParameter()) {
341 unsigned param =
m->alignmentParameter() - 1;
348 if (
m->alignmentParameter2()) {
350 param =
m->alignmentParameter2() - 1;
359 if (!
m->is2Dimensional())
361 double residual2 =
m->weight2() *
m->sensorDirection().dot(
offset);
362 m->residual2(residual2);
363 }
else if (
m->isDrift() ||
367 m->signedDriftDistance());
368 if (
m->alignmentParameter()) {
370 unsigned param =
m->alignmentParameter() - 1;
378 if (
m->alignmentParameter2()) {
380 param =
m->alignmentParameter2() - 1;
392 }
else if (
m->isPseudo())
396 if (!
m->is2Dimensional())
398 double residual2 =
m->weight2() *
m->sensorDirection().dot(
offset);
399 m->residual2(residual2);
400 }
else if (
m->isVertex()) {
402 (minimizationDirection.x() *
offset.x() +
403 minimizationDirection.y() *
offset.y()) /
404 minimizationDirection.perp();
406 if (!
m->is2Dimensional())
408 double residual2 =
m->weight2() *
m->sensorDirection().dot(
offset);
409 m->residual2(residual2);
440 if (startDirection.z() == 0. || endDirection.z() == 0.)
443 double deflectionPhi = startDirection.x() * endDirection.y() -
444 startDirection.y() * endDirection.x();
445 double deflectionTheta = startDirection.perp() * endDirection.z() -
446 startDirection.z() * endDirection.perp();
449 double shiftPhi0 = std::sqrt(covariance(2, 2));
456 startDirection =
Amg::Vector3D(sinTheta * cosPhi, sinTheta * sinPhi,
463 double deltaPhi = startDirection.x() * endDirection.y() -
464 startDirection.y() * endDirection.x() - deflectionPhi;
465 double deltaTheta = startDirection.perp() * endDirection.z() -
466 startDirection.z() * endDirection.perp() -
468 covariance(3, 3) += deltaTheta * deltaTheta;
469 if (std::abs(deflectionTheta) > 0.0001) {
472 covariance(4, 4) += deltaQOverP * deltaQOverP;
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 double dPhi = covariance(0, 2) / shiftD0;
502 cotTheta -= covariance(1, 3) / (shiftZ0 * sinTheta * sinTheta);
503 startDirection =
Amg::Vector3D(sinTheta * cosPhi, sinTheta * sinPhi,
510 double deltaPhi = startDirection.x() * endDirection.y() -
511 startDirection.y() * endDirection.x() - deflectionPhi;
512 double deltaTheta = startDirection.perp() * endDirection.z() -
513 startDirection.z() * endDirection.perp() -
517 covariance(3, 3) += deltaTheta * deltaTheta;
518 if (std::abs(deflectionTheta) > 0.0001) {
521 covariance(4, 4) += deltaQOverP * deltaQOverP;
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()) {
561 FitMeasurement& measurement) {
564 double weight = measurement.weight();
568 measurement.minimizationDirection();
569 const Amg::Vector3D& sensorDirection = measurement.sensorDirection();
572 if (std::abs(measurement.normal().dot(
intersection.direction())) < 0.001)
581 if (derivativeFlag != 0) {
586 measurement.derivative(
591 measurement.derivative(
599 measurement.derivative(
Z0, weightedProjection.z());
600 measurement.derivative(
Theta0, weightedProjection.z() * rDistance);
603 if (measurement.numericalDerivative()) {
606 measurement.derivative(
620 measurement.derivative(
D0,
m_cosPhi0 * weightedProjection.y() -
622 measurement.derivative(
Phi0, xDistance * weightedProjection.y() -
623 yDistance * weightedProjection.x());
629 std::vector<FitMeasurement*>::const_iterator
s =
m_scatterers.begin();
630 while (++param < measurement.lastParameter()) {
637 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);
647 if (measurement.alignmentParameter()) {
650 param = measurement.alignmentParameter();
661 measurement.derivative(++param,
weight * projection);
662 if (measurement.alignmentParameter2()) {
663 param = measurement.alignmentParameter2();
673 measurement.derivative(++param,
weight * projection);
680 if (derivativeFlag == 1)
682 weight = measurement.weight2();
688 measurement.derivative2(
693 measurement.derivative2(
702 measurement.derivative2(
Z0, weightedProjection.z());
703 measurement.derivative2(
Theta0, weightedProjection.z() * rDistance);
706 if (measurement.numericalDerivative()) {
709 measurement.derivative2(
716 measurement.derivative2(
722 measurement.derivative2(
D0,
m_cosPhi0 * weightedProjection.y() -
724 measurement.derivative2(
Phi0, xDistance * weightedProjection.y() -
725 yDistance * weightedProjection.x());
731 std::vector<FitMeasurement*>::const_iterator
s =
m_scatterers.begin();
732 while (++param < measurement.lastParameter()) {
733 const TrackSurfaceIntersection& scatteringCentre =
736 intersection.position().x() - scatteringCentre.position().x();
738 intersection.position().y() - scatteringCentre.position().y();
739 double rDistScat = -(scatteringCentre.direction().x() * xDistScat +
740 scatteringCentre.direction().y() * yDistScat) /
741 (scatteringCentre.direction().perp2() *
742 scatteringCentre.direction().perp());
743 measurement.derivative2(param, xDistScat * weightedProjection.y() -
744 yDistScat * weightedProjection.x());
745 measurement.derivative2(++param, weightedProjection.z() * rDistScat);
751 FitMeasurement& measurement) {
762 if (derivativeFlag != 0) {
763 double weight = measurement.weight();
764 const Amg::Vector3D& driftDirection = measurement.minimizationDirection();
765 double xDrift = driftDirection.x();
766 double yDrift = driftDirection.y();
772 measurement.derivative(
777 measurement.derivative(
781 if (measurement.numericalDerivative()) {
784 measurement.derivative(
792 measurement.derivative(
805 && !measurement.isPseudo()) {
806 measurement.derivative(
D0, 0.);
807 measurement.derivative(
Phi0, 0.);
809 measurement.derivative(
811 measurement.derivative(
812 Phi0,
weight * (xDistance * yDrift - yDistance * xDrift));
815 measurement.derivative(
Z0,
weight * driftDirection.z());
816 measurement.derivative(
Theta0,
weight * driftDirection.z() * rDistance);
821 std::vector<FitMeasurement*>::const_iterator
s =
m_scatterers.begin();
822 while (++param < measurement.lastParameter()) {
829 double rDistScat = -(scatteringCentre.
direction().x() * xDistScat +
830 scatteringCentre.
direction().y() * yDistScat) /
833 measurement.derivative(
834 param,
weight * (xDistScat * yDrift - yDistScat * xDrift));
835 measurement.derivative(++param,
weight * driftDirection.z() * rDistScat);
840 if (measurement.alignmentParameter()) {
841 param = measurement.alignmentParameter();
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);
872 if (measurement.alignmentParameter2()) {
873 param = measurement.alignmentParameter2();
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 double weight = measurement.weight2();
910 const Amg::Vector3D& wireDirection = measurement.sensorDirection();
911 double xWire = wireDirection.x();
912 double yWire = wireDirection.y();
918 measurement.derivative2(
923 measurement.derivative2(
927 if (measurement.numericalDerivative()) {
930 measurement.derivative2(
937 measurement.derivative2(
943 measurement.derivative2(
D0,
945 measurement.derivative2(
Phi0,
946 weight * (xDistance * yWire - yDistance * xWire));
949 measurement.derivative2(
Z0,
weight * wireDirection.z());
950 measurement.derivative2(
Theta0,
weight * wireDirection.z() * rDistance);
955 std::vector<FitMeasurement*>::const_iterator
s =
m_scatterers.begin();
956 while (++param < measurement.lastParameter()) {
957 const TrackSurfaceIntersection& scatteringCentre =
960 intersection.position().x() - scatteringCentre.position().x();
962 intersection.position().y() - scatteringCentre.position().y();
963 double rDistScat = -(scatteringCentre.direction().x() * xDistScat +
964 scatteringCentre.direction().y() * yDistScat) /
965 (scatteringCentre.direction().perp2() *
966 scatteringCentre.direction().perp());
967 measurement.derivative2(param,
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();
983 if ((**m).isVertex()) {
985 std::optional<TrackSurfaceIntersection> newIntersectionSTEP =
990 if (newIntersectionSTEP)
995 if (newIntersectionSTEP) {
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 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())
1109 double cosDeltaPhi = std::sqrt(1. - sinDeltaPhi * sinDeltaPhi);
1111 double tanDeltaTheta = sinDeltaTheta;
1112 if (std::abs(sinDeltaTheta) < 1.)
1113 tanDeltaTheta /= std::sqrt(1. - sinDeltaTheta * sinDeltaTheta);
1115 trackDirection /= trackDirection.perp();
1116 double cosPhi = trackDirection.x() * cosDeltaPhi -
1117 trackDirection.y() * sinDeltaPhi;
1118 double sinPhi = trackDirection.y() * cosDeltaPhi +
1119 trackDirection.x() * sinDeltaPhi;
1120 double cotTheta = (trackDirection.z() - tanDeltaTheta) /
1121 (1. + trackDirection.z() * tanDeltaTheta);
1123 trackDirection = trackDirection.unit();
1125 TrackSurfaceIntersection(
intersection->position(), trackDirection,
1136 double loss = (**m).energyLoss() * std::abs(
qOverP);
1137 qOverP *= 1. + loss + loss * loss + loss * loss * loss;