580 {
581 MagField::AtlasFieldCache fieldCache;
582
583
585
586
587 if (
m_trackQuery->isLineFit(inputSpectrometerTrack) && !fieldCache.
toroidOn()) {
return nullptr; }
588
589 ATH_MSG_DEBUG(
" standaloneFit beam position bs_x " << origin <<
" inputVertex "
590 << inputVertex);
591
592 if (msgLvl(MSG::VERBOSE)) {
593 msg(MSG::VERBOSE) <<
endmsg <<
"==== Start of standaloneFit:: " << std::setiosflags(std::ios::fixed);
594
595 if (
m_trackQuery->isExtrapolated(inputSpectrometerTrack, ctx)) {
597 msg(MSG::VERBOSE) <<
"extrapolated has lineFit";
598 } else {
599 msg(MSG::VERBOSE) <<
"extrapolated momentum " << std::setprecision(1)
600 << inputSpectrometerTrack.perigeeParameters()->momentum().mag() / Gaudi::Units::GeV << " (GeV)";
601 }
602
603 msg(MSG::VERBOSE) <<
" at eta " << std::setw(6) << std::setprecision(3)
604 << inputSpectrometerTrack.perigeeParameters()->momentum().eta() << " phi " << std::setw(6)
605 << std::setprecision(3) << inputSpectrometerTrack.perigeeParameters()->momentum().phi();
606
607 }
else if (!
m_trackQuery->isProjective(inputSpectrometerTrack)) {
608 msg(MSG::VERBOSE) <<
"spectrometer track does not project";
609 } else if (inputSpectrometerTrack.perigeeParameters()) {
611 msg(MSG::VERBOSE) <<
"spectrometer has lineFit";
612 } else {
613 msg(MSG::VERBOSE) <<
"spectrometer momentum " << std::setprecision(1)
614 << inputSpectrometerTrack.perigeeParameters()->momentum().mag() / Gaudi::Units::GeV << " (GeV)";
615 }
616
617 msg(MSG::VERBOSE) <<
" at eta " << std::setw(6) << std::setprecision(3)
618 << inputSpectrometerTrack.perigeeParameters()->position().eta() << " phi " << std::setw(6)
619 << std::setprecision(3) << inputSpectrometerTrack.perigeeParameters()->position().phi();
620
621 if (inputSpectrometerTrack.perigeeParameters()->covariance()) {
622 msg(MSG::VERBOSE) <<
" hasCov";
623 } else {
624 msg(MSG::VERBOSE) <<
" noCov ";
625 }
626 } else {
627 msg(MSG::VERBOSE) <<
" spectrometer track without PerigeeParameters";
628 }
629
630 if (inputSpectrometerTrack.fitQuality()) {
631 msg(MSG::VERBOSE) <<
" fit: chi2 /DoF " << std::setprecision(2) <<
normalizedChi2(inputSpectrometerTrack) <<
" /"
632 << std::setw(2) << inputSpectrometerTrack.fitQuality()->numberDoF();
633 }
634
635 if (
m_trackQuery->numberPseudoMeasurements(inputSpectrometerTrack)) {
636 msg(MSG::VERBOSE) <<
" pseudo " <<
m_trackQuery->numberPseudoMeasurements(inputSpectrometerTrack);
637 }
638
640 }
641
642
643 const Trk::RecVertex*
vertex =
dynamic_cast<const Trk::RecVertex*
>(inputVertex);
644 if (inputVertex && !vertex) {
645
647 return nullptr;
648 }
649
650
651 const Trk::FitQuality*
fitQuality = inputSpectrometerTrack.fitQuality();
652 const Trk::TrackStates* tsos = inputSpectrometerTrack.trackStateOnSurfaces();
653
654 if (!fitQuality || !inputSpectrometerTrack.trackStateOnSurfaces() ||
655 static_cast<int>(inputSpectrometerTrack.trackStateOnSurfaces()->size()) <
fitQuality->
numberDoF()) {
656
657 int measurements = 0;
658 for (const Trk::TrackStateOnSurface* s : *tsos) {
660 }
661
662 if (measurements < 4) {
665 return nullptr;
666 }
667
668
669 if (fitQuality && measurements < fitQuality->numberDoF() + 4) {
672 return nullptr;
673 }
674 }
675
676
677 const bool is_extrapolated =
m_trackQuery->isExtrapolated(inputSpectrometerTrack, ctx);
678 if (!is_extrapolated && !
m_trackQuery->isProjective(inputSpectrometerTrack)) {
680 return nullptr;
681 }
682
683
684 double spectrometerFitChi2 =
normalizedChi2(inputSpectrometerTrack);
685 std::unique_ptr<Trk::Track> spectrometerFit = std::make_unique<Trk::Track>(inputSpectrometerTrack);
688 if (!spectrometerFit) {
690 return nullptr;
691 }
692 }
693
694 const Trk::Track& spectrometerTrack = *spectrometerFit;
695
696
698
699 if (!measuredPerigee || !measuredPerigee->covariance()) {
700
702
704 return nullptr;
705 }
706
707
708 bool badlyDeterminedCurvature = false;
709
711 ATH_MSG_WARNING(
"standaloneFit: measuredPerigee has non-positive-definite covariance ");
714 return nullptr;
715 }
716
718
719 std::unique_ptr<Trk::RecVertex> mvertex = std::make_unique<Trk::RecVertex>(*
m_vertex);
720 std::unique_ptr<Trk::RecVertex> mbeamAxis = std::make_unique<Trk::RecVertex>(*
m_beamAxis);
721 std::unique_ptr<Trk::PerigeeSurface> mperigeeSurface = std::make_unique<Trk::PerigeeSurface>(*
m_perigeeSurface);
722
723 std::unique_ptr<const Trk::TrackParameters>
parameters;
724
725 if (vertex) {
726
728 ATH_MSG_VERBOSE(
"standaloneFit: vertex fit not attempted as curvature badly measured");
730 return nullptr;
731 }
733 } else {
734
735
736
737 if ((origin - mvertex->position()).mag() > 0.001) {
738
739
740 mperigeeSurface = std::make_unique<Trk::PerigeeSurface>(origin);
741
743 beamAxisCovariance.setZero();
747 mbeamAxis = std::make_unique<Trk::RecVertex>(origin, beamAxisCovariance);
748
750 vertexRegionCovariance.setZero();
754 mvertex = std::make_unique<Trk::RecVertex>(origin, vertexRegionCovariance);
755 }
756
758 }
759
762 return nullptr;
763 }
764
765
766 std::vector<std::unique_ptr<const Trk::TrackStateOnSurface>> spectrometerTSOS =
createSpectrometerTSOS(ctx, spectrometerTrack);
767
768 if (spectrometerTSOS.empty()) {
770 return nullptr;
771 }
773
775
776 bool haveFitWithVertex = false;
777 bool performPrefit = false;
778
781 if (
s->measurementOnTrack() && !
s->trackParameters()) {
782 performPrefit = true;
783 break;
784 }
785 }
786 }
787
788
789 std::unique_ptr<Trk::Track> prefit;
790
791 const Trk::RecVertex* vertexInFit =
vertex;
792
793 if (!vertexInFit) {
795
796 bool inCSCregion = std::abs(measuredPerigee->
momentum().eta()) > 2.0;
797
798
799
800 if (inCSCregion ||
m_trackQuery->numberPseudoMeasurements(spectrometerTrack) ||
803 performPrefit = true;
804 vertexInFit = (badlyDeterminedCurvature || inCSCregion) ? mvertex.get() : mbeamAxis.get();
805
806 if (msgLvl(MSG::DEBUG)) {
807 unsigned numberPseudo =
m_trackQuery->numberPseudoMeasurements(spectrometerTrack);
808 if (errorPhi > s_sigmaPhiSector) { ++numberPseudo; }
809
810 if (badlyDeterminedCurvature) {
811 ATH_MSG_DEBUG(
" prefit with vertex: " << std::setiosflags(std::ios::fixed) <<
" momentum " << std::setprecision(1)
812 << measuredPerigee->
momentum().mag() / Gaudi::Units::GeV <<
" (GeV), zFirst "
813 << std::setprecision(1) << std::abs(
parameters->position().z())
814 << ", phiError " << std::setprecision(2) << errorPhi << ", momentumError "
815 << std::setprecision(2) << errorP << ", numberPseudo " << numberPseudo);
816 } else {
818 << std::setiosflags(std::ios::fixed) << " momentum " << std::setprecision(1)
819 << measuredPerigee->
momentum().mag() / Gaudi::Units::GeV <<
" (GeV), zFirst " << std::setprecision(1)
820 << std::abs(
parameters->position().z()) <<
", phiError " << std::setprecision(2) << errorPhi
821 << ", momentumError " << std::setprecision(2) << errorP << ", numberPseudo " << numberPseudo);
822 }
823 }
824 }
825 }
826
827 std::unique_ptr<const Trk::Perigee> prefitResult;
828
829
830 if (performPrefit) {
832
833 if (vertexInFit) { haveFitWithVertex = true; }
834
836
837 ATH_MSG_VERBOSE(
"Calling createExtrapolatedTrack from " << __func__ <<
" at line " << __LINE__);
838 prefit =
createExtrapolatedTrack(ctx, spectrometerTrack, *parameters, particleHypothesis,
false, spectrometerTSOS, vertexInFit,
839 mbeamAxis.get(), mperigeeSurface.get());
840
841
842 if (!prefit || !prefit->fitQuality() || !prefit->perigeeParameters()) {
844 prefit.reset();
845 }
846
847 if (prefit) {
849 bool hasCov = prefit->perigeeParameters() ? (prefit->perigeeParameters()->covariance() != nullptr) : false;
851
852 if (prefit->perigeeParameters()) { prefitResult.reset(prefit->perigeeParameters()->clone()); }
853 const Trk::TrackStateOnSurface* ms_entrance = nullptr;
854 for (const Trk::TrackStateOnSurface* s : *prefit->trackStateOnSurfaces()) {
855
856 if (!
s->trackParameters() || !
s->trackParameters()->covariance()) {
continue; }
858
859
861 ATH_MSG_DEBUG(
"Found first parameters in MS " <<
s->trackParameters()->position().perp() <<
" z "
862 <<
s->trackParameters()->position().z());
864 break;
865 }
866 }
867
868 if (ms_entrance && ms_entrance != prefit->trackStateOnSurfaces()->front() && ms_entrance->
trackParameters()) {
871 } else {
872
874 }
875 }
876
877
878 spectrometerTSOS.clear();
879
880 if (!prefit) {
882 return nullptr;
883 }
885
886
887
888
890 std::find_if(prefit_tsos->
begin() + 1, prefit_tsos->
end(), [
this](
const Trk::TrackStateOnSurface* tsos) ->
bool {
891 return (tsos->trackParameters() && !m_calorimeterVolume->inside(tsos->trackParameters()->position())) ||
892 tsos->type(Trk::TrackStateOnSurface::Perigee);
893 });
894
896
897 for (;
s != prefit_tsos->
end(); ++
s) { spectrometerTSOS.emplace_back((*s)->clone()); }
898 }
899
901
902 for (std::unique_ptr<const Trk::TrackStateOnSurface>& t : spectrometerTSOS) {
903 if (!
t->measurementOnTrack() || !
t->trackParameters()) {
continue; }
904
905 const Trk::RIO_OnTrack* rot =
dynamic_cast<const Trk::RIO_OnTrack*
>(
t->measurementOnTrack());
906
907 if (!rot) continue;
909
911
912 std::unique_ptr<Trk::RIO_OnTrack> updatedRot;
919 }
920
921 if (updatedRot) {
924 }
925 }
926 }
927
928
930 bool returnAfterCleaner = !fieldCache.
toroidOn();
931
932 ATH_MSG_VERBOSE(
"Calling createExtrapolatedTrack from " << __func__ <<
" at line " << __LINE__);
935 mperigeeSurface.get(), prefitResult.get()));
936
938
939
941 if (
extrapolated && !haveFitWithVertex && !vertexInFit) {
943 std::unique_ptr<Trk::Track> badfit(std::move(
extrapolated));
944
945 auto trackStateOnSurfaces = std::make_unique<Trk::TrackStates>();
946 trackStateOnSurfaces->reserve(badfit->trackStateOnSurfaces()->size() + 1);
947
948 std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes>
type{};
950 std::unique_ptr<Trk::PseudoMeasurementOnTrack> vertexInFit =
951 vertexOnTrack(*badfit->perigeeParameters(), mvertex.get(), mbeamAxis.get());
952
954
955 trackStateOnSurfaces->push_back(new Trk::TrackStateOnSurface(
956 std::move(vertexInFit), badfit->perigeeParameters()->uniqueClone(), nullptr, type));
957
959 s != badfit->trackStateOnSurfaces()->end(); ++s) {
960 trackStateOnSurfaces->push_back((**s).clone());
961 }
962
963 std::unique_ptr<Trk::Track>
track =
964 std::make_unique<Trk::Track>(spectrometerTrack.
info(), std::move(trackStateOnSurfaces),
nullptr);
966 }
967
968
970 if (prefit && prefit->fitQuality() && caloParameters) {
971 ATH_MSG_DEBUG(
" restarting from prefit as back extrapolation fit failed");
972 spectrometerTSOS.clear();
973
975
979 }
980
981 for (;
s != prefit->trackStateOnSurfaces()->
end(); ++
s) { spectrometerTSOS.emplace_back((**s).clone()); }
982
983 ATH_MSG_VERBOSE(
"Calling createExtrapolatedTrack from " << __func__ <<
" at line " << __LINE__);
986 vertexInFit, mbeamAxis.get(), mperigeeSurface.get(), prefitResult.get());
987 returnAfterCleaner = true;
988 }
989
993
995 return nullptr;
996 }
997 }
998 }
999
1000
1004
1005
1007
1008 bool allowRefit = !badlyDeterminedCurvature;
1009 double pRatio = 1.;
1010
1012 if (returnAfterCleaner) {
1013 allowRefit = false;
1014 } else {
1015
1016
1019 while (!(**s).trackParameters() ||
m_calorimeterVolume->inside((**s).trackParameters()->position())) {
1022 }
1023
1024
1025 if (params_pRat) {
1027 } else {
1028
1030 allowRefit = false;
1031 }
1032 }
1033
1034
1035 std::unique_ptr<Trk::Track>
track;
1036
1038 if (msgLvl(MSG::VERBOSE)) {
1039 double sinTheta = params_pRat->
momentum().perp() / params_pRat->
momentum().mag();
1040
1042 << pRatio << ", pT before " << momentum * sinTheta / Gaudi::Units::GeV << ", after "
1043 << params_pRat->
momentum().perp() / Gaudi::Units::GeV <<
" GeV");
1044 }
1045
1046 spectrometerTSOS.clear();
1047 for (
const Trk::TrackStateOnSurface* s : *
extrapolated->trackStateOnSurfaces()) {
1049 }
1050
1051 ATH_MSG_VERBOSE(
"Calling createExtrapolatedTrack from " << __func__ <<
" at line " << __LINE__);
1052
1054 vertexInFit, mbeamAxis.get(), mperigeeSurface.get(),
extrapolated->perigeeParameters());
1055
1056 if (track) {
1060 }
1061 }
1063
1065
1068 return nullptr;
1069 }
1070
1071 int improvementsFailed = 0;
1072
1075
1077
1078 std::unique_ptr<Trk::Track> refinedTrack(
fit(ctx, *track,
false,
Trk::muon));
1079 if (
checkTrack(
"refineFit", refinedTrack.get())) {
1081 track.swap(refinedTrack);
1082 } else {
1084 ++improvementsFailed;
1085 }
1086 }
1087
1088
1089
1090
1092
1093
1094 if (newTrack) {
1095 if (msgLevel(MSG::DEBUG))
countAEOTs(*newTrack,
" SA track after addIDMSerrors ");
1096 dumpCaloEloss(newTrack.get(),
"SA input TSOS after refine IDMS ");
1097
1098
1099 std::unique_ptr<Trk::Track> refittedTrack(
fit(ctx, *newTrack,
false,
Trk::muon));
1100 if (msgLevel(MSG::DEBUG) && refittedTrack) {
countAEOTs(*refittedTrack,
" SA track after refit "); }
1101 dumpCaloEloss(refittedTrack.get(),
" SA refit after refine IDMS ");
1102 if (
checkTrack(
"standaloneFit", refittedTrack.get())) {
1103
1104 track.swap(refittedTrack);
1105 } else {
1106 ++improvementsFailed;
1107 }
1108 } else {
1109 ++improvementsFailed;
1110 }
1111
1112
1114
1115 if (track) {
1117
1118
1120 if (fitChi2 >
m_badFitChi2 && fitChi2 > spectrometerFitChi2 + 0.5) {
1121 ATH_MSG_DEBUG(
"standaloneFit: fit quality degraded wrt spectrometer alone. "
1122 << " Chi2/DoF= " << fitChi2);
1123
1125 if (improvementsFailed >= 2) {
1126 ATH_MSG_DEBUG(
"reject track, quality degraded and improvements failed");
1127 return nullptr;
1128 }
1129 }
1130 }
1133 }
Gaudi::Property< bool > m_refineELossStandAloneTrackFit
Gaudi::Property< bool > m_reallocateMaterial
std::vector< std::unique_ptr< const Trk::TrackStateOnSurface > > createSpectrometerTSOS(const EventContext &ctx, const Trk::Track &spectrometerTrack) const
std::unique_ptr< Trk::Track > reallocateMaterial(const EventContext &ctx, const Trk::Track &spectrometerTrack) const
Gaudi::Property< bool > m_cleanStandalone
std::unique_ptr< Trk::Track > createExtrapolatedTrack(const EventContext &ctx, const Trk::Track &spectrometerTrack, const Trk::TrackParameters ¶meters, Trk::ParticleHypothesis particleHypothesis, Trk::RunOutlierRemoval runOutlier, const std::vector< std::unique_ptr< const Trk::TrackStateOnSurface > > &trackStateOnSurfaces, const Trk::RecVertex *vertex, const Trk::RecVertex *mbeamAxis, const Trk::PerigeeSurface *mperigeeSurface, const Trk::Perigee *seedParameter=nullptr) const
Gaudi::Property< double > m_largePhiError
std::unique_ptr< Trk::TrackParameters > extrapolatedParameters(const EventContext &ctx, bool &badlyDeterminedCurvature, const Trk::Track &spectrometerTrack, const Trk::RecVertex *mvertex, const Trk::PerigeeSurface *mperigeeSurface) const
int numberDoF() const
returns the number of degrees of freedom of the overall track or vertex fit as integer
virtual ParametersBase< DIM, T > * clone() const override=0
clone method for polymorphic deep copy
virtual const Trk::PrepRawData * prepRawData() const =0
returns the PrepRawData (also known as RIO) object to which this RIO_OnTrack is associated.
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
ParticleHypothesis
Enumeration for Particle hypothesis respecting the interaction with material.