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"
22
24
26#include "GaudiKernel/PhysicalConstants.h"
29
30#include <system_error>
31
32using namespace Acts::UnitLiterals;
33using namespace Acts::PlanarHelper;
34
35namespace {
36 bool isNswSegment(const xAOD::MuonSegment& seg) {
37 using namespace Muon::MuonStationIndex;
38
39 return seg.technology() == TechnologyIndex::STGC ||
41 toStationIndex(seg.chamberIndex()) == StIndex::EE;
42 }
43
44}
45
46namespace MuonR4{
48 ATH_CHECK(m_segmentKey.initialize());
49 ATH_CHECK(m_idHelperSvc.retrieve());
50 ATH_CHECK(detStore()->retrieve(m_detMgr));
51 ATH_CHECK(m_segSelector.retrieve());
52 ATH_CHECK(m_msTrkSeedKey.initialize());
53
54 ATH_CHECK(m_visualizationTool.retrieve(EnableTool{!m_visualizationTool.empty()}));
57 ATH_CHECK(m_trackFitTool.retrieve());
58 ATH_CHECK(m_calibTool.retrieve());
59 ATH_CHECK(m_writeKey.initialize());
60 ATH_CHECK(m_summaryTool.retrieve());
61
62 if (m_trackingGeometryTool->trackingGeometry()->geometryVersion() !=
63 Acts::TrackingGeometry::GeometryVersion::Gen3){
64 ATH_MSG_ERROR("The MS track fit requires the Gen 3 geometry format");
65 return StatusCode::FAILURE;
66 }
67
68 MsTrackSeeder::Config seederCfg{};
70 seederCfg.selector = m_segSelector.get();
71 seederCfg.detMgr = m_detMgr;
72
73 m_seeder = std::make_unique<MsTrackSeeder>(name(), std::move(seederCfg));
74 return StatusCode::SUCCESS;
75 }
76
78
79 StatusCode MsTrackFindingAlg::execute(const EventContext& ctx) const {
80 ATH_MSG_VERBOSE("Run track finding in event "<<ctx.eventID().event_number());
81
82 const xAOD::MuonSegmentContainer* allEventSegs{nullptr};
83 ATH_CHECK(SG::get(allEventSegs, m_segmentKey, ctx));
84
85 auto seedContainer = findTrackSeeds(ctx, *allEventSegs);
86
87 const Acts::GeometryContext tgContext = m_trackingGeometryTool->getGeometryContext(ctx).context();
88 const Acts::MagneticFieldContext mfContext = m_extrapolationTool->getMagneticFieldContext(ctx);
89 const Acts::CalibrationContext calContext{ActsTrk::getCalibrationContext(ctx)};
90
91
92 Acts::VectorTrackContainer trackBackend{};
93 Acts::VectorMultiTrajectory trackStateBackend{};
94 ActsTrk::MutableTrackContainer cacheTrkContainer{std::move(trackBackend),
95 std::move(trackStateBackend)};
97 cacheTrkContainer.addColumn<std::size_t>("parentSeed");
98 unsigned seedIdx{0};
99 for (const MsTrackSeed& seed : *seedContainer) {
100 if (!fitSeedCandidate(tgContext, mfContext, calContext, seed,
101 cacheTrkContainer)) {
102 ++seedIdx;
103 continue;
104 }
105 auto lastTrack = cacheTrkContainer.getTrack(cacheTrkContainer.size() -1);
106 lastTrack.component<std::size_t, Acts::hashString("parentSeed")>() = seedIdx;
107 ++seedIdx;
108 }
109 SG::WriteHandle writeHandleSeed{m_msTrkSeedKey, ctx};
110 ATH_CHECK(writeHandleSeed.record(std::move(seedContainer)));
111
112 // Constant declination
113 Acts::ConstVectorTrackContainer ctrackBackend{std::move(cacheTrkContainer.container())};
114 Acts::ConstVectorMultiTrajectory ctrackStateBackend{std::move(cacheTrkContainer.trackStateContainer())};
115 auto ctc = std::make_unique<ActsTrk::TrackContainer>(std::move(ctrackBackend),
116 std::move(ctrackStateBackend));
117
118 SG::WriteHandle writeHandle{m_writeKey, ctx};
119 ATH_CHECK(writeHandle.record(std::move(ctc)));
120 return StatusCode::SUCCESS;
121 }
122
123 std::unique_ptr<MsTrackSeedContainer>
124 MsTrackFindingAlg::findTrackSeeds(const EventContext& ctx,
125 const xAOD::MuonSegmentContainer& segments) const {
126
127 auto seedContainer = m_seeder->findTrackSeeds(ctx, segments);
128
129 if (!m_visualizationTool.empty()) {
130 m_visualizationTool->displaySeeds(ctx, *m_seeder, segments, *seedContainer);
131 }
132 return seedContainer;
133 }
136 MsTrackFindingAlg::prepareFit(const Acts::GeometryContext& tgContext,
137 const Acts::MagneticFieldContext& mfContext,
138 const Acts::CalibrationContext& calContext,
139 const MsTrackSeed& seed) const {
140 const EventContext& ctx{*calContext.get<const EventContext*>()};
141 MeasVec_t measurements{};
142 measurements.reserve(100);
144 const xAOD::MuonSegment* refSeg{nullptr};
145 for (const xAOD::MuonSegment* segment : seed.segments()) {
147 m_calibTool->stampSignsOnMeasurements(*segment);
148 MeasVec_t segMeasurements = collectMeasurements(*segment, /*skipOutlier:*/ true);
149 if (msgLvl(MSG::VERBOSE)) {
150 std::stringstream sstr{};
151 for (const xAOD::UncalibratedMeasurement* m : segMeasurements) {
152 const Acts::Surface& surf{xAOD::muonSurface(m)};
153 sstr<<" *** "<<m_idHelperSvc->toString(xAOD::identify(m))
154 <<", "<<m->numDimensions()<<", "
155 <<", "<<surf.geometryId()<<" @ "<<Amg::toString(surf.localToGlobalTransform(tgContext))<<std::endl;
156 }
157 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - Fetch measurements from segment: "<<Amg::toString(segment->position())
158 <<", direction: "<<Amg::toString(segment->direction()) << " eta " << segment->direction().eta() << " phi " << segment->direction().phi() <<"\n"<<sstr.str());
159 }
160 measurements.insert(measurements.end(),
161 std::make_move_iterator(segMeasurements.begin()),
162 std::make_move_iterator(segMeasurements.end()));
163
164 // Ususally we would like to take the first segment with a sufficient amount of phi hits to set the initial position and direction of the track fit. However in some cases the segment from the NSW has a missreconstructed phi direction which causes the track fit to loose all BW and OW hits in the first iteration. Therefore if the first segment is a NSW segment we first try use a non-NSW segments with enough phi hits. If we don't find any segment with enough phi hits we will use the NSW segment as reference as long as it passes the seeding quality criteria.
165 if (!refSeg && !isNswSegment(*segment) &&
166 m_segSelector->passSeedingQuality(ctx, *detailedSegment(*segment))) {
167 refSeg = segment;
168 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - Set reference segment");
169 }
170 }
171 //if we did not find a reference segment let's try the NSW one before we give up on the track
172 if(!refSeg){
173 for (const xAOD::MuonSegment* segment : seed.segments()) {
174 if (isNswSegment(*segment) &&
175 m_segSelector->passSeedingQuality(ctx, *detailedSegment(*segment))) {
176 refSeg = segment;
177 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - NSW is the best what we have apparently....");
178 break;
179 }
180 }
181 }
182
183 if (!refSeg || measurements.empty()) {
184 ATH_MSG_WARNING(__func__<<"() "<<__LINE__
185 <<" - No reference segment passing seeding quality "<<
186 (refSeg != nullptr)<<" was found. #"<<measurements.size()<<" measurements. ");
187 return std::make_pair(OptBoundPars_t::failure(std::make_error_code(std::errc::invalid_argument)),
188 std::vector<const xAOD::UncalibratedMeasurement_v1*>{});
189 }
190 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - "<<measurements.size()<<" measurements");
191 Amg::Vector3D seedPos{atFirstSurface(tgContext, *refSeg)};
192 Amg::Vector3D seedDir{refSeg->direction()};
193 ATH_MSG_DEBUG(__func__<<"() "<<__LINE__<<" - Initial seed pos: "<<Amg::toString(seedPos)
194 <<", dir: "<<Amg::toString(seedDir) << " eta " << seedDir.eta() << " phi "
195 << (seedDir.phi() /Gaudi::Units::degree) );
196
197 const Acts::GeometryIdentifier volId = volumeId(xAOD::muonSurface(measurements.front()));
198 const Acts::TrackingVolume* volume = m_trackingGeometryTool->trackingGeometry()->findVolume(volId);
199 if (!volume) {
200 ATH_MSG_WARNING(__func__<<"() "<<__LINE__
201 <<" - Failed to find tracking volume for any seed measurement");
202 return std::make_pair(OptBoundPars_t::failure(std::make_error_code(std::errc::invalid_argument)),
203 std::vector<const xAOD::UncalibratedMeasurement_v1*>{});
204 }
205 if (volume->motherVolume() && volume->motherVolume()->isAlignable()) {
206 volume = volume->motherVolume();
207 }
208 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__
209 <<" - Bounding volume "<<volume->volumeName()
210 <<", trf: "<<Amg::toString(volume->localToGlobalTransform(tgContext))
211 <<", bounds: "<<volume->volumeBounds());
215 if (const xAOD::MuonSegment* frontSegment = seed.segments().front(); frontSegment != refSeg) {
216 const Amg::Vector3D frontSegPos = atFirstSurface(tgContext, *frontSegment);
217 const Acts::Surface& firstSurf = xAOD::muonSurface(firstMeasurement(*frontSegment));
218 const Amg::Transform3D toFirstTrf = firstSurf.localToGlobalTransform(tgContext).inverse();
219 const Amg::Vector3D locFrontSegPos = toFirstTrf * frontSegPos;
220 if (!volume->inside(tgContext, frontSegPos)) {
221 ATH_MSG_WARNING(__func__<<"() "<<__LINE__<<" - Segment "<<printID(*frontSegment)
222 <<" not inside mother volume: "<<volume->volumeName()<<", "
223 <<Amg::toString(volume->globalToLocalTransform(tgContext)*frontSegPos)
224 <<", bounds: "<<volume->volumeBounds()<<", "
225 <<SegmentFit::localSegmentPars(*frontSegment)
226 <<"\n"<<print(detailedSegment(*frontSegment)->measurements()));
227 }
228
232 const Acts::MultiIntersection firstIsect = firstSurf.intersect(tgContext, seedPos, seedDir,
233 Acts::BoundaryTolerance::Infinite());
234 const Amg::Vector3D locAtFirst = toFirstTrf * firstIsect.at(0).position();
235 if (firstSurf.type() == Acts::Surface::SurfaceType::Straw) {
236 const auto& bounds = static_cast<const Acts::LineBounds&>(firstSurf.bounds());
237 using enum Acts::LineBounds::BoundValues;
238 // we want the drift radius coordinate from the segment and the coordinate along
240 const Amg::Vector3D locStartPos{locFrontSegPos.x(), locFrontSegPos.y(),
241 std::clamp(locAtFirst.z(), -bounds.get(eHalfLengthZ), bounds.get(eHalfLengthZ))};
242 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - The first surface is a straw "
243 <<bounds<<", "<<Amg::toString(locAtFirst)<<" vs. "<<Amg::toString(locFrontSegPos));
244 seedPos = firstSurf.localToGlobalTransform(tgContext) * locStartPos;
245 } else if (firstSurf.type() == Acts::Surface::SurfaceType::Plane) {
246 if (isNswSegment(*frontSegment)) {
247 seedPos = frontSegPos;
248 }
249 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - The first surface is a straw "
250 <<firstSurf.bounds()<<", "<<Amg::toString(locAtFirst)<<" vs. "<<Amg::toString(locFrontSegPos));
251 }
252
253 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - Updated seed position: "<<Amg::toString(seedPos));
254 }
255
256
257 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - Using seed measurement "
258 << m_idHelperSvc->toString(xAOD::identify(measurements.front()))
259 << " with volume id " << volId);
260
261 auto boundSurf = MuonGMR4::bottomBoundary(*volume);
262 if (!boundSurf) {
263 ATH_MSG_WARNING(__func__<<"() "<<__LINE__<<" - Failed to find boundary surface for tracking volume");
264 return std::make_pair(OptBoundPars_t::failure(std::make_error_code(std::errc::invalid_argument)),
265 std::vector<const xAOD::UncalibratedMeasurement_v1*>{});
266 }
267 std::shared_ptr<const Acts::Surface> targetSurf{};
268
269 auto propagteToBoundary = [&](const Acts::Surface& volBoundary) -> Acts::Result<Amg::Vector3D> {
270
271 const Amg::Transform3D& trf{volBoundary.localToGlobalTransform(tgContext)};
272 auto pIsect = intersectPlane(seedPos, seedDir, trf.linear().col(2), trf.translation());
274 if (pIsect.pathLength() > Acts::s_epsilon || !pIsect.isValid()) {
275 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - Intersection @"<<Amg::toString(pIsect.position())
276 <<" is forward "<<pIsect.pathLength()<<" or invalid "<<(!pIsect.isValid())
277 <<" within volume "<<volume->inside(tgContext, pIsect.position()));
278 return Acts::Result<Amg::Vector3D>::failure(std::make_error_code(std::errc::invalid_argument));
279 }
280 Acts::Result<Amg::Vector2D> locPos = volBoundary.globalToLocal(tgContext, pIsect.position(),
281 Amg::Vector3D::Zero());
282 if (!locPos.ok()){
283 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - Intersection is not on surface "<<
284 Amg::toString(trf.inverse()*pIsect.position()));
285 return Acts::Result<Amg::Vector3D>::failure(std::make_error_code(std::errc::invalid_argument));
286 }
287 if (!volBoundary.insideBounds(*locPos)) {
288 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - Intersection is outside the boundaries: "<<
289 Amg::toString(*locPos)<<", bounds: "<<volBoundary.bounds());
290 return Acts::Result<Amg::Vector3D>::failure(std::make_error_code(std::errc::invalid_argument));
291 }
292 targetSurf = volBoundary.getSharedPtr();
293 return Acts::Result<Amg::Vector3D>::success(pIsect.position());
294 };
295
296
297 auto pIsect = propagteToBoundary(*boundSurf);
298 if (!pIsect.ok() && volume->isAlignable()) {
299 const Acts::VolumePlacementBase* placement = volume->volumePlacement();
300 for (std::size_t portal = 0; !pIsect.ok() && portal< placement->nPortalPlacements(); ++portal) {
301 pIsect = propagteToBoundary(placement->portalPlacement(portal)->surface());
302 }
303 }
304 if (!pIsect.ok()) {
305 ATH_MSG_WARNING(__func__<<"() "<<__LINE__<<" Cannot create valid start parameters from seed "<<seed);
306 // THROW_EXCEPTION("DIese kacke");
307 return std::make_pair(OptBoundPars_t::failure(std::make_error_code(std::errc::invalid_argument)),
308 std::vector<const xAOD::UncalibratedMeasurement_v1*>{});
309 }
310 auto fourPos = ActsTrk::convertPosToActs(*pIsect, (*pIsect).mag() / Gaudi::Units::c_light);
311 const double qOverP = 1./ ActsTrk::energyToActs(m_seeder->estimateQtimesP(*mfContext.get<const AtlasFieldCacheCondObj*>(), seed));
312 auto initialPars = Acts::BoundTrackParameters::create(tgContext, targetSurf, fourPos,
313 seedDir, qOverP,
314 Acts::BoundMatrix::Identity(),
315 Acts::ParticleHypothesis::muon());
316 return std::make_pair(std::move(initialPars), std::move(measurements));
317
318 }
319 bool MsTrackFindingAlg::fitSeedCandidate(const Acts::GeometryContext& tgContext,
320 const Acts::MagneticFieldContext& mfContext,
321 const Acts::CalibrationContext& calContext,
322 const MsTrackSeed& seed,
323 ActsTrk::MutableTrackContainer& outContainer) const {
324
325 ATH_MSG_DEBUG(__func__<<"() "<<__LINE__<<" - Attempt to fit a new track seed \n"<<seed);
326 const EventContext& ctx{*calContext.get<const EventContext*>()};
327 const auto [initialPars, measurements] = prepareFit(tgContext, mfContext, calContext, seed);
328
329 if (!initialPars.ok()) {
330 ATH_MSG_WARNING(__func__<<"() "<<__LINE__<<" - Failed to construct valid parameters for seed \n"<<seed);
331 if (m_visualizationTool.isEnabled()) {
332 m_visualizationTool->displayTrackSeedObj(ctx, seed, initialPars, "FailedStartPars");
333 }
334 return false;
335 }
336 auto fitTraject = m_trackFitTool->fit(measurements, *initialPars,
337 tgContext, mfContext, calContext,
338 &(*initialPars).referenceSurface());
339 if (!fitTraject || fitTraject->size() == 0) {
340 ATH_MSG_DEBUG(__func__<<"() "<<__LINE__<<" - Fit failed. Seed was \n"<<seed);
341 if (m_visualizationTool.isEnabled()) {
342 m_visualizationTool->displayTrackSeedObj(ctx, seed, initialPars, "FailedFit");
343 }
344 return false;
345 }
346
347 ActsTrk::MutableTrackContainer::TrackProxy track = fitTraject->getTrack(0);
348 const Amg::Vector3D trkP4 = ActsTrk::convertMomFromActs(track.fourMomentum()).first;
349 double pt = trkP4.perp() / 1000; //in GeV
350 if(pt < 2 ) {
351 double chi2PerDoF = track.chi2() / (std::max(track.nDoF(), 1u));
352 ATH_MSG_DEBUG(" ===cat dog: found low pt track candidate with pt "<<pt<<" GeV chi2/ndof "<< chi2PerDoF << " chi2 "<< track.chi2() << " nDOF "<< track.nDoF() <<"eta: "<<trkP4.eta());
353
354 track.container().trackStateContainer().visitBackwards(track.tipIndex(), [&](const auto& state) {
355 if(state.hasUncalibratedSourceLink()){
356 const auto* uncalib = dynamic_cast<const xAOD::MuonMeasurement*>(ActsTrk::detail::xAODUncalibMeasCalibrator::unpack(state.getUncalibratedSourceLink()));
357 if(uncalib){
358 ATH_MSG_DEBUG(" has meas: "<<m_idHelperSvc->toString(xAOD::identify(uncalib)) << " state " << state.typeFlags());
359 }
360 }
361 }
362 );
363
364
365 // Check the hit counts on track post fit and if we only have one station on track discard track
366 // Eventually we should implement some recovery mechanism for track where we loose too many stations
367 MuonR4::HitSummary summary = m_summaryTool->makeSummary(ctx, fitTraject->getTrack(0));
368 ATH_MSG_DEBUG("Track has " << static_cast<std::uint32_t>(summary.nPrecisionStations()) << " precision layers with summary "<< summary);
369 if(summary.nPrecisionStations()<2) {
370 ATH_MSG_DEBUG("rejecting single station track");
371 return false;
372 }
373
374
375 }
380 {
381 fitTraject->addColumn<std::vector<const xAOD::MuonSegment*>>("muonSegLinks");
382 fitTraject->getTrack(0).component<std::vector<const xAOD::MuonSegment*>>("muonSegLinks") = seed.segments();
383 }
384 outContainer.ensureDynamicColumns(*fitTraject);
385 auto destProxy = outContainer.getTrack(outContainer.addTrack());
386 destProxy.copyFrom(fitTraject->getTrack(0));
387 ATH_MSG_DEBUG(__func__<<"() "<<__LINE__<<" - Good track fit...");
388 if (m_visualizationTool.isEnabled()) {
389 m_visualizationTool->displayTrackSeedObj(ctx, seed,
390 destProxy.createParametersAtReference(), "GoodFit");
391 }
392 return true;
393 }
394
395}
#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
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.
ToolHandle< MuonR4::ITrackSummaryTool > m_summaryTool
Handle to the muon summary tool.
const MeasVec & measurements() const
Returns the associated measurements.
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
Amg::Vector3D direction() const
Returns the direction as Amg::Vector.
::Muon::MuonStationIndex::TechnologyIndex technology() const
Returns the main technology of the segment.
::Muon::MuonStationIndex::ChIndex chamberIndex() const
Returns the chamber index.
constexpr double energyToActs(const double athenaE)
Converts an energy scalar from Athena to Acts units.
std::pair< Amg::Vector3D, double > convertMomFromActs(const Acts::Vector4 &actsMom)
Converts an Acts four-momentum vector into an pair of an Athena three-momentum and the paritcle's ene...
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.
Parameters localSegmentPars(const xAOD::MuonSegment &seg)
Returns the localSegPars decoration from a xAODMuon::Segment.
This header ties the generic definitions in this package.
std::string printID(const xAOD::MuonSegment &seg)
Print the chamber ID of a segment, e.g.
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.
const xAOD::UncalibratedMeasurement * firstMeasurement(const xAOD::MuonSegment &segment, const bool skipOutlier=true)
Retrieves the first measurement associated with the segment.
Amg::Vector3D atFirstSurface(const Acts::GeometryContext &gctx, const xAOD::MuonSegment &segment, const bool skipOutlier=true)
Expresses the segment position on the surface of the first measurement.
std::string print(const cont_t &container)
Print a space point container to string.
const Segment * detailedSegment(const xAOD::MuonSegment &seg)
Helper function to navigate from the xAOD::MuonSegment to the MuonR4::Segment.
StIndex toStationIndex(ChIndex index)
convert ChIndex into StIndex
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
UncalibratedMeasurement_v1 UncalibratedMeasurement
Define the version of the uncalibrated measurement class.
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.
Summary struct to hold the hit counts on the track per MS layer.
Definition HitSummary.h:23
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.