ATLAS Offline Software
Loading...
Searching...
No Matches
Rec::CombinedMuonTrackBuilder Class Reference

#include <CombinedMuonTrackBuilder.h>

Inheritance diagram for Rec::CombinedMuonTrackBuilder:
Collaboration diagram for Rec::CombinedMuonTrackBuilder:

Public Member Functions

 CombinedMuonTrackBuilder (const std::string &type, const std::string &name, const IInterface *parent)
virtual ~CombinedMuonTrackBuilder ()
virtual StatusCode initialize () override
virtual StatusCode finalize () override
virtual std::unique_ptr< Trk::TrackcombinedFit (const EventContext &ctx, const Trk::Track &indetTrack, const Trk::Track &extrapolatedTrack, const Trk::Track &spectrometerTrack) const override
 ICombinedMuonTrackBuilder interface: build and fit combined ID/Calo/MS track.
virtual std::unique_ptr< Trk::TrackindetExtension (const EventContext &ctx, const Trk::Track &indetTrack, const Trk::MeasurementSet &spectrometerMeas, std::unique_ptr< Trk::TrackParameters > innerParameters, std::unique_ptr< Trk::TrackParameters > middleParameters, std::unique_ptr< Trk::TrackParameters > outerParameters) const override
 ICombinedMuonTrackBuilder interface: build and fit indet track extended to include MS Measurement set.
virtual std::unique_ptr< Trk::TrackstandaloneFit (const EventContext &ctx, const Trk::Track &spectrometerTrack, const Amg::Vector3D &bs, const Trk::Vertex *vertex) const override
 ICombinedMuonTrackBuilder interface: propagate to perigee adding calo energy-loss and material to MS track.
virtual std::unique_ptr< Trk::TrackstandaloneRefit (const EventContext &ctx, const Trk::Track &combinedTrack, const Amg::Vector3D &vec) const override
 ICombinedMuonTrackBuilder interface: refit a track removing any indet measurements with optional addition of pseudoMeasurements.
virtual std::unique_ptr< Trk::Trackfit (const EventContext &ctx, const Trk::Track &track, const Trk::RunOutlierRemoval runOutlier, const Trk::ParticleHypothesis particleHypothesis) const override

Static Public Member Functions

static const InterfaceID & interfaceID ()
 AlgTool and IAlgTool interface methods.

Protected Member Functions

std::unique_ptr< Trk::Trackfit (const EventContext &ctx, const Trk::MeasurementSet &measurementSet, const Trk::TrackParameters &perigeeStartValue, const Trk::RunOutlierRemoval runOutlier, const Trk::ParticleHypothesis particleHypothesis) const
 fit a set of MeasurementBase objects with starting value for perigeeParameters
std::unique_ptr< Trk::Trackfit (const EventContext &ctx, const Trk::Track &indetTrack, Trk::Track &extrapolatedTrack, const Trk::RunOutlierRemoval runOutlier, const Trk::ParticleHypothesis particleHypothesis) const
 combined muon fit
double normalizedChi2 (const Trk::Track &track) const
bool checkTrack (std::string_view txt, const Trk::Track *newTrack) const
unsigned int countAEOTs (const Trk::Track &track, const std::string &txt) const
bool loadMagneticField (const EventContext &ctx, MagField::AtlasFieldCache &field_cache) const

Protected Attributes

ToolHandle< Rec::IMuidCaloTrackStateOnSurfacem_caloTSOS
ToolHandle< Muon::IMuonErrorOptimisationToolm_muonErrorOptimizer
PublicToolHandle< Muon::MuonEDMPrinterToolm_printer
ToolHandle< Rec::IMuonTrackQuerym_trackQuery
ToolHandle< Trk::ITrackSummaryToolm_trackSummary
ToolHandle< Trk::ITrkMaterialProviderToolm_materialUpdator
ServiceHandle< Muon::IMuonIdHelperSvcm_idHelperSvc {this, "MuonIdHelperSvc", "Muon::MuonIdHelperSvc/MuonIdHelperSvc"}
Gaudi::Property< double > m_badFitChi2 {this, "BadFitChi2", 2.5}
Gaudi::Property< double > m_zECToroid {this, "zECToroid", 10. * Gaudi::Units::meter}
Gaudi::Property< bool > m_updateWithCaloTG {this, "UpdateWithCaloTG", false}
Gaudi::Property< bool > m_useCaloTG {this, "UseCaloTG", false}
std::unique_ptr< const Trk::Volumem_indetVolume {nullptr}
std::unique_ptr< const Trk::Volumem_calorimeterVolume {nullptr}
std::unique_ptr< MessageHelperm_messageHelper {std::make_unique<MessageHelper>(*this, 50)}

Private Member Functions

std::unique_ptr< Trk::TrackaddIDMSerrors (const Trk::Track *track) const
void appendSelectedTSOS (Trk::TrackStates &trackStateOnSurfaces, Trk::TrackStates::const_iterator begin, Trk::TrackStates::const_iterator end) const
const CaloEnergycaloEnergyParameters (const Trk::Track *combinedTrack, const Trk::Track *muonTrack, const Trk::TrackParameters *&combinedEnergyParameters, const Trk::TrackParameters *&muonEnergyParameters) const
std::unique_ptr< Trk::TrackcreateExtrapolatedTrack (const EventContext &ctx, const Trk::Track &spectrometerTrack, const Trk::TrackParameters &parameters, 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
std::unique_ptr< Trk::TrackcreateIndetTrack (const Trk::TrackInfo &info, const Trk::TrackStates *tsos) const
std::unique_ptr< Trk::TrackcreateMuonTrack (const EventContext &ctx, const Trk::Track &muonTrack, const Trk::TrackParameters *parameters, std::unique_ptr< CaloEnergy > caloEnergy, const Trk::TrackStates *tsos) const
 Summarizes the available information about the ID track, the deposited calorimeter energies and the track states into a new track --> m_materialUpdator as only tool called , but does not provide an interface method with ctx thus far.
std::unique_ptr< Trk::TrackStateOnSurfacecreatePhiPseudoMeasurement (const EventContext &ctx, const Trk::Track &track) const
std::vector< std::unique_ptr< const Trk::TrackStateOnSurface > > createSpectrometerTSOS (const EventContext &ctx, const Trk::Track &spectrometerTrack) const
std::unique_ptr< Trk::TrackStateOnSurfaceentrancePerigee (const EventContext &ctx, const Trk::TrackParameters *parameters) const
std::unique_ptr< Trk::TrackParametersextrapolatedParameters (const EventContext &ctx, bool &badlyDeterminedCurvature, const Trk::Track &spectrometerTrack, const Trk::RecVertex *mvertex, const Trk::PerigeeSurface *mperigeeSurface) const
void finalTrackBuild (const EventContext &ctx, std::unique_ptr< Trk::Track > &track) const
void momentumUpdate (std::unique_ptr< Trk::TrackParameters > &parameters, double updatedP, bool directionUpdate=false, double deltaPhi=0., double deltaTheta=0.) const
std::unique_ptr< Trk::TrackreallocateMaterial (const EventContext &ctx, const Trk::Track &spectrometerTrack) const
void replaceCaloEnergy (const CaloEnergy *caloEnergy, Trk::Track *track) const
void removeSpectrometerMaterial (std::unique_ptr< Trk::Track > &track) const
void dumpCaloEloss (const Trk::Track *track, const std::string &txt) const
const Trk::TrackingVolumegetVolume (const EventContext &ctx, const std::string &&vol_name) const
std::vector< std::unique_ptr< const Trk::TrackStateOnSurface > > getCaloTSOSfromMatProvider (const Trk::TrackParameters &track_params, const Trk::Track &me_track) const
 Helper method to retrieve the CaloTSO from the Material provider in a memory safe way.
bool optimizeErrors (const EventContext &ctx, Trk::Track &track) const

Static Private Member Functions

static std::unique_ptr< Trk::PseudoMeasurementOnTrackvertexOnTrack (const Trk::TrackParameters &parameters, const Trk::RecVertex *vertex, const Trk::RecVertex *mbeamAxis)

Private Attributes

ToolHandle< Rec::IMuidCaloEnergym_caloEnergyParam
ToolHandle< Muon::IMuonClusterOnTrackCreatorm_cscRotCreator
ToolHandle< Muon::IMuonClusterOnTrackCreatorm_muClusterRotCreator {this, "MuonRotCreator", ""}
ToolHandle< Trk::IExtrapolatorm_extrapolator
ToolHandle< Trk::IMaterialAllocatorm_materialAllocator
ToolHandle< Muon::IMdtDriftCircleOnTrackCreatorm_mdtRotCreator
ToolHandle< Muon::IMuonHoleRecoveryToolm_muonHoleRecovery
ToolHandle< Trk::IPropagatorm_propagator
ToolHandle< Trk::IPropagatorm_propagatorSL
PublicToolHandle< Muon::IMuonAlignmentUncertToolm_alignUncertTool_theta
 ToolHandles to retrieve the uncertainties for theta and phi for the scattering uncertainties.
PublicToolHandle< Muon::IMuonAlignmentUncertToolm_alignUncertTool_phi
ServiceHandle< Muon::IMuonEDMHelperSvcm_edmHelperSvc
SG::ReadCondHandleKey< Trk::TrackingGeometrym_trackingGeometryReadKey
Trk::MagneticFieldProperties m_magFieldProperties {Trk::FullField}
Gaudi::Property< bool > m_cleanCombined {this, "CleanCombined", true}
Gaudi::Property< bool > m_cleanStandalone {this, "CleanStandalone", true}
Gaudi::Property< bool > m_perigeeAtSpectrometerEntrance {this, "PerigeeAtSpectrometerEntrance", false}
Gaudi::Property< bool > m_reallocateMaterial {this, "ReallocateMaterial", true}
Gaudi::Property< double > m_largeImpact {this, "LargeImpact", 100. * Gaudi::Units::mm}
Gaudi::Property< double > m_largeMomentumChange {this, "LargeMomentumChange", 0.05}
Gaudi::Property< double > m_largeMomentumError {this, "LargeMomentumError", 0.15}
Gaudi::Property< double > m_largePhiError {this, "LargePhiError", 0.020}
Gaudi::Property< double > m_lineMomentum {this, "LineMomentum", 2. * Gaudi::Units::GeV}
Gaudi::Property< double > m_lowMomentum {this, "LowMomentum", 10. * Gaudi::Units::GeV}
Gaudi::Property< double > m_minEnergy {this, "MinEnergy", 0.3 * Gaudi::Units::GeV}
Gaudi::Property< double > m_numberSigmaFSR {this, "NumberSigmaFSR", 2.5}
Gaudi::Property< double > m_vertex2DSigmaRPhi {this, "Vertex2DSigmaRPhi", 100. * Gaudi::Units::mm}
Gaudi::Property< double > m_vertex2DSigmaZ {this, "Vertex2DSigmaZ", 100. * Gaudi::Units::meter}
Gaudi::Property< double > m_vertex3DSigmaRPhi {this, "Vertex3DSigmaRPhi", 6. * Gaudi::Units::mm}
Gaudi::Property< double > m_vertex3DSigmaZ {this, "Vertex3DSigmaZ", 60. * Gaudi::Units::mm}
bool m_redoRots {false}
std::unique_ptr< const Trk::RecVertexm_beamAxis
std::unique_ptr< const Trk::PerigeeSurfacem_perigeeSurface
std::unique_ptr< const Trk::RecVertexm_vertex
std::atomic_uint m_countAcceptedStandaloneFit {0}
std::atomic_uint m_countBeamAxis {0}
std::atomic_uint m_countDegradedStandaloneFit {0}
std::atomic_uint m_countVertexRegion {0}
Gaudi::Property< bool > m_iterateCombinedTrackFit {this, "IterateCombinedTrackFit", false}
Gaudi::Property< bool > m_refineELossCombinedTrackFit {this, "RefineELossCombinedTrackFit", true}
Gaudi::Property< bool > m_refineELossStandAloneTrackFit {this, "RefineELossStandAloneTrackFit", true}
Gaudi::Property< bool > m_addElossID {this, "AddElossID", true}
Gaudi::Property< bool > m_addIDMSerrors {this, "AddIDMSerrors", true}
Gaudi::Property< bool > m_useRefitTrackError {this, "UseRefitTrackError", true}
ToolHandle< Muon::IMuonTrackCleanerm_cleaner
ToolHandle< Trk::ITrackFitterm_fitter
ToolHandle< Trk::ITrackFitterm_fitterSL
SG::ReadCondHandleKey< AtlasFieldCacheCondObjm_fieldCacheCondObjInputKey
ServiceHandle< Trk::ITrackingVolumesSvcm_trackingVolumesSvc {this, "TrackingVolumesSvc", "Trk::TrackingVolumesSvc/TrackingVolumesSvc"}
Gaudi::Property< bool > m_allowCleanerVeto {this, "AllowCleanerVeto", true}
Gaudi::Property< unsigned > m_maxWarnings
std::atomic_uint m_countCombinedCleanerVeto {0}
std::atomic_uint m_countExtensionCleanerVeto {0}
std::atomic_uint m_countStandaloneCleanerVeto {0}

Detailed Description

Definition at line 62 of file CombinedMuonTrackBuilder.h.

Constructor & Destructor Documentation

◆ CombinedMuonTrackBuilder()

Rec::CombinedMuonTrackBuilder::CombinedMuonTrackBuilder ( const std::string & type,
const std::string & name,
const IInterface * parent )

Definition at line 58 of file CombinedMuonTrackBuilder.cxx.

58 :
59 CombinedMuonTrackFitter(type, name, parent) {
60 declareInterface<ICombinedMuonTrackBuilder>(this);
61 }

◆ ~CombinedMuonTrackBuilder()

Rec::CombinedMuonTrackBuilder::~CombinedMuonTrackBuilder ( )
virtual

Definition at line 57 of file CombinedMuonTrackBuilder.cxx.

57{}

Member Function Documentation

◆ addIDMSerrors()

std::unique_ptr< Trk::Track > Rec::CombinedMuonTrackBuilder::addIDMSerrors ( const Trk::Track * track) const
private

Use pointer in the data vector to refer on the track

it can happen that no Calorimeter Scatterers are found.

Definition at line 1560 of file CombinedMuonTrackBuilder.cxx.

1560 {
1561 //
1562 // take track and correct the two scattering planes in the Calorimeter
1563 // to take into account m_IDMS_rzSigma and m_IDMS_xySigma
1564 //
1565 // returns a new Track or nullptr does not modify the input in any way
1566 //
1567 if (!m_addIDMSerrors) { return nullptr; }
1568
1569 ATH_MSG_DEBUG(" CombinedMuonTrackBuilder addIDMSerrors to track ");
1570
1572 const Trk::TrackStateOnSurface* id_exit = nullptr;
1573 const Trk::TrackStateOnSurface* calo_entrance = nullptr;
1574 const Trk::TrackStateOnSurface* calo_exit = nullptr;
1575 const Trk::TrackStateOnSurface* ms_entrance = nullptr;
1576
1577 m_alignUncertTool_theta->get_track_state_measures(track, id_exit, calo_entrance, calo_exit, ms_entrance);
1579 if (!calo_entrance || !calo_exit || !ms_entrance) {
1580 ATH_MSG_DEBUG(" addIDMSerrors keep original track ");
1581 return nullptr;
1582 }
1583
1584 auto trackStateOnSurfaces = std::make_unique<Trk::TrackStates>();
1585 trackStateOnSurfaces->reserve(track->trackStateOnSurfaces()->size());
1586
1587 for (const Trk::TrackStateOnSurface* trk_srf : *track->trackStateOnSurfaces()) {
1588 if (calo_entrance == trk_srf || calo_entrance == trk_srf) {
1589 if (!trk_srf->materialEffectsOnTrack()) {
1590 ATH_MSG_DEBUG("No material effect on track");
1591 continue;
1592 }
1593 const Trk::MaterialEffectsOnTrack* meot =
1594 dynamic_cast<const Trk::MaterialEffectsOnTrack*>(trk_srf->materialEffectsOnTrack());
1595 if (!meot) {
1596 ATH_MSG_WARNING(" This should not happen: no MaterialEffectsOnTrack for scatterer ");
1597 continue;
1598 }
1599 const Trk::ScatteringAngles* scat = meot->scatteringAngles();
1600 if (!scat) {
1601 ATH_MSG_WARNING(" This should not happen: no Scattering Angles for scatterer ");
1602 continue;
1603 }
1604
1605 float sigmaDeltaPhi = std::hypot(scat->sigmaDeltaPhi(), m_alignUncertTool_phi->get_uncertainty(track));
1606 float sigmaDeltaTheta = std::hypot(scat->sigmaDeltaTheta(), m_alignUncertTool_theta->get_uncertainty(track));
1607 float X0 = trk_srf->materialEffectsOnTrack()->thicknessInX0();
1608 //
1609 auto energyLossNew = std::make_unique<Trk::EnergyLoss>(0., 0., 0., 0.);
1610 auto scatNew = Trk::ScatteringAngles(0., 0., sigmaDeltaPhi, sigmaDeltaTheta);
1611
1612 const Trk::Surface& surfNew = trk_srf->trackParameters()->associatedSurface();
1613
1614 std::bitset<Trk::MaterialEffectsBase::NumberOfMaterialEffectsTypes> meotPattern(0);
1617
1618 auto meotNew = std::make_unique<Trk::MaterialEffectsOnTrack>(
1619 X0,
1620 scatNew,
1621 std::move(energyLossNew),
1622 surfNew,
1623 meotPattern);
1624 auto parsNew = trk_srf->trackParameters()->uniqueClone();
1625
1626 std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes> typePatternScat(0);
1627 typePatternScat.set(Trk::TrackStateOnSurface::Scatterer);
1628
1629 const Trk::TrackStateOnSurface* newTSOS =
1630 new Trk::TrackStateOnSurface(nullptr, std::move(parsNew), std::move(meotNew), typePatternScat);
1631 trackStateOnSurfaces->push_back(newTSOS);
1632
1633 ATH_MSG_DEBUG(" old Calo scatterer had sigmaDeltaPhi mrad " << scat->sigmaDeltaPhi() * 1000 << " sigmaDeltaTheta mrad "
1634 << scat->sigmaDeltaTheta() * 1000 << " X0 " << X0);
1635
1636 ATH_MSG_DEBUG(" new Calo scatterer made with sigmaDeltaPhi mrad " << sigmaDeltaPhi * 1000 << " sigmaDeltaTheta mrad "
1637 << sigmaDeltaTheta * 1000);
1638
1639 } else {
1640 // skip AEOTs
1641 if (trk_srf->alignmentEffectsOnTrack()) {
1642 ATH_MSG_DEBUG(" addIDMSerrors alignmentEffectsOnTrack() found on track ");
1643 continue;
1644 }
1645 trackStateOnSurfaces->push_back(trk_srf->clone());
1646 }
1647 }
1648 ATH_MSG_DEBUG(" trackStateOnSurfaces on input track " << track->trackStateOnSurfaces()->size() << " trackStateOnSurfaces found "
1649 << trackStateOnSurfaces->size());
1650
1651 std::unique_ptr<Trk::Track> newTrack = std::make_unique<Trk::Track>(track->info(), std::move(trackStateOnSurfaces), nullptr);
1652 return newTrack;
1653 }
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
PublicToolHandle< Muon::IMuonAlignmentUncertTool > m_alignUncertTool_theta
ToolHandles to retrieve the uncertainties for theta and phi for the scattering uncertainties.
PublicToolHandle< Muon::IMuonAlignmentUncertTool > m_alignUncertTool_phi
@ ScatteringEffects
contains material effects due to multiple scattering
@ EnergyLossEffects
contains energy loss corrections
const ScatteringAngles * scatteringAngles() const
returns the MCS-angles object.
double sigmaDeltaPhi() const
returns the
double sigmaDeltaTheta() const
returns the
@ Scatterer
This represents a scattering point on the track, and so will contain TrackParameters and MaterialEffe...

◆ appendSelectedTSOS()

void Rec::CombinedMuonTrackBuilder::appendSelectedTSOS ( Trk::TrackStates & trackStateOnSurfaces,
Trk::TrackStates::const_iterator begin,
Trk::TrackStates::const_iterator end ) const
private

Definition at line 1655 of file CombinedMuonTrackBuilder.cxx.

1656 {
1657 // spectrometer measurement selection
1658 std::vector<const Trk::Surface*> measurementSurfaces;
1659 measurementSurfaces.reserve(trackStateOnSurfaces.size());
1660 const Trk::Surface* previousSurface = nullptr;
1661
1663 for (; s != end; ++s) {
1664 const Trk::TrackStateOnSurface& tsos = **s;
1665 if (tsos.alignmentEffectsOnTrack()) {
1666 ATH_MSG_VERBOSE("appendSelectedTSOS:: alignmentEffectsOnTrack ");
1667 }
1668 // skip non-understood features in iPatFitter
1669 if (!tsos.measurementOnTrack() && !tsos.materialEffectsOnTrack()) {
1671 ATH_MSG_VERBOSE("appendSelectedTSOS:: skip a perigee without material and measuremet "<<tsos);
1672 continue;
1673 } else if (!tsos.type(Trk::TrackStateOnSurface::Hole) || !tsos.trackParameters()) {
1674 ATH_MSG_VERBOSE("appendSelectedTSOS:: skip unrecognized TSOS " << tsos.dumpType());
1675 continue;
1676 }
1677 }
1678
1679 if (tsos.measurementOnTrack()) {
1680 // skip any pseudo measurements
1681 if (dynamic_cast<const Trk::PseudoMeasurementOnTrack*>(tsos.measurementOnTrack())) { continue; }
1682
1683 // skip duplicate measurements on same surface
1684 const Trk::Surface* surface = &tsos.measurementOnTrack()->associatedSurface();
1685 if (previousSurface &&
1686 std::find(measurementSurfaces.begin(), measurementSurfaces.end(), surface) != measurementSurfaces.end()) {
1687 // skip duplicate measurement
1688 m_messageHelper->printWarning(34, m_idHelperSvc->toString(m_edmHelperSvc->getIdentifier(*(tsos.measurementOnTrack()))));
1689 continue;
1690 }
1691
1692 measurementSurfaces.push_back(surface);
1693 previousSurface = surface;
1694 }
1695 trackStateOnSurfaces.push_back(tsos.clone());
1696 }
1697 }
#define ATH_MSG_VERBOSE(x)
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:838
value_type push_back(value_type pElem)
Add an element to the end of the collection.
size_type size() const noexcept
Returns the number of elements in the collection.
ServiceHandle< Muon::IMuonEDMHelperSvc > m_edmHelperSvc
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
std::unique_ptr< MessageHelper > m_messageHelper
virtual const Surface & associatedSurface() const =0
Interface method to get the associated Surface.
virtual TrackStateOnSurface * clone() const
Pseudo-constructor: needed to avoid excessive RTTI.
const MeasurementBase * measurementOnTrack() const
returns MeasurementBase const overload
const TrackParameters * trackParameters() const
return ptr to trackparameters const overload
std::string dumpType() const
returns a string with the expanded type of the object (i.e.
bool type(const TrackStateOnSurfaceType type) const
Use this method to find out if the TSoS is of a certain type: i.e.
@ Perigee
This represents a perigee, and so will contain a Perigee object only.
@ Hole
A hole on the track - this is defined in the following way.
const MaterialEffectsBase * materialEffectsOnTrack() const
return material effects const overload
const AlignmentEffectsOnTrack * alignmentEffectsOnTrack() const
return the the alignment effects const overload

◆ caloEnergyParameters()

const CaloEnergy * Rec::CombinedMuonTrackBuilder::caloEnergyParameters ( const Trk::Track * combinedTrack,
const Trk::Track * muonTrack,
const Trk::TrackParameters *& combinedEnergyParameters,
const Trk::TrackParameters *& muonEnergyParameters ) const
private

Definition at line 1699 of file CombinedMuonTrackBuilder.cxx.

1701 {
1702 // will also set the caloEnergyParameters (from both combinedTrack and muonTrack)
1703 combinedEnergyParameters = nullptr;
1704 muonEnergyParameters = nullptr;
1705
1706 // quit if missing track
1707 if (!combinedTrack || !muonTrack) return nullptr;
1708
1709 // muonTrack: get parameters at CaloDeposit
1711
1712 while (!(**s).type(Trk::TrackStateOnSurface::CaloDeposit)) {
1713 if (++s == muonTrack->trackStateOnSurfaces()->end()) {
1714 // muonTrack without caloEnergy association
1715 m_messageHelper->printWarning(35);
1716 return nullptr;
1717 }
1718 }
1719 muonEnergyParameters = (**s).trackParameters();
1720
1721 // find corresponding parameters from combinedTrack
1722 s = combinedTrack->trackStateOnSurfaces()->begin();
1723 while (!(**s).type(Trk::TrackStateOnSurface::CaloDeposit)) {
1724 if (++s == combinedTrack->trackStateOnSurfaces()->end()) {
1725 // combinedTrack without caloEnergy association
1726 m_messageHelper->printWarning(36);
1727 return nullptr;
1728 }
1729 }
1730
1731 combinedEnergyParameters = (**s).trackParameters();
1732 if (muonEnergyParameters && combinedEnergyParameters) {
1733 ATH_MSG_DEBUG("muon and combined EnergyParameters: " << muonEnergyParameters->momentum().mag() << " "
1734 << combinedEnergyParameters->momentum().mag());
1735 }
1736 // success!
1737 return m_trackQuery->caloEnergy(*combinedTrack);
1738 }
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
ToolHandle< Rec::IMuonTrackQuery > m_trackQuery
const Amg::Vector3D & momentum() const
Access method for the momentum.
@ CaloDeposit
This TSOS contains a CaloEnergy object.
const Trk::TrackStates * trackStateOnSurfaces() const
return a pointer to a const DataVector of const TrackStateOnSurfaces.
void combinedTrack(long int ICH, double *pv0, double *covi, double BMAG, double *par, double *covo)
Definition XYZtrp.cxx:113

◆ checkTrack()

bool Rec::CombinedMuonTrackFitter::checkTrack ( std::string_view txt,
const Trk::Track * newTrack ) const
protectedinherited

Check that the combined track contains enough MS measurements

Definition at line 588 of file CombinedMuonTrackFitter.cxx.

588 {
589 if (!newTrack) return false;
590
591 const DataVector<const Trk::TrackParameters>* pars = newTrack->trackParameters();
592 if (!pars || pars->empty() || !newTrack->fitQuality()) { return false; }
594
595 if ((*it)->position().dot((*it)->momentum()) < 0) {
596 return false;
597 ATH_MSG_DEBUG(txt <<" "<< __FILE__<<":"<<__LINE__<< " ALARM position " << (*it)->position() << " direction " << (*it)->momentum().unit());
598 } else {
599 ATH_MSG_DEBUG(txt <<" "<< __FILE__<<":"<<__LINE__<< " OK position " << (*it)->position() << " direction " << (*it)->momentum().unit());
600 }
601
602 for (const Trk::TrackParameters* par : *pars) {
603 if (!par->covariance()) { continue; }
604 if (!Amg::hasPositiveDiagElems(*par->covariance())) {
605 ATH_MSG_DEBUG(txt<<" "<<__FILE__<<":"<<__LINE__<< "covariance matrix has negative diagonal element, killing track "
606 <<std::endl<<Amg::toString(*par->covariance()));
607 return false;
608 }
609 }
610 unsigned int numberMS{0}, numberMSPrec{0};
614 for (; r != rEnd; ++r) {
615 const Trk::TrackStateOnSurface* tsos{*r};
616 if (tsos->trackParameters() && m_calorimeterVolume->inside(tsos->trackParameters()->position())) break;
617
618 if (tsos->measurementOnTrack()) {
619 ++numberMS;
620 const Trk::RIO_OnTrack* rot = dynamic_cast<const Trk::RIO_OnTrack*>(tsos->measurementOnTrack());
621 numberMSPrec+= rot && !m_idHelperSvc->measuresPhi(rot->identify());
622 }
623 }
624
625 ATH_MSG_VERBOSE( txt<< " "<<__FILE__<<":"<<__LINE__<<" "<< numberMS << "/"<< numberMSPrec<< " fitted MS measurements ");
626 // reject with insufficient MS measurements
627 if (numberMS < 5 || numberMSPrec < 3) {
628 return false;
629 }
630
631 return true;
632 }
const_reverse_iterator rend() const noexcept
Return a const_reverse_iterator pointing at the beginning of the collection.
const_reverse_iterator rbegin() const noexcept
Return a const_reverse_iterator pointing past the end of the collection.
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition DataVector.h:847
std::unique_ptr< const Trk::Volume > m_calorimeterVolume
const Amg::Vector3D & position() const
Access method for the position.
Identifier identify() const
return the identifier -extends MeasurementBase
const DataVector< const TrackParameters > * trackParameters() const
Return a pointer to a vector of TrackParameters.
const FitQuality * fitQuality() const
return a pointer to the fit quality const-overload
int r
Definition globals.cxx:22
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
bool hasPositiveDiagElems(const AmgSymMatrix(N) &mat)
Returns true if all diagonal elements of the covariance matrix are finite aka sane in the above defin...
ParametersBase< TrackParametersDim, Charged > TrackParameters

◆ combinedFit()

std::unique_ptr< Trk::Track > Rec::CombinedMuonTrackBuilder::combinedFit ( const EventContext & ctx,
const Trk::Track & indetTrack,
const Trk::Track & extrapolatedTrack,
const Trk::Track & spectrometerTrack ) const
overridevirtual

ICombinedMuonTrackBuilder interface: build and fit combined ID/Calo/MS track.

This should only happen if adding the ID/MS errors fails or the property is disabled

Final check to avoid FPEs later on

Implements Rec::ICombinedMuonTrackBuilder.

Definition at line 128 of file CombinedMuonTrackBuilder.cxx.

129 {
130 ATH_MSG_VERBOSE("===== Start of combinedFit:: ");
131
132 if (msgLevel(MSG::DEBUG)) countAEOTs(extrapolatedTrack, " extrapolatedTrack start combinedFit ");
133
134 // require MeasuredPerigee for indetTrack
135 const Trk::Perigee* indetPerigee = indetTrack.perigeeParameters();
136 if (!indetPerigee) {
137 // missing MeasuredPerigee for indet track
138 m_messageHelper->printWarning(0);
139 return nullptr;
140 }
141
142 // take inner calorimeter scattering surface from extrapolated track
143 const Trk::Surface* surface = nullptr;
144 if (m_trackQuery->isCaloAssociated(extrapolatedTrack, ctx)) {
145 for (const Trk::TrackStateOnSurface* it : *extrapolatedTrack.trackStateOnSurfaces()) {
146 if (!it->materialEffectsOnTrack()) continue;
147
148 const Amg::Vector3D& position = it->materialEffectsOnTrack()->associatedSurface().globalReferencePoint();
149
150 if (m_indetVolume->inside(position)) continue;
151 if (!m_calorimeterVolume->inside(position)) break;
152
153 surface = &it->materialEffectsOnTrack()->associatedSurface();
154 break;
155 }
156 }
157
158 // match extrapolated indet track to inner calorimeter scattering surface
159 // provided momentum defined (solenoid on)
160 MagField::AtlasFieldCache fieldCache;
161 // Get field cache object
162 if (!loadMagneticField(ctx, fieldCache)) return nullptr;
163
164 if (surface && fieldCache.solenoidOn() && !m_updateWithCaloTG) {
165 std::unique_ptr<const Trk::TrackStateOnSurface> innerTSOS;
166 if (m_useCaloTG) {
167 ATH_MSG_VERBOSE(" Retrieving Calorimeter TSOS from " << __func__ << " at line " << __LINE__);
168 std::vector<std::unique_ptr<const Trk::TrackStateOnSurface>> caloTSOS =
169 getCaloTSOSfromMatProvider(*indetTrack.perigeeParameters(), extrapolatedTrack);
170 if (!caloTSOS.empty()) { innerTSOS.swap(caloTSOS.front()); }
171 } else {
172 innerTSOS = m_caloTSOS->innerTSOS(ctx, *indetTrack.perigeeParameters());
173 }
174
175 if (!innerTSOS) {
176 ATH_MSG_DEBUG(" indet track fails to intersect the calorimeter ");
177 return nullptr;
178 }
179
180 // will re-associate the calorimeter if they are not the same surface
181 double surfaceOffset =
182 (surface->globalReferencePoint() - innerTSOS->materialEffectsOnTrack()->associatedSurface().globalReferencePoint()).mag();
183
184 if (surfaceOffset > 1. * Gaudi::Units::mm) {
185 ATH_MSG_DEBUG(" different inner-calo-surface obtained from indet extrapolation, "
186 << "surface reference " << surface->globalReferencePoint() << " with offset " << surfaceOffset
187 << "mm. Re-evaluate the caloTSOS ");
188
189 surface = nullptr;
190 }
191 }
192
193 std::unique_ptr<Trk::Track> muonTrack;
194 if (!fieldCache.toroidOn()) {
195 ATH_MSG_VERBOSE(" SL MS track: Calling createMuonTrack from " << __func__ << " at line " << __LINE__);
196 muonTrack =
197 createMuonTrack(ctx, indetTrack, indetTrack.perigeeParameters(), nullptr, extrapolatedTrack.trackStateOnSurfaces());
198 } else {
199 // create a muon track without perigee in case of non-optimal precision -
200 // such as need to replace calorimeter material or presence of pseudomeasurements
201 if (!surface) { // extrapolate outwards to associate calorimeter material effects
202 ATH_MSG_VERBOSE("Calling createMuonTrack from " << __func__ << " at line " << __LINE__);
203 muonTrack = createMuonTrack(
204 ctx, extrapolatedTrack, indetTrack.perigeeParameters(), nullptr, extrapolatedTrack.trackStateOnSurfaces());
205 } else if (m_trackQuery->numberPseudoMeasurements(extrapolatedTrack) > 1) { // remove pseudo meas
206 ATH_MSG_VERBOSE("Calling createMuonTrack from " << __func__ << " at line " << __LINE__);
207 muonTrack = createMuonTrack(ctx, extrapolatedTrack,
208 nullptr, nullptr, extrapolatedTrack.trackStateOnSurfaces());
209 } else { // otherwise can just copy the extrapolated track
210 ATH_MSG_VERBOSE("Calling createMuonTrack from " << __func__ << " at line " << __LINE__);
211 muonTrack =
212 createMuonTrack(ctx, extrapolatedTrack, extrapolatedTrack.perigeeParameters(), nullptr,
213 extrapolatedTrack.trackStateOnSurfaces());
214 }
215 }
216
217 // no combined muon when failure to intersect calo
218 if (!muonTrack) return nullptr;
219
220 if (msgLevel(MSG::DEBUG)) countAEOTs(*muonTrack, " muonTrack track before fit ");
221
222 // combined track fit
223 std::unique_ptr<Trk::Track> combinedTrack{fit(ctx, indetTrack, *muonTrack, m_cleanCombined, Trk::muon)};
224
225 // quit if fit failure or all MS measurements removed by fit or perigee outside indet
226 bool haveMS {false}, perigeeOutside{false};
227
228 if (combinedTrack) {
229 if (msgLevel(MSG::DEBUG)) countAEOTs(*combinedTrack, " combinedTrack track after fit ");
230 ATH_MSG_VERBOSE(" combined track " << m_printer->print(*combinedTrack) << std::endl
231 << m_printer->printStations(*combinedTrack));
232
233 auto rit = combinedTrack->trackStateOnSurfaces()->rbegin();
234 auto ritEnd = combinedTrack->trackStateOnSurfaces()->rend();
235 for (; rit != ritEnd; ++rit) {
236 if (!(**rit).measurementOnTrack() || !(**rit).trackParameters()) continue;
237 if (m_calorimeterVolume->inside((**rit).trackParameters()->position())) break;
238 if (!(**rit).type(Trk::TrackStateOnSurface::Outlier)) haveMS = true;
239 }
240
241 if (!haveMS) {
242 // combinedTrack fails: MS removed by cleaner
243 ATH_MSG_DEBUG("combinedFit:: fail with MS removed by cleaner"); //Used to be: m_messageHelper->printWarning(1);
244 }
245
246 if (!combinedTrack->perigeeParameters() || !m_indetVolume->inside(combinedTrack->perigeeParameters()->position())) {
247 if (!combinedTrack->perigeeParameters()) {
248 ATH_MSG_DEBUG(" no perigee");
249 } else {
250 ATH_MSG_DEBUG(" position: r " << combinedTrack->perigeeParameters()->position().perp() << " z "
251 << combinedTrack->perigeeParameters()->position().z());
252 }
253 // combinedTrack fails as perigee outside indet
254 m_messageHelper->printWarning(2);
255 perigeeOutside = true;
256 }
257 }
258
259 if (!combinedTrack || !combinedTrack->fitQuality() || !haveMS || perigeeOutside) {
260 bool hasFitQ = combinedTrack ? (combinedTrack->fitQuality() != nullptr) : false;
261 ATH_MSG_DEBUG("combinedTrack fails with bad fit" << combinedTrack.get() << " " << hasFitQ << " " << haveMS << " "
262 << perigeeOutside);
263
264 return nullptr;
265 }
266
267 // Get parameters at calo position
268 const Trk::TrackParameters* combinedEnergyParameters{nullptr}, *muonEnergyParameters{nullptr};
269 const CaloEnergy* caloEnergy {caloEnergyParameters(combinedTrack.get(), muonTrack.get(), combinedEnergyParameters, muonEnergyParameters)};
270
271 if (!caloEnergy) {
272 // combinedTrack fails with missing caloEnergy
273 m_messageHelper->printWarning(3);
274 return nullptr;
275 }
276
277 // if significant momentum change: re-evaluate calo energy and refit
278 double pRatio = muonEnergyParameters->momentum().mag() / combinedEnergyParameters->momentum().mag();
279 if (std::abs(pRatio - 1.) > m_largeMomentumChange || m_iterateCombinedTrackFit) {
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 "
283 << combinedEnergyParameters->momentum().perp() / Gaudi::Units::GeV << " GeV");
284 } else {
285 ATH_MSG_DEBUG(" iterate combined fit to recollect calorimeter material");
286 }
287
288 const Trk::TrackStates* combinedTSOS = combinedTrack->trackStateOnSurfaces();
289
290 std::unique_ptr<Trk::Track> indetNewTrack{createIndetTrack(indetTrack.info(), combinedTSOS)};
291
292 std::unique_ptr<Trk::Track> oldTrack(std::move(muonTrack));
293
294 ATH_MSG_VERBOSE("Calling createMuonTrack from " << __func__ << " at line " << __LINE__);
295 muonTrack = createMuonTrack(ctx, extrapolatedTrack, combinedEnergyParameters, nullptr, combinedTSOS);
296
297 if (indetNewTrack && muonTrack) {
298 std::unique_ptr<Trk::Track> refittedTrack{fit(ctx, *indetNewTrack, *muonTrack, m_cleanCombined, Trk::muon)};
299 caloEnergy = caloEnergyParameters(refittedTrack.get(), muonTrack.get(), combinedEnergyParameters, muonEnergyParameters);
300
301 if (caloEnergy) {
302 combinedTrack.swap(refittedTrack);
303 } else {
304 // why does the refit fail? This shouldn't really be necessary
305 muonTrack.swap(oldTrack);
306 caloEnergy = caloEnergyParameters(combinedTrack.get(), muonTrack.get(), combinedEnergyParameters, muonEnergyParameters);
307 }
308 }
309 }
310
311 // tracks with caloEnergy type 'tail' can arise from an incorrect categorization as isolated
312 // in case of significant energy gain, switch to parametrization and reclassify as NotIsolated
313 if (muonTrack && caloEnergy->energyLossType() == CaloEnergy::Tail && (!m_updateWithCaloTG || m_useCaloTG)) {
314 double tolerance = 0;
315
316 if (!indetPerigee->covariance()) {
317 ATH_MSG_WARNING(" indetPerigee has no covariance tolerance left as zero. ");
318 } else {
319 tolerance = m_numberSigmaFSR * Amg::error((*indetPerigee->covariance()), Trk::qOverP);
320 }
321
322 double indetMaxE = 1. / (std::abs(indetPerigee->parameters()[Trk::qOverP]) - tolerance);
323 double energyBalance = combinedEnergyParameters->momentum().mag() + caloEnergy->deltaE() - indetMaxE;
324
325 // get parametrised eloss if large energy imbalance and refit track
326 std::unique_ptr<CaloEnergy> paramEnergy;
327 if (indetMaxE > 0. && energyBalance > m_numberSigmaFSR * caloEnergy->sigmaMinusDeltaE()) {
328 // parametrized energy deposition
329 // run-2 schema, update default eloss with parametrised value
330 if (m_useCaloTG) {
331 paramEnergy.reset(m_materialUpdator->getParamCaloELoss(muonTrack.get()));
332 } else {
333 // run-1 schema, recalculate parametrised eloss
334 paramEnergy = m_caloEnergyParam->energyLoss(ctx, combinedEnergyParameters->momentum().mag(),
335 combinedEnergyParameters->position().eta(),
336 combinedEnergyParameters->position().phi());
337 }
338 paramEnergy->set_energyLossType(CaloEnergy::NotIsolated);
339 }
340
341 // FIXME: add criterion on energy-balance significance param vs tail ?
342 if (paramEnergy) {
343 ATH_MSG_DEBUG(" FSR check: energyBalance "
344 << energyBalance / Gaudi::Units::GeV << " signif " << energyBalance / caloEnergy->sigmaMinusDeltaE()
345 << " indet max E " << indetMaxE / Gaudi::Units::GeV << std::endl
346 << " param CaloEnergy: " << paramEnergy->deltaE() / Gaudi::Units::GeV << " + "
347 << paramEnergy->sigmaPlusDeltaE() / Gaudi::Units::GeV << " for P "
348 << combinedEnergyParameters->momentum().mag() / Gaudi::Units::GeV << " eta "
349 << combinedEnergyParameters->position().eta() << " phi " << combinedEnergyParameters->position().phi()
350 << endmsg << " tail-param energy diff "
351 << (caloEnergy->deltaE() - paramEnergy->deltaE()) / Gaudi::Units::GeV);
352
353 ATH_MSG_VERBOSE("Calling createMuonTrack from " << __func__ << " at line " << __LINE__);
354 muonTrack =
355 createMuonTrack(ctx, extrapolatedTrack, nullptr, std::move(paramEnergy), muonTrack->trackStateOnSurfaces());
356
357 if (muonTrack) {
358 std::unique_ptr<Trk::Track> refittedTrack{fit(ctx, indetTrack, *muonTrack, m_cleanCombined, Trk::muon)};
359 if (refittedTrack) { combinedTrack.swap(refittedTrack); }
360 }
361 }
362 }
363
364 // in case of the unexpected ...
365 if (!combinedTrack) {
366 // final combined track lost, this should not happen
367 m_messageHelper->printWarning(4);
368 return nullptr;
369 }
370
372 ATH_MSG_VERBOSE("Refining Calorimeter TSOS in Muon Combined Fit ...");
373 m_materialUpdator->updateCaloTSOS(*combinedTrack);
374 }
375
376 // adds uncertainties and removes AEOTs
377 // We will either have nullptr or a new Track.
378 // What we pass stays untouched.
379 std::unique_ptr<Trk::Track> newTrack = addIDMSerrors(combinedTrack.get());
380 // recollect eloss for combined track and refit
381 // newTrack will not be used after this block, either
382 // we updated the combined or kept the combined as it was
383 if (newTrack) {
384 if (msgLevel(MSG::DEBUG)) countAEOTs(*newTrack, " combinedTrack after addIDMSerrors ");
385 // Don't run the outliers anymore at this stage
386 dumpCaloEloss(newTrack.get(), "CB input TSOS after refine IDMS ");
387 std::unique_ptr<Trk::Track> refittedTrack{fit(ctx, *newTrack, false, Trk::muon)};
388 if (refittedTrack){
389 if (msgLevel(MSG::DEBUG)) countAEOTs(*refittedTrack, " CB fit after refit ");
390 dumpCaloEloss(refittedTrack.get(), "CB refit after refine IDMS ");
392 if (checkTrack("combinedFit", refittedTrack.get())) {
393 // Make the combined point to the refitted
394 combinedTrack.swap(refittedTrack);
395 }
396 }
397 }
398
400 if (!checkTrack("addIDMS failed", combinedTrack.get())) {
401 ATH_MSG_DEBUG("addIDMS errors failed and original track does not pass checkTrack");
402 return nullptr;
403 }
404 // hole recovery, error optimization, attach TrackSummary
405 finalTrackBuild(ctx, combinedTrack);
406
407 return combinedTrack;
408 }
#define endmsg
CaloEnergy::EnergyLossType energyLossType(void) const
Accessor methods.
Definition CaloEnergy.h:162
bool solenoidOn() const
status of the magnets
std::unique_ptr< Trk::Track > createMuonTrack(const EventContext &ctx, const Trk::Track &muonTrack, const Trk::TrackParameters *parameters, std::unique_ptr< CaloEnergy > caloEnergy, const Trk::TrackStates *tsos) const
Summarizes the available information about the ID track, the deposited calorimeter energies and the t...
ToolHandle< Rec::IMuidCaloEnergy > m_caloEnergyParam
std::unique_ptr< Trk::Track > createIndetTrack(const Trk::TrackInfo &info, const Trk::TrackStates *tsos) const
void dumpCaloEloss(const Trk::Track *track, const std::string &txt) const
Gaudi::Property< bool > m_refineELossCombinedTrackFit
Gaudi::Property< bool > m_iterateCombinedTrackFit
const CaloEnergy * caloEnergyParameters(const Trk::Track *combinedTrack, const Trk::Track *muonTrack, const Trk::TrackParameters *&combinedEnergyParameters, const Trk::TrackParameters *&muonEnergyParameters) const
std::unique_ptr< Trk::Track > addIDMSerrors(const Trk::Track *track) const
std::vector< std::unique_ptr< const Trk::TrackStateOnSurface > > getCaloTSOSfromMatProvider(const Trk::TrackParameters &track_params, const Trk::Track &me_track) const
Helper method to retrieve the CaloTSO from the Material provider in a memory safe way.
Gaudi::Property< double > m_largeMomentumChange
void finalTrackBuild(const EventContext &ctx, std::unique_ptr< Trk::Track > &track) const
Gaudi::Property< double > m_numberSigmaFSR
ToolHandle< Trk::ITrkMaterialProviderTool > m_materialUpdator
ToolHandle< Rec::IMuidCaloTrackStateOnSurface > m_caloTSOS
virtual std::unique_ptr< Trk::Track > fit(const EventContext &ctx, const Trk::Track &track, const Trk::RunOutlierRemoval runOutlier, const Trk::ParticleHypothesis particleHypothesis) const override
unsigned int countAEOTs(const Trk::Track &track, const std::string &txt) const
bool checkTrack(std::string_view txt, const Trk::Track *newTrack) const
bool loadMagneticField(const EventContext &ctx, MagField::AtlasFieldCache &field_cache) const
PublicToolHandle< Muon::MuonEDMPrinterTool > m_printer
Gaudi::Property< bool > m_updateWithCaloTG
std::unique_ptr< const Trk::Volume > m_indetVolume
double sigmaMinusDeltaE() const
returns the negative side
double deltaE() const
returns the
virtual const Amg::Vector3D & globalReferencePoint() const
Returns a global reference point on the surface, for PlaneSurface, StraightLineSurface,...
@ Outlier
This TSoS contains an outlier, that is, it contains a MeasurementBase/RIO_OnTrack which was not used ...
const TrackInfo & info() const
Returns a const ref to info of a const tracks.
const Perigee * perigeeParameters() const
return Perigee.
double error(const Amg::MatrixX &mat, int index)
return diagonal error of the matrix caller should ensure the matrix is symmetric and the index is in ...
Eigen::Matrix< double, 3, 1 > Vector3D
DataVector< const Trk::TrackStateOnSurface > TrackStates
ParametersT< TrackParametersDim, Charged, PerigeeSurface > Perigee
@ qOverP
perigee
Definition ParamDefs.h:67
constexpr double tolerance

