53 const double s_sigmaPhiSector =
std::tan(0.125 *
M_PI / std::sqrt(12.));
60 declareInterface<ICombinedMuonTrackBuilder>(
this);
95 beamAxisCovariance.setZero();
99 m_beamAxis = std::make_unique<Trk::RecVertex>(origin, beamAxisCovariance);
102 vertexRegionCovariance.setZero();
106 m_vertex = std::make_unique<Trk::RecVertex>(origin, vertexRegionCovariance);
114 return StatusCode::SUCCESS;
121 <<
endmsg <<
" " << std::setiosflags(std::ios::fixed) << std::setw(4) << std::setprecision(2)
132 if (msgLevel(
MSG::DEBUG))
countAEOTs(extrapolatedTrack,
" extrapolatedTrack start combinedFit ");
144 if (
m_trackQuery->isCaloAssociated(extrapolatedTrack, ctx)) {
146 if (!
it->materialEffectsOnTrack())
continue;
148 const Amg::Vector3D& position =
it->materialEffectsOnTrack()->associatedSurface().globalReferencePoint();
153 surface = &
it->materialEffectsOnTrack()->associatedSurface();
165 std::unique_ptr<const Trk::TrackStateOnSurface> innerTSOS;
167 ATH_MSG_VERBOSE(
" Retrieving Calorimeter TSOS from " << __func__ <<
" at line " << __LINE__);
168 std::vector<std::unique_ptr<const Trk::TrackStateOnSurface>> caloTSOS =
170 if (!caloTSOS.empty()) { innerTSOS.swap(caloTSOS.front()); }
176 ATH_MSG_DEBUG(
" indet track fails to intersect the calorimeter ");
181 double surfaceOffset =
185 ATH_MSG_DEBUG(
" different inner-calo-surface obtained from indet extrapolation, "
187 <<
"mm. Re-evaluate the caloTSOS ");
193 std::unique_ptr<Trk::Track> muonTrack;
195 ATH_MSG_VERBOSE(
" SL MS track: Calling createMuonTrack from " << __func__ <<
" at line " << __LINE__);
202 ATH_MSG_VERBOSE(
"Calling createMuonTrack from " << __func__ <<
" at line " << __LINE__);
205 }
else if (
m_trackQuery->numberPseudoMeasurements(extrapolatedTrack) > 1) {
206 ATH_MSG_VERBOSE(
"Calling createMuonTrack from " << __func__ <<
" at line " << __LINE__);
210 ATH_MSG_VERBOSE(
"Calling createMuonTrack from " << __func__ <<
" at line " << __LINE__);
218 if (!muonTrack)
return nullptr;
226 bool haveMS {
false}, perigeeOutside{
false};
235 for (; rit != ritEnd; ++rit) {
236 if (!(**rit).measurementOnTrack() || !(**rit).trackParameters())
continue;
255 perigeeOutside =
true;
278 double pRatio = muonEnergyParameters->momentum().mag() / combinedEnergyParameters->momentum().mag();
281 ATH_MSG_DEBUG(
" iterate combined fit to recollect calorimeter material as significant momentum change after fit "
282 << pRatio <<
", pT before " << muonEnergyParameters->momentum().perp() /
Gaudi::Units::GeV <<
", after "
285 ATH_MSG_DEBUG(
" iterate combined fit to recollect calorimeter material");
292 std::unique_ptr<Trk::Track> oldTrack(std::move(muonTrack));
294 ATH_MSG_VERBOSE(
"Calling createMuonTrack from " << __func__ <<
" at line " << __LINE__);
295 muonTrack =
createMuonTrack(ctx, extrapolatedTrack, combinedEnergyParameters,
nullptr, combinedTSOS);
297 if (indetNewTrack && muonTrack) {
299 caloEnergy =
caloEnergyParameters(refittedTrack.get(), muonTrack.get(), combinedEnergyParameters, muonEnergyParameters);
305 muonTrack.swap(oldTrack);
316 if (!indetPerigee->covariance()) {
317 ATH_MSG_WARNING(
" indetPerigee has no covariance tolerance left as zero. ");
323 double energyBalance = combinedEnergyParameters->momentum().mag() + caloEnergy->deltaE() - indetMaxE;
326 std::unique_ptr<CaloEnergy> paramEnergy;
327 if (indetMaxE > 0. && energyBalance >
m_numberSigmaFSR * caloEnergy->sigmaMinusDeltaE()) {
334 paramEnergy =
m_caloEnergyParam->energyLoss(ctx, combinedEnergyParameters->momentum().mag(),
335 combinedEnergyParameters->position().eta(),
336 combinedEnergyParameters->position().phi());
344 << energyBalance /
Gaudi::Units::GeV <<
" signif " << energyBalance / caloEnergy->sigmaMinusDeltaE()
349 << combinedEnergyParameters->position().eta() <<
" phi " << combinedEnergyParameters->position().phi()
350 <<
endmsg <<
" tail-param energy diff "
353 ATH_MSG_VERBOSE(
"Calling createMuonTrack from " << __func__ <<
" at line " << __LINE__);
386 dumpCaloEloss(newTrack.get(),
"CB input TSOS after refine IDMS ");
387 std::unique_ptr<Trk::Track> refittedTrack{
fit(ctx, *newTrack,
false,
Trk::muon)};
390 dumpCaloEloss(refittedTrack.get(),
"CB refit after refine IDMS ");
392 if (
checkTrack(
"combinedFit", refittedTrack.get())) {
401 ATH_MSG_DEBUG(
"addIDMS errors failed and original track does not pass checkTrack");
412 std::unique_ptr<Trk::TrackParameters> innerParameters,
413 std::unique_ptr<Trk::TrackParameters> middleParameters,
414 std::unique_ptr<Trk::TrackParameters> outerParameters)
const {
418 if (innerParameters || middleParameters || outerParameters) {
421 if (innerParameters) {
423 << std::setw(5) << std::setprecision(0) << innerParameters->
position().z() <<
" ";
426 if (middleParameters) {
427 msg(
MSG::VERBOSE) <<
"M:" << std::setw(5) << std::setprecision(0) << middleParameters->
position().perp() <<
","
428 << std::setw(5) << std::setprecision(0) << middleParameters->
position().z() <<
" ";
431 if (outerParameters) {
433 << std::setw(5) << std::setprecision(0) << outerParameters->
position().z();
438 if (innerParameters) {
442 if (middleParameters) {
446 if (outerParameters) {
467 ATH_MSG_VERBOSE(
"indetExtension: method switched off when solenoid 'off' / toroid 'on'");
476 std::unique_ptr<Trk::TrackParameters> frontParameters, backParameters;
478 if (innerParameters) {
479 if (innerParameters->
associatedSurface() == spectrometerMeasurements.front()->associatedSurface()) {
486 }
else if (middleParameters) {
487 if (middleParameters->
associatedSurface() == spectrometerMeasurements.front()->associatedSurface()) {
496 if (outerParameters) {
497 if (outerParameters->
associatedSurface() == spectrometerMeasurements.back()->associatedSurface()) {
504 }
else if (middleParameters) {
505 if (middleParameters->
associatedSurface() == spectrometerMeasurements.back()->associatedSurface()) {
515 std::unique_ptr<Trk::TrackParameters> midParameters;
518 if (middleParameters && innerParameters && outerParameters) {
520 double midDistance = 0.5 * direction.dot(outerParameters->
position() - innerParameters->
position());
521 double previousDistance = 0.;
523 Trk::MeasurementSet::const_iterator
m = spectrometerMeasurements.begin();
524 for (++
m;
m != spectrometerMeasurements.end(); ++
m) {
525 double distance = direction.dot((**m).globalPosition() - innerParameters->
position());
529 if (midDistance - previousDistance <
distance - midDistance) --
m;
534 if (midParameters) midMeasurement = *
m;
541 std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes> typeM;
543 std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes> typeP;
547 auto trackStateOnSurfaces = std::make_unique<Trk::TrackStates>();
549 trackStateOnSurfaces->reserve(spectrometerMeasurements.size());
553 if (frontParameters) {
554 trackStateOnSurfaces->push_back(
556 }
else if (in_meas == midMeasurement) {
557 trackStateOnSurfaces->push_back(
559 }
else if (backParameters && in_meas == spectrometerMeasurements.back()) {
560 trackStateOnSurfaces->push_back(
563 trackStateOnSurfaces->push_back(
573 ATH_MSG_VERBOSE(
"Calling combinedFit from " << __func__ <<
" at line " << __LINE__);
585 if (
m_trackQuery->isLineFit(inputSpectrometerTrack) && !fieldCache.
toroidOn()) {
return nullptr; }
587 ATH_MSG_DEBUG(
" standaloneFit beam position bs_x " << origin <<
" inputVertex "
591 msg(
MSG::VERBOSE) <<
endmsg <<
"==== Start of standaloneFit:: " << std::setiosflags(std::ios::fixed);
593 if (
m_trackQuery->isExtrapolated(inputSpectrometerTrack, ctx)) {
601 msg(
MSG::VERBOSE) <<
" at eta " << std::setw(6) << std::setprecision(3)
602 << inputSpectrometerTrack.
perigeeParameters()->momentum().eta() <<
" phi " << std::setw(6)
603 << std::setprecision(3) << inputSpectrometerTrack.
perigeeParameters()->momentum().phi();
605 }
else if (!
m_trackQuery->isProjective(inputSpectrometerTrack)) {
615 msg(
MSG::VERBOSE) <<
" at eta " << std::setw(6) << std::setprecision(3)
616 << inputSpectrometerTrack.
perigeeParameters()->position().eta() <<
" phi " << std::setw(6)
617 << std::setprecision(3) << inputSpectrometerTrack.
perigeeParameters()->position().phi();
633 if (
m_trackQuery->numberPseudoMeasurements(inputSpectrometerTrack)) {
642 if (inputVertex && !
vertex) {
655 int measurements = 0;
660 if (measurements < 4) {
667 if (
fitQuality && measurements < fitQuality->numberDoF() + 4) {
675 const bool is_extrapolated =
m_trackQuery->isExtrapolated(inputSpectrometerTrack, ctx);
676 if (!is_extrapolated && !
m_trackQuery->isProjective(inputSpectrometerTrack)) {
682 double spectrometerFitChi2 =
normalizedChi2(inputSpectrometerTrack);
683 std::unique_ptr<Trk::Track> spectrometerFit = std::make_unique<Trk::Track>(inputSpectrometerTrack);
686 if (!spectrometerFit) {
692 const Trk::Track& spectrometerTrack = *spectrometerFit;
697 if (!measuredPerigee || !measuredPerigee->covariance()) {
706 bool badlyDeterminedCurvature =
false;
709 ATH_MSG_WARNING(
"standaloneFit: measuredPerigee has non-positive-definite covariance ");
715 double errorP = std::sqrt(measuredPerigee->momentum().mag2() * (*measuredPerigee->covariance())(
Trk::qOverP,
Trk::qOverP));
717 std::unique_ptr<Trk::RecVertex> mvertex = std::make_unique<Trk::RecVertex>(*
m_vertex);
718 std::unique_ptr<Trk::RecVertex> mbeamAxis = std::make_unique<Trk::RecVertex>(*
m_beamAxis);
719 std::unique_ptr<Trk::PerigeeSurface> mperigeeSurface = std::make_unique<Trk::PerigeeSurface>(*
m_perigeeSurface);
721 std::unique_ptr<const Trk::TrackParameters>
parameters;
726 ATH_MSG_VERBOSE(
"standaloneFit: vertex fit not attempted as curvature badly measured");
735 if ((origin - mvertex->
position()).mag() > 0.001) {
738 mperigeeSurface = std::make_unique<Trk::PerigeeSurface>(origin);
741 beamAxisCovariance.setZero();
745 mbeamAxis = std::make_unique<Trk::RecVertex>(origin, beamAxisCovariance);
748 vertexRegionCovariance.setZero();
752 mvertex = std::make_unique<Trk::RecVertex>(origin, vertexRegionCovariance);
764 std::vector<std::unique_ptr<const Trk::TrackStateOnSurface>> spectrometerTSOS =
createSpectrometerTSOS(ctx, spectrometerTrack);
766 if (spectrometerTSOS.empty()) {
774 bool haveFitWithVertex =
false;
775 bool performPrefit =
false;
779 if (
s->measurementOnTrack() && !
s->trackParameters()) {
780 performPrefit =
true;
787 std::unique_ptr<Trk::Track> prefit;
794 bool inCSCregion = std::abs(measuredPerigee->momentum().eta()) > 2.0;
798 if (inCSCregion ||
m_trackQuery->numberPseudoMeasurements(spectrometerTrack) ||
801 performPrefit =
true;
802 vertexInFit = (badlyDeterminedCurvature || inCSCregion) ? mvertex.get() : mbeamAxis.get();
805 unsigned numberPseudo =
m_trackQuery->numberPseudoMeasurements(spectrometerTrack);
806 if (errorPhi > s_sigmaPhiSector) { ++numberPseudo; }
808 if (badlyDeterminedCurvature) {
809 ATH_MSG_DEBUG(
" prefit with vertex: " << std::setiosflags(std::ios::fixed) <<
" momentum " << std::setprecision(1)
811 << std::setprecision(1) << std::abs(
parameters->position().z())
812 <<
", phiError " << std::setprecision(2) << errorPhi <<
", momentumError "
813 << std::setprecision(2) << errorP <<
", numberPseudo " << numberPseudo);
816 << std::setiosflags(std::ios::fixed) <<
" momentum " << std::setprecision(1)
817 << measuredPerigee->momentum().mag() /
Gaudi::Units::GeV <<
" (GeV), zFirst " << std::setprecision(1)
818 << std::abs(
parameters->position().z()) <<
", phiError " << std::setprecision(2) << errorPhi
819 <<
", momentumError " << std::setprecision(2) << errorP <<
", numberPseudo " << numberPseudo);
825 std::unique_ptr<const Trk::Perigee> prefitResult;
831 if (vertexInFit) { haveFitWithVertex =
true; }
835 ATH_MSG_VERBOSE(
"Calling createExtrapolatedTrack from " << __func__ <<
" at line " << __LINE__);
837 mbeamAxis.get(), mperigeeSurface.get());
854 if (!
s->trackParameters() || !
s->trackParameters()->covariance()) {
continue; }
859 ATH_MSG_DEBUG(
"Found first parameters in MS " <<
s->trackParameters()->position().perp() <<
" z "
860 <<
s->trackParameters()->position().z());
876 spectrometerTSOS.clear();
889 return (tsos->trackParameters() && !m_calorimeterVolume->inside(tsos->trackParameters()->position())) ||
890 tsos->type(Trk::TrackStateOnSurface::Perigee);
895 for (;
s != prefit_tsos->
end(); ++
s) { spectrometerTSOS.emplace_back((*s)->clone()); }
900 for (std::unique_ptr<const Trk::TrackStateOnSurface>&
t : spectrometerTSOS) {
901 if (!
t->measurementOnTrack() || !
t->trackParameters()) {
continue; }
910 std::unique_ptr<Trk::RIO_OnTrack> updatedRot;
928 bool returnAfterCleaner = !fieldCache.
toroidOn();
930 ATH_MSG_VERBOSE(
"Calling createExtrapolatedTrack from " << __func__ <<
" at line " << __LINE__);
933 mperigeeSurface.get(), prefitResult.get()));
939 if (
extrapolated && !haveFitWithVertex && !vertexInFit) {
941 std::unique_ptr<Trk::Track> badfit(std::move(
extrapolated));
943 auto trackStateOnSurfaces = std::make_unique<Trk::TrackStates>();
946 std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes>
type{};
948 std::unique_ptr<Trk::PseudoMeasurementOnTrack> vertexInFit =
958 trackStateOnSurfaces->push_back((**s).clone());
961 std::unique_ptr<Trk::Track>
track =
962 std::make_unique<Trk::Track>(spectrometerTrack.
info(), std::move(trackStateOnSurfaces),
nullptr);
968 if (prefit && prefit->
fitQuality() && caloParameters) {
969 ATH_MSG_DEBUG(
" restarting from prefit as back extrapolation fit failed");
970 spectrometerTSOS.clear();
981 ATH_MSG_VERBOSE(
"Calling createExtrapolatedTrack from " << __func__ <<
" at line " << __LINE__);
984 vertexInFit, mbeamAxis.get(), mperigeeSurface.get(), prefitResult.get());
985 returnAfterCleaner =
true;
1006 bool allowRefit = !badlyDeterminedCurvature;
1010 if (returnAfterCleaner) {
1017 while (!(**s).trackParameters() ||
m_calorimeterVolume->inside((**s).trackParameters()->position())) {
1033 std::unique_ptr<Trk::Track>
track;
1037 double sinTheta = params_pRat->
momentum().perp() / params_pRat->
momentum().mag();
1044 spectrometerTSOS.clear();
1049 ATH_MSG_VERBOSE(
"Calling createExtrapolatedTrack from " << __func__ <<
" at line " << __LINE__);
1052 vertexInFit, mbeamAxis.get(), mperigeeSurface.get(),
extrapolated->perigeeParameters());
1069 int improvementsFailed = 0;
1077 if (
checkTrack(
"refineFit", refinedTrack.get())) {
1079 track.swap(refinedTrack);
1082 ++improvementsFailed;
1094 dumpCaloEloss(newTrack.get(),
"SA input TSOS after refine IDMS ");
1097 std::unique_ptr<Trk::Track> refittedTrack(
fit(ctx, *newTrack,
false,
Trk::muon));
1099 dumpCaloEloss(refittedTrack.get(),
" SA refit after refine IDMS ");
1100 if (
checkTrack(
"standaloneFit", refittedTrack.get())) {
1102 track.swap(refittedTrack);
1104 ++improvementsFailed;
1107 ++improvementsFailed;
1118 if (fitChi2 >
m_badFitChi2 && fitChi2 > spectrometerFitChi2 + 0.5) {
1119 ATH_MSG_DEBUG(
"standaloneFit: fit quality degraded wrt spectrometer alone. "
1120 <<
" Chi2/DoF= " << fitChi2);
1123 if (improvementsFailed >= 2) {
1124 ATH_MSG_DEBUG(
"reject track, quality degraded and improvements failed");
1150 ATH_MSG_DEBUG(
" StandaloneRefit beam position bs_x " << origin);
1162 ATH_MSG_DEBUG(
" StandaloneRefit new vertex d0 error " << std::sqrt(error2d0) <<
" new vertex z0 error "
1163 << std::sqrt(error2z0));
1166 (vertexRegionCovariance)(0, 0) = error2d0;
1167 (vertexRegionCovariance)(1, 1) = error2d0;
1168 (vertexRegionCovariance)(2, 2) = error2z0;
1170 std::unique_ptr<Trk::RecVertex>
vertex = std::make_unique<Trk::RecVertex>(origin, vertexRegionCovariance);
1172 ATH_MSG_DEBUG(
" StandaloneRefit new vertex position x " <<
vertex->position().x() <<
" y " <<
vertex->position().y() <<
" z "
1173 <<
vertex->position().z());
1175 bool addPhiPseudo =
false;
1178 if (spectrometerPhiQuality > 1) { addPhiPseudo =
true; }
1180 ATH_MSG_VERBOSE(
"standaloneRefit: using vertex region constraint with "
1181 <<
"spectrometerPhiQuality " << spectrometerPhiQuality);
1184 auto trackStateOnSurfaces = std::make_unique<Trk::TrackStates>();
1187 unsigned size =
combinedTrack.trackStateOnSurfaces()->size() + 3 + addPhiPseudo;
1189 trackStateOnSurfaces->reserve(
size);
1192 bool haveCaloDeposit =
false;
1198 if (
s == cmb_end_itr) {
1204 haveCaloDeposit =
true;
1207 }
while (!haveCaloDeposit);
1213 std::unique_ptr<Trk::TrackStateOnSurface> innerTSOS;
1218 std::unique_ptr<Trk::TrackParameters> param_owner;
1223 innerTSOS.reset(cmb_inner_tsos->
clone());
1237 if (
s != cmb_end_itr) {
1245 materialEffects =
nullptr;
1264 std::unique_ptr<Trk::TrackStateOnSurface> middleTSOS;
1268 middleTSOS.reset(cmb_middle_tsos->
clone());
1275 if (
s != cmb_end_itr) {
1280 materialEffects =
nullptr;
1296 std::unique_ptr<Trk::TrackStateOnSurface> outerTSOS;
1298 double pInner{0.}, pOuter{0.};
1303 outerTSOS.reset(cmb_outer_tsos->
clone());
1319 if (outerScattering && middleTSOS) {
1330 if (!param_owner) param_owner =
parameters->uniqueClone();
1345 if (!innerTSOS || !middleTSOS || !outerTSOS || !
parameters) {
return nullptr; }
1356 std::unique_ptr<Trk::TrackParameters> perigee_owner;
1365 if (!perigee_owner) { perigee_owner =
combinedTrack.perigeeParameters()->uniqueClone(); }
1388 if (!param_owner) {
return nullptr; }
1398 std::unique_ptr<Trk::RecVertex> mbeamAxis = std::make_unique<Trk::RecVertex>(*
m_beamAxis);
1400 std::unique_ptr<Trk::PseudoMeasurementOnTrack> vertexInFit{
vertexOnTrack(*perigee_owner,
vertex.get(), mbeamAxis.get())};
1411 double Eloss{0.}, sigmaEloss{0.}, X0tot{0.}, sigmaDeltaPhitot2{0.}, sigmaDeltaThetatot2{0.};
1413 std::vector<const Trk::TrackStateOnSurface*> scatter_tsos;
1414 scatter_tsos.reserve(
combinedTrack.trackStateOnSurfaces()->size());
1417 if (!comb_tsos->trackParameters())
continue;
1418 if (!
m_indetVolume->inside(comb_tsos->trackParameters()->position()))
break;
1419 if (!comb_tsos->materialEffectsOnTrack()) {
continue; }
1420 const double X0 = comb_tsos->materialEffectsOnTrack()->thicknessInX0();
1425 if (!meot) {
continue; }
1427 if (!energyLoss) {
continue; }
1428 Eloss += energyLoss->
deltaE();
1431 ATH_MSG_DEBUG(
"CombinedMuonFit ID Eloss found r " << (comb_tsos->trackParameters())->position().perp() <<
" z "
1432 << (comb_tsos->trackParameters())->position().z() <<
" value "
1433 << energyLoss->
deltaE() <<
" Eloss " << Eloss <<
" sigma Eloss "
1440 sigmaDeltaPhitot2 += sigmaDeltaPhi * sigmaDeltaPhi;
1441 sigmaDeltaThetatot2 += sigmaDeltaTheta * sigmaDeltaTheta;
1442 scatter_tsos.push_back(comb_tsos);
1446 ATH_MSG_DEBUG(
"standaloneRefit Total ID Eloss " << Eloss <<
" sigma Eloss " << sigmaEloss <<
" X0 " << X0tot
1447 <<
" sigma scat phi " << std::sqrt(sigmaDeltaPhitot2) <<
" sigma scat theta "
1448 << std::sqrt(sigmaDeltaThetatot2));
1449 if (!scatter_tsos.empty()) {
1450 const int itsosMiddle = scatter_tsos.size() / 2;
1453 std::unique_ptr<Trk::EnergyLoss> energyLossNew = std::make_unique<Trk::EnergyLoss>(Eloss, sigmaEloss, sigmaEloss, sigmaEloss);
1456 Trk::ScatteringAngles scatNew{0., 0., std::sqrt(sigmaDeltaPhitot2), std::sqrt(sigmaDeltaThetatot2)};
1458 std::bitset<Trk::MaterialEffectsBase::NumberOfMaterialEffectsTypes> meotPattern(0);
1462 ATH_MSG_DEBUG(
" itsosMiddle " << itsosMiddle <<
" tsosnr size " << scatter_tsos.size());
1464 std::unique_ptr<Trk::MaterialEffectsOnTrack> meotNew = std::make_unique<Trk::MaterialEffectsOnTrack>(X0tot, scatNew, std::move(energyLossNew), surfNew, meotPattern);
1467 std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes> typePatternScat(0);
1470 std::unique_ptr<Trk::TrackStateOnSurface> newTSOS =
1471 std::make_unique<Trk::TrackStateOnSurface>(
nullptr, std::move(parsNew), std::move(meotNew), typePatternScat);
1473 trackStateOnSurfaces->push_back(std::move(newTSOS));
1480 trackStateOnSurfaces->push_back(std::move(innerTSOS));
1481 trackStateOnSurfaces->push_back(std::move(middleTSOS));
1482 trackStateOnSurfaces->push_back(std::move(outerTSOS));
1486 std::unique_ptr<Trk::TrackStateOnSurface> entranceTSOS =
entrancePerigee(ctx, outerTSOSParam);
1487 if (entranceTSOS) trackStateOnSurfaces->push_back(std::move(entranceTSOS));
1491 bool haveLeadingMaterial =
false;
1494 for (; mat_it != cmb_end_itr; ++mat_it) {
1496 haveLeadingMaterial =
true;
1500 if (mat_it == cmb_end_itr) {
1510 if (tsos) trackStateOnSurfaces->push_back(std::move(tsos));
1517 std::unique_ptr<Trk::Track> standaloneTrack =
1518 std::make_unique<Trk::Track>(
combinedTrack.info(), std::move(trackStateOnSurfaces),
nullptr);
1520 if (
m_trackQuery->isCombined(*standaloneTrack, ctx)) {
ATH_MSG_WARNING(
" This should not happen standalone Track has ID hits "); }
1522 if (msgLevel(
MSG::DEBUG))
countAEOTs(*standaloneTrack,
" in standalone Refit standaloneTrack track before fit ");
1524 std::unique_ptr<Trk::Track> refittedTrack{
fit(ctx, *standaloneTrack,
false,
Trk::muon)};
1525 if (!
checkTrack(
"standaloneRefit", refittedTrack.get())) {
return nullptr; }
1529 if (refittedTrack) {
1530 if (!refittedTrack->fitQuality()) {
return nullptr; }
1532 if (!
m_trackQuery->isCaloAssociated(*refittedTrack, ctx)) {
1543 countAEOTs(*refittedTrack,
" before optimize ") == 0) {
1544 ATH_MSG_VERBOSE(
" perform spectrometer error optimization after cleaning ");
1545 std::unique_ptr<Trk::Track> optimizedTrack =
m_muonErrorOptimizer->optimiseErrors(*refittedTrack, ctx);
1547 if (
checkTrack(
"standaloneRefitOpt", optimizedTrack.get())) {
1548 refittedTrack.swap(optimizedTrack);
1549 if (msgLevel(
MSG::DEBUG))
countAEOTs(*refittedTrack,
" standaloneRefit alignment errors Track ");
1555 return refittedTrack;
1567 ATH_MSG_DEBUG(
" CombinedMuonTrackBuilder addIDMSerrors to track ");
1577 if (!calo_entrance || !calo_exit || !ms_entrance) {
1582 auto trackStateOnSurfaces = std::make_unique<Trk::TrackStates>();
1583 trackStateOnSurfaces->reserve(
track->trackStateOnSurfaces()->size());
1586 if (calo_entrance == trk_srf || calo_entrance == trk_srf) {
1587 if (!trk_srf->materialEffectsOnTrack()) {
1594 ATH_MSG_WARNING(
" This should not happen: no MaterialEffectsOnTrack for scatterer ");
1599 ATH_MSG_WARNING(
" This should not happen: no Scattering Angles for scatterer ");
1605 float X0 = trk_srf->materialEffectsOnTrack()->thicknessInX0();
1607 auto energyLossNew = std::make_unique<Trk::EnergyLoss>(0., 0., 0., 0.);
1610 const Trk::Surface& surfNew = trk_srf->trackParameters()->associatedSurface();
1612 std::bitset<Trk::MaterialEffectsBase::NumberOfMaterialEffectsTypes> meotPattern(0);
1616 auto meotNew = std::make_unique<Trk::MaterialEffectsOnTrack>(
1619 std::move(energyLossNew),
1622 auto parsNew = trk_srf->trackParameters()->uniqueClone();
1624 std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes> typePatternScat(0);
1629 trackStateOnSurfaces->push_back(newTSOS);
1634 ATH_MSG_DEBUG(
" new Calo scatterer made with sigmaDeltaPhi mrad " << sigmaDeltaPhi * 1000 <<
" sigmaDeltaTheta mrad "
1635 << sigmaDeltaTheta * 1000);
1639 if (trk_srf->alignmentEffectsOnTrack()) {
1640 ATH_MSG_DEBUG(
" addIDMSerrors alignmentEffectsOnTrack() found on track ");
1643 trackStateOnSurfaces->push_back(trk_srf->clone());
1646 ATH_MSG_DEBUG(
" trackStateOnSurfaces on input track " <<
track->trackStateOnSurfaces()->size() <<
" trackStateOnSurfaces found "
1647 << trackStateOnSurfaces->size());
1649 std::unique_ptr<Trk::Track> newTrack = std::make_unique<Trk::Track>(
track->info(), std::move(trackStateOnSurfaces),
nullptr);
1656 std::vector<const Trk::Surface*> measurementSurfaces;
1657 measurementSurfaces.reserve(trackStateOnSurfaces.
size());
1661 for (;
s !=
end; ++
s) {
1669 ATH_MSG_VERBOSE(
"appendSelectedTSOS:: skip a perigee without material and measuremet "<<tsos);
1683 if (previousSurface &&
1684 std::find(measurementSurfaces.begin(), measurementSurfaces.end(), surface) != measurementSurfaces.end()) {
1690 measurementSurfaces.push_back(surface);
1691 previousSurface = surface;
1701 combinedEnergyParameters =
nullptr;
1702 muonEnergyParameters =
nullptr;
1717 muonEnergyParameters = (**s).trackParameters();
1729 combinedEnergyParameters = (**s).trackParameters();
1730 if (muonEnergyParameters && combinedEnergyParameters) {
1731 ATH_MSG_DEBUG(
"muon and combined EnergyParameters: " << muonEnergyParameters->
momentum().mag() <<
" "
1732 << combinedEnergyParameters->
momentum().mag());
1741 const std::vector<std::unique_ptr<const Trk::TrackStateOnSurface>>& spectrometerTSOS,
const Trk::RecVertex*
vertex,
1747 std::vector<std::unique_ptr<const Trk::TrackStateOnSurface>> caloTSOS, leadingTSOS;
1749 std::unique_ptr<const Trk::TrackParameters> track_param_owner;
1756 trackParameters = perigee;
1763 bool haveMaterial{
false}, haveLeadingMaterial{
false}, firstMSHit{
false};
1765 for (
const std::unique_ptr<const Trk::TrackStateOnSurface>&
s : spectrometerTSOS) {
1766 if (
s->materialEffectsOnTrack()) {
1767 haveMaterial =
true;
1768 if (!firstMSHit) haveLeadingMaterial =
true;
1771 if (
s->measurementOnTrack() && !firstMSHit) { firstMSHit =
true; }
1773 if (haveMaterial && firstMSHit) {
break; }
1782 constexpr
double Emax = 50000.;
1791 std::unique_ptr<Trk::TrackParameters> correctedParameters{
parameters.associatedSurface().createUniqueTrackParameters(
1796 std::unique_ptr<std::vector<const Trk::TrackStateOnSurface*>> lead_tsos_from_alloc{
1798 if (lead_tsos_from_alloc) {
1801 if (!leadingTSOS.empty() && leadingTSOS.front()->trackParameters()) {
1802 leadingParameters = leadingTSOS.front()->trackParameters();
1808 bool caloAssociated =
false;
1811 ATH_MSG_VERBOSE(
" Retrieving Calorimeter TSOS from " << __func__ <<
" at line " << __LINE__);
1817 for (std::unique_ptr<const Trk::TrackStateOnSurface>&
m : caloTSOS) {
1818 if (!
m->materialEffectsOnTrack())
continue;
1821 double pcalo{0.}, deltaP{0.};
1822 if (!meot)
continue;
1828 if (!scatAngles) {
continue; }
1829 pcalo =
m->trackParameters()->momentum().mag();
1835 <<
" deltaTheta " << scatAngles->
deltaTheta() <<
" pull "
1839 if (!energyLoss)
continue;
1841 if (
m->trackParameters()) {
1842 ATH_MSG_DEBUG(
"Eloss found r " << (
m->trackParameters())->position().perp() <<
" z "
1843 << (
m->trackParameters())->position().z() <<
" deltaE "
1844 << energyLoss->
deltaE());
1848 double caloEloss = std::abs(energyLoss->
deltaE());
1849 if (
m->trackParameters()) { deltaP =
m->trackParameters()->momentum().mag() - pcalo; }
1851 ATH_MSG_DEBUG(
" Calorimeter Deposit " << caloEloss <<
" pcalo Entrance " << pcalo <<
" deltaP " << deltaP);
1856 caloTSOS =
m_caloTSOS->caloTSOS(ctx, *leadingParameters);
1859 if (caloTSOS.size() > 2) {
1860 caloAssociated =
true;
1868 caloTSOS.push_back(std::move(tsos));
1869 tsos =
m_caloTSOS->outerTSOS(ctx, *caloTSOS.back()->trackParameters());
1871 caloAssociated =
true;
1872 caloTSOS.push_back(std::move(tsos));
1875 ATH_MSG_VERBOSE(
"Special non-muon case for calo: " << caloAssociated);
1879 if (caloAssociated) {
1888 if(not oldParameters->covariance()) {
ATH_MSG_VERBOSE(
" createExtrapolatedTrack: no cov (0)"); }
1897 trackParameters = track_param_owner.get();
1900 if (trackParameters && !
m_indetVolume->inside(trackParameters->position())) {
1901 ATH_MSG_DEBUG(
" back extrapolation problem: probably outside indet volume ");
1902 caloAssociated =
false;
1905 if (trackParameters && !trackParameters->covariance()) {
ATH_MSG_VERBOSE(
" createExtrapolatedTrack: no cov (1)"); }
1907 if (trackParameters) {
1908 ATH_MSG_VERBOSE(
" Seed parameter: r " << trackParameters->position().perp() <<
" z " << trackParameters->position().z()
1909 <<
" pt " << trackParameters->momentum().perp());
1915 ATH_MSG_DEBUG(
" back extrapolation problem: retry with tracking out from vertex ");
1922 track_param_owner = std::make_unique<Trk::Perigee>(
vertex->position(),
momentum, 1., *mperigeeSurface);
1923 trackParameters = track_param_owner.get();
1927 ATH_MSG_VERBOSE(
" Retriving Calorimeter TSOS from " << __func__ <<
" at line " << __LINE__);
1932 std::unique_ptr<const Trk::TrackStateOnSurface> tsos =
m_caloTSOS->innerTSOS(ctx, *trackParameters);
1934 caloTSOS.push_back(std::move(tsos));
1935 tsos =
m_caloTSOS->outerTSOS(ctx, *trackParameters);
1937 caloTSOS.push_back(std::move(tsos));
1939 track_param_owner.reset();
1943 trackParameters = track_param_owner.get();
1947 if (!trackParameters || caloTSOS.empty()) {
1954 if (seedParameters) { trackParameters = seedParameters; }
1958 const unsigned int size = spectrometerTSOS.size() + 3 + caloTSOS.size() + leadingTSOS.size();
1960 auto trackStateOnSurfaces = std::make_unique<Trk::TrackStates>();
1961 trackStateOnSurfaces->reserve(
size);
1965 if (trackParameters && !trackParameters->covariance()) {
ATH_MSG_VERBOSE(
" createExtrapolatedTrack: no cov (2)"); }
1967 if (trackParameters) {
1969 ATH_MSG_DEBUG(
"createExtrapolatedTrack() - Track parameters are not perigee " << (*trackParameters));
1975 if (
vertex && trackParameters) {
1976 std::unique_ptr<Trk::PseudoMeasurementOnTrack> vertexInFit =
vertexOnTrack(*trackParameters,
vertex, mbeamAxis);
1984 for (std::unique_ptr<const Trk::TrackStateOnSurface>& c_tsos : caloTSOS) { trackStateOnSurfaces->push_back(std::move(c_tsos)); }
1989 const Trk::TrackParameters* mstrackParameters = trackStateOnSurfaces->back()->trackParameters();
1991 if (!mstrackParameters) { mstrackParameters = spectrometerTSOS.front()->trackParameters(); }
1993 if (mstrackParameters) {
1994 std::unique_ptr<Trk::TrackStateOnSurface> entranceTSOS =
entrancePerigee(ctx, mstrackParameters);
1995 if (entranceTSOS) { trackStateOnSurfaces->push_back(std::move(entranceTSOS)); }
2000 for (std::unique_ptr<const Trk::TrackStateOnSurface>& c_tsos : leadingTSOS) {
2001 if (c_tsos->materialEffectsOnTrack()) { trackStateOnSurfaces->push_back(std::move(c_tsos)); }
2003 leadingTSOS.clear();
2006 for (
const auto&
s : spectrometerTSOS) {
2009 trackStateOnSurfaces->push_back(
s->clone());
2018 std::unique_ptr<Trk::Track>
track =
2019 std::make_unique<Trk::Track>(spectrometerTrack.
info(), std::move(trackStateOnSurfaces),
nullptr);
2021 if (!
track->perigeeParameters()) {
2037 :
"usig interacting hypothesis"));
2039 std::unique_ptr<Trk::Track> fittedTrack{
fit(ctx, *
track, runOutlier, particleHypothesis)};
2044 if (fittedTrack->perigeeParameters() && !
m_indetVolume->inside(fittedTrack->perigeeParameters()->position())) {
2045 ATH_MSG_DEBUG(
" back extrapolation problem: fitted perigee outside indet volume ");
2065 auto trackStateOnSurfaces = std::make_unique<Trk::TrackStates>();
2075 std::unique_ptr<Trk::TrackStateOnSurface> perigeeTSOS {(**s).clone()};
2078 for (;
s !=
end; ++
s) {
2080 if (!
m_indetVolume->inside((**s).trackParameters()->position())) {
break; }
2084 trackStateOnSurfaces->reserve(
size);
2085 trackStateOnSurfaces->push_back(std::move(perigeeTSOS));
2090 return std::make_unique<Trk::Track>(
info, std::move(trackStateOnSurfaces),
nullptr);
2105 while ((**s).trackParameters() &&
2107 if (
m_indetVolume->inside((**s).trackParameters()->position())) { lastIDtp = (**s).trackParameters(); }
2113 auto trackStateOnSurfaces = std::make_unique<Trk::TrackStates>();
2116 bool redoCaloAssoc =
false;
2118 redoCaloAssoc =
true;
2121 while ((**s).trackParameters() &&
2128 std::vector<std::unique_ptr<const Trk::TrackStateOnSurface>> caloTSOS;
2131 ATH_MSG_VERBOSE(
" Retriving Calorimeter TSOS from " << __func__ <<
" at line " << __LINE__);
2137 if (caloTSOS.size() < 3) {
2138 ATH_MSG_DEBUG(
" muonTrack: parameters fail to fully intersect the calorimeter");
2142 size += caloTSOS.size();
2143 trackStateOnSurfaces->reserve(
size + 1);
2146 for (std::unique_ptr<const Trk::TrackStateOnSurface>& c_tsos : caloTSOS) { trackStateOnSurfaces->push_back(std::move(c_tsos)); }
2149 trackStateOnSurfaces->reserve(
size + 1);
2154 if (caloEnergy && (**s).trackParameters() &&
m_calorimeterVolume->inside((**s).trackParameters()->position())) {
2156 trackStateOnSurfaces->push_back(TSOS);
2160 if ((**s).trackParameters() &&
m_calorimeterVolume->inside((**s).trackParameters()->position())) {
2161 std::bitset<Trk::MaterialEffectsBase::NumberOfMaterialEffectsTypes> typePattern;
2164 std::unique_ptr<Trk::MaterialEffectsOnTrack> materialEffects =
2165 std::make_unique<Trk::MaterialEffectsOnTrack>(0., std::move(caloEnergy), (**s).trackParameters()->associatedSurface(), typePattern);
2169 std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes>
type;
2173 trackStateOnSurfaces->push_back(TSOS);
2182 bool hasAlreadyPerigee =
false;
2185 while ((**s).trackParameters() &&
m_calorimeterVolume->inside((**s).trackParameters()->position())) {
2188 trackStateOnSurfaces->push_back(TSOS);
2194 std::unique_ptr<Trk::TrackStateOnSurface> entranceTSOS;
2198 if (!hasAlreadyPerigee) {
2199 if ((**s).trackParameters()) {
2202 entranceTSOS =
entrancePerigee(ctx, trackStateOnSurfaces->back()->trackParameters());
2211 << (**s).trackParameters()->position().perp() <<
" z " << (**s).trackParameters()->position().z());
2213 trackStateOnSurfaces->push_back(std::move(entranceTSOS));
2214 hasAlreadyPerigee =
true;
2223 if (!hasAlreadyPerigee && std::find_if(trackStateOnSurfaces->begin(), trackStateOnSurfaces->end(),
2225 return tsos->type(Trk::TrackStateOnSurface::Perigee);
2229 std::stable_sort(trackStateOnSurfaces->begin(),trackStateOnSurfaces->end(),
2231 return a->type(Trk::TrackStateOnSurface::Perigee) > b->type(Trk::TrackStateOnSurface::Perigee);
2233 ATH_MSG_DEBUG(__FILE__<<
":"<<__LINE__<<
" No track perigee parameters were added. Copy the existing ones from the muon track");
2235 std::unique_ptr<Trk::Track> newMuonTrack = std::make_unique<Trk::Track>(muonTrack.
info(), std::move(trackStateOnSurfaces),
nullptr);
2236 unsigned int num_ms{0}, num_precMS{0};
2243 if (num_precMS < 3 || num_ms < 5) {
2244 ATH_MSG_VERBOSE(__FILE__
":"<<__LINE__<<
" MS track with too few meausrements constructed "<<std::endl<<
2254 return newMuonTrack;
2261 covarianceMatrix.setZero();
2262 covarianceMatrix(0, 0) = s_sigmaPhiSector * s_sigmaPhiSector *
parameters->position().perp2();
2264 std::unique_ptr<Trk::PseudoMeasurementOnTrack> pseudo = std::make_unique<Trk::PseudoMeasurementOnTrack>(
2266 std::move(covarianceMatrix),
2275 std::vector<std::unique_ptr<const Trk::TrackStateOnSurface>> spectrometerTSOS;
2279 if (!measuredPerigee)
2281 else if (!measuredPerigee->covariance())
2284 ATH_MSG_DEBUG(
"createSpectrometerTSOS::perigee covariance not valid");
2285 return spectrometerTSOS;
2294 unsigned numberPseudo =
m_trackQuery->numberPseudoMeasurements(spectrometerTrack);
2295 if (errorPhi > s_sigmaPhiSector) { ++numberPseudo; }
2297 if (numberPseudo > 1 && !
m_trackQuery->isSectorOverlap(spectrometerTrack)) {
2301 if (tsos) { spectrometerTSOS.emplace_back(std::move(tsos)); }
2306 bool haveMeasurement =
false;
2308 std::vector<const Trk::Surface*> measurementSurfaces;
2311 unsigned numberMaterial{0}, numberParameters{0};
2314 std::unique_ptr<const Trk::TrackStateOnSurface> previousTSOS;
2318 if (!haveMeasurement) {
2319 if (
s->measurementOnTrack()) {
2320 haveMeasurement =
true;
2321 }
else if (
s->materialEffectsOnTrack()) {
2329 if (
s->materialEffectsOnTrack()) ++numberMaterial;
2330 if (trackParameters) ++numberParameters;
2334 if (!
s->measurementOnTrack() && !
s->materialEffectsOnTrack()) {
2341 if (
s->trackParameters()) {
2342 ATH_MSG_DEBUG(
"createSpectrometerTSOS:: skip unrecognized TSOS " <<
s->dumpType() <<
" r "
2343 <<
s->trackParameters()->position().perp() <<
" z "
2344 <<
s->trackParameters()->position().z());
2353 bool trapezoid =
false;
2354 bool rotatedTrap =
false;
2355 if (
s->measurementOnTrack()) {
2362 const Trk::Surface* surface = &
s->measurementOnTrack()->associatedSurface();
2364 if (previousSurface) {
deltaZ = std::abs(previousSurface->
center().z() - surface->
center().z()); }
2375 if (previousSurface &&
2376 std::find(measurementSurfaces.begin(), measurementSurfaces.end(), surface) != measurementSurfaces.end()) {
2381 measurementSurfaces.push_back(surface);
2382 previousSurface = surface;
2384 }
else if (previousTSOS) {
2385 spectrometerTSOS.emplace_back(std::move(previousTSOS));
2389 std::unique_ptr<const Trk::TrackStateOnSurface> TSOS(
s->clone());
2392 spectrometerTSOS.emplace_back(std::move(TSOS));
2393 TSOS = std::move(previousTSOS);
2395 spectrometerTSOS.emplace_back(std::move(previousTSOS));
2400 previousTSOS.swap(TSOS);
2404 spectrometerTSOS.emplace_back(std::move(TSOS));
2407 if (previousTSOS) spectrometerTSOS.emplace_back(std::move(previousTSOS));
2410 << numberMaterial <<
" have MaterialEffects and " << numberParameters
2411 <<
" have TrackParameters");
2413 return spectrometerTSOS;
2420 if (!spectrometerEntrance)
return nullptr;
2422 std::unique_ptr<Trk::TrackParameters> entranceParameters{
2425 if (!entranceParameters)
return nullptr;
2428 std::unique_ptr<Trk::TrackParameters> trackParameters{
m_extrapolator->extrapolateDirectly(ctx, *entranceParameters, surface)};
2430 if (!trackParameters)
return nullptr;
2432 std::unique_ptr<Trk::Perigee> perigee =
2433 std::make_unique<Trk::Perigee>(trackParameters->position(), trackParameters->momentum(), trackParameters->charge(), std::move(surface));
2438 const EventContext& ctx,
bool& badlyDeterminedCurvature,
const Trk::Track& spectrometerTrack,
const Trk::RecVertex* mvertex,
2440 badlyDeterminedCurvature =
false;
2443 if (!measuredPerigee || !measuredPerigee->covariance()) {
2457 double errorP = std::sqrt(measuredPerigee->momentum().mag2() * (*measuredPerigee->covariance())(
Trk::qOverP,
Trk::qOverP));
2460 std::unique_ptr<Trk::TrackParameters> correctedParameters{};
2462 double trackEnergy = 1. / std::abs(parameterVector[
Trk::qOverP]);
2476 bool curvatureOK =
false;
2493 std::unique_ptr<CaloEnergy> caloEnergy{
2496 if (trackEnergy + caloEnergy->deltaE() <
m_minEnergy) {
2502 correctedParameters =
parameters->associatedSurface().createUniqueTrackParameters(
2509 double spectrometerEnergyLoss = 0.;
2513 for (;
s != sEnd; ++
s) {
2514 if (!(**s).materialEffectsOnTrack()) {
continue; }
2521 if (std::abs(spectrometerEnergyLoss) > 1.5 * std::abs(caloEnergy->deltaE())) {
2522 curvatureOK =
false;
2523 ATH_MSG_DEBUG(
"standaloneFit: excessive energy loss in spectrometer "
2525 <<
" in calo " << std::abs(caloEnergy->deltaE() /
Gaudi::Units::GeV) <<
" GeV");
2532 std::unique_ptr<Trk::TrackParameters> perigee{propagator->
propagate(
2536 ATH_MSG_DEBUG(
"standaloneFit: failed back extrapolation to perigee");
2542 ATH_MSG_DEBUG(
"Track d0 perigee: " << std::abs(perigee->parameters()[
Trk::d0]) <<
" which is smaller than "
2548 double deltaR = (position - perigee->position()).
perp();
2565 correctedParameters =
parameters->associatedSurface().createUniqueTrackParameters(
2574 deltaR = (position - perigee->position()).
perp();
2580 ATH_MSG_VERBOSE(
"standaloneFit: corrected perigee impact " << perigee->parameters()[
Trk::d0] <<
" deltaR, deltaPhi "
2589 correctedParameters =
parameters->associatedSurface().createUniqueTrackParameters(
2602 correctedParameters =
parameters->associatedSurface().createUniqueTrackParameters(
2610 if (!perigee || !
m_indetVolume->inside(perigee->position())) {
2611 if (perigee && perigee->position().z() * perigee->momentum().z() < 0. && perigee->momentum().eta() > 2.0) {
2612 ATH_MSG_DEBUG(
"standaloneFit: halo candidate, perigee at R " << perigee->position().perp() <<
" Z "
2613 << perigee->position().z());
2615 ATH_MSG_DEBUG(
"standaloneFit: perigee outside indet volume");
2622 badlyDeterminedCurvature =
true;
2625 std::unique_ptr<const Trk::TrackParameters> trigParameters{
m_trackQuery->triggerStationParameters(spectrometerTrack, ctx)};
2630 if (trigParameters) {
2632 <<
" start with line from origin to 1st trigger station ");
2635 <<
" start with line from origin to 1st measurement ");
2639 std::unique_ptr<Trk::TrackParameters> perigee =
2640 std::make_unique<Trk::Perigee>(mvertex->
position(),
momentum, 1., *mperigeeSurface);
2646 ATH_MSG_DEBUG(
"standaloneFit: failed back extrapolation to perigee");
2668 if (!
checkTrack(
"finalTrackBuild1", recoveredTrack.get())) {
2674 if (chi2After <
m_badFitChi2 || chi2After < chi2Before + 0.1) {
2675 track.swap(recoveredTrack);
2677 ATH_MSG_VERBOSE(
" track rejected by recovery as chi2 " << chi2After <<
" compared to " << chi2Before);
2731 if (
checkTrack(
"finalTrackBuild2", optimizedTrack.get())) {
2732 track.swap(optimizedTrack);
2741 bool directionUpdate,
double deltaPhi,
double deltaTheta)
const {
2744 std::unique_ptr<Trk::TrackParameters> updatedParameters;
2749 if (directionUpdate) {
2750 double cosDeltaPhi = 0.;
2753 if (std::abs(sinDeltaPhi) < 1.) { cosDeltaPhi = std::sqrt(1. - sinDeltaPhi * sinDeltaPhi); }
2755 double cosDeltaTheta = 0.;
2756 double sinDeltaTheta =
std::sin(deltaTheta);
2758 if (std::abs(sinDeltaTheta) < 1.) { cosDeltaTheta = std::sqrt(1. - sinDeltaTheta * sinDeltaTheta); }
2760 double cosTheta = direction.z() * cosDeltaTheta - direction.perp() * sinDeltaTheta;
2761 if (std::abs(cosTheta) < 1.) {
2762 direction =
Amg::Vector3D(direction.x() * cosDeltaPhi - direction.y() * sinDeltaPhi,
2763 direction.y() * cosDeltaPhi + direction.x() * sinDeltaPhi,
2764 direction.perp() * cosTheta / std::sqrt(1. - cosTheta * cosTheta));
2769 direction = direction.unit();
2779 parameters->covariance() ? std::optional<AmgSymMatrix(5)>(*(
parameters->covariance())) : std::nullopt;
2783 if (updatedParameters) {
2794 double perigeeDistance = 0.;
2800 for (;
s != sEnd; ++
s) {
2806 spectrometerMeasurements.push_back((**s).measurementOnTrack()->clone());
2807 if (!(**s).trackParameters() || (perigeeStartValue && (**s).trackParameters()->
position().mag() > perigeeDistance)) {
2811 perigeeDistance = (**s).trackParameters()->position().mag();
2812 perigeeStartValue = (**s).trackParameters();
2817 if (!perigeeStartValue) {
2825 std::unique_ptr<Trk::Track> spectrometerFit =
fit(ctx, spectrometerMeasurements, *perigeeStartValue,
true,
Trk::muon);
2826 if (!spectrometerFit) {
2827 spectrometerFit =
fit(ctx, spectrometerMeasurements, *perigeeStartValue,
false,
Trk::muon);
2829 if (!spectrometerFit) {
2832 if (!spectrometerFit) {
2842 auto mEnd = spectrometerMeasurements.end();
2843 for (;
m != mEnd; ++
m) {
delete *
m; }
2845 return spectrometerFit;
2850 bool limitMomentum =
false;
2851 double momentum =
track->perigeeParameters()->momentum().mag();
2857 if (measuredPerigee) {
2860 while (!(**r).trackParameters()) { --
r; }
2862 limitMomentum =
true;
2864 if (!measuredPerigee->covariance()) {
2865 ATH_MSG_DEBUG(
"measuredPerigee has no covariance, qOverP not set");
2878 std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes> defaultType;
2879 std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes>
type = defaultType;
2880 auto trackStateOnSurfaces = std::make_unique<Trk::TrackStates>();
2882 trackStateOnSurfaces->reserve(
track->trackStateOnSurfaces()->size());
2883 bool is_first{
true};
2886 if (tsos->trackParameters()) {
2887 if (limitMomentum && is_first && tsos->trackParameters()->covariance() &&
2889 Amg::VectorX parameterVector = tsos->trackParameters()->parameters();
2893 std::unique_ptr<Trk::TrackParameters>
parameters =
2894 tsos->trackParameters()->associatedSurface().createUniqueTrackParameters(
2896 parameterVector[
Trk::qOverP], *tsos->trackParameters()->covariance());
2901 std::unique_ptr<Trk::MeasurementBase> measurementBase;
2902 if (tsos->measurementOnTrack()) {
2903 measurementBase = tsos->measurementOnTrack()->
uniqueClone();
2906 trackStateOnSurfaces->push_back(
2909 trackStateOnSurfaces->push_back(tsos->clone());
2917 if (tsos->materialEffectsOnTrack() &&
2918 !
m_calorimeterVolume->inside(tsos->materialEffectsOnTrack()->associatedSurface().globalReferencePoint())) {
2919 if (tsos->measurementOnTrack()) {
2920 Amg::VectorX parameterVector = tsos->trackParameters()->parameters();
2922 std::unique_ptr<Trk::TrackParameters> trackParameters =
2923 tsos->trackParameters()->associatedSurface().createUniqueTrackParameters(
2926 tsos->trackParameters()->covariance() ? std::optional<
AmgSymMatrix(5)>(*tsos->trackParameters()->covariance())
2933 std::unique_ptr<Trk::MeasurementBase> measurementBase;
2934 measurementBase = tsos->measurementOnTrack()->
uniqueClone();
2935 trackStateOnSurfaces->push_back(
2939 }
else if (!tsos->measurementOnTrack() && tsos->trackParameters() &&
2944 if (limitMomentum && tsos->trackParameters()) {
2945 Amg::VectorX parameterVector = tsos->trackParameters()->parameters();
2947 std::unique_ptr<Trk::TrackParameters> trackParameters =
2948 tsos->trackParameters()->associatedSurface().createUniqueTrackParameters(
2951 tsos->trackParameters()->covariance() ? std::optional<
AmgSymMatrix(5)>(*tsos->trackParameters()->covariance())
2956 std::unique_ptr<Trk::MeasurementBase> measurementBase;
2957 if (tsos->measurementOnTrack()) {
2962 measurementBase = tsos->measurementOnTrack()->
uniqueClone();
2965 std::unique_ptr<Trk::MaterialEffectsBase> materialEffects;
2966 if (tsos->materialEffectsOnTrack()) {
2970 materialEffects = tsos->materialEffectsOnTrack()->
uniqueClone();
2972 trackStateOnSurfaces->push_back(
new Trk::TrackStateOnSurface(std::move(measurementBase), std::move(trackParameters),
2973 std::move(materialEffects),
type));
2975 trackStateOnSurfaces->push_back(tsos->clone());
2981 std::unique_ptr<Trk::FitQuality>
fitQuality =
nullptr;
2982 if (
track->fitQuality()) {
fitQuality = std::make_unique<Trk::FitQuality>(*
track->fitQuality()); }
2994 covarianceMatrix.setZero();
2998 double ptInv = 1. /
parameters.momentum().perp();
3000 if (
vertex == mbeamAxis) {
3006 jacobian(0, 0) = -ptInv *
parameters.momentum().y();
3007 jacobian(0, 1) = ptInv *
parameters.momentum().x();
3010 covarianceMatrix =
cov.similarity(jacobian);
3016 jacobian(0, 0) = -ptInv *
parameters.momentum().y();
3017 jacobian(0, 1) = ptInv *
parameters.momentum().x();
3018 jacobian(1, 2) = 1.0;
3021 covarianceMatrix =
cov.similarity(jacobian);
3024 return std::make_unique<Trk::PseudoMeasurementOnTrack>(std::move(localParameters),
3025 std::move(covarianceMatrix),
3048 double idEloss = 0.;
3049 double caloEloss = 0.;
3050 double msEloss = 0.;
3055 double pMuonEntry = 0.;
3057 for (
const auto*
m : *trackTSOS) {
3060 if (
m->trackParameters()) { pMuonEntry =
m->trackParameters()->momentum().mag(); }
3064 if (
id.is_valid()) {
3070 if (pstart == 0 &&
m->trackParameters()) {
3071 pstart =
m->trackParameters()->momentum().mag();
3072 eta =
m->trackParameters()->momentum().eta();
3074 ATH_MSG_DEBUG(
"Start pars found eta " <<
eta <<
" r " << (
m->trackParameters())->position().perp() <<
" z "
3075 << (
m->trackParameters())->position().z() <<
" pstart " << pstart);
3078 if (
m->materialEffectsOnTrack()) {
3088 pcalo =
m->trackParameters()->momentum().mag();
3094 << pullPhi <<
" deltaTheta (mrad) " << 1000 * scatAngles->
deltaTheta() <<
" sigma "
3101 if (
m->trackParameters()) {
3102 ATH_MSG_DEBUG(
"Eloss found r " << (
m->trackParameters())->position().perp() <<
" z "
3103 << (
m->trackParameters())->position().z() <<
" value " << energyLoss->
deltaE()
3104 <<
" Eloss " << Eloss);
3109 caloEloss = std::abs(energyLoss->
deltaE());
3112 if (
m->trackParameters()) { deltaP =
m->trackParameters()->momentum().mag() - pcalo; }
3117 ATH_MSG_DEBUG(
txt <<
" Calorimeter delta p " << deltaP <<
" deltaE " << caloEloss
3118 <<
" delta pID = pcaloEntry-pstart " << pcalo - pstart);
3121 Eloss += std::abs(energyLoss->
deltaE());
3129 Eloss = idEloss + caloEloss + msEloss;
3132 <<
" caloEloss " << caloEloss <<
" msEloss " << msEloss <<
" Total " << Eloss <<
" pstart - pMuonEntry "
3133 << pstart - pMuonEntry);
3149 std::vector<std::unique_ptr<const Trk::TrackStateOnSurface>> to_ret;
3150 std::unique_ptr<std::vector<const Trk::TrackStateOnSurface*>> tsos_vec{
m_materialUpdator->getCaloTSOS(track_params, me_track)};
3152 to_ret.reserve(tsos_vec->size());