ATLAS Offline Software
Loading...
Searching...
No Matches
MsTrackFindingAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include "MsTrackFindingAlg.h"
6
7#include "Acts/Surfaces/PerigeeSurface.hpp"
8#include "Acts/Surfaces/PlaneSurface.hpp"
9#include "Acts/Surfaces/detail/PlanarHelper.hpp"
10
11
17
18#include "GaudiKernel/PhysicalConstants.h"
21
23#include "GaudiKernel/PhysicalConstants.h"
26
27#include <system_error>
28
29using namespace Acts::UnitLiterals;
30using namespace Acts::PlanarHelper;
31
32namespace MuonR4{
34 ATH_CHECK(m_segmentKey.initialize());
35 ATH_CHECK(m_idHelperSvc.retrieve());
36 ATH_CHECK(detStore()->retrieve(m_detMgr));
37 ATH_CHECK(m_segSelector.retrieve());
38 ATH_CHECK(m_msTrkSeedKey.initialize());
39
40 ATH_CHECK(m_visualizationTool.retrieve(EnableTool{!m_visualizationTool.empty()}));
43 ATH_CHECK(m_trackFitTool.retrieve());
44 ATH_CHECK(m_calibTool.retrieve());
45 ATH_CHECK(m_writeKey.initialize());
46
47 if (m_trackingGeometryTool->trackingGeometry()->geometryVersion() !=
48 Acts::TrackingGeometry::GeometryVersion::Gen3){
49 ATH_MSG_ERROR("The MS track fit requires the Gen 3 geometry format");
50 return StatusCode::FAILURE;
51 }
52
53 MsTrackSeeder::Config seederCfg{};
55 seederCfg.selector = m_segSelector.get();
56 seederCfg.detMgr = m_detMgr;
57
58 m_seeder = std::make_unique<MsTrackSeeder>(name(), std::move(seederCfg));
59 return StatusCode::SUCCESS;
60 }
61
63
64 StatusCode MsTrackFindingAlg::execute(const EventContext& ctx) const {
65 ATH_MSG_VERBOSE("Run track finding in event "<<ctx.eventID().event_number());
66
67 const xAOD::MuonSegmentContainer* allEventSegs{nullptr};
68 ATH_CHECK(SG::get(allEventSegs, m_segmentKey, ctx));
69
70 auto seedContainer = findTrackSeeds(ctx, *allEventSegs);
71
72 const Acts::GeometryContext tgContext = m_trackingGeometryTool->getGeometryContext(ctx).context();
73 const Acts::MagneticFieldContext mfContext = m_extrapolationTool->getMagneticFieldContext(ctx);
74 const Acts::CalibrationContext calContext{ActsTrk::getCalibrationContext(ctx)};
75
76
77 Acts::VectorTrackContainer trackBackend{};
78 Acts::VectorMultiTrajectory trackStateBackend{};
79 ActsTrk::MutableTrackContainer cacheTrkContainer{std::move(trackBackend),
80 std::move(trackStateBackend)};
82 cacheTrkContainer.addColumn<std::size_t>("parentSeed");
83 unsigned seedIdx{0};
84 for (const MsTrackSeed& seed : *seedContainer) {
85 if (!fitSeedCandidate(tgContext, mfContext, calContext, seed,
86 cacheTrkContainer)) {
87 ++seedIdx;
88 continue;
89 }
90 auto lastTrack = cacheTrkContainer.getTrack(cacheTrkContainer.size() -1);
91 lastTrack.component<std::size_t, Acts::hashString("parentSeed")>() = seedIdx;
92 ++seedIdx;
93 }
94 SG::WriteHandle writeHandleSeed{m_msTrkSeedKey, ctx};
95 ATH_CHECK(writeHandleSeed.record(std::move(seedContainer)));
96
97 // Constant declination
98 Acts::ConstVectorTrackContainer ctrackBackend{std::move(cacheTrkContainer.container())};
99 Acts::ConstVectorMultiTrajectory ctrackStateBackend{std::move(cacheTrkContainer.trackStateContainer())};
100 auto ctc = std::make_unique<ActsTrk::TrackContainer>(std::move(ctrackBackend),
101 std::move(ctrackStateBackend));
102
103 SG::WriteHandle writeHandle{m_writeKey, ctx};
104 ATH_CHECK(writeHandle.record(std::move(ctc)));
105 return StatusCode::SUCCESS;
106 }
107
108 std::unique_ptr<MsTrackSeedContainer>
109 MsTrackFindingAlg::findTrackSeeds(const EventContext& ctx,
110 const xAOD::MuonSegmentContainer& segments) const {
111
112 auto seedContainer = m_seeder->findTrackSeeds(ctx, m_trackingGeometryTool->getGeometryContext(ctx), segments);
113
114 if (!m_visualizationTool.empty()) {
115 m_visualizationTool->displaySeeds(ctx, *m_seeder, segments, *seedContainer);
116 }
117 return seedContainer;
118 }
121 MsTrackFindingAlg::prepareFit(const Acts::GeometryContext& tgContext,
122 const Acts::MagneticFieldContext& mfContext,
123 const Acts::CalibrationContext& calContext,
124 const MsTrackSeed& seed) const {
125 const EventContext& ctx{*calContext.get<const EventContext*>()};
126 MeasVec_t measurements{};
127 measurements.reserve(100);
129 const xAOD::MuonSegment* refSeg{nullptr};
130 for (const xAOD::MuonSegment* segment : seed.segments()) {
132 m_calibTool->stampSignsOnMeasurements(*segment);
133 MeasVec_t segMeasurements = collectMeasurements(*segment, /*skipOutlier:*/ true);
134 if (msgLvl(MSG::VERBOSE)) {
135 std::stringstream sstr{};
136 for (const xAOD::UncalibratedMeasurement* m : segMeasurements) {
137 const Acts::Surface& surf{xAOD::muonSurface(m)};
138 sstr<<" *** "<<m_idHelperSvc->toString(xAOD::identify(m))
139 <<", "<<m->numDimensions()<<", "
140 <<", "<<surf.geometryId()<<" @ "<<Amg::toString(surf.localToGlobalTransform(tgContext))<<std::endl;
141 }
142 ATH_MSG_VERBOSE("Fetch measurements from segment: "<<Amg::toString(segment->position())
143 <<", direction: "<<Amg::toString(segment->direction())<<"\n"<<sstr.str());
144 }
145 measurements.insert(measurements.end(),
146 std::make_move_iterator(segMeasurements.begin()),
147 std::make_move_iterator(segMeasurements.end()));
148
149 if (!refSeg && m_segSelector->passSeedingQuality(ctx, *detailedSegment(*segment))) {
150 refSeg = segment;
151 }
152 }
153 if (!refSeg || measurements.empty()) {
154 ATH_MSG_WARNING(__func__<<"() "<<__LINE__
155 <<" - No reference segment passing seeding quality "<<
156 (refSeg != nullptr)<<" was found. #"<<measurements.size()<<" measurements. ");
157 return std::make_pair(Acts::Result<Acts::BoundTrackParameters>::failure(std::make_error_code(std::errc::invalid_argument)),
158 std::vector<const xAOD::UncalibratedMeasurement_v1*>{});
159 }
160 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - "<<measurements.size()<<" measurements");
161 Amg::Vector3D seedPos{refSeg->position()};
162 Amg::Vector3D seedDir{refSeg->direction()};
166 if (refSeg != seed.segments().front()) {
167 const MuonGMR4::SpectrometerSector* innerPlane = m_seeder->envelope(*seed.segments().front());
168 const Acts::PlaneSurface& surf = innerPlane->surface();
169 const Amg::Transform3D toInnerPlane = surf.localToGlobalTransform(tgContext).inverse();
170 const Amg::Vector3D locSeedPos = toInnerPlane * seedPos;
171 const Amg::Vector3D locSeedDir = toInnerPlane.linear() * seedDir;
172
173 auto seedOnInner = Acts::PlanarHelper::intersectPlane(locSeedPos, locSeedDir,
174 Amg::Vector3D::UnitZ(), 0.);
175
176 using enum SegmentFit::ParamDefs;
177 SegmentFit::Parameters innerPars = SegmentFit::localSegmentPars(*seed.segments().front());
178 innerPars[Acts::toUnderlying(x0)] = seedOnInner.position().x();
179 const Amg::Vector3D innerSegDir =
180 Acts::makeDirectionFromPhiTheta(innerPars[Acts::toUnderlying(phi)],
181 innerPars[Acts::toUnderlying(theta)]);
182 const Amg::Vector3D combSegDir =
183 Acts::makeDirectionFromAxisTangents(houghTanAlpha(locSeedDir),
184 houghTanBeta(innerSegDir));
185 seedPos = surf.localToGlobalTransform(tgContext) * Amg::Vector3D{innerPars[Acts::toUnderlying(x0)],
186 innerPars[Acts::toUnderlying(y0)], 0};
187 seedDir = surf.localToGlobalTransform(tgContext).linear() * combSegDir;
188 }
195 const xAOD::UncalibratedMeasurement* firstVolumeMeas{nullptr};
196 const Acts::TrackingVolume* volume{nullptr};
197 for (const xAOD::UncalibratedMeasurement* meas : measurements) {
198 const Acts::GeometryIdentifier volId = volumeId(xAOD::muonSurface(meas));
199 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - Check measurement "
200 <<m_idHelperSvc->toString(xAOD::identify(meas))<<", "<<xAOD::muonSurface(meas).geometryId());
201 volume = m_trackingGeometryTool->trackingGeometry()->findVolume(volId);
202 if (volume) {
203 firstVolumeMeas = meas;
204 break;
205 }
206 }
207
208 if (!volume) {
209 ATH_MSG_WARNING(__func__<<"() "<<__LINE__
210 <<" - Failed to find tracking volume for any seed measurement");
211 return std::make_pair(Acts::Result<Acts::BoundTrackParameters>::failure(std::make_error_code(std::errc::invalid_argument)),
212 std::vector<const xAOD::UncalibratedMeasurement_v1*>{});
213 }
214 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - Using seed measurement "
215 << m_idHelperSvc->toString(xAOD::identify(firstVolumeMeas))
216 << " with volume id " << volumeId(xAOD::muonSurface(firstVolumeMeas)));
217
218 auto boundSurf = MuonGMR4::bottomBoundary(*volume);
219 if (!boundSurf) {
220 ATH_MSG_WARNING(__func__<<"() "<<__LINE__<<" - Failed to find boundary surface for tracking volume");
221 return std::make_pair(Acts::Result<Acts::BoundTrackParameters>::failure(std::make_error_code(std::errc::invalid_argument)),
222 std::vector<const xAOD::UncalibratedMeasurement_v1*>{});
223 }
224 auto targetSurf = boundSurf->getSharedPtr();
225 using namespace Acts::PlanarHelper;
226
227 auto pIsect = intersectPlane(seedPos, seedDir,
228 targetSurf->localToGlobalTransform(tgContext).linear().col(2),
229 targetSurf->center(tgContext));
230
231 auto fourPos = ActsTrk::convertPosToActs(pIsect.position(), pIsect.position().mag() / Gaudi::Units::c_light);
232 const double qOverP = 1./ m_seeder->estimateQtimesP(*tgContext.get<const ActsTrk::GeometryContext*>(),
233 *mfContext.get<const AtlasFieldCacheCondObj*>(), seed);
234 auto initialPars = Acts::BoundTrackParameters::create(tgContext, targetSurf, fourPos,
235 seedDir, ActsTrk::energyToActs(qOverP),
236 Acts::BoundMatrix::Identity(),
237 Acts::ParticleHypothesis::muon());
238 return std::make_pair(std::move(initialPars), std::move(measurements));
239
240 }
241 bool MsTrackFindingAlg::fitSeedCandidate(const Acts::GeometryContext& tgContext,
242 const Acts::MagneticFieldContext& mfContext,
243 const Acts::CalibrationContext& calContext,
244 const MsTrackSeed& seed,
245 ActsTrk::MutableTrackContainer& outContainer) const {
246
247 ATH_MSG_DEBUG(__func__<<"() "<<__LINE__<<" - Attempt to fit a new track seed \n"<<seed);
248 const EventContext& ctx{*calContext.get<const EventContext*>()};
249 const auto [initialPars, measurements] = prepareFit(tgContext, mfContext, calContext, seed);
250
251 if (!initialPars.ok()) {
252 ATH_MSG_WARNING(__func__<<"() "<<__LINE__<<" - Failed to construct valid parameters for seed \n"<<seed);
253 if (m_visualizationTool.isEnabled()) {
254 m_visualizationTool->displayTrackSeedObj(ctx, seed, initialPars, "FailedStartPars");
255 }
256 return false;
257 }
258 auto fitTraject = m_trackFitTool->fit(measurements, *initialPars,
259 tgContext, mfContext, calContext,
260 &(*initialPars).referenceSurface());
261 if (!fitTraject || fitTraject->size() == 0) {
262 ATH_MSG_DEBUG(__func__<<"() "<<__LINE__<<" - Fit failed ");
263 if (m_visualizationTool.isEnabled()) {
264 m_visualizationTool->displayTrackSeedObj(ctx, seed, initialPars, "FailedFit");
265 }
266 return false;
267 }
272 {
273 fitTraject->addColumn<std::vector<const xAOD::MuonSegment*>>("muonSegLinks");
274 fitTraject->getTrack(0).component<std::vector<const xAOD::MuonSegment*>>("muonSegLinks") = seed.segments();
275 }
276 outContainer.ensureDynamicColumns(*fitTraject);
277 auto destProxy = outContainer.getTrack(outContainer.addTrack());
278 destProxy.copyFrom(fitTraject->getTrack(0));
279 ATH_MSG_DEBUG(__func__<<"() "<<__LINE__<<" - Good track fit...");
280 if (m_visualizationTool.isEnabled()) {
281 m_visualizationTool->displayTrackSeedObj(ctx, seed,
282 destProxy.createParametersAtReference(), "GoodFit");
283 }
284 return true;
285 }
286
287}
Scalar phi() const
phi method
Scalar theta() const
theta method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
ATLAS-specific HepMC functions.
const ServiceHandle< StoreGateSvc > & detStore() const
bool msgLvl(const MSG::Level lvl) const
A spectrometer sector forms the envelope of all chambers that are placed in the same MS sector & laye...
const Acts::PlaneSurface & surface() const
Returns the associated surface.
Acts::Result< Acts::BoundTrackParameters > OptBoundPars_t
Gaudi::Property< double > m_seedHalfLength
Maximum search window to search segments for.
std::unique_ptr< MsTrackSeedContainer > findTrackSeeds(const EventContext &ctx, const xAOD::MuonSegmentContainer &segments) const
Iterates over the search tree and combines close-by segments to a track seed.
std::vector< const xAOD::UncalibratedMeasurement * > MeasVec_t
SG::WriteHandleKey< ActsTrk::TrackContainer > m_writeKey
Key to the output track container.
std::unique_ptr< MsTrackSeeder > m_seeder
Pointer to the actual seeder implementation.
SG::WriteHandleKey< MsTrackSeedContainer > m_msTrkSeedKey
Temporary container write handle to push the seeds to store gate for later efficiency analysis.
virtual StatusCode execute(const EventContext &ctx) const override final
Standard algorithm execution hook.
ToolHandle< ISpacePointCalibrator > m_calibTool
Calibration tool to fill the track states.
ToolHandle< MuonValR4::ITrackVisualizationTool > m_visualizationTool
Visualization tool to debug the track finding.
const MuonGMR4::MuonDetectorManager * m_detMgr
Pointer to the MuonDetectorManager.
ToolHandle< ActsTrk::IFitterTool > m_trackFitTool
Track fitting tool.
PublicToolHandle< ActsTrk::ITrackingGeometryTool > m_trackingGeometryTool
Tracking geometry tool.
virtual StatusCode initialize() override final
Standard algorithm hook to setup the extrapolator, retrieve the tools and declare algorithm's data de...
ToolHandle< ISegmentSelectionTool > m_segSelector
Segment selection tool to pick the good quality segments.
std::pair< OptBoundPars_t, MeasVec_t > prepareFit(const Acts::GeometryContext &tgContext, const Acts::MagneticFieldContext &mfContext, const Acts::CalibrationContext &calContext, const MsTrackSeed &seed) const
Prepares the input by the fit by collecting the measurements on the segment &.
ToolHandle< ActsTrk::IExtrapolationTool > m_extrapolationTool
Track extrapolation tool.
SG::ReadHandleKey< xAOD::MuonSegmentContainer > m_segmentKey
Declare the data dependency on the standard Mdt+Rpc+Tgc segment container & on the NSW segment contai...
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
IdHelperSvc to decode the Identifiers.
bool fitSeedCandidate(const Acts::GeometryContext &gCtx, const Acts::MagneticFieldContext &mCtx, const Acts::CalibrationContext &cCtx, const MsTrackSeed &seed, ActsTrk::MutableTrackContainer &outContainer) const
Attempts to fit the track seed candidate to a full track and returns whether the fit succeeded.
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
Amg::Vector3D direction() const
Returns the direction as Amg::Vector.
Amg::Vector3D position() const
Returns the position as Amg::Vector.
constexpr double energyToActs(const double athenaE)
Converts an energy scalar from Athena to Acts units.
Acts::TrackContainer< MutableTrackBackend, MutableTrackStateBackend, Acts::detail::ValueHolder > MutableTrackContainer
Acts::CalibrationContext getCalibrationContext(const EventContext &ctx)
The Acts::Calibration context is piped through the Acts fitters to (re)calibrate the Acts::SourceLink...
Acts::Vector4 convertPosToActs(const Amg::Vector3D &athenaPos, const double athenaTime=0.)
Converts a position vector & time from Athena units into Acts units.
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
const Acts::Surface * bottomBoundary(const Acts::TrackingVolume &volume)
Returns the boundary surface parallel to the x-y plane at negative local z.
SeedingAux::FitParIndex ParamDefs
Use the same parameter indices as used by the CompSpacePointAuxiliaries.
Parameters localSegmentPars(const xAOD::MuonSegment &seg)
Returns the localSegPars decoration from a xAODMuon::Segment.
Acts::Experimental::CompositeSpacePointLineFitter::ParamVec_t Parameters
This header ties the generic definitions in this package.
double houghTanBeta(const Amg::Vector3D &v)
Returns the hough tanBeta [y] / [z].
std::vector< const xAOD::UncalibratedMeasurement * > collectMeasurements(const xAOD::MuonSegment &segment, bool skipOutlier=true)
Helper function to extract the measurements from the segment.
Acts::GeometryIdentifier volumeId(const Acts::Surface &surface)
Returns the identifier of the volume in which the surface is embedded.
double houghTanAlpha(const Amg::Vector3D &v)
: Returns the hough tanAlpha [x] / [z]
const Segment * detailedSegment(const xAOD::MuonSegment &seg)
Helper function to navigate from the xAOD::MuonSegment to the MuonR4::Segment.
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
MuonSegmentContainer_v1 MuonSegmentContainer
Definition of the current "MuonSegment container version".
const Identifier & identify(const UncalibratedMeasurement *meas)
Returns the associated identifier from the muon measurement.
MuonSegment_v1 MuonSegment
Reference the current persistent version:
const Acts::Surface & muonSurface(const UncalibratedMeasurement *meas)
Returns the associated Acts surface to the measurement.
UncalibratedMeasurement_v1 UncalibratedMeasurement
Define the version of the uncalibrated measurement class.
Configuration object.
const MuonGMR4::MuonDetectorManager * detMgr
Detector manager to fetch the sector enevelope transforms.
double seedHalfLength
Maximum separation of point on the cylinder to be picked up onto a seed.
const ISegmentSelectionTool * selector
Pointer to the segement selection tool which compares two segments for their compatibilitiy.