16 #include "GaudiKernel/SystemOfUnits.h"
18 #include "Identifier/Identifier.h"
38 const IInterface*
parent,
bool globalFit)
40 m_globalFit(globalFit),
42 m_messageHelper = std::make_unique<MessageHelper>(*
this, 26);
43 declareInterface<ITrackFitter>(
this);
50 "fit (Track): outlier removal not implemented");
53 2,
"fit (Track): track without trackStateOnSurfaces");
55 3,
"fit (Track + PrepRawDataSet): interface not implemented");
57 4,
"fit (PrepRawDataSet): interface not implemented");
59 5,
"fit (Track + MeasurementSet): outlier removal not implemented");
61 6,
"fit (Track + MeasurementSet): track without trackStateOnSurfaces");
63 7,
"fit (Track + MeasurementSet): track without measuredPerigee");
65 8,
"fit (Track + MeasurementSet): FIX material may get double counted");
67 9,
"fit (Perigee + MeasurementSet): outlier removal not implemented");
69 "fit (Perigee + MeasurementSet): null perigee");
71 11,
"fit (combined muon): outlier removal not implemented");
73 "fit (combined muon): no perigee start value");
75 13,
"fit (combined muon): indet track without trackStateOnSurfaces");
77 14,
"fit (combined muon): indet track without measuredPerigee");
79 15,
"addMeasurements: no intersection to MeasurementSet");
81 16,
"addMeasurements: skip TSOS as not understood. Type: ");
83 17,
"addMeasurements: skip TSOS with missing trackParameters. Type: ");
86 "addMeasurements: skip measurement as fail to intersect associated "
87 "surface from given starting parameters");
88 m_messageHelper->setMessage(19,
"addMeasurements: TSOS skipped. Type: ");
90 "fail fit as CaloDeposit outside calo volume");
92 21,
"conflicting energy deposit sign for inDet material");
94 22,
"conflicting energy deposit sign for spectrometer material");
95 m_messageHelper->setMessage(23,
"excessive calorimeter energy loss : ");
96 m_messageHelper->setMessage(24,
"excessive spectrometer energy loss : ");
108 return StatusCode::FAILURE;
129 return StatusCode::SUCCESS;
136 double iterations = 0.;
147 <<
" track-fits attempted, out of which " << std::setw(5)
148 << std::setprecision(1) << goodFit
149 <<
"% converged, taking an average " << std::setw(5)
150 << std::setprecision(2) << iterations <<
" iterations");
154 double goodRefit = 0.;
155 double refitIterations = 0.;
165 <<
" refits attempted, out of which " << std::setw(5)
166 << std::setprecision(1) << goodRefit
167 <<
"% converged, taking an average " << std::setw(5)
168 << std::setprecision(2) << refitIterations <<
" iterations");
173 return StatusCode::SUCCESS;
179 -> std::pair<std::unique_ptr<Track>, std::unique_ptr<FitState>> {
181 auto fitState = std::make_unique<FitState>();
183 m_countFitAttempts++;
186 m_messageHelper->printWarning(0);
194 std::unique_ptr<Perigee> newPerigee;
195 std::unique_ptr<PerigeeSurface> perigeeSurface;
198 auto i =
track.trackStateOnSurfaces()->begin();
199 while (
i !=
track.trackStateOnSurfaces()->end() &&
200 !(**i).trackParameters()) {
204 if (!
s.trackParameters()) {
206 m_messageHelper->printWarning(1);
207 return {
nullptr, std::move(fitState)};
211 perigeeSurface = std::make_unique<PerigeeSurface>(origin);
212 newPerigee = std::make_unique<Perigee>(
213 s.trackParameters()->position(),
s.trackParameters()->momentum(),
214 s.trackParameters()->charge(), *perigeeSurface);
220 fitState->parameters = std::make_unique<FitParameters>(perigee);
223 if (!
track.trackStateOnSurfaces()) {
225 m_messageHelper->printWarning(2);
226 return {
nullptr, std::move(fitState)};
229 fitState->newMeasurements();
232 addMeasurements(ctx, fitState->getMeasurements(), *fitState->parameters,
233 particleHypothesis, *
track.trackStateOnSurfaces());
238 m_materialAllocator->allocateMaterial(
239 fitState->getMeasurements(), particleHypothesis, *fitState->parameters,
246 std::unique_ptr<Trk::Track> fittedTrack{performFit(
247 *fitState, particleHypothesis,
trackInfo,
nullptr,
nullptr, garbage)};
250 for (
int i = 0;
i < m_forcedRefitsForValidation; ++
i) {
252 refit(ctx, *fitState, *fittedTrack, runOutlier, particleHypothesis);
256 return {std::move(fittedTrack), std::move(fitState)};
263 auto [fittedTrack, fitState] =
266 return std::move(fittedTrack);
270 const EventContext&,
const Track& ,
303 if (!
track.trackStateOnSurfaces()) {
309 (**
track.trackStateOnSurfaces()->begin()).trackParameters());
317 fitState.
parameters = std::make_unique<FitParameters>(*perigee);
322 particleHypothesis, *
track.trackStateOnSurfaces()))
330 *(
track.trackStateOnSurfaces()->back()->trackParameters());
340 track.trackStateOnSurfaces(),
track.fitQuality(), garbage);
355 const Perigee* perigee =
dynamic_cast<const Perigee*
>(&perigeeStartValue);
363 fitState.
parameters = std::make_unique<FitParameters>(*perigee);
373 perigeeStartValue, garbage);
383 const EventContext& ctx,
const Track& indetTrack,
394 bool haveMaterial =
true;
415 const Perigee* spectrometerPerigee =
417 if (spectrometerPerigee &&
420 spectrometerPerigee =
nullptr;
424 spectrometerPerigee) {
426 !indetPerigee || !indetPerigee->covariance()) {
433 }
else if (indetPerigee) {
434 if (spectrometerPerigee->covariance() &&
440 " set starting momentum from spectrometer "
457 haveMaterial =
false;
465 haveMaterial =
false;
470 if (startingPerigee) {
473 *startingPerigee, garbage);
474 delete startingPerigee;
483 std::unique_ptr<Trk::Track> fittedTrack =
performFit(
484 fitState, particleHypothesis,
trackInfo,
nullptr,
nullptr, garbage);
489 refit(ctx, fitState, *fittedTrack, runOutlier, particleHypothesis);
503 std::unique_ptr<Trk::Track> fittedTrack =
performFit(
510 refit(ctx, fitState, *fittedTrack, runOutlier, particleHypothesis);
518 std::vector<FitMeasurement*>& measurements,
524 double previousDistanceR = previousDistance;
525 double previousDistanceZ = previousDistance;
526 bool reorder =
false;
534 int hit = measurements.size();
535 for (MeasurementSet::const_iterator
m = measurementSet.begin();
536 m != measurementSet.end(); ++
m, ++hit) {
537 std::optional<TrackSurfaceIntersection> newIntersection{
539 startIntersection,
qOverP,
541 if (newIntersection) {
547 startDirection.dot(
intersection.position() - startPosition);
549 double distanceR = std::sqrt((positionMst.x() - startPosition.x()) *
550 (positionMst.x() - startPosition.x()) +
551 (positionMst.y() - startPosition.y()) *
552 (positionMst.y() - startPosition.y()));
553 double distanceZ = (positionMst.z() - startPosition.z());
554 if (startDirection.z() < 0) {
555 distanceZ = -distanceZ;
557 if (
distance < previousDistance && distanceR < previousDistanceR &&
558 distanceZ < previousDistanceZ) {
561 <<
distance - previousDistance <<
" R distance "
562 << distanceR - previousDistanceR <<
" Z distance "
563 << distanceZ - previousDistanceZ);
575 auto measurement = std::make_unique<FitMeasurement>(hit,
nullptr, *
m);
577 measurement->qOverP(
qOverP);
578 measurements.push_back(measurement.release());
580 startIntersection = (measurements.back()->intersection(
type));
591 const EventContext& ctx, std::vector<FitMeasurement*>& measurements,
595 std::vector<Identifier> misAlignedTSOS;
596 std::vector<int> misAlignmentNumbers;
597 int misAlignmentNumber = 0;
601 i != trackStateOnSurfaces.
end(); ++
i, ++tsos) {
603 if (!
r.alignmentEffectsOnTrack() || !
r.trackParameters()) {
607 ++misAlignmentNumber;
609 misAlignedTSOS.push_back(
a);
610 misAlignmentNumbers.push_back(misAlignmentNumber);
614 " tsos " << tsos <<
" misAlignedTSOS.size() " << misAlignedTSOS.size()
615 <<
" misAlignmentNumber " << misAlignmentNumber
623 bool haveMaterial =
false;
624 bool haveMeasurement =
false;
625 int hit = measurements.size();
627 double previousDistanceR = previousDistance;
628 double previousDistanceZ = previousDistance;
629 bool reorder =
false;
630 const bool skipVertexMeasurement = !measurements.empty();
635 bool measurementsFlipped =
false;
640 i != trackStateOnSurfaces.
end(); ++
i, ++hit, ++tsos) {
642 std::unique_ptr<FitMeasurement> measurement1;
643 std::unique_ptr<FitMeasurement> measurement2;
644 const Surface* surface =
nullptr;
645 if (
s.materialEffectsOnTrack() &&
s.trackParameters()) {
650 surface = &
s.trackParameters()->associatedSurface();
653 bool keepScatterer =
true;
654 if (
s.materialEffectsOnTrack()->thicknessInX0() < 0.0001) {
655 keepScatterer =
false;
659 s.materialEffectsOnTrack());
664 keepScatterer =
true;
670 measurement1 = std::make_unique<FitMeasurement>(
671 s.materialEffectsOnTrack(),
674 if (!calo && !haveMaterial &&
675 (haveMeasurement ||
s.measurementOnTrack())) {
682 }
else if (
s.alignmentEffectsOnTrack() &&
s.trackParameters()) {
685 measurement1 = std::make_unique<FitMeasurement>(
686 s.alignmentEffectsOnTrack(), direction, position);
689 if (measurementBase) {
694 if (skipVertexMeasurement &&
696 measurement1.reset();
699 haveMeasurement =
true;
700 surface = &
s.measurementOnTrack()->associatedSurface();
702 std::make_unique<FitMeasurement>(hit,
nullptr, measurementBase);
704 measurement2->setOutlier();
719 if (misAlignmentNumber) {
721 if (measurementBase) {
736 for (
unsigned int im = 0;
im < misAlignedTSOS.size(); ++
im) {
737 if (misAlignedTSOS[
im] !=
id) {
740 measurement2->alignmentParameter(misAlignmentNumbers[
im]);
743 for (
unsigned int im = 0;
im < misAlignedTSOS.size(); ++
im) {
744 if (misAlignedTSOS[
im] !=
id) {
747 if (measurement2->isDrift()) {
749 <<
" with misAlignmentNumber "
750 << misAlignmentNumbers[
im]);
753 <<
" with misAlignmentNumber "
754 << misAlignmentNumbers[
im]);
759 }
else if (!measurement1 &&
s.trackParameters()) {
761 measurement2 = std::make_unique<FitMeasurement>(
s);
763 if (
i == trackStateOnSurfaces.
begin()) {
767 dynamic_cast<const Perigee*
>(
s.trackParameters());
771 measurement2 = std::make_unique<FitMeasurement>(*perigee);
779 }
else if (
s.materialEffectsOnTrack()) {
780 surface = &
s.materialEffectsOnTrack()->associatedSurface();
781 }
else if (
s.alignmentEffectsOnTrack()) {
782 surface = &
s.alignmentEffectsOnTrack()->associatedSurface();
791 if (
s.trackParameters() && (measurement1 || measurement2)) {
793 if (startDirection.dot(direction) < 0.) {
794 measurementsFlipped =
true;
795 direction = -direction;
797 measurement1->flipDriftDirection();
800 measurement2->flipDriftDirection();
805 s.trackParameters()->position(), direction, 0.);
806 }
else if (surface) {
807 std::optional<TrackSurfaceIntersection> newIntersection =
811 if (!newIntersection) {
813 measurement2.reset();
818 if (
s.materialEffectsOnTrack()) {
822 measurement1 = std::make_unique<FitMeasurement>(
823 s.materialEffectsOnTrack(),
826 if (!calo && !haveMaterial && haveMeasurement) {
829 }
else if (!measurement2) {
840 startDirection.dot(
intersection.position() - startPosition);
842 if (
s.measurementOnTrack()) {
843 positionMst =
s.measurementOnTrack()->globalPosition();
845 if (
s.materialEffectsOnTrack()) {
846 positionMst =
s.materialEffectsOnTrack()->associatedSurface().center();
848 double distanceR = std::sqrt((positionMst.x() - startPosition.x()) *
849 (positionMst.x() - startPosition.x()) +
850 (positionMst.y() - startPosition.y()) *
851 (positionMst.y() - startPosition.y()));
852 double distanceZ = (positionMst.z() - startPosition.z());
853 if (startDirection.z() < 0) {
854 distanceZ = -distanceZ;
856 if (
distance < previousDistance && distanceR < previousDistanceR &&
857 distanceZ < previousDistanceZ) {
860 <<
distance - previousDistance <<
" R distance "
861 << distanceR - previousDistanceR <<
" Z distance "
862 << distanceZ - previousDistanceZ);
873 measurement1->intersection(
type, intersectionCopy);
874 measurements.push_back(measurement1.release());
877 measurement1->qOverP(
qOverP);
878 measurements.push_back(measurement1.release());
883 measurement2->qOverP(
qOverP);
884 measurements.push_back(measurement2.release());
893 if (measurementsFlipped) {
905 std::vector<FitMeasurement*>& measurements = fitState.getMeasurements();
930 std::unique_ptr<Track> fittedTrack;
947 *fittedTrack->trackStateOnSurfaces()) {
951 if (tsos->trackParameters()) {
952 const Amg::Vector3D position = tsos->trackParameters()->position();
961 "fail fit as CaloDeposit outside calo volume: " << (*fittedTrack));
977 double caloEloss = 0.;
980 double indetEloss = 0.;
983 double spectEloss = 0.;
985 if (
m->isEnergyDeposit()) {
987 caloEloss +=
m->energyLoss();
988 }
else if (!
m->isScatterer()) {
994 indetX0 +=
m->materialEffects()->thicknessInX0();
995 indetEloss +=
m->energyLoss();
997 if (
m->energyLoss() * indetEloss < 0.) {
1005 caloX0 +=
m->materialEffects()->thicknessInX0();
1010 spectX0 +=
m->materialEffects()->thicknessInX0();
1011 spectEloss +=
m->energyLoss();
1013 if (
m->energyLoss() * spectEloss < 0.) {
1023 std::stringstream
ss;
1025 << fittedTrack->perigeeParameters()->momentum().mag() /
1033 (std::abs(spectEloss * caloX0) >
1034 std::abs(4. * caloEloss * spectX0)) &&
1036 std::stringstream
ss;
1039 <<
" calorimeter energy loss). Track has P "
1040 << fittedTrack->perigeeParameters()->momentum().mag() /
1049 msg() << std::setw(5) << indet <<
" indet scatterers with"
1050 <<
" material: X0" << std::setw(6) << std::setprecision(3)
1052 if (calo && caloEloss < 0.) {
1053 msg() <<
" energyGain";
1055 msg() <<
" energyLoss";
1057 msg() << std::setw(6) << std::setprecision(3)
1062 msg() << std::setw(5) << spect <<
" spectrometer scatterers with"
1063 <<
" material: X0" << std::setw(8) << std::setprecision(3)
1065 if (calo && caloEloss < 0.) {
1066 msg() <<
" energyGain";
1068 msg() <<
" energyLoss";
1070 msg() << std::setw(7) << std::setprecision(3)
1074 if (!indet && !spect) {
1075 msg() <<
" 0 scatterers - no tracking material";
1094 msg(MSG::INFO) <<
" track with " <<
track.trackStateOnSurfaces()->size()
1098 track.trackStateOnSurfaces()->begin();
1099 t !=
track.trackStateOnSurfaces()->end(); ++
t, ++tsos) {
1100 msg() << std::setiosflags(std::ios::fixed | std::ios::right) <<
" TSOS# "
1101 << std::setw(3) << tsos <<
" parameters: " << std::setw(7)
1102 << std::setprecision(1) << (**t).trackParameters()->position().perp()
1103 << std::setw(8) << std::setprecision(4)
1104 << (**t).trackParameters()->position().phi() << std::setw(9)
1105 << std::setprecision(1) << (**t).trackParameters()->position().z()
1106 <<
" position " << std::setw(8) << std::setprecision(4)
1107 << (**t).trackParameters()->momentum().phi() <<
" phi "
1108 << std::setw(7) << std::setprecision(4)
1109 << (**t).trackParameters()->momentum().theta() <<
" theta "
1110 << std::setw(9) << std::setprecision(4)
1114 if ((**t).measurementOnTrack()) {
1119 if ((**t).materialEffectsOnTrack()) {
1145 std::unique_ptr<Perigee> newPerigee;
1146 std::unique_ptr<PerigeeSurface> perigeeSurface;
1149 auto i =
track.trackStateOnSurfaces()->begin();
1150 while (
i !=
track.trackStateOnSurfaces()->end() &&
1151 !(**i).trackParameters()) {
1154 const TrackStateOnSurface&
s = (**i);
1155 if (!
s.trackParameters()) {
1166 perigeeSurface = std::make_unique<PerigeeSurface>(origin);
1167 newPerigee = std::make_unique<Perigee>(
1168 s.trackParameters()->position(),
s.trackParameters()->momentum(),
1169 s.trackParameters()->charge(), *perigeeSurface);
1175 fitState.parameters = std::make_unique<FitParameters>(perigee);
1178 if (!
track.trackStateOnSurfaces()) {
1188 fitState.newMeasurements();
1191 addMeasurements(ctx, fitState.getMeasurements(), *fitState.parameters,
1192 particleHypothesis, *
track.trackStateOnSurfaces());
1198 fitState.getMeasurements(), particleHypothesis, *fitState.parameters,
1205 std::unique_ptr<Trk::Track> fittedTrack{
performFit(
1206 fitState, particleHypothesis,
trackInfo,
nullptr,
nullptr, garbage)};