◆ countAEOTs()

unsigned int Rec::CombinedMuonTrackFitter::countAEOTs ( const Trk::Track & track,
const std::string & txt ) const
protectedinherited

Definition at line 634 of file CombinedMuonTrackFitter.cxx.

634 {
635 const Trk::TrackStates* trackTSOS = track.trackStateOnSurfaces();
636 unsigned int naeots = 0;
637
638 if (!trackTSOS){
639 ATH_MSG_ERROR("No trackStateOnSurfaces");
640 return naeots;
641 }
642
643 for (const auto* m : *trackTSOS) {
644 if (m && m->alignmentEffectsOnTrack()) naeots++;
645 }
646
647 ATH_MSG_DEBUG(" count AEOTs " << txt << " " << naeots);
648
649 // add VEBOSE for checking TSOS order
650
651
652 int tsos{0}, nperigee{0};
653 for ( const Trk::TrackStateOnSurface* it : *trackTSOS) {
654 tsos++;
655
657 ATH_MSG_DEBUG("perigee");
658 nperigee++;
659 }
660
661 if (it->trackParameters()) {
662 ATH_MSG_VERBOSE(" check tsos " << tsos << " TSOS tp "
663 << " r " << it->trackParameters()->position().perp() << " z "
664 << it->trackParameters()->position().z() << " momentum "
665 << it->trackParameters()->momentum().mag());
666 } else if (it->measurementOnTrack()) {
667 ATH_MSG_VERBOSE(" check tsos " << tsos << " TSOS mst "
668 << " r " << it->measurementOnTrack()->associatedSurface().center().perp() << " z "
669 << it->measurementOnTrack()->associatedSurface().center().z());
670 } else if (it->materialEffectsOnTrack()) {
671 ATH_MSG_VERBOSE(" check tsos " << tsos << " TSOS mat "
672 << " r "
673 << it->materialEffectsOnTrack()->associatedSurface().globalReferencePoint().perp()
674 << " z " << it->materialEffectsOnTrack()->associatedSurface().globalReferencePoint().z());
675 } else {
676 ATH_MSG_VERBOSE(" check tsos other than above " << tsos);
677 }
678 }
679
680 ATH_MSG_VERBOSE(" track with number of TSOS perigees " << nperigee);
681
682 return naeots;
683 }
#define ATH_MSG_ERROR(x)

◆ createExtrapolatedTrack()

