32 if (
track.fitQuality())
return track.fitQuality()->doubleNumberDoF();
42 const IInterface*
parent) :
46 ATH_MSG_INFO(
"Initializing OutwardsCombinedMuonTrackBuilder.");
48 msg(MSG::INFO) <<
" with options: ";
83 return StatusCode::SUCCESS;
106 std::unique_ptr<Trk::TrackParameters> ,
107 std::unique_ptr<Trk::TrackParameters> ,
108 std::unique_ptr<Trk::TrackParameters> )
const {
111 auto trajectory = std::make_unique<Trk::TrackStates>();
126 ATH_MSG_FATAL(
"This method should actually never be called");
132 ATH_MSG_DEBUG(
" start OutwardsCombinedMuonTrackBuilder standaloneRefit");
136 double vertex3DSigmaRPhi = 6.0;
137 double vertex3DSigmaZ = 60.0;
139 auto trackStateOnSurfaces = std::make_unique<Trk::TrackStates>();
141 bool addVertexRegion =
true;
143 vertexRegionCovariance.setZero();
144 vertexRegionCovariance(0, 0) = vertex3DSigmaRPhi * vertex3DSigmaRPhi;
145 vertexRegionCovariance(1, 1) = vertex3DSigmaRPhi * vertex3DSigmaRPhi;
146 vertexRegionCovariance(2, 2) = vertex3DSigmaZ * vertex3DSigmaZ;
157 if ((**t).alignmentEffectsOnTrack())
continue;
164 trackStateOnSurfaces->push_back(TSOS);
167 if (addVertexRegion) {
171 std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes>
type;
173 trackStateOnSurfaces->push_back(
174 std::make_unique<Trk::TrackStateOnSurface>(std::move(vertexInFit),
nullptr,
nullptr,
type));
189 if ((**t).alignmentEffectsOnTrack())
continue;
190 if (!(**t).trackParameters())
continue;
192 if ((**t).materialEffectsOnTrack()) {
193 if (!
m_indetVolume->inside((**t).trackParameters()->position()))
break;
195 double X0 = (**t).materialEffectsOnTrack()->thicknessInX0();
202 Eloss += std::abs(energyLoss->
deltaE());
204 ATH_MSG_DEBUG(
"OutwardsCombinedMuonFit ID Eloss found r " << ((**t).trackParameters())->position().perp() <<
" z "
205 << ((**t).trackParameters())->position().z() <<
" value "
206 << energyLoss->
deltaE() <<
" Eloss " << Eloss);
214 auto energyLossNew = std::make_unique<Trk::EnergyLoss>(
219 const Trk::Surface& surfNew = (**t).trackParameters()->associatedSurface();
221 std::bitset<Trk::MaterialEffectsBase::NumberOfMaterialEffectsTypes> meotPattern(0);
226 std::make_unique<Trk::MaterialEffectsOnTrack>(
X0,
228 std::move(energyLossNew),
233 auto parsNew = ((**t).trackParameters())->
uniqueClone();
235 std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes> typePatternScat(0);
238 std::unique_ptr<Trk::TrackStateOnSurface> newTSOS =
239 std::make_unique<Trk::TrackStateOnSurface>(
nullptr, std::move(parsNew), std::move(meotNew), typePatternScat);
241 trackStateOnSurfaces->push_back(std::move(newTSOS));
248 ATH_MSG_DEBUG(
"OutwardsCombinedMuonFit Total ID Eloss " << Eloss <<
" nr of states " << itsos);
255 if ((**t).alignmentEffectsOnTrack())
continue;
257 trackStateOnSurfaces->push_back((**t).clone());
260 ATH_MSG_DEBUG(
" trackStateOnSurfaces found " << trackStateOnSurfaces->size() <<
" from total " << itsos);
262 std::unique_ptr<Trk::Track> standaloneTrack =
263 std::make_unique<Trk::Track>(
combinedTrack.info(), std::move(trackStateOnSurfaces),
nullptr);
266 std::unique_ptr<Trk::Track> refittedTrack =
fit(ctx, *standaloneTrack,
false,
Trk::muon);
268 if (!refittedTrack) {
269 ATH_MSG_DEBUG(
" OutwardsCombinedMuonTrackBuilder standaloneRefit FAILED ");
273 ATH_MSG_DEBUG(
" OutwardsCombinedMuonTrackBuilder standaloneRefit OK ");
276 return refittedTrack;
286 <<
" requested. Must be 0 or 2 (nonInteracting or muon) ");
291 std::unique_ptr<Trk::Track> fittedTrack{
m_fitter->fit(ctx,
track,
false, particleHypothesis)};
292 if (!fittedTrack)
return nullptr;
298 ATH_MSG_VERBOSE(
" perform spectrometer error optimization before cleaning ");
300 std::unique_ptr<Trk::Track> optimizedTrack =
m_muonErrorOptimizer->optimiseErrors(*fittedTrack, ctx);
301 if (optimizedTrack) { fittedTrack.swap(optimizedTrack); }
307 std::unique_ptr<Trk::Track> cleanTrack =
m_cleaner->clean(*fittedTrack, ctx);
311 }
else if (!(*cleanTrack->
perigeeParameters() == *fittedTrack->perigeeParameters())) {
315 fittedTrack.swap(cleanTrack);
331 <<
" requested. Must be 0 or 2 (nonInteracting or muon) ");
336 std::unique_ptr<Trk::Track> fittedTrack{
m_fitter->fit(ctx, indetTrack, extrapolatedTrack,
false, particleHypothesis)};
338 if (!fittedTrack) {
return nullptr; }
340 if (!fittedTrack->perigeeParameters()) {
341 ATH_MSG_WARNING(
" Fitter returned a track without perigee, failing fit");
349 ATH_MSG_VERBOSE(
" perform spectrometer error optimization before cleaning ");
350 std::unique_ptr<Trk::Track> optimizedTrack{
m_muonErrorOptimizer->optimiseErrors(*fittedTrack, ctx)};
351 if (optimizedTrack) {
353 fittedTrack.swap(optimizedTrack);
358 std::unique_ptr<Trk::Track> cleanTrack =
m_cleaner->clean(*fittedTrack, ctx);
362 }
else if (!(*cleanTrack->
perigeeParameters() == *fittedTrack->perigeeParameters())) {
366 fittedTrack.swap(cleanTrack);
373 std::unique_ptr<Trk::Track> newTrack{
addIDMSerrors(*fittedTrack)};
375 std::unique_ptr<Trk::Track> refittedTrack{
fit(ctx, *newTrack,
false,
Trk::muon)};
378 if (refittedTrack->fitQuality()) { fittedTrack.swap(refittedTrack); }
384 std::unique_ptr<Trk::Track> recoveredTrack{
m_muonHoleRecovery->recover(*fittedTrack, ctx)};
385 double oldfitqual = fittedTrack->fitQuality()->chiSquared() / fittedTrack->fitQuality()->numberDoF();
387 if (recoveredTrack && recoveredTrack != fittedTrack) {
388 double newfitqual = recoveredTrack->fitQuality()->chiSquared() / recoveredTrack->fitQuality()->numberDoF();
389 if (newfitqual < oldfitqual || newfitqual < 1.5 || (newfitqual < 2 && newfitqual < oldfitqual + .5)) {
390 fittedTrack.swap(recoveredTrack);
420 if (fittedTrack && !fittedTrack->perigeeParameters()) {
421 ATH_MSG_WARNING(
" Fitter returned a track without perigee, failing fit");
425 if (runOutlier && fittedTrack) {
426 double fitqual = fittedTrack->fitQuality()->chiSquared() / fittedTrack->fitQuality()->numberDoF();
428 if (fitqual > 5 || (fittedTrack->perigeeParameters()->pT() < 20000 && fitqual > 2.5)) {
435 for (; itStates != endStates; ++itStates) {
436 if ((*itStates)->materialEffectsOnTrack()) {
448 if (pullphi > 7 || pulltheta > 7) {
462 std::unique_ptr<Trk::Track> optimizedTrack{
m_muonErrorOptimizer->optimiseErrors(*fittedTrack, ctx)};
463 if (optimizedTrack) {
465 fittedTrack.swap(optimizedTrack);
480 ATH_MSG_VERBOSE(
" OutwardsCombinedMuonTrackBuilder addIDMSerrors to track ");
487 int itsosCaloFirst = -1;
488 int itsosCaloLast = -1;
492 for (;
t !=
track.trackStateOnSurfaces()->
end(); ++
t) {
495 if ((**t).trackParameters()) {
497 if (
m_indetVolume->inside((**t).trackParameters()->position())) {
continue; }
499 if ((**t).trackParameters()->position().mag() < 1000) {
continue; }
504 double X0 = (**t).materialEffectsOnTrack()->thicknessInX0();
506 if (
X0 < 10)
continue;
508 if (itsosCaloFirst != -1) {
509 itsosCaloLast = itsos;
510 positionCaloLast = (**t).trackParameters()->position();
513 if (itsosCaloFirst == -1) {
514 itsosCaloFirst = itsos;
515 positionCaloFirst = (**t).trackParameters()->position();
520 if ((**t).measurementOnTrack()) {
522 positionMS = (**t).trackParameters()->position();
531 ATH_MSG_DEBUG(
" OutwardsCombinedMuonTrackBuilder addIDMSerrors p muon GeV "
532 <<
p <<
" First Calorimeter Scatterer radius " << positionCaloFirst.perp() <<
" z " << positionCaloFirst.z()
533 <<
" Second Scatterer r " << positionCaloLast.perp() <<
" z " << positionCaloLast.z() <<
" First Muon hit r "
534 << positionMS.perp() <<
" z " << positionMS.z());
536 if (itsosCaloFirst < 0 || itsosCaloLast < 0) {
542 positionCaloFirst = positionCaloFirst - positionMS;
543 positionCaloLast = positionCaloLast - positionMS;
545 double sigmaDeltaPhiIDMS2 =
m_IDMS_xySigma / (positionCaloFirst.perp() + positionCaloLast.perp());
546 double sigmaDeltaThetaIDMS2 =
m_IDMS_rzSigma / (positionCaloFirst.mag() + positionCaloLast.mag());
548 sigmaDeltaPhiIDMS2 *= sigmaDeltaPhiIDMS2;
549 sigmaDeltaThetaIDMS2 *= sigmaDeltaThetaIDMS2;
551 auto trackStateOnSurfaces = std::make_unique<Trk::TrackStates>();
552 trackStateOnSurfaces->reserve(
track.trackStateOnSurfaces()->size());
554 t =
track.trackStateOnSurfaces()->begin();
557 for (;
t !=
track.trackStateOnSurfaces()->
end(); ++
t) {
560 if ((**t).alignmentEffectsOnTrack()) {
continue; }
562 if (itsos == itsosCaloFirst || itsos == itsosCaloLast) {
563 if ((**t).materialEffectsOnTrack()) {
564 double X0 = (**t).materialEffectsOnTrack()->thicknessInX0();
575 double sigmaDeltaTheta =
578 auto energyLossNew = std::make_unique<Trk::EnergyLoss>(0., 0., 0., 0.);
582 const Trk::Surface& surfNew = (**t).trackParameters()->associatedSurface();
584 std::bitset<Trk::MaterialEffectsBase::NumberOfMaterialEffectsTypes> meotPattern(0);
589 std::make_unique<Trk::MaterialEffectsOnTrack>(
X0,
591 std::move(energyLossNew),
595 auto parsNew = ((**t).trackParameters())->
uniqueClone();
597 std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes> typePatternScat(0);
603 trackStateOnSurfaces->push_back(newTSOS);
609 ATH_MSG_DEBUG(
" new Calo scatterer made with sigmaDeltaPhi mrad "
610 << sigmaDeltaPhi * 1000 <<
" sigmaDeltaTheta mrad " << sigmaDeltaTheta * 1000);
613 " This should not happen: no Scattering Angles for "
618 " This should not happen: no MaterialEffectsOnTrack "
625 trackStateOnSurfaces->push_back(TSOS);
628 ATH_MSG_DEBUG(
" trackStateOnSurfaces on input track " <<
track.trackStateOnSurfaces()->size() <<
" trackStateOnSurfaces found "
629 << trackStateOnSurfaces->size());
631 return std::make_unique<Trk::Track>(
track.info(), std::move(trackStateOnSurfaces),
nullptr);
634 std::unique_ptr<Trk::PseudoMeasurementOnTrack>
644 covarianceMatrix.setZero();
649 double ptInv = 1. /
parameters->momentum().perp();
655 jacobian(0, 0) = -ptInv *
parameters->momentum().y();
656 jacobian(0, 1) = ptInv *
parameters->momentum().x();
657 jacobian(1, 2) = 1.0;
660 covarianceMatrix =
cov.similarity(jacobian);
662 return std::make_unique<Trk::PseudoMeasurementOnTrack>(std::move(localParameters),
663 std::move(covarianceMatrix),
667 double chi2 = 999999.;
668 if (
track.fitQuality()) {
669 if (
track.fitQuality()->numberDoF()) {
670 chi2 =
track.fitQuality()->chiSquared() /
track.fitQuality()->doubleNumberDoF();