std::unique_ptr< Trk::Track > Rec::CombinedMuonTrackBuilder::createExtrapolatedTrack ( const EventContext & ctx,
const Trk::Track & spectrometerTrack,
const Trk::TrackParameters & parameters,
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
private

Actually I am not certain whether the paramters need a clone or we can move them

Definition at line 1740 of file CombinedMuonTrackBuilder.cxx.

1744 {
1745 ATH_MSG_DEBUG(" createExtrapolatedTrack() - " << __LINE__ << ": pt " << parameters.momentum().perp() << " r "
1746 << parameters.position().perp() << " z " << parameters.position().z() << " cov "
1747 << parameters.covariance() << " muonfit " << (particleHypothesis == Trk::muon));
1748
1749 std::vector<std::unique_ptr<const Trk::TrackStateOnSurface>> caloTSOS, leadingTSOS;
1750
1751 std::unique_ptr<const Trk::TrackParameters> track_param_owner;
1752 const Trk::TrackParameters* trackParameters{nullptr};
1753 const Trk::Perigee* perigee{nullptr};
1754
1755 if (vertex && m_indetVolume->inside(parameters.position())) { perigee = dynamic_cast<const Trk::Perigee*>(&parameters); }
1756 if (perigee) {
1757 ATH_MSG_DEBUG("createExtrapolatedTrack(): Got a perigee ");
1758 trackParameters = perigee;
1759 } else {
1760 ATH_MSG_DEBUG("createExtrapolatedTrack(): no perigee");
1761 // extrapolate backwards to associate leading material in spectrometer
1762 // (provided material has already been allocated between measurements)
1763 const Trk::TrackParameters* leadingParameters = &parameters;
1764 if (particleHypothesis == Trk::muon) {
1765 bool haveMaterial{false}, haveLeadingMaterial{false}, firstMSHit{false};
1766
1767 for (const std::unique_ptr<const Trk::TrackStateOnSurface>& s : spectrometerTSOS) {
1768 if (s->materialEffectsOnTrack()) {
1769 haveMaterial = true;
1770 if (!firstMSHit) haveLeadingMaterial = true;
1771 }
1772
1773 if (s->measurementOnTrack() && !firstMSHit) { firstMSHit = true; }
1774
1775 if (haveMaterial && firstMSHit) { break; }
1776 }
1777
1778 // only add leading material if there is no material in fron of first muon measurement
1779
1780 if (!m_materialAllocator.empty() && haveMaterial && !haveLeadingMaterial) {
1781 // protect the momentum to avoid excessive Eloss
1782 Amg::VectorX parameterVector = parameters.parameters();
1783
1784 constexpr double Emax = 50000.;
1785
1786 if (parameterVector[Trk::qOverP] == 0.) {
1787 parameterVector[Trk::qOverP] = 1. / Emax;
1788 } else {
1789 if (std::abs(parameterVector[Trk::qOverP]) * Emax < 1) {
1790 parameterVector[Trk::qOverP] = parameters.charge() / Emax;
1791 }
1792 }
1793 std::unique_ptr<Trk::TrackParameters> correctedParameters{parameters.associatedSurface().createUniqueTrackParameters(
1794 parameterVector[Trk::loc1], parameterVector[Trk::loc2], parameterVector[Trk::phi], parameterVector[Trk::theta],
1795 parameterVector[Trk::qOverP], std::nullopt)};
1796
1798 std::unique_ptr<std::vector<const Trk::TrackStateOnSurface*>> lead_tsos_from_alloc{
1799 m_materialAllocator->leadingSpectrometerTSOS(*correctedParameters, garbage)};
1800 if (lead_tsos_from_alloc) {
1801 for (const Trk::TrackStateOnSurface* l_tsos : *lead_tsos_from_alloc) leadingTSOS.emplace_back(l_tsos);
1802 }
1803 if (!leadingTSOS.empty() && leadingTSOS.front()->trackParameters()) {
1804 leadingParameters = leadingTSOS.front()->trackParameters();
1805 }
1806 }
1807 }
1808
1809 // extrapolate backwards to associate calorimeter material effects
1810 bool caloAssociated = false;
1811
1812 if (particleHypothesis == Trk::muon) {
1813 ATH_MSG_VERBOSE(" Retrieving Calorimeter TSOS from " << __func__ << " at line " << __LINE__);
1814 if (m_useCaloTG) {
1815 caloTSOS = getCaloTSOSfromMatProvider(*leadingParameters, spectrometerTrack);
1816 // Dump CaloTSOS
1817 //
1818 if (msgLevel(MSG::DEBUG)) {
1819 for (std::unique_ptr<const Trk::TrackStateOnSurface>& m : caloTSOS) {
1820 if (!m->materialEffectsOnTrack()) continue;
1821 const Trk::MaterialEffectsOnTrack* meot =
1822 dynamic_cast<const Trk::MaterialEffectsOnTrack*>(m->materialEffectsOnTrack());
1823 double pcalo{0.}, deltaP{0.};
1824 if (!meot) continue;
1825 if (meot->thicknessInX0() <= 20) { continue; }
1826 const Trk::ScatteringAngles* scatAngles = meot->scatteringAngles();
1827
1828 ATH_MSG_DEBUG(" Calorimeter X0 " << meot->thicknessInX0() << " pointer scat " << scatAngles);
1829
1830 if (!scatAngles) { continue; }
1831 pcalo = m->trackParameters()->momentum().mag();
1832
1833 const double pullPhi = scatAngles->deltaPhi() / scatAngles->sigmaDeltaPhi();
1834 const double pullTheta = scatAngles->deltaTheta() / scatAngles->sigmaDeltaTheta();
1835
1836 ATH_MSG_DEBUG(" Calorimeter scatterer deltaPhi " << scatAngles->deltaPhi() << " pull " << pullPhi
1837 << " deltaTheta " << scatAngles->deltaTheta() << " pull "
1838 << pullTheta);
1839
1840 const Trk::EnergyLoss* energyLoss = meot->energyLoss();
1841 if (!energyLoss) continue;
1842
1843 if (m->trackParameters()) {
1844 ATH_MSG_DEBUG("Eloss found r " << (m->trackParameters())->position().perp() << " z "
1845 << (m->trackParameters())->position().z() << " deltaE "
1846 << energyLoss->deltaE());
1847 }
1848
1850 double caloEloss = std::abs(energyLoss->deltaE());
1851 if (m->trackParameters()) { deltaP = m->trackParameters()->momentum().mag() - pcalo; }
1852
1853 ATH_MSG_DEBUG(" Calorimeter Deposit " << caloEloss << " pcalo Entrance " << pcalo << " deltaP " << deltaP);
1854 }
1855 }
1856 }
1857 } else {
1858 caloTSOS = m_caloTSOS->caloTSOS(ctx, *leadingParameters);
1859 }
1860
1861 if (caloTSOS.size() > 2) {
1862 caloAssociated = true;
1863 } else {
1864 ATH_MSG_VERBOSE("Failed to associated calorimeter");
1865 }
1866 } else {
1867 // TDDO Run2 Calo TG
1868 std::unique_ptr<const Trk::TrackStateOnSurface> tsos = m_caloTSOS->innerTSOS(ctx, parameters);
1869 if (tsos) {
1870 caloTSOS.push_back(std::move(tsos));
1871 tsos = m_caloTSOS->outerTSOS(ctx, *caloTSOS.back()->trackParameters());
1872 if (tsos) {
1873 caloAssociated = true;
1874 caloTSOS.push_back(std::move(tsos));
1875 }
1876 }
1877 ATH_MSG_VERBOSE("Special non-muon case for calo: " << caloAssociated);
1878 }
1879
1880 // if association OK, create perigee surface and back-track to it
1881 if (caloAssociated) {
1882 MagField::AtlasFieldCache fieldCache;
1883 // Get field cache object
1884 if (!loadMagneticField(ctx, fieldCache)) return nullptr;
1885
1886 if (fieldCache.toroidOn()) {
1887 const Trk::TrackParameters* oldParameters = caloTSOS.front()->trackParameters();
1888
1889 if (oldParameters){
1890 if(not oldParameters->covariance()) { ATH_MSG_VERBOSE(" createExtrapolatedTrack: no cov (0)"); }
1891 // chickened out of sorting out ownership
1892 track_param_owner = m_propagator->propagate(ctx, *oldParameters, *mperigeeSurface, Trk::oppositeMomentum, false,
1894 }
1895 } else {
1896 track_param_owner = m_propagatorSL->propagate(ctx, parameters, *mperigeeSurface, Trk::oppositeMomentum, false,
1898 }
1899 trackParameters = track_param_owner.get();
1900
1901 // only accept when perigee in indet tracking volume
1902 if (trackParameters && !m_indetVolume->inside(trackParameters->position())) {
1903 ATH_MSG_DEBUG(" back extrapolation problem: probably outside indet volume ");
1904 caloAssociated = false;
1905 }
1906
1907 if (trackParameters && !trackParameters->covariance()) { ATH_MSG_VERBOSE(" createExtrapolatedTrack: no cov (1)"); }
1908
1909 if (trackParameters) {
1910 ATH_MSG_VERBOSE(" Seed parameter: r " << trackParameters->position().perp() << " z " << trackParameters->position().z()
1911 << " pt " << trackParameters->momentum().perp());
1912 }
1913
1914 } // if (caloAssociated) {
1915 // start from vertex in case of calo association problem
1916 else if (vertex) {
1917 ATH_MSG_DEBUG(" back extrapolation problem: retry with tracking out from vertex ");
1918 // delete any existing calo objects
1919 caloTSOS.clear();
1920
1921 // track out from vertex
1922 const Amg::Vector3D momentum = parameters.position().unit() * Gaudi::Units::TeV;
1923
1924 track_param_owner = std::make_unique<Trk::Perigee>(vertex->position(), momentum, 1., *mperigeeSurface);
1925 trackParameters = track_param_owner.get();
1926 particleHypothesis = Trk::nonInteracting;
1927 runOutlier = false;
1928
1929 ATH_MSG_VERBOSE(" Retrieving Calorimeter TSOS from " << __func__ << " at line " << __LINE__);
1930
1931 if (m_useCaloTG) {
1932 caloTSOS = getCaloTSOSfromMatProvider(*trackParameters, spectrometerTrack);
1933 } else {
1934 std::unique_ptr<const Trk::TrackStateOnSurface> tsos = m_caloTSOS->innerTSOS(ctx, *trackParameters);
1935 if (tsos) {
1936 caloTSOS.push_back(std::move(tsos));
1937 tsos = m_caloTSOS->outerTSOS(ctx, *trackParameters);
1938 if (tsos) {
1939 caloTSOS.push_back(std::move(tsos));
1940 } else {
1941 track_param_owner.reset();
1942 }
1943 }
1944 }
1945 trackParameters = track_param_owner.get();
1946 }
1947
1948 // failure in calo association and/or extrapolation to indet
1949 if (!trackParameters || caloTSOS.empty()) {
1950 ATH_MSG_DEBUG(" perigee back-extrapolation fails ");
1951 return nullptr;
1952 }
1953 } // if (perigee) {
1954
1955 // set seed if provided
1956 if (seedParameters) { trackParameters = seedParameters; }
1957
1958 // append TSOS objects into DataVector
1959 // reserve allows for perigee + vertex + calo + entrancePerigee + spectrometer TSOS
1960 const unsigned int size = spectrometerTSOS.size() + 3 + caloTSOS.size() + leadingTSOS.size();
1961
1962 auto trackStateOnSurfaces = std::make_unique<Trk::TrackStates>();
1963 trackStateOnSurfaces->reserve(size);
1964
1965 // start with perigee TSOS (this just carries the perigee parameters)
1966
1967 if (trackParameters && !trackParameters->covariance()) { ATH_MSG_VERBOSE(" createExtrapolatedTrack: no cov (2)"); }
1968
1969 if (trackParameters) {
1970 if (trackParameters->surfaceType() != Trk::SurfaceType::Perigee) {
1971 ATH_MSG_DEBUG("createExtrapolatedTrack() - Track parameters are not perigee " << (*trackParameters));
1972 }
1973 trackStateOnSurfaces->push_back(Muon::MuonTSOSHelper::createPerigeeTSOS(trackParameters->uniqueClone()));
1974 }
1975
1976 // optionally append a pseudoMeasurement describing the vertex
1977 if (vertex && trackParameters) {
1978 std::unique_ptr<Trk::PseudoMeasurementOnTrack> vertexInFit = vertexOnTrack(*trackParameters, vertex, mbeamAxis);
1979 if (vertexInFit) {
1980 ATH_MSG_VERBOSE("Adding vertex constraint ");
1981 trackStateOnSurfaces->push_back(Muon::MuonTSOSHelper::createMeasTSOS(std::move(vertexInFit), nullptr, Trk::TrackStateOnSurface::Measurement));
1982 }
1983 }
1984
1985 // append calo TSOS
1986 for (std::unique_ptr<const Trk::TrackStateOnSurface>& c_tsos : caloTSOS) { trackStateOnSurfaces->push_back(std::move(c_tsos)); }
1987 caloTSOS.clear();
1988 // MS entrance perigee
1990 ATH_MSG_DEBUG("adding perigee at spectrometer entrance");
1991 const Trk::TrackParameters* mstrackParameters = trackStateOnSurfaces->back()->trackParameters();
1992
1993 if (!mstrackParameters) { mstrackParameters = spectrometerTSOS.front()->trackParameters(); }
1994
1995 if (mstrackParameters) {
1996 std::unique_ptr<Trk::TrackStateOnSurface> entranceTSOS = entrancePerigee(ctx, mstrackParameters);
1997 if (entranceTSOS) { trackStateOnSurfaces->push_back(std::move(entranceTSOS)); }
1998 }
1999 }
2000
2001 // append leading MS material TSOS
2002 for (std::unique_ptr<const Trk::TrackStateOnSurface>& c_tsos : leadingTSOS) {
2003 if (c_tsos->materialEffectsOnTrack()) { trackStateOnSurfaces->push_back(std::move(c_tsos)); }
2004 }
2005 leadingTSOS.clear();
2006
2007 // append the remaining spectrometer TSOS
2008 for (const auto& s : spectrometerTSOS) {
2011 trackStateOnSurfaces->push_back(s->clone());
2012 }
2013
2014 if (s->measurementOnTrack() && dynamic_cast<const Trk::PseudoMeasurementOnTrack*>(s->measurementOnTrack())) {
2015 ATH_MSG_VERBOSE(" MS Pseudo");
2016 }
2017 }
2018
2019 // create track
2020 std::unique_ptr<Trk::Track> track =
2021 std::make_unique<Trk::Track>(spectrometerTrack.info(), std::move(trackStateOnSurfaces), nullptr);
2022
2023 if (!track->perigeeParameters()) {
2024 ATH_MSG_DEBUG("Reject track without perigee.");
2025 return nullptr;
2026 }
2027 dumpCaloEloss(track.get(), " createExtrapolatedTrack ");
2028 if (msgLevel(MSG::DEBUG)) countAEOTs(*track, " createExtrapolatedTrack before fit ");
2029
2030 // remove material when curvature badly determined (to remove energy loss uncertainty)
2031 if (particleHypothesis == Trk::nonInteracting) {
2032 ATH_MSG_VERBOSE(" remove spectrometer material ");
2034 }
2035
2036 // fit the track
2037 ATH_MSG_VERBOSE(" fit SA track with " << track->trackStateOnSurfaces()->size() << " TSOS"
2038 << (particleHypothesis == Trk::nonInteracting ? " using nonInteracting hypothesis"
2039 : "usig interacting hypothesis"));
2040
2041 std::unique_ptr<Trk::Track> fittedTrack{fit(ctx, *track, runOutlier, particleHypothesis)};
2042 if (fittedTrack) {
2043 if (msgLevel(MSG::DEBUG)) countAEOTs(*fittedTrack, " createExtrapolatedTrack after fit");
2044
2045 // only accept when perigee in indet tracking volume
2046 if (fittedTrack->perigeeParameters() && !m_indetVolume->inside(fittedTrack->perigeeParameters()->position())) {
2047 ATH_MSG_DEBUG(" back extrapolation problem: fitted perigee outside indet volume ");
2048 return nullptr;
2049 }
2050
2051 // limit momentum for future energy loss allocation
2052 if (particleHypothesis != Trk::muon) {
2053 ATH_MSG_VERBOSE(" set momentum limit ");
2054 removeSpectrometerMaterial(fittedTrack);
2055 }
2056
2057 ATH_MSG_VERBOSE(" found track " << m_printer->print(*fittedTrack));
2058 return fittedTrack;
2059 }
2060 // return the unfitted track in case of problem
2061 return track;
2062 }
static std::unique_ptr< Trk::TrackStateOnSurface > createMeasTSOS(std::unique_ptr< Trk::MeasurementBase > meas, std::unique_ptr< Trk::TrackParameters > pars, Trk::TrackStateOnSurface::TrackStateOnSurfaceType type)
create a TSOS with a measurement, takes ownership of the pointers
static std::unique_ptr< Trk::TrackStateOnSurface > createPerigeeTSOS(std::unique_ptr< Trk::TrackParameters > perigee)
create a perigee TSOS, takes ownership of the Perigee
void removeSpectrometerMaterial(std::unique_ptr< Trk::Track > &track) const
ToolHandle< Trk::IMaterialAllocator > m_materialAllocator
ToolHandle< Trk::IPropagator > m_propagator
static std::unique_ptr< Trk::PseudoMeasurementOnTrack > vertexOnTrack(const Trk::TrackParameters &parameters, const Trk::RecVertex *vertex, const Trk::RecVertex *mbeamAxis)
ToolHandle< Trk::IPropagator > m_propagatorSL
Gaudi::Property< bool > m_perigeeAtSpectrometerEntrance
std::unique_ptr< Trk::TrackStateOnSurface > entrancePerigee(const EventContext &ctx, const Trk::TrackParameters *parameters) const
Trk::MagneticFieldProperties m_magFieldProperties
std::vector< std::unique_ptr< const TrackStateOnSurface > > Garbage_t
double thicknessInX0() const
returns the actually traversed material .
const EnergyLoss * energyLoss() const
returns the energy loss object.
virtual constexpr SurfaceType surfaceType() const override=0
Returns the Surface Type enum for the surface used to define the derived class.
std::unique_ptr< ParametersBase< DIM, T > > uniqueClone() const
clone method for polymorphic deep copy returning unique_ptr; it is not overriden, but uses the existi...
double deltaPhi() const
returns the
double deltaTheta() const
returns the
@ Measurement
This is a measurement, and will at least contain a Trk::MeasurementBase.
Eigen::Matrix< double, Eigen::Dynamic, 1 > VectorX
Dynamic Vector - dynamic allocation.
@ oppositeMomentum
@ theta
Definition ParamDefs.h:66
@ loc2
generic first and second local coordinate
Definition ParamDefs.h:35
@ phi
Definition ParamDefs.h:75
@ loc1
Definition ParamDefs.h:34

◆ createIndetTrack()

std::unique_ptr< Trk::Track > Rec::CombinedMuonTrackBuilder::createIndetTrack ( const Trk::TrackInfo & info,
const Trk::TrackStates * tsos ) const
private

Definition at line 2064 of file CombinedMuonTrackBuilder.cxx.

2065 {
2066 // create indet track TSOS vector
2067 auto trackStateOnSurfaces = std::make_unique<Trk::TrackStates>();
2070
2071
2072 // set end iterator to be the first TSOS after the indet
2073 unsigned size = 1;
2074
2076
2077 std::unique_ptr<Trk::TrackStateOnSurface> perigeeTSOS {(**s).clone()};
2078
2079 ++s; // keep start perigee where-ever!
2080 for (; s != end; ++s) {
2081 ++size;
2082 if (!m_indetVolume->inside((**s).trackParameters()->position())) { break; }
2083 }
2084 end = s;
2085
2086 trackStateOnSurfaces->reserve(size);
2087 trackStateOnSurfaces->push_back(std::move(perigeeTSOS));
2088
2089 // then append selected TSOS
2090 appendSelectedTSOS(*trackStateOnSurfaces, begin, end);
2091
2092 return std::make_unique<Trk::Track>(info, std::move(trackStateOnSurfaces), nullptr);
2093 }
void appendSelectedTSOS(Trk::TrackStates &trackStateOnSurfaces, Trk::TrackStates::const_iterator begin, Trk::TrackStates::const_iterator end) const

◆ createMuonTrack()

std::unique_ptr< Trk::Track > Rec::CombinedMuonTrackBuilder::createMuonTrack ( const EventContext & ctx,
const Trk::Track & muonTrack,
const Trk::TrackParameters * parameters,
std::unique_ptr< CaloEnergy > caloEnergy,
const Trk::TrackStates * tsos ) const
private

Summarizes the available information about the ID track, the deposited calorimeter energies and the track states into a new track --> m_materialUpdator as only tool called , but does not provide an interface method with ctx thus far.

Check that the perigee parameters exist

Move the perigee to the front

Definition at line 2095 of file CombinedMuonTrackBuilder.cxx.

2097 {
2100 size_t size = tsos->size();
2101
2102 if (msgLevel(MSG::DEBUG)) countAEOTs(muonTrack, " createMuonTrack ");
2103
2104 // set iterator to current TSOS on input track to be after the indet
2105 const Trk::TrackParameters* lastIDtp = nullptr;
2107 while ((**s).trackParameters() &&
2108 (m_indetVolume->inside((**s).trackParameters()->position()) || (**s).type(Trk::TrackStateOnSurface::Perigee))) {
2109 if (m_indetVolume->inside((**s).trackParameters()->position())) { lastIDtp = (**s).trackParameters(); }
2110 ++s;
2111 --size;
2112 }
2113
2114 // create muon track TSOS vector
2115 auto trackStateOnSurfaces = std::make_unique<Trk::TrackStates>();
2116
2117 // redo calo association from inside if requested
2118 bool redoCaloAssoc = false;
2119 if (parameters) {
2120 redoCaloAssoc = true;
2121
2122 // move current TSOS iterator to be outside the calorimeter
2123 while ((**s).trackParameters() &&
2124 (m_calorimeterVolume->inside((**s).trackParameters()->position()) || (**s).type(Trk::TrackStateOnSurface::Perigee))) {
2125 ++s;
2126 --size;
2127 }
2128
2129 // associate calo by extrapolation from last ID parameters
2130 std::vector<std::unique_ptr<const Trk::TrackStateOnSurface>> caloTSOS;
2131 if (m_useCaloTG) {
2132 if (!lastIDtp) { lastIDtp = parameters; }
2133 ATH_MSG_VERBOSE(" Retrieving Calorimeter TSOS from " << __func__ << " at line " << __LINE__);
2134 caloTSOS = getCaloTSOSfromMatProvider(*lastIDtp, muonTrack);
2135 } else {
2136 caloTSOS = m_caloTSOS->caloTSOS(ctx, *parameters);
2137 }
2138
2139 if (caloTSOS.size() < 3) {
2140 ATH_MSG_DEBUG(" muonTrack: parameters fail to fully intersect the calorimeter");
2141 return nullptr;
2142 }
2143
2144 size += caloTSOS.size();
2145 trackStateOnSurfaces->reserve(size + 1);
2146
2147 // start with the calo TSOS
2148 for (std::unique_ptr<const Trk::TrackStateOnSurface>& c_tsos : caloTSOS) { trackStateOnSurfaces->push_back(std::move(c_tsos)); }
2149
2150 } else {
2151 trackStateOnSurfaces->reserve(size + 1);
2152 }
2153
2154 // if requested, replace caloEnergy on appropriate TSOS
2156 if (caloEnergy && (**s).trackParameters() && m_calorimeterVolume->inside((**s).trackParameters()->position())) {
2157 const Trk::TrackStateOnSurface* TSOS = (**s).clone();
2158 trackStateOnSurfaces->push_back(TSOS);
2159 ++s;
2160
2161 // create MEOT owning CaloEnergy
2162 if ((**s).trackParameters() && m_calorimeterVolume->inside((**s).trackParameters()->position())) {
2163 std::bitset<Trk::MaterialEffectsBase::NumberOfMaterialEffectsTypes> typePattern;
2165
2166 std::unique_ptr<Trk::MaterialEffectsOnTrack> materialEffects =
2167 std::make_unique<Trk::MaterialEffectsOnTrack>(0., std::move(caloEnergy), (**s).trackParameters()->associatedSurface(), typePattern);
2168
2169 // create TSOS
2170
2171 std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes> type;
2173
2174 TSOS = new Trk::TrackStateOnSurface(nullptr, (**s).trackParameters()->uniqueClone(),std::move(materialEffects), type);
2175 trackStateOnSurfaces->push_back(TSOS);
2176 ++s;
2177 } else {
2178 // should never happen: FSR caloEnergy delete
2179 m_messageHelper->printWarning(37);
2180 }
2181 }
2182
2183 // MS entrance perigee
2184 bool hasAlreadyPerigee = false;
2186 // copy calorimeter TSOS
2187 while ((**s).trackParameters() && m_calorimeterVolume->inside((**s).trackParameters()->position())) {
2188 if (!(**s).type(Trk::TrackStateOnSurface::Perigee)) {
2189 const Trk::TrackStateOnSurface* TSOS = (**s).clone();
2190 trackStateOnSurfaces->push_back(TSOS);
2191 }
2192 ++s;
2193 }
2194
2195 // add entrance TSOS if not already present
2196 std::unique_ptr<Trk::TrackStateOnSurface> entranceTSOS;
2197
2198 if ((**s).type(Trk::TrackStateOnSurface::Perigee)) { hasAlreadyPerigee = true; }
2199
2200 if (!hasAlreadyPerigee) {
2201 if ((**s).trackParameters()) {
2202 entranceTSOS = entrancePerigee(ctx, (**s).trackParameters());
2203 } else {
2204 entranceTSOS = entrancePerigee(ctx, trackStateOnSurfaces->back()->trackParameters());
2205 }
2206 if (entranceTSOS) {
2207 double distance = (entranceTSOS->trackParameters()->position() - (**s).trackParameters()->position()).mag();
2208
2209 if (distance > 2000) {
2210 ATH_MSG_DEBUG(" Added Muon Entrance "
2211 << " r " << entranceTSOS->trackParameters()->position().perp() << " z "
2212 << entranceTSOS->trackParameters()->position().z() << " track pars r "
2213 << (**s).trackParameters()->position().perp() << " z " << (**s).trackParameters()->position().z());
2214 }
2215 trackStateOnSurfaces->push_back(std::move(entranceTSOS));
2216 hasAlreadyPerigee = true;
2217 }
2218 }
2219 }
2220
2221
2222 // then append selected TSOS from the extrapolated or spectrometer track
2223 appendSelectedTSOS(*trackStateOnSurfaces, s, end);
2225 if (!hasAlreadyPerigee && std::find_if(trackStateOnSurfaces->begin(), trackStateOnSurfaces->end(),
2226 [] (const Trk::TrackStateOnSurface* tsos){
2227 return tsos->type(Trk::TrackStateOnSurface::Perigee);
2228 }) == trackStateOnSurfaces->end() && muonTrack.perigeeParameters() ){
2229 trackStateOnSurfaces->push_back( Muon::MuonTSOSHelper::createPerigeeTSOS(muonTrack.perigeeParameters()->uniqueClone()));
2231 std::stable_sort(trackStateOnSurfaces->begin(),trackStateOnSurfaces->end(),
2232 [](const Trk::TrackStateOnSurface* a , const Trk::TrackStateOnSurface* b){
2233 return a->type(Trk::TrackStateOnSurface::Perigee) > b->type(Trk::TrackStateOnSurface::Perigee);
2234 });
2235 ATH_MSG_DEBUG(__FILE__<<":"<<__LINE__<<" No track perigee parameters were added. Copy the existing ones from the muon track");
2236 }
2237 std::unique_ptr<Trk::Track> newMuonTrack = std::make_unique<Trk::Track>(muonTrack.info(), std::move(trackStateOnSurfaces), nullptr);
2238 unsigned int num_ms{0}, num_precMS{0};
2239 for (const Trk::MeasurementBase* meas : *newMuonTrack->measurementsOnTrack()) {
2240 const Trk::RIO_OnTrack* rio = dynamic_cast<const Trk::RIO_OnTrack*>(meas);
2241 if (!rio || !m_idHelperSvc->isMuon(rio->identify())) continue;
2242 ++num_ms;
2243 num_precMS += !m_idHelperSvc->measuresPhi(rio->identify());
2244 }
2245 if (num_precMS < 3 || num_ms < 5) {
2246 ATH_MSG_VERBOSE(__FILE__":"<<__LINE__<<" MS track with too few meausrements constructed "<<std::endl<<
2247 m_printer->print(newMuonTrack->measurementsOnTrack()->stdcont()) );
2248 return nullptr;
2249 }
2250 // Updates the calo TSOS with the ones from TG+corrections (if needed)
2251 if (m_updateWithCaloTG && !m_useCaloTG && redoCaloAssoc) {
2252 ATH_MSG_VERBOSE("Updating Calorimeter TSOS in CreateMuonTrack ...");
2253 m_materialUpdator->updateCaloTSOS(*newMuonTrack, parameters);
2254 }
2255
2256 return newMuonTrack;
2257 }
static Double_t a
float distance(const Amg::Vector3D &p1, const Amg::Vector3D &p2)
calculates the distance between two point in 3D space
void stable_sort(DataModel_detail::iterator< DVL > beg, DataModel_detail::iterator< DVL > end)
Specialization of stable_sort for DataVector/List.

◆ createPhiPseudoMeasurement()

std::unique_ptr< Trk::TrackStateOnSurface > Rec::CombinedMuonTrackBuilder::createPhiPseudoMeasurement ( const EventContext & ctx,
const Trk::Track & track ) const
private

Definition at line 2259 of file CombinedMuonTrackBuilder.cxx.

2260 {
2261 auto parameters = m_trackQuery->spectrometerParameters(track, ctx);
2262 Amg::MatrixX covarianceMatrix(1, 1);
2263 covarianceMatrix.setZero();
2264 covarianceMatrix(0, 0) = s_sigmaPhiSector * s_sigmaPhiSector * parameters->position().perp2();
2265
2266 std::unique_ptr<Trk::PseudoMeasurementOnTrack> pseudo = std::make_unique<Trk::PseudoMeasurementOnTrack>(
2267 Trk::LocalParameters(Trk::DefinedParameter(0., Trk::locY)),
2268 std::move(covarianceMatrix),
2269 parameters->associatedSurface());
2270
2271 return Muon::MuonTSOSHelper::createMeasTSOS(std::move(pseudo), std::move(parameters), Trk::TrackStateOnSurface::Measurement);
2272 }
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic Matrix - dynamic allocation.
@ locY
local cartesian
Definition ParamDefs.h:38
std::pair< double, ParamDefs > DefinedParameter
Typedef to of a std::pair<double, ParamDefs> to identify a passed-through double as a specific type o...

◆ createSpectrometerTSOS()

std::vector< std::unique_ptr< const Trk::TrackStateOnSurface > > Rec::CombinedMuonTrackBuilder::createSpectrometerTSOS ( const EventContext & ctx,
const Trk::Track & spectrometerTrack ) const
private

Definition at line 2274 of file CombinedMuonTrackBuilder.cxx.

2275 {
2276 const Trk::Perigee* measuredPerigee = spectrometerTrack.perigeeParameters();
2277 std::vector<std::unique_ptr<const Trk::TrackStateOnSurface>> spectrometerTSOS;
2278
2279 if (!measuredPerigee || !measuredPerigee->covariance() || !Amg::hasPositiveDiagElems(*measuredPerigee->covariance())) {
2280 // missing MeasuredPerigee for spectrometer track
2281 if (!measuredPerigee)
2282 m_messageHelper->printWarning(38);
2283 else if (!measuredPerigee->covariance())
2284 m_messageHelper->printWarning(38);
2285 else
2286 ATH_MSG_DEBUG("createSpectrometerTSOS::perigee covariance not valid");
2287 return spectrometerTSOS;
2288 }
2289
2290 double errorPhi = std::sqrt((*measuredPerigee->covariance())(Trk::phi0, Trk::phi0));
2291
2292 // create the spectrometer TSOS's for the extrapolated fit
2293 spectrometerTSOS.reserve(spectrometerTrack.trackStateOnSurfaces()->size());
2294
2295 // start with a 'phi sector constraint' pseudomeasurement when necessary
2296 unsigned numberPseudo = m_trackQuery->numberPseudoMeasurements(spectrometerTrack);
2297 if (errorPhi > s_sigmaPhiSector) { ++numberPseudo; }
2298
2299 if (numberPseudo > 1 && !m_trackQuery->isSectorOverlap(spectrometerTrack)) {
2300 ATH_MSG_VERBOSE("standaloneFit: add pseudo to constrain phi sector");
2301
2302 std::unique_ptr<Trk::TrackStateOnSurface> tsos = {createPhiPseudoMeasurement(ctx, spectrometerTrack)};
2303 if (tsos) { spectrometerTSOS.emplace_back(std::move(tsos)); }
2304 }
2305
2306 // make a measurement selection to fixup non-standard TSOS's
2307 double deltaZ = 0.;
2308 bool haveMeasurement = false;
2309
2310 std::vector<const Trk::Surface*> measurementSurfaces;
2311 measurementSurfaces.reserve(spectrometerTrack.trackStateOnSurfaces()->size());
2312
2313 unsigned numberMaterial{0}, numberParameters{0};
2314
2315 const Trk::Surface* previousSurface = nullptr;
2316 std::unique_ptr<const Trk::TrackStateOnSurface> previousTSOS;
2317
2318 for (const Trk::TrackStateOnSurface* s : *spectrometerTrack.trackStateOnSurfaces()) {
2319 // skip any leading material
2320 if (!haveMeasurement) {
2321 if (s->measurementOnTrack()) {
2322 haveMeasurement = true;
2323 } else if (s->materialEffectsOnTrack()) {
2324 continue;
2325 }
2326 }
2327
2328 // input statistics for VERBOSE
2329 const Trk::TrackParameters* trackParameters = s->trackParameters();
2330 if (msgLvl(MSG::VERBOSE)) {
2331 if (s->materialEffectsOnTrack()) ++numberMaterial;
2332 if (trackParameters) ++numberParameters;
2333 }
2334
2335 // skip unwanted TSOS and non-understood features in iPatFitter
2336 if (!s->measurementOnTrack() && !s->materialEffectsOnTrack()) {
2337 // remove holes as they will be reallocated
2338 if (s->type(Trk::TrackStateOnSurface::Hole)) continue;
2339
2340 // same for MS perigee
2341 if (s->type(Trk::TrackStateOnSurface::Perigee)) continue;
2342
2343 if (s->trackParameters()) {
2344 ATH_MSG_DEBUG("createSpectrometerTSOS:: skip unrecognized TSOS " << s->dumpType() << " r "
2345 << s->trackParameters()->position().perp() << " z "
2346 << s->trackParameters()->position().z());
2347 } else {
2348 // skip unrecognized TSOS without TrackParameters
2349 m_messageHelper->printWarning(39, s->dumpType());
2350 }
2351 continue;
2352 }
2353
2354 // several checks applied to measurements:
2355 bool trapezoid = false;
2356 bool rotatedTrap = false;
2357 if (s->measurementOnTrack()) {
2358 // skip pseudo
2359 if (dynamic_cast<const Trk::PseudoMeasurementOnTrack*>(s->measurementOnTrack())) {
2360 continue;
2361 }
2362 // careful with trapezoid ordering (put trapezoid before
2363 // rotatedTrapezoid)
2364 const Trk::Surface* surface = &s->measurementOnTrack()->associatedSurface();
2365
2366 if (previousSurface) { deltaZ = std::abs(previousSurface->center().z() - surface->center().z()); }
2367
2368 if (dynamic_cast<const Trk::PlaneSurface*>(surface)) {
2369 if (dynamic_cast<const Trk::TrapezoidBounds*>(&surface->bounds())) {
2370 trapezoid = true;
2371 } else if (dynamic_cast<const Trk::RotatedTrapezoidBounds*>(&surface->bounds())) {
2372 rotatedTrap = true;
2373 }
2374 }
2375
2376 // skip duplicate measurements on same surface
2377 if (previousSurface &&
2378 std::find(measurementSurfaces.begin(), measurementSurfaces.end(), surface) != measurementSurfaces.end()) {
2379 // skip duplicate measurement
2380 m_messageHelper->printWarning(40, m_idHelperSvc->toString(m_edmHelperSvc->getIdentifier(*(s->measurementOnTrack()))));
2381 continue;
2382 }
2383 measurementSurfaces.push_back(surface);
2384 previousSurface = surface;
2385
2386 } else if (previousTSOS) {
2387 spectrometerTSOS.emplace_back(std::move(previousTSOS));
2388 }
2389
2390 // trapezoid precedes rotatedTrapezoid
2391 std::unique_ptr<const Trk::TrackStateOnSurface> TSOS(s->clone());
2392 //cppcheck-suppress accessMoved
2393 if (previousTSOS) {
2394 if (trapezoid && deltaZ < 1. * Gaudi::Units::mm) {
2395 spectrometerTSOS.emplace_back(std::move(TSOS));
2396 TSOS = std::move(previousTSOS);
2397 } else {
2398 spectrometerTSOS.emplace_back(std::move(previousTSOS));
2399 }
2400 }
2401
2402 if (rotatedTrap) {
2403 previousTSOS.swap(TSOS);
2404 continue;
2405 }
2406
2407 spectrometerTSOS.emplace_back(std::move(TSOS));
2408 }
2409
2410 if (previousTSOS) spectrometerTSOS.emplace_back(std::move(previousTSOS));
2411
2412 ATH_MSG_VERBOSE(" input spectrometer track with " << spectrometerTrack.trackStateOnSurfaces()->size() << " TSOS, of which "
2413 << numberMaterial << " have MaterialEffects and " << numberParameters
2414 << " have TrackParameters");
2415
2416 return spectrometerTSOS;
2417 }
std::unique_ptr< Trk::TrackStateOnSurface > createPhiPseudoMeasurement(const EventContext &ctx, const Trk::Track &track) const
virtual const SurfaceBounds & bounds() const =0
Surface Bounds method.
const Amg::Vector3D & center() const
Returns the center position of the Surface.
@ phi0
Definition ParamDefs.h:65

◆ dumpCaloEloss()

void Rec::CombinedMuonTrackBuilder::dumpCaloEloss ( const Trk::Track * track,
const std::string & txt ) const
private

Definition at line 3035 of file CombinedMuonTrackBuilder.cxx.

3035 {
3036 // will refit if extrapolated track was definitely bad
3037 if (!track || !msgLevel(MSG::DEBUG)) return;
3038 if (!m_trackQuery->isCaloAssociated(*track, Gaudi::Hive::currentContext())) {
3039 ATH_MSG_DEBUG(txt << " no TSOS in Calorimeter ");
3040 return;
3041 }
3042
3043 const Trk::Track& originalTrack = *track;
3044 const CaloEnergy* caloEnergy = m_trackQuery->caloEnergy(originalTrack);
3045 if (caloEnergy) {
3046 ATH_MSG_DEBUG(txt << " Calorimeter Eloss " << caloEnergy->deltaE());
3047 } else {
3048 ATH_MSG_DEBUG(txt << " No Calorimeter Eloss");
3049 }
3050
3051 const Trk::TrackStates* trackTSOS = track->trackStateOnSurfaces();
3052
3053 double Eloss = 0.;
3054 double idEloss = 0.;
3055 double caloEloss = 0.;
3056 double msEloss = 0.;
3057 double deltaP = 0.;
3058 double pcalo = 0.;
3059 double pstart = 0.;
3060 double eta = 0.;
3061 double pMuonEntry = 0.;
3062
3063 for (const auto* m : *trackTSOS) {
3064 const Trk::MeasurementBase* mot = m->measurementOnTrack();
3065
3066 if (m->trackParameters()) { pMuonEntry = m->trackParameters()->momentum().mag(); }
3067
3068 if (mot) {
3069 Identifier id = Trk::IdentifierExtractor::extract(mot);
3070 if (id.is_valid()) {
3071 // skip after first Muon hit
3072 if (m_idHelperSvc->isMuon(id)) { break; }
3073 }
3074 }
3075
3076 if (pstart == 0 && m->trackParameters()) {
3077 pstart = m->trackParameters()->momentum().mag();
3078 eta = m->trackParameters()->momentum().eta();
3079
3080 ATH_MSG_DEBUG("Start pars found eta " << eta << " r " << (m->trackParameters())->position().perp() << " z "
3081 << (m->trackParameters())->position().z() << " pstart " << pstart);
3082 }
3083
3084 if (m->materialEffectsOnTrack()) {
3085 const Trk::MaterialEffectsOnTrack* meot = dynamic_cast<const Trk::MaterialEffectsOnTrack*>(m->materialEffectsOnTrack());
3086
3087 if (meot) {
3088 if (meot->thicknessInX0() > 20) {
3089 const Trk::ScatteringAngles* scatAngles = meot->scatteringAngles();
3090
3091 ATH_MSG_DEBUG(" Calorimeter X0 " << meot->thicknessInX0() << " pointer scat " << scatAngles);
3092
3093 if (scatAngles) {
3094 pcalo = m->trackParameters()->momentum().mag();
3095 double pullPhi = scatAngles->deltaPhi() / scatAngles->sigmaDeltaPhi();
3096 double pullTheta = scatAngles->deltaTheta() / scatAngles->sigmaDeltaTheta();
3097
3098 ATH_MSG_DEBUG(" Calorimeter scatterer deltaPhi (mrad) "
3099 << 1000 * scatAngles->deltaPhi() << " sigma " << 1000 * scatAngles->sigmaDeltaPhi() << " pull "
3100 << pullPhi << " deltaTheta (mrad) " << 1000 * scatAngles->deltaTheta() << " sigma "
3101 << 1000 * scatAngles->sigmaDeltaTheta() << " pull " << pullTheta);
3102 }
3103 }
3104
3105 const Trk::EnergyLoss* energyLoss = meot->energyLoss();
3106 if (energyLoss) {
3107 if (m->trackParameters()) {
3108 ATH_MSG_DEBUG("Eloss found r " << (m->trackParameters())->position().perp() << " z "
3109 << (m->trackParameters())->position().z() << " value " << energyLoss->deltaE()
3110 << " Eloss " << Eloss);
3111 }
3112
3114 idEloss = Eloss;
3115 caloEloss = std::abs(energyLoss->deltaE());
3116 Eloss = 0.;
3117
3118 if (m->trackParameters()) { deltaP = m->trackParameters()->momentum().mag() - pcalo; }
3119
3120 const Trk::Surface& surface = m->surface();
3121
3122 ATH_MSG_DEBUG(" Calorimeter surface " << surface);
3123 ATH_MSG_DEBUG(txt << " Calorimeter delta p " << deltaP << " deltaE " << caloEloss
3124 << " delta pID = pcaloEntry-pstart " << pcalo - pstart);
3125
3126 } else {
3127 Eloss += std::abs(energyLoss->deltaE());
3128 }
3129 }
3130 }
3131 }
3132 }
3133
3134 msEloss = Eloss;
3135 Eloss = idEloss + caloEloss + msEloss;
3136
3137 ATH_MSG_DEBUG(txt << " eta " << eta << " pstart " << pstart / Gaudi::Units::GeV << " Eloss on TSOS idEloss " << idEloss
3138 << " caloEloss " << caloEloss << " msEloss " << msEloss << " Total " << Eloss << " pstart - pMuonEntry "
3139 << pstart - pMuonEntry);
3140
3141 return;
3142 }
Scalar eta() const
pseudorapidity method
static void extract(std::vector< Identifier > &ids, const std::vector< const MeasurementBase * > &measurements)

◆ entrancePerigee()

std::unique_ptr< Trk::TrackStateOnSurface > Rec::CombinedMuonTrackBuilder::entrancePerigee ( const EventContext & ctx,
const Trk::TrackParameters * parameters ) const
private

Definition at line 2419 of file CombinedMuonTrackBuilder.cxx.

2419 {
2420 // make sure the spectrometer entrance volume is available
2421 if (!parameters) return nullptr;
2422 const Trk::TrackingVolume* spectrometerEntrance = getVolume(ctx, "MuonSpectrometerEntrance");
2423 if (!spectrometerEntrance) return nullptr;
2424
2425 std::unique_ptr<Trk::TrackParameters> entranceParameters{
2426 m_extrapolator->extrapolateToVolume(ctx, *parameters, *spectrometerEntrance, Trk::anyDirection, Trk::nonInteracting)};
2427
2428 if (!entranceParameters) return nullptr;
2429
2430 Trk::PerigeeSurface surface(entranceParameters->position());
2431 std::unique_ptr<Trk::TrackParameters> trackParameters{m_extrapolator->extrapolateDirectly(ctx, *entranceParameters, surface)};
2432
2433 if (!trackParameters) return nullptr;
2434
2435 std::unique_ptr<Trk::Perigee> perigee =
2436 std::make_unique<Trk::Perigee>(trackParameters->position(), trackParameters->momentum(), trackParameters->charge(), std::move(surface));
2437 return std::unique_ptr<Trk::TrackStateOnSurface>(Muon::MuonTSOSHelper::createPerigeeTSOS(std::move(perigee)));
2438 }
ToolHandle< Trk::IExtrapolator > m_extrapolator
const Trk::TrackingVolume * getVolume(const EventContext &ctx, const std::string &&vol_name) const
@ anyDirection

◆ extrapolatedParameters()

std::unique_ptr< Trk::TrackParameters > Rec::CombinedMuonTrackBuilder::extrapolatedParameters ( const EventContext & ctx,
bool & badlyDeterminedCurvature,
const Trk::Track & spectrometerTrack,
const Trk::RecVertex * mvertex,
const Trk::PerigeeSurface * mperigeeSurface ) const
private

if (haveSpectrometerRefit) delete spectrometerFit;

Definition at line 2440 of file CombinedMuonTrackBuilder.cxx.

2442 {
2443 badlyDeterminedCurvature = false;
2444 const Trk::Perigee* measuredPerigee = spectrometerTrack.perigeeParameters();
2445
2446 if (!measuredPerigee || !measuredPerigee->covariance()) {
2447 // missing MeasuredPerigee for spectrometer track
2448 m_messageHelper->printWarning(42);
2449 return nullptr;
2450 }
2451
2452 // set starting parameters and measured momentum error
2453 auto parameters = m_trackQuery->spectrometerParameters(spectrometerTrack, ctx);
2454 if (!parameters || !parameters->covariance()) {
2455 // missing spectrometer parameters on spectrometer track
2456 m_messageHelper->printWarning(43);
2457 return nullptr;
2458 }
2459
2460 double errorP = std::sqrt(measuredPerigee->momentum().mag2() * (*measuredPerigee->covariance())(Trk::qOverP, Trk::qOverP));
2461
2462 // corrected parameters ensure the track fitting starts with a projective approximation
2463 std::unique_ptr<Trk::TrackParameters> correctedParameters{};
2464 Amg::VectorX parameterVector = parameters->parameters();
2465 double trackEnergy = 1. / std::abs(parameterVector[Trk::qOverP]);
2466
2467 // careful: need to reset parameters to have a sensible energy if starting from a lineFit
2468 if (m_trackQuery->isLineFit(spectrometerTrack)) {
2469 trackEnergy = m_lineMomentum;
2470 parameterVector[Trk::qOverP] = parameters->charge() / trackEnergy;
2471
2472 parameters = parameters->associatedSurface().createUniqueTrackParameters(
2473 parameterVector[Trk::loc1], parameterVector[Trk::loc2], parameterVector[Trk::phi], parameterVector[Trk::theta],
2474 parameterVector[Trk::qOverP], AmgSymMatrix(5)(*parameters->covariance()));
2475 }
2476
2477 // check if the track curvature is well determined (with sufficient energy to penetrate material)
2478 // (i.e. field off or small momentum error, starting parameters upstream of endcap toroid)
2479 bool curvatureOK = false;
2480
2481 const Trk::IPropagator* propagator = m_propagator.get();
2482 MagField::AtlasFieldCache fieldCache;
2483 // Get field cache object
2484 if (!loadMagneticField(ctx, fieldCache)) return nullptr;
2485 if (!fieldCache.toroidOn()) {
2486 curvatureOK = true;
2487 propagator = m_propagatorSL.get();
2488 } else if (std::abs(parameters->position().z()) < m_zECToroid &&
2489 (!m_trackQuery->isLineFit(spectrometerTrack) && errorP < m_largeMomentumError)) {
2490 curvatureOK = true;
2491 }
2492
2493 if (curvatureOK) {
2494 // TDDO Run2 Calo TG
2495 // energy loss correction
2496 std::unique_ptr<CaloEnergy> caloEnergy{
2497 m_caloEnergyParam->energyLoss(ctx, trackEnergy, parameters->position().eta(), parameters->position().phi())};
2498
2499 if (trackEnergy + caloEnergy->deltaE() < m_minEnergy) {
2500 ATH_MSG_DEBUG("standaloneFit: trapped in calorimeter");
2501 return nullptr;
2502 }
2503
2504 parameterVector[Trk::qOverP] = parameters->charge() / (trackEnergy + caloEnergy->deltaE());
2505 correctedParameters = parameters->associatedSurface().createUniqueTrackParameters(
2506 parameterVector[Trk::loc1], parameterVector[Trk::loc2], parameterVector[Trk::phi], parameterVector[Trk::theta],
2507 parameterVector[Trk::qOverP], AmgSymMatrix(5)(*parameters->covariance()));
2508
2509 // protect against spectrometer track with unrealistic energy loss
2510 // check material in spectrometer is not vastly greater than in the calo
2511 // (there are some very dense spectrometer regions)
2512 double spectrometerEnergyLoss = 0.;
2513
2515 Trk::TrackStates::const_iterator sEnd = spectrometerTrack.trackStateOnSurfaces()->end();
2516 for (; s != sEnd; ++s) {
2517 if (!(**s).materialEffectsOnTrack()) { continue; }
2518
2519 const Trk::MaterialEffectsOnTrack* meot = dynamic_cast<const Trk::MaterialEffectsOnTrack*>((**s).materialEffectsOnTrack());
2520
2521 if (meot && meot->energyLoss()) { spectrometerEnergyLoss += meot->energyLoss()->deltaE(); }
2522 }
2523
2524 if (std::abs(spectrometerEnergyLoss) > 1.5 * std::abs(caloEnergy->deltaE())) {
2525 curvatureOK = false;
2526 ATH_MSG_DEBUG("standaloneFit: excessive energy loss in spectrometer "
2527 << std::abs(spectrometerEnergyLoss / Gaudi::Units::GeV) << " GeV"
2528 << " in calo " << std::abs(caloEnergy->deltaE() / Gaudi::Units::GeV) << " GeV");
2529 }
2530 }
2531
2532 // check perigee in indet volume when the curvature is well determined
2533 // otherwise will assume projectivity for starting parameters
2534 if (curvatureOK) {
2535 std::unique_ptr<Trk::TrackParameters> perigee{propagator->propagate(
2536 ctx, *correctedParameters, *mperigeeSurface, Trk::oppositeMomentum, false, m_magFieldProperties, Trk::nonInteracting)};
2537
2538 if (!perigee) {
2539 ATH_MSG_DEBUG("standaloneFit: failed back extrapolation to perigee");
2540 return nullptr;
2541 }
2542
2543 // large impact: set phi to be projective (note iteration)
2544 if (std::abs(perigee->parameters()[Trk::d0]) < m_largeImpact || !fieldCache.toroidOn()) {
2545 ATH_MSG_DEBUG("Track d0 perigee: " << std::abs(perigee->parameters()[Trk::d0]) << " which is smaller than "
2546 << m_largeImpact);
2547 } else {
2548 Amg::Vector3D position = correctedParameters->position();
2549
2550 double deltaPhi = 0.;
2551 double deltaR = (position - perigee->position()).perp();
2552
2553 if (std::abs(deltaR * M_PI) > std::abs(perigee->parameters()[Trk::d0])) {
2554 deltaPhi = perigee->parameters()[Trk::d0] / deltaR;
2555 }
2556
2557 ATH_MSG_DEBUG("standaloneFit: large perigee impact " << perigee->parameters()[Trk::d0] << " deltaR, deltaPhi " << deltaR
2558 << ", " << deltaPhi);
2559
2560 parameterVector[Trk::phi0] += deltaPhi;
2561
2562 if (parameterVector[Trk::phi0] > M_PI) {
2563 parameterVector[Trk::phi0] -= 2. * M_PI;
2564 } else if (parameterVector[Trk::phi0] < -M_PI) {
2565 parameterVector[Trk::phi0] += 2. * M_PI;
2566 }
2567
2568 correctedParameters = parameters->associatedSurface().createUniqueTrackParameters(
2569 parameterVector[Trk::loc1], parameterVector[Trk::loc2], parameterVector[Trk::phi], parameterVector[Trk::theta],
2570 parameterVector[Trk::qOverP], AmgSymMatrix(5)(*parameters->covariance()));
2571
2572 perigee = propagator->propagate(ctx, *correctedParameters, *mperigeeSurface, Trk::oppositeMomentum, false,
2574
2575 if (perigee) {
2576 deltaPhi = 0.;
2577 deltaR = (position - perigee->position()).perp();
2578
2579 if (std::abs(deltaR * M_PI) > std::abs(perigee->parameters()[Trk::d0])) {
2580 deltaPhi = perigee->parameters()[Trk::d0] / deltaR;
2581 }
2582
2583 ATH_MSG_VERBOSE("standaloneFit: corrected perigee impact " << perigee->parameters()[Trk::d0] << " deltaR, deltaPhi "
2584 << deltaR << ", " << deltaPhi);
2585
2586 parameterVector[Trk::phi0] += deltaPhi;
2587 if (parameterVector[Trk::phi0] > M_PI) {
2588 parameterVector[Trk::phi0] -= 2. * M_PI;
2589 } else if (parameterVector[Trk::phi0] < -M_PI) {
2590 parameterVector[Trk::phi0] += 2. * M_PI;
2591 }
2592 correctedParameters = parameters->associatedSurface().createUniqueTrackParameters(
2593 parameterVector[Trk::loc1], parameterVector[Trk::loc2], parameterVector[Trk::phi], parameterVector[Trk::theta],
2594 parameterVector[Trk::qOverP], AmgSymMatrix(5)(*parameters->covariance()));
2595
2596 perigee = propagator->propagate(ctx, *correctedParameters, *mperigeeSurface, Trk::oppositeMomentum, false,
2598 }
2599
2600 if (perigee) {
2601 ATH_MSG_VERBOSE("standaloneFit: restart with impact " << perigee->parameters()[Trk::d0] << " phi0 "
2602 << perigee->parameters()[Trk::phi0]);
2603 }
2604 parameterVector[Trk::qOverP] = parameters->charge() / trackEnergy;
2605 correctedParameters = parameters->associatedSurface().createUniqueTrackParameters(
2606 parameterVector[Trk::loc1], parameterVector[Trk::loc2], parameterVector[Trk::phi], parameterVector[Trk::theta],
2607 parameterVector[Trk::qOverP], AmgSymMatrix(5)(*parameters->covariance()));
2608
2609 parameters = std::move(correctedParameters);
2610 }
2611
2612 // cut if perigee outside indet (but keep endcap halo)
2613 if (!perigee || !m_indetVolume->inside(perigee->position())) {
2614 if (perigee && perigee->position().z() * perigee->momentum().z() < 0. && perigee->momentum().eta() > 2.0) {
2615 ATH_MSG_DEBUG("standaloneFit: halo candidate, perigee at R " << perigee->position().perp() << " Z "
2616 << perigee->position().z());
2617 } else {
2618 ATH_MSG_DEBUG("standaloneFit: perigee outside indet volume");
2620 return nullptr;
2621 }
2622 }
2623 } else {
2624 // otherwise track out from origin (fix bug #54820)
2625 badlyDeterminedCurvature = true;
2626 Amg::Vector3D momentum = parameters->position().unit() * Gaudi::Units::TeV;
2627
2628 std::unique_ptr<const Trk::TrackParameters> trigParameters{m_trackQuery->triggerStationParameters(spectrometerTrack, ctx)};
2629
2630 if (trigParameters) { momentum = trigParameters->position().unit() * Gaudi::Units::TeV; }
2631
2632 if (msgLvl(MSG::VERBOSE)) {
2633 if (trigParameters) {
2634 ATH_MSG_VERBOSE("standaloneFit: imprecise curvature measurement -"
2635 << " start with line from origin to 1st trigger station ");
2636 } else {
2637 ATH_MSG_VERBOSE("standaloneFit: imprecise curvature measurement -"
2638 << " start with line from origin to 1st measurement ");
2639 }
2640 }
2641
2642 std::unique_ptr<Trk::TrackParameters> perigee =
2643 std::make_unique<Trk::Perigee>(mvertex->position(), momentum, 1., *mperigeeSurface);
2644
2645 parameters = m_propagator->propagate(ctx, *perigee, perigee->associatedSurface(), Trk::alongMomentum, false,
2647
2648 if (!parameters) {
2649 ATH_MSG_DEBUG("standaloneFit: failed back extrapolation to perigee");
2650 return nullptr;
2651 }
2652 }
2653
2654 return parameters;
2655 }
#define M_PI
Scalar deltaPhi(const MatrixBase< Derived > &vec) const
Scalar deltaR(const MatrixBase< Derived > &vec) const
#define AmgSymMatrix(dim)
Gaudi::Property< double > m_lineMomentum
Gaudi::Property< double > m_largeImpact
Gaudi::Property< double > m_largeMomentumError
Gaudi::Property< double > m_minEnergy
Gaudi::Property< double > m_zECToroid
virtual std::unique_ptr< NeutralParameters > propagate(const NeutralParameters &parameters, const Surface &sf, PropDirection dir, const BoundaryCheck &bcheck, bool returnCurv=false) const =0
Main propagation method for NeutralParameters.
const Amg::Vector3D & position() const
return position of vertex
Definition Vertex.cxx:63
@ alongMomentum
@ d0
Definition ParamDefs.h:63

◆ finalize()

StatusCode Rec::CombinedMuonTrackBuilder::finalize ( )
overridevirtual

Reimplemented from Rec::CombinedMuonTrackFitter.

Definition at line 117 of file CombinedMuonTrackBuilder.cxx.

117 {
119 double norm = 100. / static_cast<double>(m_countAcceptedStandaloneFit);
120 ATH_MSG_INFO("Finalizing CombinedMuonTrackBuilder:"
121 << endmsg << " " << std::setiosflags(std::ios::fixed) << std::setw(4) << std::setprecision(2)
122 << norm * static_cast<double>(m_countBeamAxis) << "% with beamAxis constraint" << endmsg << " " << std::setw(4)
123 << std::setprecision(2) << norm * static_cast<double>(m_countVertexRegion) << "% with vertexRegion constraint"
124 << endmsg << " " << m_countDegradedStandaloneFit << " degraded standalone fit-chi2 ");
125 }
127 }
#define ATH_MSG_INFO(x)
virtual StatusCode finalize() override

◆ finalTrackBuild()

void Rec::CombinedMuonTrackBuilder::finalTrackBuild ( const EventContext & ctx,
std::unique_ptr< Trk::Track > & track ) const
private

Definition at line 2657 of file CombinedMuonTrackBuilder.cxx.

2657 {
2658 // as a final step:
2659 // refit the track if any holes can be recovered,
2660 // refit with optimization of the spectrometer hit errors,
2661 // add the corresponding TrackSummary to the track
2662 if (msgLevel(MSG::DEBUG)) countAEOTs(*track, " finalTrackBuilt input ");
2663 if (!m_muonHoleRecovery.empty()) {
2664 // chi2 before recovery
2665 double chi2Before = normalizedChi2(*track);
2666
2667 ATH_MSG_VERBOSE(" perform spectrometer hole recovery procedure... ");
2668
2669 std::unique_ptr<Trk::Track> recoveredTrack{m_muonHoleRecovery->recover(*track, ctx)};
2670
2671 // if (!checkTrack("finalTrackBuild1", recoveredTrack.get())) {
2672 // final track lost, this should not happen
2673 // m_messageHelper->printWarning(44);
2674 // As discussed in ATLASRECTS-7603, we want to suppress this until we can work on it
2675 // Keeping it here so we don't forget.
2676 // FIXME!
2677
2678 if (checkTrack("finalTrackBuild1", recoveredTrack.get())) {
2679 double chi2After = normalizedChi2(*recoveredTrack);
2680 if (chi2After < m_badFitChi2 || chi2After < chi2Before + 0.1) {
2681 track.swap(recoveredTrack);
2682 } else {
2683 ATH_MSG_VERBOSE(" track rejected by recovery as chi2 " << chi2After << " compared to " << chi2Before);
2684
2685 if (chi2Before > m_badFitChi2) {
2686 track.reset();
2687 return;
2688 }
2689 }
2690 }
2691 ATH_MSG_VERBOSE(" finished hole recovery procedure ");
2692 }
2693 /*
2694 * DO NOT REMOVE THIS CODE BLOCK AS IT WILL BE NEEDED IN A FUTURE MR!
2695 if (!m_muonHoleRecovery.empty()) {
2696 ATH_MSG_VERBOSE(" perform spectrometer hole recovery procedure... ");
2697 using MSTrackRecovery = Muon::IMuonHoleRecoveryTool::MSTrackRecovery;
2698 MSTrackRecovery recoverResult{};
2699 constexpr unsigned int max_itr = 3;
2700 unsigned int num_itr{0};
2701 do {
2702 const double chi2Before = normalizedChi2(*track);
2703 recoverResult = m_muonHoleRecovery->recover(ctx,*track);
2704 if (!recoverResult.track) {
2705 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" track got lost during hole recovery. That should not happen");
2706 break;
2707 }
2708 if (!checkTrack("holeRecovery", recoverResult.track.get())){
2709 m_messageHelper->printWarning(44);
2710 break;
2711 }
2712 if (recoverResult.new_meas) {
2713 recoverResult.track = fit(ctx, *recoverResult.track, true, Trk::muon);
2714 if (!recoverResult.track) {
2715 ATH_MSG_VERBOSE(__FILE__<<":"<<__LINE__<<" track got lost during refit of recovery.");
2716 break;
2717 }
2718 const double chi2After = normalizedChi2(*recoverResult.track);
2719 if (chi2After < chi2Before) {
2720 track.swap(recoverResult.track);
2721 ATH_MSG_VERBOSE("Recovered track has better quality... old chi2:"<<chi2Before<<". New chi2: "<<chi2After
2722 <<std::endl<<m_printer->printMeasurements(*recoverResult.track)<<std::endl
2723 <<std::endl<<m_printer->printMeasurements(*track));
2724 } else break;
2725 } else {
2726 track.swap(recoverResult.track);
2727 }
2728 } while(recoverResult.new_meas && (++num_itr) <= max_itr);
2729 ATH_MSG_VERBOSE(" finished hole recovery procedure ");
2730 }
2731 */
2732 // final fit with optimized spectrometer errors
2733 if (!m_muonErrorOptimizer.empty() && !track->info().trackProperties(Trk::TrackInfo::StraightTrack) &&
2734 countAEOTs(*track, " before optimize ") == 0) {
2735 ATH_MSG_VERBOSE(" perform spectrometer error optimization... ");
2736 std::unique_ptr<Trk::Track> optimizedTrack = m_muonErrorOptimizer->optimiseErrors(*track, ctx);
2737 if (checkTrack("finalTrackBuild2", optimizedTrack.get())) {
2738 track.swap(optimizedTrack);
2739 if (msgLevel(MSG::DEBUG)) countAEOTs(*track, " finalTrackBuilt alignment errors Track ");
2740 }
2741 }
2742
2743 // add the track summary
2744 m_trackSummary->updateTrack(ctx, *track);
2745 }
ToolHandle< Muon::IMuonHoleRecoveryTool > m_muonHoleRecovery
ToolHandle< Muon::IMuonErrorOptimisationTool > m_muonErrorOptimizer
Gaudi::Property< double > m_badFitChi2
ToolHandle< Trk::ITrackSummaryTool > m_trackSummary
double normalizedChi2(const Trk::Track &track) const

◆ fit() [1/3]

std::unique_ptr< Trk::Track > Rec::CombinedMuonTrackFitter::fit ( const EventContext & ctx,
const Trk::MeasurementSet & measurementSet,
const Trk::TrackParameters & perigeeStartValue,
const Trk::RunOutlierRemoval runOutlier,
const Trk::ParticleHypothesis particleHypothesis ) const
protectedinherited

fit a set of MeasurementBase objects with starting value for perigeeParameters

Definition at line 317 of file CombinedMuonTrackFitter.cxx.

320 {
321 // check valid particleHypothesis
322 if (particleHypothesis != Trk::muon && particleHypothesis != Trk::nonInteracting) {
323 // invalid particle hypothesis
324 std::stringstream ss;
325 ss << particleHypothesis;
326 m_messageHelper->printWarning(31, ss.str());
327 return nullptr;
328 }
329
330 // select straightLine fitter when magnets downstream of leading measurement are off
331 MagField::AtlasFieldCache fieldCache;
332 // Get field cache object
333 if (!loadMagneticField(ctx, fieldCache)) return nullptr;
334
335 const Trk::ITrackFitter* fitter = m_fitter.get();
336 if (!fieldCache.toroidOn() || std::abs(perigeeStartValue.position().z()) > m_zECToroid) {
337 fitter = m_fitterSL.get();
338 ATH_MSG_VERBOSE(" fit (track refit method): select SL fitter ");
339 }
340
341 // redo ROTs: ID, CROT and MDT specific treatments
342 // if (m_redoRots) redoRots(track);
343
344 // calo association (if relevant)
345
346 // create Perigee if starting parameters given for a different surface type
347 std::unique_ptr<Trk::TrackParameters> perigee = perigeeStartValue.uniqueClone();
348 std::unique_ptr<Trk::PerigeeSurface> perigeeSurface;
349
350 if (perigee->surfaceType() != Trk::SurfaceType::Perigee) {
351 Amg::Vector3D origin(perigeeStartValue.position());
352 perigeeSurface = std::make_unique<Trk::PerigeeSurface>(origin);
353
354 perigee = std::make_unique<Trk::Perigee>(perigeeStartValue.position(), perigeeStartValue.momentum(), perigeeStartValue.charge(),
355 *perigeeSurface);
356 }
357
358 // FIT
359 std::unique_ptr<Trk::Track> fittedTrack(fitter->fit(ctx, measurementSet, *perigee, false, particleHypothesis));
360
361 if (!checkTrack("fitInterface2", fittedTrack.get())) { return nullptr; }
362
363 // eventually this whole tool will use unique_ptrs
364 // in the meantime, this allows the MuonErrorOptimisationTool and MuonRefitTool to use them
365
366 // track cleaning
367 if (runOutlier) {
368 // fit with optimized spectrometer errors
369
370 if (!m_muonErrorOptimizer.empty() && !fittedTrack->info().trackProperties(Trk::TrackInfo::StraightTrack) &&
371 optimizeErrors(ctx, *fittedTrack)) {
372 ATH_MSG_VERBOSE(" perform spectrometer error optimization after cleaning ");
373 std::unique_ptr<Trk::Track> optimizedTrack = m_muonErrorOptimizer->optimiseErrors(*fittedTrack, ctx);
374 if (checkTrack("fitInterface2Opt", optimizedTrack.get())) {
375 fittedTrack.swap(optimizedTrack);
376 if (msgLevel(MSG::DEBUG)) countAEOTs(*fittedTrack, " fit mstSet scaled errors Track ");
377 }
378
379 }
380
381 // chi2 before clean
382 double chi2Before = normalizedChi2(*fittedTrack);
383
384 // muon cleaner
385 ATH_MSG_VERBOSE(__FILE__<<":"<<__LINE__<<" perform track cleaning... ");
386
387 if (msgLevel(MSG::DEBUG)) countAEOTs(*fittedTrack, " fit mstSet before cleaning ");
388
389 std::unique_ptr<Trk::Track> cleanTrack = m_cleaner->clean(*fittedTrack, ctx);
390
391 if (msgLevel(MSG::DEBUG)) countAEOTs(*cleanTrack, " fit mstSet clean Track ");
392
393 if (!checkTrack("fitInterface2Cleaner", cleanTrack.get())) { cleanTrack.reset(); }
394
395 if (!cleanTrack) {
396 if (m_allowCleanerVeto && chi2Before > m_badFitChi2) {
397 ATH_MSG_DEBUG(" cleaner veto B");
399 fittedTrack.reset();
400 } else {
401 ATH_MSG_DEBUG(" keep original extension track despite cleaner veto ");
402 }
403 } else if (!(*cleanTrack->perigeeParameters() == *fittedTrack->perigeeParameters())) {
404 double chi2After = normalizedChi2(*cleanTrack);
405 if (chi2After < m_badFitChi2 || chi2After < chi2Before) {
406 ATH_MSG_VERBOSE(" found and removed spectrometer outlier(s) ");
407 fittedTrack.swap(cleanTrack);
408 } else {
409 ATH_MSG_VERBOSE(" keep original track despite cleaning ");
410 }
411 }
412
413 // FIXME: provide indet cleaner
414 ATH_MSG_VERBOSE(" Finished cleaning");
415 }
416 // have to use release until the whole code uses unique_ptr
417 return fittedTrack;
418 }
static Double_t ss
bool fit(const LArSamples::AbsShape &data, const AbsShape &reference, double &k, double &deltaT, double &chi2, const ScaledErrorData *sed=0) const
bool optimizeErrors(const EventContext &ctx, Trk::Track &track) const
ToolHandle< Muon::IMuonTrackCleaner > m_cleaner
ToolHandle< Trk::ITrackFitter > m_fitterSL
ToolHandle< Trk::ITrackFitter > m_fitter
Gaudi::Property< bool > m_allowCleanerVeto
double charge() const
Returns the charge.
const ShapeFitter * fitter

◆ fit() [2/3]

std::unique_ptr< Trk::Track > Rec::CombinedMuonTrackFitter::fit ( const EventContext & ctx,
const Trk::Track & indetTrack,
Trk::Track & extrapolatedTrack,
const Trk::RunOutlierRemoval runOutlier,
const Trk::ParticleHypothesis particleHypothesis ) const
protectedinherited

combined muon fit

Definition at line 421 of file CombinedMuonTrackFitter.cxx.

423 {
424 // check valid particleHypothesis
425 if (particleHypothesis != Trk::muon && particleHypothesis != Trk::nonInteracting) {
426 // invalid particle hypothesis
427 std::stringstream ss;
428 ss << particleHypothesis;
429 m_messageHelper->printWarning(32, ss.str());
430 return nullptr;
431 }
432
433 // select straightLine fitter when solenoid and toroid are off
434 const Trk::ITrackFitter* fitter = m_fitter.get();
435 MagField::AtlasFieldCache fieldCache;
436 // Get field cache object
437 if (!loadMagneticField(ctx, fieldCache)) return nullptr;
438
439 if (!fieldCache.toroidOn() && !fieldCache.solenoidOn()) {
440 fitter = m_fitterSL.get();
441 ATH_MSG_VERBOSE(" fit (combined muon fit method): select SL fitter ");
442 }
443
444 // redo ROTs: ID, CROT and MDT specific treatments
445
446 // calo association (for now just WARN if missing)
447 if (particleHypothesis == Trk::muon && !m_trackQuery->isCaloAssociated(extrapolatedTrack, ctx)) {
448 // combined muon track is missing the TSOS's describing calorimeter association
449 m_messageHelper->printWarning(33);
450 }
451
452 // Updates the calo TSOS with the ones from TG+corrections
453 if (m_updateWithCaloTG && !m_useCaloTG && particleHypothesis == Trk::muon) {
454 ATH_MSG_VERBOSE("Updating Calorimeter TSOS in Muon Combined Fit ...");
455 m_materialUpdator->updateCaloTSOS(indetTrack, extrapolatedTrack);
456 }
457
458 // FIT
459 ATH_MSG_VERBOSE(" perform combined fit... " << std::endl
460 << m_printer->print(indetTrack) << std::endl
461 << m_printer->print(extrapolatedTrack));
462
463 std::unique_ptr<Trk::Track> fittedTrack(fitter->fit(ctx, indetTrack, extrapolatedTrack, false, particleHypothesis));
464
465 if (!fittedTrack) return nullptr;
466 // track cleaning
467 if (runOutlier) {
468 // fit with optimized spectrometer errors
469
470 if (!m_muonErrorOptimizer.empty() && !fittedTrack->info().trackProperties(Trk::TrackInfo::StraightTrack) &&
471 optimizeErrors(ctx, *fittedTrack)) {
472 ATH_MSG_VERBOSE(" perform spectrometer error optimization after cleaning ");
473 std::unique_ptr<Trk::Track> optimizedTrack = m_muonErrorOptimizer->optimiseErrors(*fittedTrack, ctx);
474 if (checkTrack("Error opt", optimizedTrack.get()) &&
475 normalizedChi2(*optimizedTrack) < normalizedChi2(*fittedTrack)) {
476 fittedTrack.swap(optimizedTrack);
477 if (msgLevel(MSG::DEBUG)) countAEOTs(*fittedTrack, " cbfit scaled errors Track ");
478 }
479 }
480
481 // chi2 before clean
482 double chi2Before = normalizedChi2(*fittedTrack);
483
484 // muon cleaner
485 ATH_MSG_VERBOSE(__FILE__<<":"<<__LINE__<<" perform track cleaning... " << m_printer->print(*fittedTrack) << std::endl
486 << m_printer->printStations(*fittedTrack));
487
488 if (msgLevel(MSG::DEBUG)) { countAEOTs(*fittedTrack, " cb before clean Track "); }
489 std::unique_ptr<Trk::Track> cleanTrack = m_cleaner->clean(*fittedTrack, ctx);
490 if (cleanTrack && msgLevel(MSG::DEBUG)) { countAEOTs(*cleanTrack, " cb after clean Track "); }
491
492 if (!cleanTrack) {
493 if (m_allowCleanerVeto && chi2Before > m_badFitChi2) {
494 ATH_MSG_DEBUG("cleaner veto C "<<chi2Before<<" Cut: "<<m_badFitChi2);
496 fittedTrack.reset();
497 } else {
498 ATH_MSG_DEBUG(" keep original combined track despite cleaner veto ");
499 }
500 } else if (!(*cleanTrack->perigeeParameters() == *fittedTrack->perigeeParameters())) {
501 double chi2After = normalizedChi2(*cleanTrack);
502 if (chi2After < m_badFitChi2 || chi2After < chi2Before) {
503 ATH_MSG_VERBOSE(" found and removed spectrometer outlier(s) ");
504 fittedTrack.swap(cleanTrack);
505 } else {
506 ATH_MSG_VERBOSE(" keep original track despite cleaning ");
507 }
508 }
509
510 // FIXME: provide indet cleaner
511 ATH_MSG_VERBOSE(" finished cleaning");
512 }
513 // have to use release until the whole code uses unique_ptr
514 return fittedTrack;
515 }

◆ fit() [3/3]

std::unique_ptr< Trk::Track > Rec::CombinedMuonTrackFitter::fit ( const EventContext & ctx,
const Trk::Track & track,
const Trk::RunOutlierRemoval runOutlier,
const Trk::ParticleHypothesis particleHypothesis ) const
overridevirtualinherited

Definition at line 148 of file CombinedMuonTrackFitter.cxx.

150 {
151 ATH_MSG_VERBOSE(" fit() " << m_printer->print(track) << std::endl
152 << m_printer->printMeasurements(track) << std::endl
153 << m_printer->printStations(track));
154 // check valid particleHypothesis
155 if (particleHypothesis != Trk::muon && particleHypothesis != Trk::nonInteracting) {
156 // invalid particle hypothesis
157 std::stringstream ss;
158 ss << particleHypothesis;
159 m_messageHelper->printWarning(29, ss.str());
160 return nullptr;
161 }
162
163 // check if combined or subsystem track
164 bool isCombined = m_trackQuery->isCombined(track, ctx);
165 // select straightLine fitter when magnets downstream of leading measurement are off
166 const Trk::ITrackFitter* fitter = m_fitter.get();
167 MagField::AtlasFieldCache fieldCache;
168 // Get field cache object
169
170 if (!loadMagneticField(ctx, fieldCache)) return nullptr;
171
172 if (!fieldCache.toroidOn() && !(isCombined && fieldCache.solenoidOn())) {
173 fitter = m_fitterSL.get();
174 ATH_MSG_VERBOSE(" fit (track refit method): select SL fitter ");
175 }
176
177 // redo ROTs: ID, CROT and MDT specific treatments
178 // if (m_redoRots) redoRots(track);
179
180 // perform fit after ensuring calo is associated for combined tracks
181 // calo association for combined tracks (WARN if missing from input)
182 std::unique_ptr<Trk::Track> fittedTrack = std::make_unique<Trk::Track>(track);
183 if (isCombined && particleHypothesis == Trk::muon && !m_trackQuery->isCaloAssociated(*fittedTrack, ctx)) {
184 // about to add the TSOS's describing calorimeter association to a combined muon;
185 ATH_MSG_VERBOSE( "fit:: about to add the TSOS's describing calorimeter association to a combined muon" );
186
187 auto combinedTSOS = std::make_unique<Trk::TrackStates>();
188
189 combinedTSOS->reserve(fittedTrack->trackStateOnSurfaces()->size() + 3);
190 bool caloAssociated = false;
191
192 // run-2 schema, update default eloss with parametrised value
193 if (m_useCaloTG) {
194 ATH_MSG_VERBOSE("Updating Calorimeter TSOS in Muon Combined (re)Fit ...");
195 m_materialUpdator->updateCaloTSOS(*fittedTrack);
196 caloAssociated = true;
197 }
198
199 for (const Trk::TrackStateOnSurface* in_tsos : *fittedTrack->trackStateOnSurfaces()) {
200 if (caloAssociated) {
201 combinedTSOS->push_back(in_tsos->clone());
202 } else if ((in_tsos->measurementOnTrack() && m_indetVolume->inside(in_tsos->measurementOnTrack()->globalPosition())) ||
203 (in_tsos->trackParameters() && m_indetVolume->inside(in_tsos->trackParameters()->position()))) {
204 combinedTSOS->push_back(in_tsos->clone());
205 } else {
206 std::unique_ptr<const Trk::TrackStateOnSurface> tsos = m_caloTSOS->innerTSOS(ctx, *fittedTrack->perigeeParameters());
207 if (tsos) {
208 combinedTSOS->push_back(std::move(tsos));
209 const Trk::TrackParameters* parameters = combinedTSOS->back()->trackParameters();
210 if (in_tsos->type(Trk::TrackStateOnSurface::CaloDeposit)) {
211 combinedTSOS->push_back(in_tsos->clone());
212 tsos = m_caloTSOS->outerTSOS(ctx, *parameters);
213 if (tsos) combinedTSOS->push_back(std::move(tsos));
214 } else {
215 tsos = m_caloTSOS->middleTSOS(ctx, *parameters);
216 if (tsos) combinedTSOS->push_back(std::move(tsos));
217 tsos = m_caloTSOS->outerTSOS(ctx, *parameters);
218 if (tsos) combinedTSOS->push_back(std::move(tsos));
219 combinedTSOS->push_back(in_tsos->clone());
220 }
221 }
222 caloAssociated = true;
223 }
224 }
225
226 std::unique_ptr<Trk::Track> combinedTrack = std::make_unique<Trk::Track>(fittedTrack->info(), std::move(combinedTSOS), nullptr);
227
228 if (msgLevel(MSG::DEBUG)) countAEOTs(*combinedTrack, " combinedTrack track before fit ");
229
230 caloAssociated = m_trackQuery->isCaloAssociated(*combinedTrack, ctx);
231
232 // Updates the calo TSOS with the ones from TG+corrections
233 if (m_updateWithCaloTG && !m_useCaloTG && particleHypothesis == Trk::muon) {
234 ATH_MSG_VERBOSE("Updating Calorimeter TSOS in Muon Combined (re)Fit ...");
235 m_materialUpdator->updateCaloTSOS(*combinedTrack);
236 }
237 // FIT
238 fittedTrack = fitter->fit(ctx, *combinedTrack, false, particleHypothesis);
239 } else {
240 // Updates the calo TSOS with the ones from TG+corrections
241 if (m_updateWithCaloTG && !m_useCaloTG && particleHypothesis == Trk::muon) {
242 ATH_MSG_VERBOSE("Updating Calorimeter TSOS in Muon Standalone Fit ...");
243 m_materialUpdator->updateCaloTSOS(*fittedTrack);
244 }
245
246 // FIT
247 fittedTrack = fitter->fit(ctx, *fittedTrack, false, particleHypothesis);
248 }
249
250 // quit if fit has failed
251 if (!fittedTrack) return nullptr;
252
253
254 if (!checkTrack("fitInterface1", fittedTrack.get())) return nullptr;
255
256
257 // eventually this whole tool will use unique_ptrs
258 // in the meantime, this allows the MuonErrorOptimisationTool and MuonRefitTool to use them
259 // track cleaning
260 if (runOutlier) {
261 // fit with optimized spectrometer errors
262
263 const double chi2BeforeOptimizer = normalizedChi2(*fittedTrack);
264 if (!m_muonErrorOptimizer.empty() && !fittedTrack->info().trackProperties(Trk::TrackInfo::StraightTrack) &&
265 optimizeErrors(ctx, *fittedTrack)) {
266 ATH_MSG_VERBOSE(" perform spectrometer error optimization after cleaning ");
267 std::unique_ptr<Trk::Track> optimizedTrack = m_muonErrorOptimizer->optimiseErrors(*fittedTrack, ctx);
268 if (checkTrack("fitInterface1Opt", optimizedTrack.get()) && chi2BeforeOptimizer > normalizedChi2(*optimizedTrack)) {
269 fittedTrack.swap(optimizedTrack);
270 if (msgLevel(MSG::DEBUG)) countAEOTs(*fittedTrack, " re fit scaled errors Track ");
271 }
272 }
273
274 // chi2 before clean
275 const double chi2Before = normalizedChi2(*fittedTrack);
276
277 // muon cleaner
278 ATH_MSG_VERBOSE(__FILE__<<":"<<__LINE__<<" perform track cleaning... " << m_printer->print(*fittedTrack) << std::endl
279 << m_printer->printStations(*fittedTrack));
280
281 if (msgLevel(MSG::DEBUG)) countAEOTs(*fittedTrack, " refit: fitted track before cleaning ");
282
283 std::unique_ptr<Trk::Track> cleanTrack = m_cleaner->clean(*fittedTrack, ctx);
284
285 if (msgLevel(MSG::DEBUG)) countAEOTs(*cleanTrack, " refit: after cleaning");
286
287 if (!checkTrack("fitInterface1Cleaner", cleanTrack.get())) { cleanTrack.reset(); }
288
289 if (!cleanTrack) {
290 if (m_allowCleanerVeto && chi2Before > m_badFitChi2) {
291 ATH_MSG_DEBUG(" cleaner veto A "<<chi2Before<<" "<<m_badFitChi2<<" "<<m_printer->printMeasurements(*fittedTrack) );
293 fittedTrack.reset();
294 } else {
295 ATH_MSG_DEBUG(" keep original standalone track despite cleaner veto ");
296 }
297 } else if (!(*cleanTrack->perigeeParameters() == *fittedTrack->perigeeParameters())) {
298 double chi2After = normalizedChi2(*cleanTrack);
299
300 if (chi2After < m_badFitChi2 || chi2After < chi2Before) {
301 ATH_MSG_VERBOSE(" found and removed spectrometer outlier(s) ");
302 fittedTrack.swap(cleanTrack);
303 } else {
304 ATH_MSG_VERBOSE(" keep original track despite cleaning ");
305 }
306 }
307
308 // FIXME: provide indet cleaner
309 if (fittedTrack) {
310 ATH_MSG_VERBOSE(" finished track cleaning... " << m_printer->print(*fittedTrack) << std::endl
311 << m_printer->printStations(*fittedTrack));
312 }
313 }
314 return fittedTrack;
315 }

◆ getCaloTSOSfromMatProvider()

std::vector< std::unique_ptr< const Trk::TrackStateOnSurface > > Rec::CombinedMuonTrackBuilder::getCaloTSOSfromMatProvider ( const Trk::TrackParameters & track_params,
const Trk::Track & me_track ) const
private

Helper method to retrieve the CaloTSO from the Material provider in a memory safe way.

Definition at line 3153 of file CombinedMuonTrackBuilder.cxx.

3154 {
3155 std::vector<std::unique_ptr<const Trk::TrackStateOnSurface>> to_ret;
3156 std::unique_ptr<std::vector<const Trk::TrackStateOnSurface*>> tsos_vec{m_materialUpdator->getCaloTSOS(track_params, me_track)};
3157 if (tsos_vec) {
3158 to_ret.reserve(tsos_vec->size());
3159 for (const Trk::TrackStateOnSurface* tsos : *tsos_vec) to_ret.emplace_back(tsos);
3160 }
3161 return to_ret;
3162 }

◆ getVolume()

const Trk::TrackingVolume * Rec::CombinedMuonTrackBuilder::getVolume ( const EventContext & ctx,
const std::string && vol_name ) const
private

Tracking geometry is provided by the TrackingGeometryAlg

Definition at line 3144 of file CombinedMuonTrackBuilder.cxx.

3144 {
3146 SG::ReadCondHandle<Trk::TrackingGeometry> handle(m_trackingGeometryReadKey, ctx);
3147 if (!handle.isValid()) {
3148 ATH_MSG_WARNING("Could not retrieve a valid tracking geometry");
3149 return nullptr;
3150 }
3151 return handle.cptr()->trackingVolume(vol_name);
3152 }
SG::ReadCondHandleKey< Trk::TrackingGeometry > m_trackingGeometryReadKey

◆ indetExtension()

std::unique_ptr< Trk::Track > Rec::CombinedMuonTrackBuilder::indetExtension ( const EventContext & ctx,
const Trk::Track & indetTrack,
const Trk::MeasurementSet & spectrometerMeas,
std::unique_ptr< Trk::TrackParameters > innerParameters,
std::unique_ptr< Trk::TrackParameters > middleParameters,
std::unique_ptr< Trk::TrackParameters > outerParameters ) const
overridevirtual

ICombinedMuonTrackBuilder interface: build and fit indet track extended to include MS Measurement set.

Adds material effects as appropriate plus calo energy-loss treatment

Need to check with Will whether this propagator is actually needed or not

Implements Rec::ICombinedMuonTrackBuilder.

Definition at line 409 of file CombinedMuonTrackBuilder.cxx.

414 {
415 if (msgLvl(MSG::VERBOSE)) {
416 msg(MSG::VERBOSE) << endmsg << "indetExtension fit:: " << std::setiosflags(std::ios::fixed);
417
418 if (innerParameters || middleParameters || outerParameters) {
419 msg(MSG::VERBOSE) << " parameters at R,Z ";
420
421 if (innerParameters) {
422 msg(MSG::VERBOSE) << "I:" << std::setw(5) << std::setprecision(0) << innerParameters->position().perp() << ","
423 << std::setw(5) << std::setprecision(0) << innerParameters->position().z() << " ";
424 }
425
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() << " ";
429 }
430
431 if (outerParameters) {
432 msg(MSG::VERBOSE) << "O:" << std::setw(6) << std::setprecision(0) << outerParameters->position().perp() << ","
433 << std::setw(5) << std::setprecision(0) << outerParameters->position().z();
434 }
435
436 msg(MSG::VERBOSE) << " with P ";
437
438 if (innerParameters) {
439 msg(MSG::VERBOSE) << std::setw(9) << std::setprecision(3) << innerParameters->momentum().mag() / Gaudi::Units::GeV;
440 }
441
442 if (middleParameters) {
443 msg(MSG::VERBOSE) << std::setw(9) << std::setprecision(3) << middleParameters->momentum().mag() / Gaudi::Units::GeV;
444 }
445
446 if (outerParameters) {
447 msg(MSG::VERBOSE) << std::setw(9) << std::setprecision(3) << outerParameters->momentum().mag() / Gaudi::Units::GeV;
448 }
449
450 msg(MSG::VERBOSE) << " (GeV)" << endmsg;
451 } else {
452 msg(MSG::VERBOSE) << " without parameters" << endmsg;
453 }
454 }
455
456 // propagate appropriate trackParameters to front, back and middle measurements
457 // fail when solenoid off and toroid on (as extrapolation from ID is not the correct strategy)
458 const Trk::IPropagator* propagator = m_propagatorSL.get();
459
460 MagField::AtlasFieldCache fieldCache;
461 // Get field cache object
462 if (!loadMagneticField(ctx, fieldCache)) return nullptr;
463 if (fieldCache.toroidOn()) {
464 // fail when solenoid off and toroid on - as extrapolation from ID is not the correct strategy
465 // for material effects, fit starting value etc
466 if (!fieldCache.solenoidOn()) {
467 ATH_MSG_VERBOSE("indetExtension: method switched off when solenoid 'off' / toroid 'on'");
468 return nullptr;
469 }
470
473 propagator = m_propagator.get();
474 }
475
476 std::unique_ptr<Trk::TrackParameters> frontParameters, backParameters;
477
478 if (innerParameters) {
479 if (innerParameters->associatedSurface() == spectrometerMeasurements.front()->associatedSurface()) {
480 frontParameters = innerParameters->uniqueClone();
481 } else {
482 // TSoS will own this
483 frontParameters = propagator->propagate(ctx, *innerParameters, spectrometerMeasurements.front()->associatedSurface(),
485 }
486 } else if (middleParameters) {
487 if (middleParameters->associatedSurface() == spectrometerMeasurements.front()->associatedSurface()) {
488 frontParameters = middleParameters->uniqueClone();
489 } else {
490 // TSoS will own this
491 frontParameters = propagator->propagate(ctx, *middleParameters, spectrometerMeasurements.front()->associatedSurface(),
493 }
494 }
495
496 if (outerParameters) {
497 if (outerParameters->associatedSurface() == spectrometerMeasurements.back()->associatedSurface()) {
498 backParameters = outerParameters->uniqueClone();
499 } else {
500 // TSoS will own this
501 backParameters = propagator->propagate(ctx, *outerParameters, spectrometerMeasurements.back()->associatedSurface(),
503 }
504 } else if (middleParameters) {
505 if (middleParameters->associatedSurface() == spectrometerMeasurements.back()->associatedSurface()) {
506 backParameters = middleParameters->uniqueClone();
507 } else {
508 // TSoS will own this
509 backParameters = propagator->propagate(ctx, *middleParameters, spectrometerMeasurements.back()->associatedSurface(),
511 }
512 }
513
514 // find middle measurement
515 std::unique_ptr<Trk::TrackParameters> midParameters;
516 const Trk::MeasurementBase* midMeasurement = nullptr;
517
518 if (middleParameters && innerParameters && outerParameters) {
519 Amg::Vector3D direction = (outerParameters->position() - innerParameters->position()).unit();
520 double midDistance = 0.5 * direction.dot(outerParameters->position() - innerParameters->position());
521 double previousDistance = 0.;
522
523 Trk::MeasurementSet::const_iterator m = spectrometerMeasurements.begin();
524 for (++m; m != spectrometerMeasurements.end(); ++m) {
525 double distance = direction.dot((**m).globalPosition() - innerParameters->position());
526 if (distance < midDistance) {
527 previousDistance = distance;
528 } else {
529 if (midDistance - previousDistance < distance - midDistance) --m;
530 // TSoS will own this
531 midParameters = m_propagator->propagate(ctx, *middleParameters, (**m).associatedSurface(), Trk::anyDirection, false,
533
534 if (midParameters) midMeasurement = *m;
535 break;
536 }
537 }
538 }
539
540 // create muon track from spectrometer measurements
541 std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes> typeM;
543 std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes> typeP;
546
547 auto trackStateOnSurfaces = std::make_unique<Trk::TrackStates>();
548
549 trackStateOnSurfaces->reserve(spectrometerMeasurements.size());
550
551 // append the spectrometer measurements
552 for (const Trk::MeasurementBase* const in_meas : spectrometerMeasurements) {
553 //if the unique_ptr has been moved, it will be nullptr after
554 //cppcheck-suppress accessMoved
555 if (frontParameters) {
556 trackStateOnSurfaces->push_back(
557 new Trk::TrackStateOnSurface(in_meas->uniqueClone(), std::move(frontParameters), nullptr, typeP));
558 } else if (in_meas == midMeasurement) {
559 trackStateOnSurfaces->push_back(
560 new Trk::TrackStateOnSurface(in_meas->uniqueClone(), std::move(midParameters), nullptr, typeP));
561 } else if (backParameters && in_meas == spectrometerMeasurements.back()) {
562 trackStateOnSurfaces->push_back(
563 new Trk::TrackStateOnSurface(in_meas->uniqueClone(), std::move(backParameters), nullptr, typeP));
564 } else {
565 trackStateOnSurfaces->push_back(
566 new Trk::TrackStateOnSurface(in_meas->uniqueClone(), nullptr, nullptr, typeM));
567 }
568 }
569
570 Trk::TrackInfo trackInfo(Trk::TrackInfo::Unknown, Trk::muon);
571
572 Trk::Track muonTrack(trackInfo, std::move(trackStateOnSurfaces), nullptr);
573 if (msgLevel(MSG::DEBUG)) countAEOTs(muonTrack, " in detExtension muonTrack ");
574 // perform combined fit
575 ATH_MSG_VERBOSE("Calling combinedFit from " << __func__ << " at line " << __LINE__);
576 std::unique_ptr<Trk::Track> combinedTrack{combinedFit(ctx, indetTrack, muonTrack, muonTrack)};
577 return combinedTrack;
578 }
virtual std::unique_ptr< Trk::Track > combinedFit(const EventContext &ctx, const Trk::Track &indetTrack, const Trk::Track &extrapolatedTrack, const Trk::Track &spectrometerTrack) const override
ICombinedMuonTrackBuilder interface: build and fit combined ID/Calo/MS track.
@ Parameter
This TSOS contains a Trk::ParameterBase.
MsgStream & msg
Definition testRead.cxx:32

◆ initialize()

StatusCode Rec::CombinedMuonTrackBuilder::initialize ( )
overridevirtual

Reimplemented from Rec::CombinedMuonTrackFitter.

Definition at line 63 of file CombinedMuonTrackBuilder.cxx.

63 {
65 ATH_MSG_DEBUG("Initializing CombinedMuonTrackBuilder.");
66 ATH_CHECK(m_caloEnergyParam.retrieve());
67 ATH_MSG_DEBUG("Retrieved tool " << m_caloEnergyParam);
68
69 m_redoRots = !m_cscRotCreator.empty() || !m_muClusterRotCreator.empty() || !m_mdtRotCreator.empty();
70 ATH_CHECK(m_cscRotCreator.retrieve(DisableTool{m_cscRotCreator.empty()}));
71 ATH_CHECK(m_muClusterRotCreator.retrieve(DisableTool{m_muClusterRotCreator.empty()}));
72 ATH_CHECK(m_mdtRotCreator.retrieve(DisableTool{m_mdtRotCreator.empty()}));
73
74 ATH_CHECK(m_materialAllocator.retrieve(DisableTool{m_materialAllocator.empty()}));
75 ATH_CHECK(m_extrapolator.retrieve());
76 ATH_MSG_DEBUG("Retrieved tool " << m_extrapolator);
77
78 ATH_CHECK(m_muonHoleRecovery.retrieve(DisableTool{m_muonHoleRecovery.empty()}));
79
80
81 ATH_CHECK(m_propagator.retrieve());
82 ATH_MSG_DEBUG("Retrieved tool " << m_propagator);
83 ATH_CHECK(m_propagatorSL.retrieve());
84 ATH_MSG_DEBUG("Retrieved tool " << m_propagatorSL);
85
86
88
89
90 // create beamAxis and vertexRegion for constrained (projective) track fits
91 Amg::Vector3D origin(0., 0., 0.);
92 m_perigeeSurface = std::make_unique<Trk::PerigeeSurface>(origin);
93
94 AmgSymMatrix(3) beamAxisCovariance;
95 beamAxisCovariance.setZero();
96 (beamAxisCovariance)(0, 0) = m_vertex2DSigmaRPhi * m_vertex2DSigmaRPhi;
97 (beamAxisCovariance)(1, 1) = m_vertex2DSigmaRPhi * m_vertex2DSigmaRPhi;
98 (beamAxisCovariance)(2, 2) = m_vertex2DSigmaZ * m_vertex2DSigmaZ;
99 m_beamAxis = std::make_unique<Trk::RecVertex>(origin, beamAxisCovariance);
100
101 AmgSymMatrix(3) vertexRegionCovariance;
102 vertexRegionCovariance.setZero();
103 (vertexRegionCovariance)(0, 0) = m_vertex3DSigmaRPhi * m_vertex3DSigmaRPhi;
104 (vertexRegionCovariance)(1, 1) = m_vertex3DSigmaRPhi * m_vertex3DSigmaRPhi;
105 (vertexRegionCovariance)(2, 2) = m_vertex3DSigmaZ * m_vertex3DSigmaZ;
106 m_vertex = std::make_unique<Trk::RecVertex>(origin, vertexRegionCovariance);
107 ATH_CHECK(m_alignUncertTool_theta.retrieve(DisableTool{!m_addIDMSerrors}));
108 ATH_CHECK(m_alignUncertTool_phi.retrieve(DisableTool{!m_addIDMSerrors}));
109
110#ifndef NDEBUG
111 ATH_MSG_DEBUG(" vertex region: ");
112 m_vertex->dump(msg(MSG::DEBUG));
113#endif
114 return StatusCode::SUCCESS;
115 }
#define ATH_CHECK
Evaluate an expression and check for errors.
ToolHandle< Muon::IMuonClusterOnTrackCreator > m_cscRotCreator
Gaudi::Property< double > m_vertex3DSigmaZ
ToolHandle< Muon::IMdtDriftCircleOnTrackCreator > m_mdtRotCreator
std::unique_ptr< const Trk::RecVertex > m_beamAxis
std::unique_ptr< const Trk::RecVertex > m_vertex
Gaudi::Property< double > m_vertex2DSigmaZ
std::unique_ptr< const Trk::PerigeeSurface > m_perigeeSurface
Gaudi::Property< double > m_vertex3DSigmaRPhi
Gaudi::Property< double > m_vertex2DSigmaRPhi
ToolHandle< Muon::IMuonClusterOnTrackCreator > m_muClusterRotCreator
virtual StatusCode initialize() override

◆ interfaceID()

const InterfaceID & Rec::ICombinedMuonTrackBuilder::interfaceID ( )
inlinestaticinherited

AlgTool and IAlgTool interface methods.

Definition at line 42 of file ICombinedMuonTrackBuilder.h.

42 {
43 static const InterfaceID IID_ICombinedMuonTrackBuilder("ICombinedMuonTrackBuilder", 1, 0);
44 return IID_ICombinedMuonTrackBuilder;
45 }

◆ loadMagneticField()

bool Rec::CombinedMuonTrackFitter::loadMagneticField ( const EventContext & ctx,
MagField::AtlasFieldCache & field_cache ) const
protectedinherited

Definition at line 531 of file CombinedMuonTrackFitter.cxx.

531 {
532 SG::ReadCondHandle<AtlasFieldCacheCondObj> fieldCondObj{m_fieldCacheCondObjInputKey, ctx};
533 if (!fieldCondObj.isValid()) {
534 ATH_MSG_ERROR("Failed to retrieve AtlasFieldCacheCondObj with key " << m_fieldCacheCondObjInputKey.key());
535 return false;
536 }
537 fieldCondObj->getInitializedCache(fieldCache);
538 return true;
539 }
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_fieldCacheCondObjInputKey

◆ momentumUpdate()

void Rec::CombinedMuonTrackBuilder::momentumUpdate ( std::unique_ptr< Trk::TrackParameters > & parameters,
double updatedP,
bool directionUpdate = false,
double deltaPhi = 0.,
double deltaTheta = 0. ) const
private

Definition at line 2746 of file CombinedMuonTrackBuilder.cxx.

2747 {
2748 if (!parameters) return;
2749
2750 std::unique_ptr<Trk::TrackParameters> updatedParameters;
2751
2752 // update for angle change
2753 Amg::Vector3D direction = parameters->momentum().unit();
2754
2755 if (directionUpdate) {
2756 double cosDeltaPhi = 0.;
2757 double sinDeltaPhi = std::sin(deltaPhi);
2758
2759 if (std::abs(sinDeltaPhi) < 1.) { cosDeltaPhi = std::sqrt(1. - sinDeltaPhi * sinDeltaPhi); }
2760
2761 double cosDeltaTheta = 0.;
2762 double sinDeltaTheta = std::sin(deltaTheta);
2763
2764 if (std::abs(sinDeltaTheta) < 1.) { cosDeltaTheta = std::sqrt(1. - sinDeltaTheta * sinDeltaTheta); }
2765
2766 double cosTheta = direction.z() * cosDeltaTheta - direction.perp() * sinDeltaTheta;
2767 if (std::abs(cosTheta) < 1.) {
2768 direction = Amg::Vector3D(direction.x() * cosDeltaPhi - direction.y() * sinDeltaPhi,
2769 direction.y() * cosDeltaPhi + direction.x() * sinDeltaPhi,
2770 direction.perp() * cosTheta / std::sqrt(1. - cosTheta * cosTheta));
2771
2772 } else {
2773 direction = Amg::Vector3D(0., 0., cosTheta);
2774 }
2775 direction = direction.unit();
2776 }
2777
2778 // update for momentum (magnitude) change
2779 Amg::Vector3D momentum = updatedP * direction;
2780
2781 // create updated parameters
2782 double charge = parameters->charge();
2783 Amg::Vector3D position = parameters->position();
2784 std::optional<AmgSymMatrix(5)> covariance =
2785 parameters->covariance() ? std::optional<AmgSymMatrix(5)>(*(parameters->covariance())) : std::nullopt;
2786 const Trk::Surface* surface = &(parameters->associatedSurface());
2787 updatedParameters = surface->createUniqueTrackParameters(position, momentum, charge, covariance);
2788
2789 if (updatedParameters) {
2790 parameters = std::move(updatedParameters);
2791 } else {
2792 // update failed, keeping original value
2793 m_messageHelper->printWarning(45);
2794 }
2795 }
double charge(const T &p)
Definition AtlasPID.h:997
virtual ChargedTrackParametersUniquePtr createUniqueTrackParameters(double l1, double l2, double phi, double theat, double qop, std::optional< AmgSymMatrix(5)> cov=std::nullopt) const =0
Use the Surface as a ParametersBase constructor, from local parameters - charged.

◆ normalizedChi2()

double Rec::CombinedMuonTrackFitter::normalizedChi2 ( const Trk::Track & track) const
protectedinherited

Definition at line 518 of file CombinedMuonTrackFitter.cxx.

518 {
519 double chi2 = 999999.;
520 if (track.fitQuality()) {
521 if (track.fitQuality()->numberDoF()) {
522 chi2 = track.fitQuality()->chiSquared() / track.fitQuality()->doubleNumberDoF();
523 } else {
525 }
526 }
527
528 return chi2;
529 }
double chi2(TH1 *h0, TH1 *h1)

◆ optimizeErrors()

bool Rec::CombinedMuonTrackFitter::optimizeErrors ( const EventContext & ctx,
Trk::Track & track ) const
privateinherited

Definition at line 540 of file CombinedMuonTrackFitter.cxx.

540 {
541 const Trk::MuonTrackSummary* muonSummary = nullptr;
542 const Trk::TrackSummary* summary = track.trackSummary();
543
544 if (summary) {
545 muonSummary = summary->muonTrackSummary();
546 } else {
547 m_trackSummary->updateTrack(ctx, track);
548 summary = track.trackSummary();
549 muonSummary = summary->muonTrackSummary();
550 }
551
552 if (!muonSummary) return false;
553
554
555 unsigned int optimize{0},nBarrel{0}, nEndcap{0}, nSmall{0}, nLarge{0};
556
557 for (const Trk::MuonTrackSummary::ChamberHitSummary& summary : muonSummary->chamberHitSummary()) {
558 const Identifier& id = summary.chamberId();
559 bool isMdt = m_idHelperSvc->isMdt(id);
560 if (!isMdt) continue;
561
562 using namespace Muon::MuonStationIndex;
563
564 const ChIndex chIdx = m_idHelperSvc->chamberIndex(id);
565 const bool isSmall = m_idHelperSvc->isSmallChamber(id);
566 nBarrel += isBarrel(chIdx);
567 nEndcap += !isBarrel(chIdx);
568 nSmall+= isSmall;
569 nLarge += !isSmall;
570
571 if (chIdx == ChIndex::BIS &&
572 std::abs(m_idHelperSvc->stationEta(id)) > 6) {
573 optimize = 2;
574 } else if (chIdx == ChIndex::BEE) {
575 optimize = 1;
576 }
577 }
578
579 if (nBarrel > 0 && nEndcap > 0) { optimize += 10; }
580
581 if (nSmall > 0 && nLarge > 0) { optimize += 100; }
582
583 if (optimize > 0) { ATH_MSG_DEBUG(" OptimizeErrors with value " << optimize); }
584
585 return optimize > 0;
586 }
const std::vector< ChamberHitSummary > & chamberHitSummary() const
access to the vector of chamber hit summaries on the track
bool isSmall(const ChIndex index)
Returns true if the chamber index is in a small sector.
ChIndex
enum to classify the different chamber layers in the muon spectrometer

◆ reallocateMaterial()

std::unique_ptr< Trk::Track > Rec::CombinedMuonTrackBuilder::reallocateMaterial ( const EventContext & ctx,
const Trk::Track & spectrometerTrack ) const
private

Definition at line 2796 of file CombinedMuonTrackBuilder.cxx.

2797 {
2798 // build MeasurementSet for the spectrometer
2799 const Trk::TrackParameters* perigeeStartValue = nullptr;
2800 double perigeeDistance = 0.;
2801
2802 Trk::MeasurementSet spectrometerMeasurements;
2803
2805 auto sEnd = spectrometerTrack.trackStateOnSurfaces()->end();
2806 for (; s != sEnd; ++s) {
2807 if ((**s).measurementOnTrack() && !(**s).type(Trk::TrackStateOnSurface::Outlier)) {
2808 // skip pseudo measurement(s)
2809 // FIXME - need phi pseudo in some cases
2810 if (dynamic_cast<const Trk::PseudoMeasurementOnTrack*>((**s).measurementOnTrack())) { continue; }
2811
2812 spectrometerMeasurements.push_back((**s).measurementOnTrack()->clone());
2813 if (!(**s).trackParameters() || (perigeeStartValue && (**s).trackParameters()->position().mag() > perigeeDistance)) {
2814 continue;
2815 }
2816
2817 perigeeDistance = (**s).trackParameters()->position().mag();
2818 perigeeStartValue = (**s).trackParameters();
2819 }
2820 }
2821
2822 // check perigeeStartValue defined
2823 if (!perigeeStartValue) {
2824 // FIXME: use spectrometerTrack.perigeeParameters()
2825 // null perigeeStartValue
2826 m_messageHelper->printWarning(46);
2827 return nullptr;
2828 }
2829
2830 // fit with various recovery strategies
2831 std::unique_ptr<Trk::Track> spectrometerFit = fit(ctx, spectrometerMeasurements, *perigeeStartValue, true, Trk::muon);
2832 if (!spectrometerFit) {
2833 spectrometerFit = fit(ctx, spectrometerMeasurements, *perigeeStartValue, false, Trk::muon);
2834
2835 if (!spectrometerFit) {
2836 spectrometerFit = fit(ctx, spectrometerMeasurements, *perigeeStartValue, false, Trk::nonInteracting);
2837
2838 if (!spectrometerFit) {
2839 // spectrometer refit fails
2840 m_messageHelper->printWarning(47);
2841 }
2842 }
2843 }
2844
2845 if (spectrometerFit) { spectrometerFit->info().addPatternReco(spectrometerTrack.info()); }
2846
2847 Trk::MeasurementSet::iterator m = spectrometerMeasurements.begin();
2848 auto mEnd = spectrometerMeasurements.end();
2849 for (; m != mEnd; ++m) { delete *m; }
2850
2851 return spectrometerFit;
2852 }
std::vector< const MeasurementBase * > MeasurementSet
vector of fittable measurements
Definition FitterTypes.h:30

◆ removeSpectrometerMaterial()

void Rec::CombinedMuonTrackBuilder::removeSpectrometerMaterial ( std::unique_ptr< Trk::Track > & track) const
private

aaaaaahhhhh

Definition at line 2854 of file CombinedMuonTrackBuilder.cxx.

2854 {
2855 // limit momentum to avoid refit allocating excessive energy loss
2856 bool limitMomentum = false;
2857 double momentum = track->perigeeParameters()->momentum().mag();
2858 double qOverP = 0.;
2859
2860 if (momentum > m_lowMomentum) {
2861 const Trk::Perigee* measuredPerigee = track->perigeeParameters();
2862
2863 if (measuredPerigee) {
2864 Trk::TrackStates::const_reverse_iterator r = track->trackStateOnSurfaces()->rbegin();
2865
2866 while (!(**r).trackParameters()) { --r; }
2867
2868 limitMomentum = true;
2869
2870 if (!measuredPerigee->covariance()) {
2871 ATH_MSG_DEBUG("measuredPerigee has no covariance, qOverP not set");
2872 qOverP = (**r).trackParameters()->parameters()[Trk::qOverP];
2873 } else {
2874 qOverP = (**r).trackParameters()->parameters()[Trk::qOverP] +
2875 measuredPerigee->charge() * std::sqrt((*measuredPerigee->covariance())(Trk::qOverP, Trk::qOverP));
2876
2877 ATH_MSG_DEBUG(" limit momentum to " << 1. / std::abs(qOverP * Gaudi::Units::GeV) << " from original value "
2878 << momentum / Gaudi::Units::GeV);
2879 }
2880 }
2881 }
2882
2883 // remove spectrometer material from track
2884 std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes> defaultType;
2885 std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes> type = defaultType;
2886 auto trackStateOnSurfaces = std::make_unique<Trk::TrackStates>();
2887
2888 trackStateOnSurfaces->reserve(track->trackStateOnSurfaces()->size());
2889 bool is_first{true};
2890 for (const Trk::TrackStateOnSurface* tsos : *track->trackStateOnSurfaces()) {
2891 // limit perigee
2892 if (tsos->trackParameters()) {
2893 if (limitMomentum && is_first && tsos->trackParameters()->covariance() &&
2894 tsos->trackParameters()->surfaceType() == Trk::SurfaceType::Perigee) {
2895 Amg::VectorX parameterVector = tsos->trackParameters()->parameters();
2896 parameterVector[Trk::qOverP] = qOverP;
2897
2899 std::unique_ptr<Trk::TrackParameters> parameters =
2900 tsos->trackParameters()->associatedSurface().createUniqueTrackParameters(
2901 parameterVector[Trk::loc1], parameterVector[Trk::loc2], parameterVector[Trk::phi], parameterVector[Trk::theta],
2902 parameterVector[Trk::qOverP], *tsos->trackParameters()->covariance());
2903
2904 type = defaultType;
2906
2907 std::unique_ptr<Trk::MeasurementBase> measurementBase;
2908 if (tsos->measurementOnTrack()) {
2909 measurementBase = tsos->measurementOnTrack()->uniqueClone();
2911 }
2912 trackStateOnSurfaces->push_back(
2913 new Trk::TrackStateOnSurface(std::move(measurementBase), std::move(parameters), nullptr, type));
2914 } else {
2915 trackStateOnSurfaces->push_back(tsos->clone());
2916 }
2917 is_first = false;
2918 continue;
2919 }
2920 is_first = false;
2921
2922 // material in spectrometer
2923 if (tsos->materialEffectsOnTrack() &&
2924 !m_calorimeterVolume->inside(tsos->materialEffectsOnTrack()->associatedSurface().globalReferencePoint())) {
2925 if (tsos->measurementOnTrack()) {
2926 Amg::VectorX parameterVector = tsos->trackParameters()->parameters();
2927 if (limitMomentum) { parameterVector[Trk::qOverP] = qOverP; }
2928 std::unique_ptr<Trk::TrackParameters> trackParameters =
2929 tsos->trackParameters()->associatedSurface().createUniqueTrackParameters(
2930 parameterVector[Trk::loc1], parameterVector[Trk::loc2], parameterVector[Trk::phi], parameterVector[Trk::theta],
2931 parameterVector[Trk::qOverP],
2932 tsos->trackParameters()->covariance() ? std::optional<AmgSymMatrix(5)>(*tsos->trackParameters()->covariance())
2933 : std::nullopt);
2934
2935 type = defaultType;
2937
2939 std::unique_ptr<Trk::MeasurementBase> measurementBase;
2940 measurementBase = tsos->measurementOnTrack()->uniqueClone();
2941 trackStateOnSurfaces->push_back(
2942 new Trk::TrackStateOnSurface(std::move(measurementBase), std::move(trackParameters), nullptr, type));
2943 }
2944 continue;
2945 } else if (!tsos->measurementOnTrack() && tsos->trackParameters() &&
2946 !m_calorimeterVolume->inside(tsos->trackParameters()->position())) {
2947 continue;
2948 }
2949
2950 if (limitMomentum && tsos->trackParameters()) {
2951 Amg::VectorX parameterVector = tsos->trackParameters()->parameters();
2952 parameterVector[Trk::qOverP] = qOverP;
2953 std::unique_ptr<Trk::TrackParameters> trackParameters =
2954 tsos->trackParameters()->associatedSurface().createUniqueTrackParameters(
2955 parameterVector[Trk::loc1], parameterVector[Trk::loc2], parameterVector[Trk::phi], parameterVector[Trk::theta],
2956 parameterVector[Trk::qOverP],
2957 tsos->trackParameters()->covariance() ? std::optional<AmgSymMatrix(5)>(*tsos->trackParameters()->covariance())
2958 : std::nullopt);
2959
2960 type = defaultType;
2961
2962 std::unique_ptr<Trk::MeasurementBase> measurementBase;
2963 if (tsos->measurementOnTrack()) {
2965
2967
2968 measurementBase = tsos->measurementOnTrack()->uniqueClone();
2969 }
2970
2971 std::unique_ptr<Trk::MaterialEffectsBase> materialEffects;
2972 if (tsos->materialEffectsOnTrack()) {
2975
2976 materialEffects = tsos->materialEffectsOnTrack()->uniqueClone();
2977 }
2978 trackStateOnSurfaces->push_back(new Trk::TrackStateOnSurface(std::move(measurementBase), std::move(trackParameters),
2979 std::move(materialEffects), type));
2980 } else {
2981 trackStateOnSurfaces->push_back(tsos->clone());
2982 }
2983 }
2984
2985 // replace track
2986 Trk::TrackInfo trackInfo = track->info();
2987 std::unique_ptr<Trk::FitQuality> fitQuality = nullptr;
2988 if (track->fitQuality()) { fitQuality = std::make_unique<Trk::FitQuality>(*track->fitQuality()); }
2989
2990 track = std::make_unique<Trk::Track>(trackInfo, std::move(trackStateOnSurfaces), std::move(fitQuality));
2991 }
Gaudi::Property< double > m_lowMomentum
@ qOverP
perigee
FitQualityOnSurface fitQuality(const MultiComponentState &, const MeasurementBase &)
Method for determining the chi2 of the multi-component state and the number of degrees of freedom.

◆ replaceCaloEnergy()

void Rec::CombinedMuonTrackBuilder::replaceCaloEnergy ( const CaloEnergy * caloEnergy,
Trk::Track * track ) const
private

◆ standaloneFit()

std::unique_ptr< Trk::Track > Rec::CombinedMuonTrackBuilder::standaloneFit ( const EventContext & ctx,
const Trk::Track & spectrometerTrack,
const Amg::Vector3D & bs,
const Trk::Vertex * vertex ) const
overridevirtual

ICombinedMuonTrackBuilder interface: propagate to perigee adding calo energy-loss and material to MS track.

Delete manually until we switch to unique_ptrs

Implements Rec::ICombinedMuonTrackBuilder.

Definition at line 579 of file CombinedMuonTrackBuilder.cxx.

580 {
581 MagField::AtlasFieldCache fieldCache;
582 // Get field cache object
583
584 if (!loadMagneticField(ctx, fieldCache)) return nullptr;
585
586 // no SA fit with vertex constraint for Toroid off data
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)) {
596 if (m_trackQuery->isLineFit(inputSpectrometerTrack)) {
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()) {
610 if (m_trackQuery->isLineFit(inputSpectrometerTrack)) {
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
639 msg(MSG::VERBOSE) << endmsg;
640 }
641
642 // check input vertex OK
643 const Trk::RecVertex* vertex = dynamic_cast<const Trk::RecVertex*>(inputVertex);
644 if (inputVertex && !vertex) {
645 // input vertex fails dynamic_cast
646 m_messageHelper->printWarning(6);
647 return nullptr;
648 }
649
650 // fail input tracks with insufficient measurements or inconsistent structure
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 // count measurements
657 int measurements = 0;
658 for (const Trk::TrackStateOnSurface* s : *tsos) {
660 }
661 // insufficient measurements
662 if (measurements < 4) {
663 m_messageHelper->printWarning(48);
664 ATH_MSG_VERBOSE(" SA::failed (1)");
665 return nullptr;
666 }
667
668 // inconsistent TSOS on input track
669 if (fitQuality && measurements < fitQuality->numberDoF() + 4) {
670 m_messageHelper->printWarning(49);
671 ATH_MSG_VERBOSE(" SA::failed (2)");
672 return nullptr;
673 }
674 }
675
676 // check the track is roughly projective in phi
677 const bool is_extrapolated = m_trackQuery->isExtrapolated(inputSpectrometerTrack, ctx);
678 if (!is_extrapolated && !m_trackQuery->isProjective(inputSpectrometerTrack)) {
679 ATH_MSG_VERBOSE(" SA::failed (3)");
680 return nullptr;
681 }
682
683 // possibly refit the spectrometer track with material reallocation
684 double spectrometerFitChi2 = normalizedChi2(inputSpectrometerTrack);
685 std::unique_ptr<Trk::Track> spectrometerFit = std::make_unique<Trk::Track>(inputSpectrometerTrack);
686 if (!vertex && (m_reallocateMaterial || is_extrapolated)) {
687 spectrometerFit = reallocateMaterial(ctx, inputSpectrometerTrack);
688 if (!spectrometerFit) {
689 ATH_MSG_VERBOSE(" SA::failed (4)");
690 return nullptr;
691 }
692 }
693
694 const Trk::Track& spectrometerTrack = *spectrometerFit;
695
696 // require a Perigee from the spectrometer track
697 const Trk::Perigee* measuredPerigee = spectrometerTrack.perigeeParameters();
698
699 if (!measuredPerigee || !measuredPerigee->covariance()) {
700 // missing MeasuredPerigee for spectrometer track
701 m_messageHelper->printWarning(7);
702
703 ATH_MSG_VERBOSE(" SA::failed (5)");
704 return nullptr;
705 }
706
707 // set measured momentum error and starting parameters
708 bool badlyDeterminedCurvature = false;
709
710 if (!Amg::hasPositiveDiagElems(*measuredPerigee->covariance())) {
711 ATH_MSG_WARNING("standaloneFit: measuredPerigee has non-positive-definite covariance ");
712 ATH_MSG_VERBOSE(" SA::failed (5.5)");
714 return nullptr;
715 }
716
717 double errorP = std::sqrt(measuredPerigee->momentum().mag2() * (*measuredPerigee->covariance())(Trk::qOverP, Trk::qOverP));
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 // vertex association only makes sense for magnet-on tracks with measured curvature
727 if (!fieldCache.toroidOn() || m_trackQuery->isLineFit(spectrometerTrack) || errorP > m_largeMomentumError) {
728 ATH_MSG_VERBOSE("standaloneFit: vertex fit not attempted as curvature badly measured");
729 ATH_MSG_VERBOSE(" SA::failed (6)");
730 return nullptr;
731 }
732 parameters = std::make_unique<Trk::Perigee>(*spectrometerTrack.perigeeParameters());
733 } else {
734 //
735 // update -if needed vertex and beam axis positions
736 //
737 if ((origin - mvertex->position()).mag() > 0.001) {
738 // recreate beamAxis and vertexRegion for constrained (projective) track fits
739
740 mperigeeSurface = std::make_unique<Trk::PerigeeSurface>(origin);
741
742 AmgSymMatrix(3) beamAxisCovariance;
743 beamAxisCovariance.setZero();
744 (beamAxisCovariance)(0, 0) = m_vertex2DSigmaRPhi * m_vertex2DSigmaRPhi;
745 (beamAxisCovariance)(1, 1) = m_vertex2DSigmaRPhi * m_vertex2DSigmaRPhi;
746 (beamAxisCovariance)(2, 2) = m_vertex2DSigmaZ * m_vertex2DSigmaZ;
747 mbeamAxis = std::make_unique<Trk::RecVertex>(origin, beamAxisCovariance);
748
749 AmgSymMatrix(3) vertexRegionCovariance;
750 vertexRegionCovariance.setZero();
751 (vertexRegionCovariance)(0, 0) = m_vertex3DSigmaRPhi * m_vertex3DSigmaRPhi;
752 (vertexRegionCovariance)(1, 1) = m_vertex3DSigmaRPhi * m_vertex3DSigmaRPhi;
753 (vertexRegionCovariance)(2, 2) = m_vertex3DSigmaZ * m_vertex3DSigmaZ;
754 mvertex = std::make_unique<Trk::RecVertex>(origin, vertexRegionCovariance);
755 }
756
757 parameters = extrapolatedParameters(ctx, badlyDeterminedCurvature, spectrometerTrack, mvertex.get(), mperigeeSurface.get());
758 }
759
760 if (!parameters) {
761 ATH_MSG_VERBOSE(" SA::failed (7)");
762 return nullptr;
763 }
764
765 // create the spectrometer TSOS's for the extrapolated fit
766 std::vector<std::unique_ptr<const Trk::TrackStateOnSurface>> spectrometerTSOS = createSpectrometerTSOS(ctx, spectrometerTrack);
767
768 if (spectrometerTSOS.empty()) {
769 ATH_MSG_VERBOSE(" SA::failed (8)");
770 return nullptr;
771 }
772 const Trk::TrackParameters* caloParameters = nullptr;
773
774 Trk::ParticleHypothesis particleHypothesis = Trk::muon;
775
776 bool haveFitWithVertex = false;
777 bool performPrefit = false;
778
779 if (m_redoRots) {
780 for (const Trk::TrackStateOnSurface* s : *spectrometerTrack.trackStateOnSurfaces()) {
781 if (s->measurementOnTrack() && !s->trackParameters()) {
782 performPrefit = true;
783 break;
784 }
785 }
786 }
787
788 // badly defined tracks use weak vertex constraint with prefit before calo association
789 std::unique_ptr<Trk::Track> prefit;
790
791 const Trk::RecVertex* vertexInFit = vertex;
792
793 if (!vertexInFit) {
794 double errorPhi = std::sqrt((*measuredPerigee->covariance())(Trk::phi0, Trk::phi0));
795
796 bool inCSCregion = std::abs(measuredPerigee->momentum().eta()) > 2.0;
797
798 // FIXME: missing prefit case for excessive spectrometer eloss WARNING
799 // spot from line starting approx from vertex??
800 if (inCSCregion || m_trackQuery->numberPseudoMeasurements(spectrometerTrack) ||
801 (fieldCache.toroidOn() &&
802 (badlyDeterminedCurvature || errorPhi > m_largePhiError || measuredPerigee->momentum().mag() < m_lowMomentum))) {
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 {
817 ATH_MSG_DEBUG(" prefit with beamAxis: "
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 // prefit to stabilize calo look-up and/or provide trackParameters
830 if (performPrefit) {
831 if (!vertexInFit) { ATH_MSG_VERBOSE(" prefit without vertex"); }
832
833 if (vertexInFit) { haveFitWithVertex = true; }
834
835 if (badlyDeterminedCurvature && parameters->momentum().mag() > m_lowMomentum) { particleHypothesis = Trk::nonInteracting; }
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 // demand prefit success
842 if (!prefit || !prefit->fitQuality() || !prefit->perigeeParameters()) {
843 ATH_MSG_DEBUG(" prefit failure ");
844 prefit.reset();
845 }
846
847 if (prefit) {
848 dumpCaloEloss(prefit.get(), " prefit ");
849 bool hasCov = prefit->perigeeParameters() ? (prefit->perigeeParameters()->covariance() != nullptr) : false;
850 ATH_MSG_VERBOSE(" got prefit " << m_printer->print(*prefit) << " hasCov " << hasCov);
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 // look for first measured TSOS in muon volume
856 if (!s->trackParameters() || !s->trackParameters()->covariance()) { continue; }
857 if (m_calorimeterVolume->inside(s->trackParameters()->position())) { continue; }
858
859 // check that it is a measurement
861 ATH_MSG_DEBUG("Found first parameters in MS " << s->trackParameters()->position().perp() << " z "
862 << s->trackParameters()->position().z());
863 ms_entrance = s;
864 break;
865 }
866 }
867
868 if (ms_entrance && ms_entrance != prefit->trackStateOnSurfaces()->front() && ms_entrance->trackParameters()) {
869 parameters.reset(ms_entrance->trackParameters()->clone());
870 caloParameters = parameters.get();
871 } else {
872 // prefit: no parameter extrapolation to calo
873 m_messageHelper->printWarning(9);
874 }
875 }
876
877 // give up if prefit fails
878 spectrometerTSOS.clear();
879
880 if (!prefit) {
881 ATH_MSG_VERBOSE(" SA::failed (9)");
882 return nullptr;
883 }
884 const Trk::TrackStates* prefit_tsos = prefit->trackStateOnSurfaces();
885 // create spectrometerTSOS corresponding to prefit
886 // skip start perigee, then preferentially take everything following MS perigee,
887 // otherwise (if no MS perigee) rely on VolumesSvc,
888 // but be aware that by design there are inconsistencies wrt tracking geometry
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
895 if (s != prefit_tsos->end() && (*s)->type(Trk::TrackStateOnSurface::Perigee)) ++s;
896
897 for (; s != prefit_tsos->end(); ++s) { spectrometerTSOS.emplace_back((*s)->clone()); }
898 }
899
900 if (m_redoRots) {
901 // recalibration: correct rots
902 for (std::unique_ptr<const Trk::TrackStateOnSurface>& t : spectrometerTSOS) {
903 if (!t->measurementOnTrack() || !t->trackParameters()) { continue; } // end of if
904
905 const Trk::RIO_OnTrack* rot = dynamic_cast<const Trk::RIO_OnTrack*>(t->measurementOnTrack());
906
907 if (!rot) continue;
908 Identifier id = rot->identify();
909
910 if (!m_idHelperSvc->isMuon(id)) continue;
911
912 std::unique_ptr<Trk::RIO_OnTrack> updatedRot;
913 if (!m_cscRotCreator.empty() && m_idHelperSvc->isCsc(id)) {
914 updatedRot.reset(m_cscRotCreator->correct(*rot->prepRawData(), *(*t).trackParameters(), ctx));
915 } else if (!m_mdtRotCreator.empty() && m_idHelperSvc->isMdt(id)) {
916 updatedRot.reset(m_mdtRotCreator->correct(*rot->prepRawData(), *(*t).trackParameters(), ctx));
917 } else if (!m_muClusterRotCreator.empty() && (m_idHelperSvc->isMM(id) || m_idHelperSvc->issTgc(id))) {
918 updatedRot.reset(m_muClusterRotCreator->correct(*rot->prepRawData(), *(*t).trackParameters(), ctx));
919 }
920
921 if (updatedRot) {
922 t = Muon::MuonTSOSHelper::createMeasTSOS(std::move(updatedRot), t->trackParameters()->uniqueClone(),
924 }
925 }
926 }
927
928 // extrapolate and fit track
929 particleHypothesis = Trk::muon;
930 bool returnAfterCleaner = !fieldCache.toroidOn();
931
932 ATH_MSG_VERBOSE("Calling createExtrapolatedTrack from " << __func__ << " at line " << __LINE__);
933 std::unique_ptr<Trk::Track> extrapolated(createExtrapolatedTrack(ctx, spectrometerTrack, *parameters, particleHypothesis,
934 m_cleanStandalone, spectrometerTSOS, vertexInFit, mbeamAxis.get(),
935 mperigeeSurface.get(), prefitResult.get()));
936
937 if (extrapolated) dumpCaloEloss(extrapolated.get(), " extrapolated ");
938
939 // fit problem: try fixup using vertex region or prefit
940 if (!extrapolated || !extrapolated->fitQuality()) {
941 if (extrapolated && !haveFitWithVertex && !vertexInFit) {
942 ATH_MSG_DEBUG(" bad fitQuality: retry with vertex ");
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
953 if (vertexInFit) type.set(Trk::TrackStateOnSurface::Measurement);
954
955 trackStateOnSurfaces->push_back(new Trk::TrackStateOnSurface(
956 std::move(vertexInFit), badfit->perigeeParameters()->uniqueClone(), nullptr, type));
957
958 for (Trk::TrackStates::const_iterator s = badfit->trackStateOnSurfaces()->begin() + 1;
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);
965 extrapolated = fit(ctx, *track, m_cleanStandalone, particleHypothesis);
966 }
967
968 // restart from prefit without cleaning
969 if (!extrapolated || !extrapolated->fitQuality()) {
970 if (prefit && prefit->fitQuality() && caloParameters) {
971 ATH_MSG_DEBUG(" restarting from prefit as back extrapolation fit failed");
972 spectrometerTSOS.clear();
973 // create spectrometerTSOS corresponding to prefit
974 Trk::TrackStates::const_iterator s = prefit->trackStateOnSurfaces()->begin();
975
976 while (m_calorimeterVolume->inside((**s).trackParameters()->position()) ||
978 ++s;
979 } // end of while
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__);
985 createExtrapolatedTrack(ctx, spectrometerTrack, *caloParameters, particleHypothesis, false, spectrometerTSOS,
986 vertexInFit, mbeamAxis.get(), mperigeeSurface.get(), prefitResult.get());
987 returnAfterCleaner = true;
988 }
989
990 if (!extrapolated || !extrapolated->fitQuality()) {
991 bool hasFQ = extrapolated ? (extrapolated->fitQuality() != nullptr) : false;
992 ATH_MSG_DEBUG("fail track as back extrapolation fit failed " << extrapolated.get() << " hasFQ " << hasFQ);
993
994 ATH_MSG_VERBOSE(" SA::failed (10)");
995 return nullptr;
996 }
997 }
998 }
999
1000 // keep statistics for successful fits
1002 if (vertexInFit == mbeamAxis.get()) ++m_countBeamAxis;
1003 if (vertexInFit == mvertex.get()) ++m_countVertexRegion;
1004
1005 // refit when there's been a significant momentum change (parameters at last calo scatterer)
1006 double momentum = parameters->momentum().mag();
1007
1008 bool allowRefit = !badlyDeterminedCurvature;
1009 double pRatio = 1.;
1010
1011 const Trk::TrackParameters* params_pRat = parameters.get();
1012 if (returnAfterCleaner) {
1013 allowRefit = false;
1014 } else {
1015 // pRatio is the ratio of fitted to start momentum value at calo exit
1016 // find parameters at calo exit
1017 const Trk::TrackParameters* params_pRat = nullptr;
1018 auto s = extrapolated->trackStateOnSurfaces()->begin();
1019 while (!(**s).trackParameters() || m_calorimeterVolume->inside((**s).trackParameters()->position())) {
1020 if ((**s).trackParameters() && !(**s).type(Trk::TrackStateOnSurface::Perigee)) params_pRat = (**s).trackParameters();
1021 ++s;
1022 }
1023
1024 // extrapolated fit with missing calo parameters - this should never happen!
1025 if (params_pRat) {
1026 pRatio = momentum / parameters->momentum().mag();
1027 } else {
1028 // extrapolated track missing TrackParameters at calo scatterer
1029 m_messageHelper->printWarning(10);
1030 allowRefit = false;
1031 }
1032 }
1033
1034 // in case of a significant momentum change: iterate (re-associate calo and refit)
1035 std::unique_ptr<Trk::Track> track;
1036
1037 if (allowRefit && std::abs(pRatio - 1.) > m_largeMomentumChange) {
1038 if (msgLvl(MSG::VERBOSE)) {
1039 double sinTheta = params_pRat->momentum().perp() / params_pRat->momentum().mag();
1040
1041 ATH_MSG_VERBOSE(" iterate as significant momentum change after fit "
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()) {
1048 if (!s->type(Trk::TrackStateOnSurface::Perigee)) spectrometerTSOS.emplace_back(s->clone());
1049 }
1050
1051 ATH_MSG_VERBOSE("Calling createExtrapolatedTrack from " << __func__ << " at line " << __LINE__);
1052
1053 track = createExtrapolatedTrack(ctx, spectrometerTrack, *parameters, particleHypothesis, m_cleanStandalone, spectrometerTSOS,
1054 vertexInFit, mbeamAxis.get(), mperigeeSurface.get(), extrapolated->perigeeParameters());
1055
1056 if (track) {
1057 double extrapChi2 = normalizedChi2(*extrapolated);
1058 double fitChi2 = normalizedChi2(*track);
1059 if (fitChi2 < m_badFitChi2 || fitChi2 < extrapChi2 + 0.5) { extrapolated.reset(); }
1060 }
1061 }
1062 if (extrapolated) { track.swap(extrapolated); }
1063
1064 if (!m_trackQuery->isCaloAssociated(*track, ctx)) { // still want to perform this check probably though
1065 // fail as calo incorrectly described
1066 m_messageHelper->printWarning(12);
1067 ATH_MSG_VERBOSE(" SA::failed (12)");
1068 return nullptr;
1069 }
1070
1071 int improvementsFailed = 0; // count the number of times the fit fails after improvements
1072
1074 ATH_MSG_VERBOSE("Refining Calorimeter TSOS in StandAlone Fit ...");
1075
1076 m_materialUpdator->updateCaloTSOS(*track);
1077
1078 std::unique_ptr<Trk::Track> refinedTrack(fit(ctx, *track, false, Trk::muon));
1079 if (checkTrack("refineFit", refinedTrack.get())) {
1080 ATH_MSG_VERBOSE(__FILE__<<":"<<__LINE__<<"refined track checks out");
1081 track.swap(refinedTrack);
1082 } else {
1083 ATH_MSG_VERBOSE("refined track fit failed");
1084 ++improvementsFailed;
1085 }
1086 }
1087
1088 // adds uncertainties
1089 // We will either have nullptr or a new Track.
1090 // What we pass stays untouched.
1091 std::unique_ptr<Trk::Track> newTrack = addIDMSerrors(track.get());
1092 // newTrack will not be used after this block, either
1093 // we updated the track or kept the track as it was
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 // Don't run the outliers anymore at this stage
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 // Here we swap
1104 track.swap(refittedTrack);
1105 } else {
1106 ++improvementsFailed;
1107 }
1108 } else {
1109 ++improvementsFailed;
1110 }
1111
1112 // hole recovery, error optimization, attach TrackSummary
1113 finalTrackBuild(ctx, track);
1114
1115 if (track) {
1116 dumpCaloEloss(track.get(), " finalTrackBuild ");
1117
1118 // report when extrapolated fit quality significantly worse than spectrometer quality
1119 double fitChi2 = normalizedChi2(*track);
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 }
1131 ATH_MSG_VERBOSE(" SA::ok ");
1132 return track;
1133 }
if(febId1==febId2)
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 &parameters, 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
Definition FitQuality.h:60
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?)
Definition hcg.cxx:130
ParticleHypothesis
Enumeration for Particle hypothesis respecting the interaction with material.

◆ standaloneRefit()

std::unique_ptr< Trk::Track > Rec::CombinedMuonTrackBuilder::standaloneRefit ( const EventContext & ctx,
const Trk::Track & combinedTrack,
const Amg::Vector3D & vec ) const
overridevirtual

ICombinedMuonTrackBuilder interface: refit a track removing any indet measurements with optional addition of pseudoMeasurements.

At this stage we have the first calo scatterer or end up with nothing

The while loop above goes one iterator back after it found the calorimeter deposit. So we go back to the calo deposit

Make another check that the pointer is valid

Prepare for the outer TSOS

The extrapolation from above could actually fail

Now we need to check whether we actually own the parameters

Ensure that the parameters are also updated accordingly

We do not need the parameters pointer anymore

create perigee by back extrapolation from middleSurface via innerSurface

From this point we can be sure that the parameters down the chain orignate from some propagation

If the perigee parameters are not of Type Trk::Peirgee forget what has been tried

Create the vertex element before the perigee_owner looses ownership

Implements Rec::ICombinedMuonTrackBuilder.

Definition at line 1134 of file CombinedMuonTrackBuilder.cxx.

1135 {
1136 //
1137 // update -if needed vertex and beam axis positions
1138 //
1139
1140 if (msgLevel(MSG::DEBUG)) countAEOTs(combinedTrack, " in standalone Refit input combinedTrack ");
1141
1142 MagField::AtlasFieldCache fieldCache;
1143 // Get field cache object
1144
1145 if (!loadMagneticField(ctx, fieldCache)) return nullptr;
1146
1147 if (!fieldCache.toroidOn()) {
1148 // no standalone refit for Toroid off
1149 return nullptr;
1150 }
1151
1152 ATH_MSG_DEBUG(" StandaloneRefit beam position bs_x " << origin);
1153
1154 // vertex will change track by track
1155 AmgSymMatrix(3) vertexRegionCovariance{AmgSymMatrix(3)::Zero()};
1156
1157 double error2d0 = m_vertex3DSigmaRPhi * m_vertex3DSigmaRPhi;
1158 double error2z0 = m_vertex3DSigmaZ * m_vertex3DSigmaZ;
1159 const Trk::Perigee* measuredPerigee = combinedTrack.perigeeParameters();
1160
1161 if (measuredPerigee && measuredPerigee->covariance() && m_useRefitTrackError) {
1162 error2d0 = (*measuredPerigee->covariance())(Trk::d0, Trk::d0);
1163 error2z0 = (*measuredPerigee->covariance())(Trk::z0, Trk::z0);
1164 ATH_MSG_DEBUG(" StandaloneRefit new vertex d0 error " << std::sqrt(error2d0) << " new vertex z0 error "
1165 << std::sqrt(error2z0));
1166 }
1167
1168 (vertexRegionCovariance)(0, 0) = error2d0;
1169 (vertexRegionCovariance)(1, 1) = error2d0;
1170 (vertexRegionCovariance)(2, 2) = error2z0;
1171
1172 std::unique_ptr<Trk::RecVertex> vertex = std::make_unique<Trk::RecVertex>(origin, vertexRegionCovariance);
1173
1174 ATH_MSG_DEBUG(" StandaloneRefit new vertex position x " << vertex->position().x() << " y " << vertex->position().y() << " z "
1175 << vertex->position().z());
1176
1177 bool addPhiPseudo = false;
1178 // release 21
1179 unsigned spectrometerPhiQuality = m_trackQuery->spectrometerPhiQuality(combinedTrack, ctx);
1180 if (spectrometerPhiQuality > 1) { addPhiPseudo = true; }
1181
1182 ATH_MSG_VERBOSE("standaloneRefit: using vertex region constraint with "
1183 << "spectrometerPhiQuality " << spectrometerPhiQuality);
1184
1185 // create standalone track TSOS vector
1186 auto trackStateOnSurfaces = std::make_unique<Trk::TrackStates>();
1187
1188 // size will allow for perigee + all TSOS outside indet
1189 unsigned size = combinedTrack.trackStateOnSurfaces()->size() + 3 + addPhiPseudo;
1190
1191 trackStateOnSurfaces->reserve(size);
1192
1193 // position TSOS iterator to be just after the indet
1194 bool haveCaloDeposit = false;
1195
1196 Trk::TrackStates::const_iterator s = combinedTrack.trackStateOnSurfaces()->begin();
1197 const Trk::TrackStates::const_iterator cmb_end_itr = combinedTrack.trackStateOnSurfaces()->end();
1198 do {
1199 ++s;
1200 if (s == cmb_end_itr) {
1201 // fail track as no TSOS with type CaloDeposit
1202 m_messageHelper->printWarning(13);
1203 return nullptr;
1204 }
1205 if ((*s)->type(Trk::TrackStateOnSurface::CaloDeposit)) {
1206 haveCaloDeposit = true;
1207 --s;
1208 }
1209 } while (!haveCaloDeposit);
1211 const Trk::TrackStateOnSurface* const cmb_inner_tsos = (*s);
1212 // inner calo scatterer - keep scattering angles for vertex constraint
1213 // Amg::Vector3D direction;
1214 const Trk::ScatteringAngles* innerScattering = nullptr;
1215 std::unique_ptr<Trk::TrackStateOnSurface> innerTSOS;
1216 const Trk::MaterialEffectsBase* materialEffects = cmb_inner_tsos->materialEffectsOnTrack();
1217 const Trk::TrackParameters* middleParameters = nullptr;
1218 const Trk::ScatteringAngles* outerScattering = nullptr;
1219 const Trk::TrackParameters* parameters = cmb_inner_tsos->trackParameters();
1220 std::unique_ptr<Trk::TrackParameters> param_owner;
1221 if (materialEffects && parameters && m_calorimeterVolume->inside(parameters->position())) {
1222 // keep scattering angles when vertex constrained
1223 // in r21, addVertexRegion is always true
1224
1225 innerTSOS.reset(cmb_inner_tsos->clone());
1226 const Trk::MaterialEffectsOnTrack* meot = dynamic_cast<const Trk::MaterialEffectsOnTrack*>(materialEffects);
1227
1228 if (!meot) {
1229 // innerScattering dynamic_cast failed
1230 m_messageHelper->printWarning(16);
1231 return nullptr;
1232 }
1233 innerScattering = meot->scatteringAngles();
1236 if (s != cmb_end_itr && !(*s)->type(Trk::TrackStateOnSurface::CaloDeposit)) { ++s; }
1237
1239 if (s != cmb_end_itr) {
1240 const Trk::TrackStateOnSurface* const cmb_middle_tsos = (*s);
1241 materialEffects = cmb_middle_tsos->materialEffectsOnTrack();
1242 parameters = cmb_middle_tsos->trackParameters();
1243 middleParameters = parameters;
1244 } else {
1245 // no TSOS of type CaloDeposit found
1246 m_messageHelper->printWarning(17);
1247 materialEffects = nullptr;
1248 parameters = nullptr;
1249 }
1250
1251 } else {
1252 // no inner material or parameters
1253 if (!materialEffects) m_messageHelper->printWarning(14);
1254 if (!parameters) m_messageHelper->printWarning(15);
1255 }
1256
1257 if (!innerTSOS) {
1258 // no inner scattering TSOS found
1259 m_messageHelper->printWarning(18);
1260 return nullptr;
1261 }
1262
1263 // middle calo scatterer (for energy deposit)
1264 double energyDeposit{0.};
1265
1266 std::unique_ptr<Trk::TrackStateOnSurface> middleTSOS;
1267
1268 if (materialEffects && parameters && m_calorimeterVolume->inside(parameters->position())) {
1269 const Trk::TrackStateOnSurface* const cmb_middle_tsos = (*s);
1270 middleTSOS.reset(cmb_middle_tsos->clone());
1271 const Trk::MaterialEffectsOnTrack* meot = dynamic_cast<const Trk::MaterialEffectsOnTrack*>(materialEffects);
1272
1273 if (meot && meot->energyLoss()) energyDeposit = meot->energyLoss()->deltaE();
1275
1276 ++s;
1277 if (s != cmb_end_itr) {
1278 const Trk::TrackStateOnSurface* const cmb_outer_tsos = (*s);
1279 materialEffects = cmb_outer_tsos->materialEffectsOnTrack();
1280 parameters = cmb_outer_tsos->trackParameters();
1281 } else {
1282 materialEffects = nullptr;
1283 parameters = nullptr;
1284 }
1285 } else {
1286 // no middle material or parameters
1287 if (!materialEffects) m_messageHelper->printWarning(19);
1288 if (!parameters) m_messageHelper->printWarning(20);
1289 }
1290
1291 if (!middleTSOS) {
1292 // no CaloDeposit TSOS found
1293 m_messageHelper->printWarning(21);
1294 return nullptr;
1295 }
1296
1297 // outer calo scatterer
1298 std::unique_ptr<Trk::TrackStateOnSurface> outerTSOS;
1299
1300 double pInner{0.}, pOuter{0.};
1301 if (materialEffects && parameters && m_calorimeterVolume->inside(parameters->position())) {
1302 const Trk::TrackStateOnSurface* const cmb_outer_tsos = (*s);
1303 pOuter = parameters->momentum().mag();
1304
1305 outerTSOS.reset(cmb_outer_tsos->clone());
1306
1307 const Trk::MaterialEffectsOnTrack* meot = dynamic_cast<const Trk::MaterialEffectsOnTrack*>(materialEffects);
1308
1309 if (!meot) {
1310 // outerScattering dynamic_cast failed
1311 m_messageHelper->printWarning(24);
1312 return nullptr;
1313 }
1314 outerScattering = meot->scatteringAngles();
1315
1316 // Go to the next surface
1317 ++s;
1318
1319 // get parameters at middleSurface for energy correction,
1320 // start with parameters from middle surface when vertex in fit
1321 if (outerScattering && middleTSOS) {
1322 parameters = middleTSOS->trackParameters();
1323 } else {
1324 // otherwise extrapolate outer to middleSurface without scattering correction
1325 param_owner = m_propagator->propagate(ctx, *parameters, middleTSOS->trackParameters()->associatedSurface(),
1327 parameters = param_owner.get();
1328 }
1330 if (parameters) {
1332 if (!param_owner) param_owner = parameters->uniqueClone();
1333 // corrected parameters (include unfitted calo energy deposit),
1334 // inner momentum = outer momentum plus energy deposit
1335 pInner = pOuter + energyDeposit;
1336 momentumUpdate(param_owner, pInner);
1338 parameters = param_owner.get();
1339 }
1340 } else {
1341 // no outer material or parameters
1342 if (!materialEffects) m_messageHelper->printWarning(22);
1343 if (!parameters) m_messageHelper->printWarning(23);
1344 }
1345
1346 // fail track if missing any calo surface or extrapolation failure
1347 if (!innerTSOS || !middleTSOS || !outerTSOS || !parameters) { return nullptr; }
1349 parameters = nullptr;
1350
1352 param_owner = m_propagator->propagate(ctx, *param_owner, innerTSOS->trackParameters()->associatedSurface(), Trk::oppositeMomentum,
1354
1356 if (innerScattering) { momentumUpdate(param_owner, pInner, true, -innerScattering->deltaPhi(), -innerScattering->deltaTheta()); }
1357
1358 std::unique_ptr<Trk::TrackParameters> perigee_owner;
1359 if (param_owner) {
1360 perigee_owner = m_propagator->propagate(ctx, *param_owner, *m_perigeeSurface, Trk::oppositeMomentum, false,
1363 if (perigee_owner && perigee_owner->surfaceType() != Trk::SurfaceType::Perigee) { perigee_owner.reset(); }
1364 }
1365
1366 // in case of problem above: clone combined perigee
1367 if (!perigee_owner) { perigee_owner = combinedTrack.perigeeParameters()->uniqueClone(); }
1368 // track back out to the 3 calo surfaces applying small correction for non-linearity
1369 param_owner = m_propagator->propagate(ctx, *perigee_owner, innerTSOS->trackParameters()->associatedSurface(), Trk::alongMomentum,
1371 if (!param_owner) {
1372 // failed propagation to innerTSOS
1373 m_messageHelper->printWarning(26);
1374 } else {
1375 if (innerScattering) { momentumUpdate(param_owner, pInner, true, innerScattering->deltaPhi(), innerScattering->deltaTheta()); }
1376
1377 param_owner = m_propagator->propagate(ctx, *param_owner, middleParameters->associatedSurface(), Trk::alongMomentum, false,
1379
1380 if (!param_owner) {
1381 // failed propagation to middleTSOS
1382 m_messageHelper->printWarning(27);
1383 } else {
1384 momentumUpdate(param_owner, pOuter);
1385 param_owner = m_propagator->propagate(ctx, *param_owner, outerTSOS->trackParameters()->associatedSurface(),
1387 }
1388 }
1389
1390 if (!param_owner) { return nullptr; }
1391
1392 if (outerScattering) { momentumUpdate(param_owner, pOuter, true, outerScattering->deltaPhi(), outerScattering->deltaTheta()); }
1393
1394 // small correction term
1395 const double deltaPhi = xAOD::P4Helpers::deltaPhi(outerTSOS->trackParameters()->momentum().phi(), param_owner->momentum().phi());
1396 const double deltaTheta = outerTSOS->trackParameters()->momentum().theta() - param_owner->momentum().theta();
1397
1398 momentumUpdate(perigee_owner, pInner, true, deltaPhi, deltaTheta);
1399
1400 std::unique_ptr<Trk::RecVertex> mbeamAxis = std::make_unique<Trk::RecVertex>(*m_beamAxis);
1402 std::unique_ptr<Trk::PseudoMeasurementOnTrack> vertexInFit{vertexOnTrack(*perigee_owner, vertex.get(), mbeamAxis.get())};
1403
1404 // create perigee TSOS
1405 trackStateOnSurfaces->push_back(Muon::MuonTSOSHelper::createPerigeeTSOS(std::move(perigee_owner)));
1406
1407 // including vertex region pseudoMeas if requested: in r21, this is always requested
1408 if (vertexInFit) {
1409 trackStateOnSurfaces->push_back(Muon::MuonTSOSHelper::createMeasTSOS(std::move(vertexInFit), nullptr, Trk::TrackStateOnSurface::Measurement));
1410 }
1411
1412 if (m_addElossID) {
1413 double Eloss{0.}, sigmaEloss{0.}, X0tot{0.}, sigmaDeltaPhitot2{0.}, sigmaDeltaThetatot2{0.};
1414
1415 std::vector<const Trk::TrackStateOnSurface*> scatter_tsos;
1416 scatter_tsos.reserve(combinedTrack.trackStateOnSurfaces()->size());
1417
1418 for (const Trk::TrackStateOnSurface* comb_tsos : *combinedTrack.trackStateOnSurfaces()) {
1419 if (!comb_tsos->trackParameters()) continue;
1420 if (!m_indetVolume->inside(comb_tsos->trackParameters()->position())) break;
1421 if (!comb_tsos->materialEffectsOnTrack()) { continue; }
1422 const double X0 = comb_tsos->materialEffectsOnTrack()->thicknessInX0();
1423 X0tot += X0;
1424 const Trk::MaterialEffectsOnTrack* meot =
1425 dynamic_cast<const Trk::MaterialEffectsOnTrack*>(comb_tsos->materialEffectsOnTrack());
1426
1427 if (!meot) { continue; }
1428 const Trk::EnergyLoss* energyLoss = meot->energyLoss();
1429 if (!energyLoss) { continue; }
1430 Eloss += energyLoss->deltaE();
1431 sigmaEloss += energyLoss->sigmaDeltaE();
1432
1433 ATH_MSG_DEBUG("CombinedMuonFit ID Eloss found r " << (comb_tsos->trackParameters())->position().perp() << " z "
1434 << (comb_tsos->trackParameters())->position().z() << " value "
1435 << energyLoss->deltaE() << " Eloss " << Eloss << " sigma Eloss "
1436 << energyLoss->sigmaDeltaE() << " X0 " << X0);
1437
1438 const Trk::ScatteringAngles* scat = meot->scatteringAngles();
1439 if (scat) {
1440 double sigmaDeltaPhi = scat->sigmaDeltaPhi();
1441 double sigmaDeltaTheta = scat->sigmaDeltaTheta();
1442 sigmaDeltaPhitot2 += sigmaDeltaPhi * sigmaDeltaPhi;
1443 sigmaDeltaThetatot2 += sigmaDeltaTheta * sigmaDeltaTheta;
1444 scatter_tsos.push_back(comb_tsos);
1445 }
1446 }
1447
1448 ATH_MSG_DEBUG("standaloneRefit Total ID Eloss " << Eloss << " sigma Eloss " << sigmaEloss << " X0 " << X0tot
1449 << " sigma scat phi " << std::sqrt(sigmaDeltaPhitot2) << " sigma scat theta "
1450 << std::sqrt(sigmaDeltaThetatot2));
1451 if (!scatter_tsos.empty()) {
1452 const int itsosMiddle = scatter_tsos.size() / 2;
1453 const Trk::TrackStateOnSurface* mid_scatter = scatter_tsos[itsosMiddle];
1454
1455 std::unique_ptr<Trk::EnergyLoss> energyLossNew = std::make_unique<Trk::EnergyLoss>(Eloss, sigmaEloss, sigmaEloss, sigmaEloss);
1456
1457 const Trk::Surface& surfNew = mid_scatter->trackParameters()->associatedSurface();
1458 Trk::ScatteringAngles scatNew{0., 0., std::sqrt(sigmaDeltaPhitot2), std::sqrt(sigmaDeltaThetatot2)};
1459
1460 std::bitset<Trk::MaterialEffectsBase::NumberOfMaterialEffectsTypes> meotPattern(0);
1463
1464 ATH_MSG_DEBUG(" itsosMiddle " << itsosMiddle << " tsosnr size " << scatter_tsos.size());
1465
1466 std::unique_ptr<Trk::MaterialEffectsOnTrack> meotNew = std::make_unique<Trk::MaterialEffectsOnTrack>(X0tot, scatNew, std::move(energyLossNew), surfNew, meotPattern);
1467
1468 std::unique_ptr<Trk::TrackParameters> parsNew = mid_scatter->trackParameters()->uniqueClone();
1469 std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes> typePatternScat(0);
1470 typePatternScat.set(Trk::TrackStateOnSurface::Scatterer);
1471
1472 std::unique_ptr<Trk::TrackStateOnSurface> newTSOS =
1473 std::make_unique<Trk::TrackStateOnSurface>(nullptr, std::move(parsNew), std::move(meotNew), typePatternScat);
1474
1475 trackStateOnSurfaces->push_back(std::move(newTSOS));
1476 ATH_MSG_DEBUG(" add new TSOS for ID ");
1477 }
1478
1479 } // end m_addElossID
1480
1481 // add the 3 surface calo model
1482 trackStateOnSurfaces->push_back(std::move(innerTSOS));
1483 trackStateOnSurfaces->push_back(std::move(middleTSOS));
1484 trackStateOnSurfaces->push_back(std::move(outerTSOS));
1485 const Trk::TrackParameters* outerTSOSParam = trackStateOnSurfaces->back()->trackParameters();
1486 // MS entrance perigee
1488 std::unique_ptr<Trk::TrackStateOnSurface> entranceTSOS = entrancePerigee(ctx, outerTSOSParam);
1489 if (entranceTSOS) trackStateOnSurfaces->push_back(std::move(entranceTSOS));
1490 }
1491
1492 // leading spectrometer material
1493 bool haveLeadingMaterial = false;
1494
1496 for (; mat_it != cmb_end_itr; ++mat_it) {
1497 if ((*mat_it)->type(Trk::TrackStateOnSurface::Measurement)) break;
1498 haveLeadingMaterial = true;
1499 }
1500
1501 // protection against overruning the end of the vector
1502 if (mat_it == cmb_end_itr) {
1503 ATH_MSG_WARNING("At end of TSOS vector");
1504 return nullptr;
1505 }
1506
1507 if (haveLeadingMaterial) appendSelectedTSOS(*trackStateOnSurfaces, s, ++mat_it);
1508
1509 // insert phi pseudo measurement if necessary
1510 if (addPhiPseudo) {
1511 std::unique_ptr<Trk::TrackStateOnSurface> tsos = createPhiPseudoMeasurement(ctx, combinedTrack);
1512 if (tsos) trackStateOnSurfaces->push_back(std::move(tsos));
1513 }
1514
1515 // then append the remaining TSOS from the input track
1516 appendSelectedTSOS(*trackStateOnSurfaces, mat_it, cmb_end_itr);
1517
1518 // create track for refit
1519 std::unique_ptr<Trk::Track> standaloneTrack =
1520 std::make_unique<Trk::Track>(combinedTrack.info(), std::move(trackStateOnSurfaces), nullptr);
1521 standaloneTrack->info().setPatternRecognitionInfo(Trk::TrackInfo::MuidStandaloneRefit);
1522 if (m_trackQuery->isCombined(*standaloneTrack, ctx)) { ATH_MSG_WARNING(" This should not happen standalone Track has ID hits "); }
1523
1524 if (msgLevel(MSG::DEBUG)) countAEOTs(*standaloneTrack, " in standalone Refit standaloneTrack track before fit ");
1525
1526 std::unique_ptr<Trk::Track> refittedTrack{fit(ctx, *standaloneTrack, false, Trk::muon)};
1527 if (!checkTrack("standaloneRefit", refittedTrack.get())) { return nullptr; }
1528
1529 // eventually this whole tool will use unique_ptrs
1530 // in the meantime, this allows the MuonErrorOptimisationTool and MuonRefitTool to use them
1531 if (refittedTrack) {
1532 if (!refittedTrack->fitQuality()) { return nullptr; }
1533
1534 if (!m_trackQuery->isCaloAssociated(*refittedTrack, ctx)) {
1535 // fail as calo incorrectly described
1536 m_messageHelper->printWarning(28);
1537 return nullptr;
1538 }
1539
1540 if (msgLevel(MSG::DEBUG)) countAEOTs(*refittedTrack, " standaloneRefit final refittedTrack ");
1541
1542 // fit with optimized spectrometer errors
1543 // this should also be inside the "if(refittedTrack) statement
1544 if (!m_muonErrorOptimizer.empty() && !refittedTrack->info().trackProperties(Trk::TrackInfo::StraightTrack) &&
1545 countAEOTs(*refittedTrack, " before optimize ") == 0) {
1546 ATH_MSG_VERBOSE(" perform spectrometer error optimization after cleaning ");
1547 std::unique_ptr<Trk::Track> optimizedTrack = m_muonErrorOptimizer->optimiseErrors(*refittedTrack, ctx);
1548
1549 if (checkTrack("standaloneRefitOpt", optimizedTrack.get())) {
1550 refittedTrack.swap(optimizedTrack);
1551 if (msgLevel(MSG::DEBUG)) countAEOTs(*refittedTrack, " standaloneRefit alignment errors Track ");
1552 }
1553 }
1554 }
1555
1556 // have to release it until the whole tool is migrated to unique_ptr
1557 return refittedTrack;
1558 }
Gaudi::Property< bool > m_useRefitTrackError
void momentumUpdate(std::unique_ptr< Trk::TrackParameters > &parameters, double updatedP, bool directionUpdate=false, double deltaPhi=0., double deltaTheta=0.) const
double sigmaDeltaE() const
returns the symmatric error
virtual const Surface & associatedSurface() const override=0
Access to the Surface associated to the Parameters.
@ MuidStandaloneRefit
Standalone muon that was obtained by refitting a combined muon using the calorimeter information of t...
@ energyDeposit
void Zero(TH1D *hin)
Definition generate.cxx:32
double deltaPhi(double phiA, double phiB)
delta Phi in range [-pi,pi[

◆ vertexOnTrack()

std::unique_ptr< Trk::PseudoMeasurementOnTrack > Rec::CombinedMuonTrackBuilder::vertexOnTrack ( const Trk::TrackParameters & parameters,
const Trk::RecVertex * vertex,
const Trk::RecVertex * mbeamAxis )
staticprivate

Definition at line 2993 of file CombinedMuonTrackBuilder.cxx.

2995 {
2996 // create the corresponding PerigeeSurface, localParameters and covarianceMatrix
2997 const Trk::PerigeeSurface surface(vertex->position());
2998 Trk::LocalParameters localParameters;
2999 Amg::MatrixX covarianceMatrix;
3000 covarianceMatrix.setZero();
3001
3002 // transform Cartesian (x,y,z) to beam axis or perigee
3003 Amg::Vector2D localPosition(0, 0);
3004 double ptInv = 1. / parameters.momentum().perp();
3005
3006 if (vertex == mbeamAxis) {
3008 localParameters = Trk::LocalParameters(d0);
3009
3010 Amg::MatrixX jacobian(1, 3);
3011 jacobian.setZero();
3012 jacobian(0, 0) = -ptInv * parameters.momentum().y();
3013 jacobian(0, 1) = ptInv * parameters.momentum().x();
3014
3015 const Amg::MatrixX& cov = vertex->covariancePosition();
3016 covarianceMatrix = cov.similarity(jacobian);
3017 } else {
3018 localParameters = Trk::LocalParameters(localPosition);
3019
3020 Amg::MatrixX jacobian(2, 3);
3021 jacobian.setZero();
3022 jacobian(0, 0) = -ptInv * parameters.momentum().y();
3023 jacobian(0, 1) = ptInv * parameters.momentum().x();
3024 jacobian(1, 2) = 1.0;
3025
3026 const Amg::MatrixX& cov = vertex->covariancePosition();
3027 covarianceMatrix = cov.similarity(jacobian);
3028 }
3029
3030 return std::make_unique<Trk::PseudoMeasurementOnTrack>(std::move(localParameters),
3031 std::move(covarianceMatrix),
3032 surface);
3033 }
Eigen::Matrix< double, 2, 1 > Vector2D
@ locX
Definition ParamDefs.h:37

Member Data Documentation

◆ m_addElossID

Gaudi::Property<bool> Rec::CombinedMuonTrackBuilder::m_addElossID {this, "AddElossID", true}
private

Definition at line 254 of file CombinedMuonTrackBuilder.h.

254{this, "AddElossID", true};

◆ m_addIDMSerrors

Gaudi::Property<bool> Rec::CombinedMuonTrackBuilder::m_addIDMSerrors {this, "AddIDMSerrors", true}
private

Definition at line 255 of file CombinedMuonTrackBuilder.h.

255{this, "AddIDMSerrors", true};

◆ m_alignUncertTool_phi

PublicToolHandle<Muon::IMuonAlignmentUncertTool> Rec::CombinedMuonTrackBuilder::m_alignUncertTool_phi
private
Initial value:
{this, "AlignmentUncertToolPhi",
"Muon::MuonAlignmentUncertTool/MuonAlignmentUncertToolPhi"}

Definition at line 195 of file CombinedMuonTrackBuilder.h.

195 {this, "AlignmentUncertToolPhi",
196 "Muon::MuonAlignmentUncertTool/MuonAlignmentUncertToolPhi"};

◆ m_alignUncertTool_theta

PublicToolHandle<Muon::IMuonAlignmentUncertTool> Rec::CombinedMuonTrackBuilder::m_alignUncertTool_theta
private
Initial value:
{this, "AlignmentUncertToolTheta",
"Muon::MuonAlignmentUncertTool/MuonAlignmentUncertToolTheta" }

ToolHandles to retrieve the uncertainties for theta and phi for the scattering uncertainties.

Definition at line 193 of file CombinedMuonTrackBuilder.h.

193 {this, "AlignmentUncertToolTheta",
194 "Muon::MuonAlignmentUncertTool/MuonAlignmentUncertToolTheta" };

◆ m_allowCleanerVeto

Gaudi::Property<bool> Rec::CombinedMuonTrackFitter::m_allowCleanerVeto {this, "AllowCleanerVeto", true}
privateinherited

Definition at line 139 of file CombinedMuonTrackFitter.h.

139{this, "AllowCleanerVeto", true};

◆ m_badFitChi2

Gaudi::Property<double> Rec::CombinedMuonTrackFitter::m_badFitChi2 {this, "BadFitChi2", 2.5}
protectedinherited

Definition at line 144 of file CombinedMuonTrackFitter.h.

144{this, "BadFitChi2", 2.5};

◆ m_beamAxis

std::unique_ptr<const Trk::RecVertex> Rec::CombinedMuonTrackBuilder::m_beamAxis
private

Definition at line 239 of file CombinedMuonTrackBuilder.h.

◆ m_caloEnergyParam

ToolHandle<Rec::IMuidCaloEnergy> Rec::CombinedMuonTrackBuilder::m_caloEnergyParam
private
Initial value:
{
this,
"CaloEnergyParam",
"",
}

Definition at line 146 of file CombinedMuonTrackBuilder.h.

146 {
147 this,
148 "CaloEnergyParam",
149 "",
150 };

◆ m_calorimeterVolume

std::unique_ptr<const Trk::Volume> Rec::CombinedMuonTrackFitter::m_calorimeterVolume {nullptr}
protectedinherited

Definition at line 152 of file CombinedMuonTrackFitter.h.

152{nullptr};

◆ m_caloTSOS

ToolHandle<Rec::IMuidCaloTrackStateOnSurface> Rec::CombinedMuonTrackFitter::m_caloTSOS
protectedinherited
Initial value:
{
this,
"CaloTSOS",
"",
}

Definition at line 99 of file CombinedMuonTrackFitter.h.

99 {
100 this,
101 "CaloTSOS",
102 "",
103 };

◆ m_cleanCombined

Gaudi::Property<bool> Rec::CombinedMuonTrackBuilder::m_cleanCombined {this, "CleanCombined", true}
private

Definition at line 212 of file CombinedMuonTrackBuilder.h.

212{this, "CleanCombined", true};

◆ m_cleaner

ToolHandle<Muon::IMuonTrackCleaner> Rec::CombinedMuonTrackFitter::m_cleaner
privateinherited
Initial value:
{
this,
"Cleaner",
"Muon::MuonTrackCleaner/MuidTrackCleaner",
}

Definition at line 82 of file CombinedMuonTrackFitter.h.

82 {
83 this,
84 "Cleaner",
85 "Muon::MuonTrackCleaner/MuidTrackCleaner",
86 };

◆ m_cleanStandalone

Gaudi::Property<bool> Rec::CombinedMuonTrackBuilder::m_cleanStandalone {this, "CleanStandalone", true}
private

Definition at line 213 of file CombinedMuonTrackBuilder.h.

213{this, "CleanStandalone", true};

◆ m_countAcceptedStandaloneFit

std::atomic_uint Rec::CombinedMuonTrackBuilder::m_countAcceptedStandaloneFit {0}
mutableprivate

Definition at line 245 of file CombinedMuonTrackBuilder.h.

245{0};

◆ m_countBeamAxis

std::atomic_uint Rec::CombinedMuonTrackBuilder::m_countBeamAxis {0}
mutableprivate

Definition at line 246 of file CombinedMuonTrackBuilder.h.

246{0};

◆ m_countCombinedCleanerVeto

std::atomic_uint Rec::CombinedMuonTrackFitter::m_countCombinedCleanerVeto {0}
mutableprivateinherited

Definition at line 158 of file CombinedMuonTrackFitter.h.

158{0};

◆ m_countDegradedStandaloneFit

std::atomic_uint Rec::CombinedMuonTrackBuilder::m_countDegradedStandaloneFit {0}
mutableprivate

Definition at line 247 of file CombinedMuonTrackBuilder.h.

247{0};

◆ m_countExtensionCleanerVeto

std::atomic_uint Rec::CombinedMuonTrackFitter::m_countExtensionCleanerVeto {0}
mutableprivateinherited

Definition at line 159 of file CombinedMuonTrackFitter.h.

159{0};

◆ m_countStandaloneCleanerVeto

std::atomic_uint Rec::CombinedMuonTrackFitter::m_countStandaloneCleanerVeto {0}
mutableprivateinherited

Definition at line 160 of file CombinedMuonTrackFitter.h.

160{0};

◆ m_countVertexRegion

std::atomic_uint Rec::CombinedMuonTrackBuilder::m_countVertexRegion {0}
mutableprivate

Definition at line 248 of file CombinedMuonTrackBuilder.h.

248{0};

◆ m_cscRotCreator

ToolHandle<Muon::IMuonClusterOnTrackCreator> Rec::CombinedMuonTrackBuilder::m_cscRotCreator
private
Initial value:
{
this,
"CscRotCreator",
"",
}

Definition at line 151 of file CombinedMuonTrackBuilder.h.

151 {
152 this,
153 "CscRotCreator",
154 "",
155 };

◆ m_edmHelperSvc

ServiceHandle<Muon::IMuonEDMHelperSvc> Rec::CombinedMuonTrackBuilder::m_edmHelperSvc
private
Initial value:
{this, "edmHelper", "Muon::MuonEDMHelperSvc/MuonEDMHelperSvc",
"Handle to the service providing the IMuonEDMHelperSvc interface"}

Definition at line 199 of file CombinedMuonTrackBuilder.h.

199 {this, "edmHelper", "Muon::MuonEDMHelperSvc/MuonEDMHelperSvc",
200 "Handle to the service providing the IMuonEDMHelperSvc interface"};

◆ m_extrapolator

ToolHandle<Trk::IExtrapolator> Rec::CombinedMuonTrackBuilder::m_extrapolator
private
Initial value:
{
this,
"Extrapolator",
"Trk::Extrapolator/AtlasExtrapolator",
}

Definition at line 159 of file CombinedMuonTrackBuilder.h.

159 {
160 this,
161 "Extrapolator",
162 "Trk::Extrapolator/AtlasExtrapolator",
163 };

◆ m_fieldCacheCondObjInputKey

SG::ReadCondHandleKey<AtlasFieldCacheCondObj> Rec::CombinedMuonTrackFitter::m_fieldCacheCondObjInputKey
privateinherited
Initial value:
{this, "AtlasFieldCacheCondObj", "fieldCondObj",
"Name of the Magnetic Field conditions object key"}

Definition at line 133 of file CombinedMuonTrackFitter.h.

133 {this, "AtlasFieldCacheCondObj", "fieldCondObj",
134 "Name of the Magnetic Field conditions object key"};

◆ m_fitter

ToolHandle<Trk::ITrackFitter> Rec::CombinedMuonTrackFitter::m_fitter
privateinherited
Initial value:
{
this,
"Fitter",
"Trk::iPatFitter/iPatFitter",
}

Definition at line 87 of file CombinedMuonTrackFitter.h.

87 {
88 this,
89 "Fitter",
90 "Trk::iPatFitter/iPatFitter",
91 }; // curved track fitter

◆ m_fitterSL

ToolHandle<Trk::ITrackFitter> Rec::CombinedMuonTrackFitter::m_fitterSL
privateinherited
Initial value:
{
this,
"SLFitter",
"Trk::iPatFitter/iPatSLFitter",
}

Definition at line 92 of file CombinedMuonTrackFitter.h.

92 {
93 this,
94 "SLFitter",
95 "Trk::iPatFitter/iPatSLFitter",
96 }; // straight line fitter

◆ m_idHelperSvc

ServiceHandle<Muon::IMuonIdHelperSvc> Rec::CombinedMuonTrackFitter::m_idHelperSvc {this, "MuonIdHelperSvc", "Muon::MuonIdHelperSvc/MuonIdHelperSvc"}
protectedinherited

Definition at line 129 of file CombinedMuonTrackFitter.h.

129{this, "MuonIdHelperSvc", "Muon::MuonIdHelperSvc/MuonIdHelperSvc"};

◆ m_indetVolume

std::unique_ptr<const Trk::Volume> Rec::CombinedMuonTrackFitter::m_indetVolume {nullptr}
protectedinherited

Definition at line 151 of file CombinedMuonTrackFitter.h.

151{nullptr};

◆ m_iterateCombinedTrackFit

Gaudi::Property<bool> Rec::CombinedMuonTrackBuilder::m_iterateCombinedTrackFit {this, "IterateCombinedTrackFit", false}
private

Definition at line 251 of file CombinedMuonTrackBuilder.h.

251{this, "IterateCombinedTrackFit", false};

◆ m_largeImpact

Gaudi::Property<double> Rec::CombinedMuonTrackBuilder::m_largeImpact {this, "LargeImpact", 100. * Gaudi::Units::mm}
private

Definition at line 219 of file CombinedMuonTrackBuilder.h.

219{this, "LargeImpact", 100. * Gaudi::Units::mm};

◆ m_largeMomentumChange

Gaudi::Property<double> Rec::CombinedMuonTrackBuilder::m_largeMomentumChange {this, "LargeMomentumChange", 0.05}
private

Definition at line 221 of file CombinedMuonTrackBuilder.h.

221{this, "LargeMomentumChange", 0.05};

◆ m_largeMomentumError

Gaudi::Property<double> Rec::CombinedMuonTrackBuilder::m_largeMomentumError {this, "LargeMomentumError", 0.15}
private

Definition at line 222 of file CombinedMuonTrackBuilder.h.

222{this, "LargeMomentumError", 0.15};

◆ m_largePhiError

Gaudi::Property<double> Rec::CombinedMuonTrackBuilder::m_largePhiError {this, "LargePhiError", 0.020}
private

Definition at line 223 of file CombinedMuonTrackBuilder.h.

223{this, "LargePhiError", 0.020};

◆ m_lineMomentum

Gaudi::Property<double> Rec::CombinedMuonTrackBuilder::m_lineMomentum {this, "LineMomentum", 2. * Gaudi::Units::GeV}
private

Definition at line 224 of file CombinedMuonTrackBuilder.h.

224{this, "LineMomentum", 2. * Gaudi::Units::GeV};

◆ m_lowMomentum

Gaudi::Property<double> Rec::CombinedMuonTrackBuilder::m_lowMomentum {this, "LowMomentum", 10. * Gaudi::Units::GeV}
private

Definition at line 225 of file CombinedMuonTrackBuilder.h.

225{this, "LowMomentum", 10. * Gaudi::Units::GeV};

◆ m_magFieldProperties

Trk::MagneticFieldProperties Rec::CombinedMuonTrackBuilder::m_magFieldProperties {Trk::FullField}
private

Definition at line 209 of file CombinedMuonTrackBuilder.h.

@ FullField
Field is set to be realistic, but within a given Volume.

◆ m_materialAllocator

ToolHandle<Trk::IMaterialAllocator> Rec::CombinedMuonTrackBuilder::m_materialAllocator
private
Initial value:
{
this,
"MaterialAllocator",
"",
}

Definition at line 164 of file CombinedMuonTrackBuilder.h.

164 {
165 this,
166 "MaterialAllocator",
167 "",
168 };

◆ m_materialUpdator

ToolHandle<Trk::ITrkMaterialProviderTool> Rec::CombinedMuonTrackFitter::m_materialUpdator
protectedinherited
Initial value:
{
this,
"CaloMaterialProvider",
"",
}

Definition at line 124 of file CombinedMuonTrackFitter.h.

124 {
125 this,
126 "CaloMaterialProvider",
127 "",
128 };

◆ m_maxWarnings

Gaudi::Property<unsigned> Rec::CombinedMuonTrackFitter::m_maxWarnings
privateinherited
Initial value:
{this, "MaxNumberOfWarnings", 10,
"Maximum number of permitted WARNING messages per message type."}

Definition at line 140 of file CombinedMuonTrackFitter.h.

140 {this, "MaxNumberOfWarnings", 10,
141 "Maximum number of permitted WARNING messages per message type."};

◆ m_mdtRotCreator

ToolHandle<Muon::IMdtDriftCircleOnTrackCreator> Rec::CombinedMuonTrackBuilder::m_mdtRotCreator
private
Initial value:
{
this,
"MdtRotCreator",
"",
}

Definition at line 169 of file CombinedMuonTrackBuilder.h.

169 {
170 this,
171 "MdtRotCreator",
172 "",
173 };

◆ m_messageHelper

std::unique_ptr<MessageHelper> Rec::CombinedMuonTrackFitter::m_messageHelper {std::make_unique<MessageHelper>(*this, 50)}
protectedinherited

Definition at line 155 of file CombinedMuonTrackFitter.h.

155{std::make_unique<MessageHelper>(*this, 50)};

◆ m_minEnergy

Gaudi::Property<double> Rec::CombinedMuonTrackBuilder::m_minEnergy {this, "MinEnergy", 0.3 * Gaudi::Units::GeV}
private

Definition at line 227 of file CombinedMuonTrackBuilder.h.

227{this, "MinEnergy", 0.3 * Gaudi::Units::GeV};

◆ m_muClusterRotCreator

ToolHandle<Muon::IMuonClusterOnTrackCreator> Rec::CombinedMuonTrackBuilder::m_muClusterRotCreator {this, "MuonRotCreator", ""}
private

Definition at line 157 of file CombinedMuonTrackBuilder.h.

157{this, "MuonRotCreator", ""};

◆ m_muonErrorOptimizer

ToolHandle<Muon::IMuonErrorOptimisationTool> Rec::CombinedMuonTrackFitter::m_muonErrorOptimizer
protectedinherited
Initial value:
{
this,
"MuonErrorOptimizer",
"",
}

Definition at line 104 of file CombinedMuonTrackFitter.h.

104 {
105 this,
106 "MuonErrorOptimizer",
107 "",
108 };

◆ m_muonHoleRecovery

ToolHandle<Muon::IMuonHoleRecoveryTool> Rec::CombinedMuonTrackBuilder::m_muonHoleRecovery
private
Initial value:
{
this,
"MuonHoleRecovery",
"",
}

Definition at line 174 of file CombinedMuonTrackBuilder.h.

174 {
175 this,
176 "MuonHoleRecovery",
177 "",
178 };

◆ m_numberSigmaFSR

Gaudi::Property<double> Rec::CombinedMuonTrackBuilder::m_numberSigmaFSR {this, "NumberSigmaFSR", 2.5}
private

Definition at line 228 of file CombinedMuonTrackBuilder.h.

228{this, "NumberSigmaFSR", 2.5};

◆ m_perigeeAtSpectrometerEntrance

Gaudi::Property<bool> Rec::CombinedMuonTrackBuilder::m_perigeeAtSpectrometerEntrance {this, "PerigeeAtSpectrometerEntrance", false}
private

Definition at line 215 of file CombinedMuonTrackBuilder.h.

215{this, "PerigeeAtSpectrometerEntrance", false};

◆ m_perigeeSurface

std::unique_ptr<const Trk::PerigeeSurface> Rec::CombinedMuonTrackBuilder::m_perigeeSurface
private

Definition at line 240 of file CombinedMuonTrackBuilder.h.

◆ m_printer

PublicToolHandle<Muon::MuonEDMPrinterTool> Rec::CombinedMuonTrackFitter::m_printer
protectedinherited
Initial value:
{
this,
"Printer",
"Muon::MuonEDMPrinterTool/MuonEDMPrinterTool",
}

Definition at line 109 of file CombinedMuonTrackFitter.h.

109 {
110 this,
111 "Printer",
112 "Muon::MuonEDMPrinterTool/MuonEDMPrinterTool",
113 };

◆ m_propagator

ToolHandle<Trk::IPropagator> Rec::CombinedMuonTrackBuilder::m_propagator
private
Initial value:
{
this,
"Propagator",
"Trk::IntersectorWrapper/IntersectorWrapper",
}

Definition at line 179 of file CombinedMuonTrackBuilder.h.

179 {
180 this,
181 "Propagator",
182 "Trk::IntersectorWrapper/IntersectorWrapper",
183 };

◆ m_propagatorSL

ToolHandle<Trk::IPropagator> Rec::CombinedMuonTrackBuilder::m_propagatorSL
private
Initial value:
{
this,
"SLPropagator",
"Trk::StraightLinePropagator/MuonStraightLinePropagator",
}

Definition at line 184 of file CombinedMuonTrackBuilder.h.

184 {
185 this,
186 "SLPropagator",
187 "Trk::StraightLinePropagator/MuonStraightLinePropagator",
188 };

◆ m_reallocateMaterial

Gaudi::Property<bool> Rec::CombinedMuonTrackBuilder::m_reallocateMaterial {this, "ReallocateMaterial", true}
private

Definition at line 216 of file CombinedMuonTrackBuilder.h.

216{this, "ReallocateMaterial", true};

◆ m_redoRots

bool Rec::CombinedMuonTrackBuilder::m_redoRots {false}
private

Definition at line 235 of file CombinedMuonTrackBuilder.h.

235{false};

◆ m_refineELossCombinedTrackFit

Gaudi::Property<bool> Rec::CombinedMuonTrackBuilder::m_refineELossCombinedTrackFit {this, "RefineELossCombinedTrackFit", true}
private

Definition at line 252 of file CombinedMuonTrackBuilder.h.

252{this, "RefineELossCombinedTrackFit", true};

◆ m_refineELossStandAloneTrackFit

Gaudi::Property<bool> Rec::CombinedMuonTrackBuilder::m_refineELossStandAloneTrackFit {this, "RefineELossStandAloneTrackFit", true}
private

Definition at line 253 of file CombinedMuonTrackBuilder.h.

253{this, "RefineELossStandAloneTrackFit", true};

◆ m_trackingGeometryReadKey

SG::ReadCondHandleKey<Trk::TrackingGeometry> Rec::CombinedMuonTrackBuilder::m_trackingGeometryReadKey
private
Initial value:
{this, "TrackingGeometryReadKey", "",
"Key of the TrackingGeometry conditions data."}

Definition at line 205 of file CombinedMuonTrackBuilder.h.

205 {this, "TrackingGeometryReadKey", "",
206 "Key of the TrackingGeometry conditions data."};

◆ m_trackingVolumesSvc

ServiceHandle<Trk::ITrackingVolumesSvc> Rec::CombinedMuonTrackFitter::m_trackingVolumesSvc {this, "TrackingVolumesSvc", "Trk::TrackingVolumesSvc/TrackingVolumesSvc"}
privateinherited

Definition at line 136 of file CombinedMuonTrackFitter.h.

136{this, "TrackingVolumesSvc", "Trk::TrackingVolumesSvc/TrackingVolumesSvc"};

◆ m_trackQuery

ToolHandle<Rec::IMuonTrackQuery> Rec::CombinedMuonTrackFitter::m_trackQuery
protectedinherited
Initial value:
{
this,
"TrackQuery",
"Rec::MuonTrackQuery/MuonTrackQuery",
}

Definition at line 114 of file CombinedMuonTrackFitter.h.

114 {
115 this,
116 "TrackQuery",
117 "Rec::MuonTrackQuery/MuonTrackQuery",
118 };

◆ m_trackSummary

ToolHandle<Trk::ITrackSummaryTool> Rec::CombinedMuonTrackFitter::m_trackSummary
protectedinherited
Initial value:
{
this,
"TrackSummaryTool",
"Trk::TrackSummaryTool/MuidTrackSummaryTool",
}

Definition at line 119 of file CombinedMuonTrackFitter.h.

119 {
120 this,
121 "TrackSummaryTool",
122 "Trk::TrackSummaryTool/MuidTrackSummaryTool",
123 };

◆ m_updateWithCaloTG

Gaudi::Property<bool> Rec::CombinedMuonTrackFitter::m_updateWithCaloTG {this, "UpdateWithCaloTG", false}
protectedinherited

Definition at line 147 of file CombinedMuonTrackFitter.h.

147{this, "UpdateWithCaloTG", false};

◆ m_useCaloTG

Gaudi::Property<bool> Rec::CombinedMuonTrackFitter::m_useCaloTG {this, "UseCaloTG", false}
protectedinherited

Definition at line 148 of file CombinedMuonTrackFitter.h.

148{this, "UseCaloTG", false};

◆ m_useRefitTrackError

Gaudi::Property<bool> Rec::CombinedMuonTrackBuilder::m_useRefitTrackError {this, "UseRefitTrackError", true}
private

Definition at line 256 of file CombinedMuonTrackBuilder.h.

256{this, "UseRefitTrackError", true};

◆ m_vertex

std::unique_ptr<const Trk::RecVertex> Rec::CombinedMuonTrackBuilder::m_vertex
private

Definition at line 242 of file CombinedMuonTrackBuilder.h.

◆ m_vertex2DSigmaRPhi

Gaudi::Property<double> Rec::CombinedMuonTrackBuilder::m_vertex2DSigmaRPhi {this, "Vertex2DSigmaRPhi", 100. * Gaudi::Units::mm}
private

Definition at line 230 of file CombinedMuonTrackBuilder.h.

230{this, "Vertex2DSigmaRPhi", 100. * Gaudi::Units::mm};

◆ m_vertex2DSigmaZ

Gaudi::Property<double> Rec::CombinedMuonTrackBuilder::m_vertex2DSigmaZ {this, "Vertex2DSigmaZ", 100. * Gaudi::Units::meter}
private

Definition at line 231 of file CombinedMuonTrackBuilder.h.

231{this, "Vertex2DSigmaZ", 100. * Gaudi::Units::meter};

◆ m_vertex3DSigmaRPhi

Gaudi::Property<double> Rec::CombinedMuonTrackBuilder::m_vertex3DSigmaRPhi {this, "Vertex3DSigmaRPhi", 6. * Gaudi::Units::mm}
private

Definition at line 232 of file CombinedMuonTrackBuilder.h.

232{this, "Vertex3DSigmaRPhi", 6. * Gaudi::Units::mm};

◆ m_vertex3DSigmaZ

Gaudi::Property<double> Rec::CombinedMuonTrackBuilder::m_vertex3DSigmaZ {this, "Vertex3DSigmaZ", 60. * Gaudi::Units::mm}
private

Definition at line 233 of file CombinedMuonTrackBuilder.h.

233{this, "Vertex3DSigmaZ", 60. * Gaudi::Units::mm};

◆ m_zECToroid

Gaudi::Property<double> Rec::CombinedMuonTrackFitter::m_zECToroid {this, "zECToroid", 10. * Gaudi::Units::meter}
protectedinherited

Definition at line 146 of file CombinedMuonTrackFitter.h.

146{this, "zECToroid", 10. * Gaudi::Units::meter};

The documentation for this class was generated from the following files: