ATLAS Offline Software
Loading...
Searching...
No Matches
ActsTrk::ActsToTrkConverterTool Class Reference

#include <ActsToTrkConverterTool.h>

Inheritance diagram for ActsTrk::ActsToTrkConverterTool:
Collaboration diagram for ActsTrk::ActsToTrkConverterTool:

Public Member Functions

virtual StatusCode initialize () override
virtual const Trk::SurfaceactsSurfaceToTrkSurface (const Acts::Surface &actsSurface) const override
 Find the ATLAS surface corresponding to the Acts surface Only work if the Acts surface has an associated detector element (Pixel and SCT)
virtual const Acts::Surface & trkSurfaceToActsSurface (const Trk::Surface &atlasSurface) const override
 Find the Acts surface corresponding to the ATLAS surface Use a map associating ATLAS ID to Acts surfaces (Pixel and SCT)
virtual std::vector< Acts::SourceLink > trkTrackToSourceLinks (const Trk::Track &track) const override
 Transform an ATLAS track into a vector of SourceLink to be use in the avts tracking Transform both measurement and outliers.
virtual void toSourceLinks (const std::vector< const Trk::MeasurementBase * > &measSet, std::vector< Acts::SourceLink > &links) const override final
virtual void toSourceLinks (const std::vector< const Trk::PrepRawData * > &prdSet, std::vector< Acts::SourceLink > &links) const override final
virtual std::unique_ptr< Trk::TrackconvertFitResult (const EventContext &ctx, ActsTrk::MutableTrackContainer &tracks, TrackFitResult_t &fitResult, const Trk::TrackInfo::TrackFitter fitAuthor, const detail::SourceLinkType slType) const override final
virtual const Acts::BoundTrackParameters trkTrackParametersToActsParameters (const Trk::TrackParameters &atlasParameter, const Acts::GeometryContext &gctx, Trk::ParticleHypothesis=Trk::pion) const override
 Create Acts TrackParameter from ATLAS one.
virtual std::unique_ptr< Trk::TrackParametersactsTrackParametersToTrkParameters (const Acts::BoundTrackParameters &actsParameter, const Acts::GeometryContext &gctx) const override
 Create ATLAS TrackParameter from Acts one.
virtual void trkTrackCollectionToActsTrackContainer (ActsTrk::MutableTrackContainer &tc, const TrackCollection &trackColl, const Acts::GeometryContext &gctx) const override
 Convert TrackCollection to Acts track container.

Private Member Functions

bool actsTrackParameterPositionCheck (const Acts::BoundTrackParameters &actsParameter, const Trk::TrackParameters &tsos, const Acts::GeometryContext &gctx) const

Private Attributes

PublicToolHandle< ActsTrk::ITrackingGeometryToolm_trackingGeometryTool {this, "TrackingGeometryTool", "ActsTrackingGeometryTool"}
ToolHandle< Trk::IExtendedTrackSummaryToolm_trkSummaryTool {this, "SummaryTool", "", "ToolHandle for track summary tool"}
 Tools needed to create Trk::Tracks from the ACts fit result.
ToolHandle< Trk::IBoundaryCheckToolm_boundaryCheckTool {this, "BoundaryCheckTool", "", "Boundary checking tool for detector sensitivities"}
ToolHandle< Trk::IRIO_OnTrackCreatorm_ROTcreator {this, "RotCreatorTool", ""}
std::shared_ptr< const Acts::TrackingGeometry > m_trackingGeometry {}
std::unordered_map< Identifier, const Acts::Surface * > m_actsSurfaceMap {}
Gaudi::Property< bool > m_visualDebugOutput
Gaudi::Property< bool > m_extractMuonSurfaces
ServiceHandle< Muon::IMuonIdHelperSvcm_idHelperSvc {this, "MuonIdHelperSvc", "Muon::MuonIdHelperSvc/MuonIdHelperSvc"}
SG::ReadCondHandleKey< MuonGM::MuonDetectorManagerm_muonMgrKey {this, "MuonManagerKey", "MuonDetectorManager"}
 Detector manager to fetch the legacy Trk surfaces.

Detailed Description

Definition at line 34 of file ActsToTrkConverterTool.h.

Member Function Documentation

◆ actsSurfaceToTrkSurface()

const Trk::Surface & ActsTrk::ActsToTrkConverterTool::actsSurfaceToTrkSurface ( const Acts::Surface & actsSurface) const
overridevirtual

Find the ATLAS surface corresponding to the Acts surface Only work if the Acts surface has an associated detector element (Pixel and SCT)

Definition at line 131 of file ActsToTrkConverterTool.cxx.

132 {
133
134 const auto *detEleBase= dynamic_cast<const IDetectorElementBase*>(actsSurface.associatedDetectorElement());
135 if (!detEleBase) {
136 ATH_MSG_ERROR(actsSurface.toString(m_trackingGeometryTool->getNominalGeometryContext().context()));
137 throw std::domain_error("ActsToTrkConverterTool() - Surface does not have an associated detector element. ");
138 }
139 switch (detEleBase->detectorType()) {
140 using enum DetectorType;
141 case Pixel:
142 case Sct:
143 case Hgtd:
144 case Trt: {
145 const auto actsElement = dynamic_cast<const ActsDetectorElement*>(detEleBase);
146 if (actsElement) {
147 return actsElement->atlasSurface();
148 }
149 break;
150 }
151 case Mdt:
152 case Rpc:
153 case Tgc:
154 case Csc:
155 case sTgc:
156 case Mm: {
157 const MuonGM::MuonDetectorManager* detMgr{nullptr};
158 if (!SG::get(detMgr, m_muonMgrKey, Gaudi::Hive::currentContext()).isSuccess() || !detMgr) {
159 THROW_EXCEPTION("Failed to retrieve the muon detector manager");
160 }
161 return detMgr->getReadoutElement(detEleBase->identify())->surface(detEleBase->identify());
162
163 } default:
164 break;
165 }
166 throw std::domain_error("ActsToTrkConverterTool() - No ATLAS surface corresponding to the Acts one");
167}
#define ATH_MSG_ERROR(x)
SG::ReadCondHandleKey< MuonGM::MuonDetectorManager > m_muonMgrKey
Detector manager to fetch the legacy Trk surfaces.
PublicToolHandle< ActsTrk::ITrackingGeometryTool > m_trackingGeometryTool
const MuonReadoutElement * getReadoutElement(const Identifier &id) const
Get any read out element.
virtual const Surface & surface() const =0
Return surface associated with this detector element.
DetectorType
Simple enum to Identify the Type of the ACTS sub detector.
@ Mm
Maybe not needed in the migration.
@ Tgc
Resitive Plate Chambers.
@ Pixel
Inner detector legacy.
@ sTgc
Micromegas (NSW)
@ Rpc
Monitored Drift Tubes.
@ Csc
Thin gap champers.
@ Trt
Maybe the Sct / Pixel for Itk become seperate entries?
@ Mdt
MuonSpectrometer.
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
#define THROW_EXCEPTION(MESSAGE)
Definition throwExcept.h:10

◆ actsTrackParameterPositionCheck()

bool ActsTrk::ActsToTrkConverterTool::actsTrackParameterPositionCheck ( const Acts::BoundTrackParameters & actsParameter,
const Trk::TrackParameters & tsos,
const Acts::GeometryContext & gctx ) const
private

Definition at line 549 of file ActsToTrkConverterTool.cxx.

552 {
553 auto actsPos = parameters.position(gctx);
554 // ATH_MSG_VERBOSE("Acts position: \n"
555 // << actsPos << " vs trk position: \n"
556 // << trkparameters.position());
557 // ATH_MSG_VERBOSE(parameters.referenceSurface().toString(gctx));
558 // ATH_MSG_VERBOSE("GeometryId "<<parameters.referenceSurface().geometryId().value());
559
560 if ( (actsPos - trkparameters.position()).mag() > 0.1) {
561 ATH_MSG_WARNING("Parameter position mismatch. Acts \n"
562 << actsPos << " vs Trk \n"
563 << trkparameters.position());
564 ATH_MSG_WARNING("Acts surface:");
565 ATH_MSG_WARNING(parameters.referenceSurface().toString(gctx));
566 ATH_MSG_WARNING("Trk surface:");
567 ATH_MSG_WARNING(trkparameters.associatedSurface());
568 return false;
569 }
570 return true;
571}
#define ATH_MSG_WARNING(x)

◆ actsTrackParametersToTrkParameters()

std::unique_ptr< Trk::TrackParameters > ActsTrk::ActsToTrkConverterTool::actsTrackParametersToTrkParameters ( const Acts::BoundTrackParameters & actsParameter,
const Acts::GeometryContext & gctx ) const
overridevirtual

Create ATLAS TrackParameter from Acts one.

Take care of unit conversion between the two.

Convert to free parameters

Back conversion to bound parameters of the helper plane

Definition at line 299 of file ActsToTrkConverterTool.cxx.

301 {
302
303 using namespace Acts::UnitLiterals;
304 std::optional<AmgSymMatrix(5)> cov = std::nullopt;
305 if (actsParameter.covariance()) {
306 AmgSymMatrix(5) newcov(actsParameter.covariance()->topLeftCorner<5, 5>());
307 // Convert the covariance matrix to GeV
308 for (int i = 0; i < newcov.rows(); i++) {
309 newcov(i, 4) = newcov(i, 4) * 1_MeV;
310 }
311 for (int i = 0; i < newcov.cols(); i++) {
312 newcov(4, i) = newcov(4, i) * 1_MeV;
313 }
314 cov = std::optional<AmgSymMatrix(5)>(newcov);
315 }
316
317 const Acts::Surface &actsSurface = actsParameter.referenceSurface();
318 switch (actsSurface.type()) {
319 case Acts::Surface::SurfaceType::Cone: {
320 const auto &coneSurface = static_cast<const Trk::ConeSurface&>(actsSurfaceToTrkSurface(actsSurface));
321 return std::make_unique<Trk::AtaCone>(
322 actsParameter.get<Acts::eBoundLoc0>(),
323 actsParameter.get<Acts::eBoundLoc1>(),
324 actsParameter.get<Acts::eBoundPhi>(),
325 actsParameter.get<Acts::eBoundTheta>(),
326 actsParameter.get<Acts::eBoundQOverP>() * 1_MeV, coneSurface, cov);
327 } case Acts::Surface::SurfaceType::Cylinder: {
328 const auto &cylSurface{static_cast<const Trk::CylinderSurface&>(actsSurfaceToTrkSurface(actsSurface))};
329 return std::make_unique<Trk::AtaCylinder>(
330 actsParameter.get<Acts::eBoundLoc0>(),
331 actsParameter.get<Acts::eBoundLoc1>(),
332 actsParameter.get<Acts::eBoundPhi>(),
333 actsParameter.get<Acts::eBoundTheta>(),
334 actsParameter.get<Acts::eBoundQOverP>() * 1_MeV, cylSurface, cov);
335 } case Acts::Surface::SurfaceType::Disc: {
336 const Trk::Surface& trkSurface{actsSurfaceToTrkSurface(actsSurface)};
337 if (trkSurface.type() == Trk::SurfaceType::Disc) {
338 const auto& discSurface{static_cast<const Trk::DiscSurface&>(trkSurface)};
339 return std::make_unique<Trk::AtaDisc>(
340 actsParameter.get<Acts::eBoundLoc0>(),
341 actsParameter.get<Acts::eBoundLoc1>(),
342 actsParameter.get<Acts::eBoundPhi>(),
343 actsParameter.get<Acts::eBoundTheta>(),
344 actsParameter.get<Acts::eBoundQOverP>() * 1_MeV, discSurface, cov);
345 } else if (trkSurface.type() == Trk::SurfaceType::Plane) {
346 auto& planeSurface{static_cast<const Trk::PlaneSurface&>(trkSurface)};
347 // need to convert to plane position on plane surface (annulus bounds)
348 auto helperSurface = Acts::Surface::makeShared<Acts::PlaneSurface>(planeSurface.transform());
349
350 auto covpc = actsParameter.covariance().value();
352 Acts::FreeVector freePars = Acts::transformBoundToFreeParameters(actsSurface, gctx,
353 actsParameter.parameters());
354
356 Acts::BoundVector targetPars = Acts::transformFreeToBoundParameters(freePars,
357 *helperSurface, gctx).value();
358
359 Acts::FreeMatrix freeTransportJacobian{Acts::FreeMatrix::Identity()};
360
361 Acts::FreeVector freeToPathDerivatives{Acts::FreeVector::Zero()};
362 freeToPathDerivatives.head<3>() = freePars.segment<3>(Acts::eFreeDir0);
363
364 auto boundToFreeJacobian = actsSurface.boundToFreeJacobian(gctx, freePars.segment<3>(Acts::eFreePos0),
365 freePars.segment<3>(Acts::eFreeDir0));
366
367 Acts::BoundMatrix boundToBoundJac = Acts::detail::boundToBoundTransportJacobian(gctx, freePars,
368 boundToFreeJacobian, freeTransportJacobian, freeToPathDerivatives, *helperSurface);
369
370 Acts::BoundMatrix targetCov{boundToBoundJac * covpc * boundToBoundJac.transpose()};
371
372 auto pars = std::make_unique<Trk::AtaPlane>(
373 targetPars[Acts::eBoundLoc0], targetPars[Acts::eBoundLoc1],
374 targetPars[Acts::eBoundPhi], targetPars[Acts::eBoundTheta],
375 targetPars[Acts::eBoundQOverP] * 1_MeV, planeSurface,
376 targetCov.topLeftCorner<5, 5>());
377
379 ActsTrackParameterCheck(actsParameter, gctx, covpc, targetPars,
380 targetCov, &planeSurface);
381 }
382 return pars;
383
384 } else {
385 throw std::domain_error("Acts::DiscSurface is not associated with ATLAS disc or plane surface");
386 }
387 break;
388 } case Acts::Surface::SurfaceType::Perigee: {
389 const Trk::PerigeeSurface perSurface(actsSurface.center(gctx));
390 return std::make_unique<Trk::Perigee>(
391 actsParameter.get<Acts::eBoundLoc0>(),
392 actsParameter.get<Acts::eBoundLoc1>(),
393 actsParameter.get<Acts::eBoundPhi>(),
394 actsParameter.get<Acts::eBoundTheta>(),
395 actsParameter.get<Acts::eBoundQOverP>() * 1_MeV, perSurface, cov);
396 } case Acts::Surface::SurfaceType::Plane: {
397 auto &plaSurface{static_cast<const Trk::PlaneSurface&>(actsSurfaceToTrkSurface(actsSurface))};
398 return std::make_unique<Trk::AtaPlane>(
399 actsParameter.get<Acts::eBoundLoc0>(),
400 actsParameter.get<Acts::eBoundLoc1>(),
401 actsParameter.get<Acts::eBoundPhi>(),
402 actsParameter.get<Acts::eBoundTheta>(),
403 actsParameter.get<Acts::eBoundQOverP>() * 1_MeV, plaSurface, cov);
404 } case Acts::Surface::SurfaceType::Straw: {
405 auto& lineSurface{static_cast<const Trk::StraightLineSurface&>(actsSurfaceToTrkSurface(actsSurface))};
406 return std::make_unique<Trk::AtaStraightLine>(
407 actsParameter.get<Acts::eBoundLoc0>(),
408 actsParameter.get<Acts::eBoundLoc1>(),
409 actsParameter.get<Acts::eBoundPhi>(),
410 actsParameter.get<Acts::eBoundTheta>(),
411 actsParameter.get<Acts::eBoundQOverP>() * 1_MeV, lineSurface, cov);
412 } case Acts::Surface::SurfaceType::Curvilinear: {
413 return std::make_unique<Trk::CurvilinearParameters>(
414 actsParameter.position(gctx), actsParameter.get<Acts::eBoundPhi>(),
415 actsParameter.get<Acts::eBoundTheta>(),
416 actsParameter.get<Acts::eBoundQOverP>() * 1_MeV, cov);
417 break;
418 } case Acts::Surface::SurfaceType::Other: {
419 break;
420 }
421 }
422 throw std::domain_error("Surface type not found");
423}
#define AmgSymMatrix(dim)
virtual const Trk::Surface & actsSurfaceToTrkSurface(const Acts::Surface &actsSurface) const override
Find the ATLAS surface corresponding to the Acts surface Only work if the Acts surface has an associa...
Gaudi::Property< bool > m_visualDebugOutput
virtual constexpr SurfaceType type() const =0
Returns the Surface type to avoid dynamic casts.
static void ActsTrackParameterCheck(const Acts::BoundTrackParameters &actsParameter, const Acts::GeometryContext &gctx, const Acts::BoundSquareMatrix &covpc, const Acts::BoundVector &targetPars, const Acts::BoundSquareMatrix &targetCov, const Trk::PlaneSurface *planeSurface)

◆ convertFitResult()

std::unique_ptr< Trk::Track > ActsTrk::ActsToTrkConverterTool::convertFitResult ( const EventContext & ctx,
ActsTrk::MutableTrackContainer & tracks,
TrackFitResult_t & fitResult,
const Trk::TrackInfo::TrackFitter fitAuthor,
const detail::SourceLinkType slType ) const
finaloverridevirtual

Definition at line 741 of file ActsToTrkConverterTool.cxx.

745 {
746 detail::TrkMeasurementCalibrator measCalib{};
747 detail::TrkPrepRawDataCalibrator prdCalib{this, m_ROTcreator.get()};
748
749 if (not fitResult.ok()) {
750 ATH_MSG_VERBOSE("Fit did not converge");
751 return nullptr;
752 }
753 const Acts::CalibrationContext cctx{getCalibrationContext(ctx)};
754 const Acts::GeometryContext gctx{m_trackingGeometryTool->getGeometryContext(ctx).context()};
755 Acts::ParticleHypothesis hypothesis{Acts::ParticleHypothesis::pion()};
756
757 // Get the fit output object
758 const auto& acts_track = fitResult.value();
759
760 auto finalTrajectory = std::make_unique<Trk::TrackStates>();
761 // initialise the number of dead Pixel and Acts strip
762 unsigned int numberOfDeadPixel{0}, numberOfDeadSCT{0};
763 int nDoF{0};
764
765 double chi2{0};
766
767 // Loop over all the output state to create track state
768 tracks.trackStateContainer().visitBackwards(acts_track.tipIndex(),
769 [&] (const auto &state) -> void {
770 // First only consider state with an associated detector element
771 const auto* associatedDetEl = dynamic_cast<const IDetectorElementBase*>(
772 state.referenceSurface().associatedDetectorElement());
773
774 if (not associatedDetEl) {
775 ATH_MSG_VERBOSE("State is not associated with a measurement sruface");
776 return;
777 }
778 ATH_MSG_VERBOSE("Associated det: "<<to_string(associatedDetEl->detectorType()));
779 auto flag = state.typeFlags();
780
781 // We need to determine the type of state
782 std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes> typePattern;
783 std::unique_ptr<Trk::TrackParameters> measPars{};
784 std::unique_ptr<Trk::MeasurementBase> measState{};
785
786 // State is a hole (no associated measurement), use predicted parameters
787 if (flag.test(Acts::TrackStateFlag::HoleFlag)){
788 const Acts::BoundTrackParameters actsParam(state.referenceSurface().getSharedPtr(),
789 state.parameters(),
790 state.covariance(),
791 hypothesis);
792 measPars = actsTrackParametersToTrkParameters(actsParam, gctx);
793 if (associatedDetEl->detectorType() == DetectorType::Pixel ||
794 associatedDetEl->detectorType() == DetectorType::Sct) {
795 ATH_MSG_VERBOSE("Check if this is a hole, a dead sensors or a state outside the sensor boundary");
796 switch (m_boundaryCheckTool->boundaryCheck(*measPars)) {
797 case Trk::BoundaryCheckResult::DeadElement:
798 numberOfDeadPixel += (associatedDetEl->detectorType() == DetectorType::Pixel);
799 numberOfDeadSCT+= (associatedDetEl->detectorType() == DetectorType::Sct);
800 break;
801 case Trk::BoundaryCheckResult::Candidate:
802 break;
803 default:
804 return;
805 }
806 }
807 typePattern.set(Trk::TrackStateOnSurface::Hole);
808 }
809 // The state is a measurement state, use smoothed parameters
810 else if (flag.test(Acts::TrackStateFlag::MeasurementFlag)) {
811 Acts::BoundTrackParameters actsParam(state.referenceSurface().getSharedPtr(),
812 state.parameters(),
813 state.covariance(),
814 hypothesis);
815 typePattern.set(Trk::TrackStateOnSurface::Measurement);
816 switch (slType) {
817 using enum detail::SourceLinkType;
818 case TrkMeasurement:
819 measState = measCalib.unpack(state.getUncalibratedSourceLink())->uniqueClone();
820 break;
821 case TrkPrepRawData:
822 measState = prdCalib.createROT(gctx, cctx, state.getUncalibratedSourceLink(), state);
823 break;
824 case xAODUnCalibMeas:
825 ATH_MSG_WARNING("Uncalibrated measurement is not implemented");
826 return;
827 case nTypes:
828 ATH_MSG_WARNING("Invalid type enumaration parsed");
829 return;
830 }
831 nDoF = state.calibratedSize();
832 chi2 = state.chi2();
833
834 }
835 auto perState = std::make_unique<Trk::TrackStateOnSurface>(Trk::FitQualityOnSurface{chi2, nDoF},
836 std::move(measState),
837 std::move(measPars), nullptr, typePattern);
838 // If a state was succesfully created add it to the trajectory
839 ATH_MSG_VERBOSE("State succesfully creates, adding it to the trajectory");
840 finalTrajectory->insert(finalTrajectory->begin(), std::move(perState));
841 });
842 // Convert the perigee state and add it to the trajectory
843 const Acts::BoundTrackParameters actsPer(acts_track.referenceSurface().getSharedPtr(),
844 acts_track.parameters(),
845 acts_track.covariance(),
846 acts_track.particleHypothesis());
847 std::unique_ptr<Trk::TrackParameters> per = actsTrackParametersToTrkParameters(actsPer, gctx);
848 std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes> typePattern;
849 typePattern.set(Trk::TrackStateOnSurface::Perigee);
850 auto perState = std::make_unique<Trk::TrackStateOnSurface>(nullptr, std::move(per), nullptr, typePattern);
851 finalTrajectory->insert(finalTrajectory->begin(), std::move(perState));
852
853 // Create the track using the states
854 Trk::TrackInfo newInfo{fitAuthor, Trk::noHypothesis};
855 auto newtrack = std::make_unique<Trk::Track>(newInfo, std::move(finalTrajectory), nullptr);
856 if (newtrack) {
857 // Create the track summary and update the holes information
858 if (!newtrack->trackSummary()) {
859 newtrack->setTrackSummary(std::make_unique<Trk::TrackSummary>());
860 newtrack->trackSummary()->update(Trk::numberOfPixelDeadSensors, numberOfDeadPixel);
861 newtrack->trackSummary()->update(Trk::numberOfSCTDeadSensors, numberOfDeadSCT);
862 }
863 m_trkSummaryTool->updateTrackSummary(ctx, *newtrack, true);
864 }
865 return newtrack;
866 }
#define ATH_MSG_VERBOSE(x)
if(febId1==febId2)
ToolHandle< Trk::IExtendedTrackSummaryTool > m_trkSummaryTool
Tools needed to create Trk::Tracks from the ACts fit result.
virtual std::unique_ptr< Trk::TrackParameters > actsTrackParametersToTrkParameters(const Acts::BoundTrackParameters &actsParameter, const Acts::GeometryContext &gctx) const override
Create ATLAS TrackParameter from Acts one.
ToolHandle< Trk::IRIO_OnTrackCreator > m_ROTcreator
@ 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.
double chi2(TH1 *h0, TH1 *h1)
std::string to_string(const DetectorType &type)
Acts::CalibrationContext getCalibrationContext(const EventContext &ctx)
The Acts::Calibration context is piped through the Acts fitters to (re)calibrate the Acts::SourceLink...
@ numberOfPixelDeadSensors
number of pixel hits with broad errors (width/sqrt(12))
bool flag
Definition master.py:29

◆ initialize()

StatusCode ActsTrk::ActsToTrkConverterTool::initialize ( )
overridevirtual

Definition at line 78 of file ActsToTrkConverterTool.cxx.

78 {
79 ATH_MSG_VERBOSE("Initializing ACTS to ATLAS converter tool");
80 if (!m_trackingGeometryTool.empty()) {
82 m_trackingGeometry = m_trackingGeometryTool->trackingGeometry();
83
84 m_trackingGeometry->visitSurfaces([&](const Acts::Surface *surface) {
85 // find acts surface with the same detector element ID
86 if (!surface)
87 return;
88 const auto *actsElement = dynamic_cast<const IDetectorElementBase*>(
89 surface->associatedDetectorElement());
90 if (!actsElement) {
91 return;
92 }
93 // Conversion from Acts to ATLAS surface impossible for the TRT so the TRT
94 // surfaces are not stored in this map
95 if (actsElement->detectorType() == DetectorType::Trt) {
96 return;
97 }
98
99 auto [it, ok] = m_actsSurfaceMap.insert({actsElement->identify(), surface});
100 if (!ok) {
101 ATH_MSG_WARNING("ATLAS ID " << actsElement->identify()
102 << " has two ACTS surfaces: "
103 << it->second->geometryId() << " and "
104 << surface->geometryId());
105 }
106 });
107 }
108
109 ATH_CHECK(m_trkSummaryTool.retrieve());
110 ATH_CHECK(m_boundaryCheckTool.retrieve(EnableTool{!m_boundaryCheckTool.empty()}));
111 ATH_CHECK(m_ROTcreator.retrieve());
112
115 ATH_CHECK(m_idHelperSvc.retrieve());
116 const MuonGMR4::MuonDetectorManager* muonMgr{nullptr};
117 ATH_CHECK(detStore()->retrieve(muonMgr));
118 unsigned int mapSize = m_actsSurfaceMap.size(); // For debugging message later
119 for (auto readoutElement : muonMgr->getAllReadoutElements()) {
120 std::vector<std::shared_ptr<Acts::Surface>> reSurfaces = readoutElement->getSurfaces();
121 for ( const auto& surf : reSurfaces) {
122 const Identifier id = static_cast<const SurfaceCache*>(surf->associatedDetectorElement())->identify();
123 m_actsSurfaceMap.insert(std::make_pair(id, surf.get()));
124 }
125 }
126 ATH_MSG_VERBOSE("After adding muon surfaces, the map has grown from "<<mapSize<<" to "<<m_actsSurfaceMap.size());
127 }
128 return StatusCode::SUCCESS;
129}
#define ATH_CHECK
Evaluate an expression and check for errors.
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
std::unordered_map< Identifier, const Acts::Surface * > m_actsSurfaceMap
ToolHandle< Trk::IBoundaryCheckTool > m_boundaryCheckTool
Gaudi::Property< bool > m_extractMuonSurfaces
std::shared_ptr< const Acts::TrackingGeometry > m_trackingGeometry
std::vector< const MuonReadoutElement * > getAllReadoutElements() const
Returns the list of all detector elements.
retrieve(aClass, aKey=None)
Definition PyKernel.py:110

◆ toSourceLinks() [1/2]

void ActsTrk::ActsToTrkConverterTool::toSourceLinks ( const std::vector< const Trk::MeasurementBase * > & measSet,
std::vector< Acts::SourceLink > & links ) const
finaloverridevirtual

Definition at line 193 of file ActsToTrkConverterTool.cxx.

194 {
195 if (sourceLinks.capacity() < sourceLinks.size() + measSet.size()) {
196 sourceLinks.reserve(sourceLinks.size() + measSet.size());
197 }
198 std::ranges::transform(measSet, std::back_inserter(sourceLinks), [](const Trk::MeasurementBase* meas) {
200 });
201}
static Acts::SourceLink pack(const Trk::MeasurementBase *meas)
Packs the pointer to the track measurement into an Acts::SouceLink.

◆ toSourceLinks() [2/2]

void ActsTrk::ActsToTrkConverterTool::toSourceLinks ( const std::vector< const Trk::PrepRawData * > & prdSet,
std::vector< Acts::SourceLink > & links ) const
finaloverridevirtual

Definition at line 202 of file ActsToTrkConverterTool.cxx.

203 {
204 if (links.capacity() < links.size() + prdSet.size()) {
205 links.reserve(links.size() + prdSet.size());
206 }
207 std::ranges::transform(prdSet, std::back_inserter(links), [](const Trk::PrepRawData* prd) {
209 });
210}
static Acts::SourceLink pack(const SourceLink_t prd)
Pack the PrepRaw data measurement into a source link.

◆ trkSurfaceToActsSurface()

const Acts::Surface & ActsTrk::ActsToTrkConverterTool::trkSurfaceToActsSurface ( const Trk::Surface & atlasSurface) const
overridevirtual

Find the Acts surface corresponding to the ATLAS surface Use a map associating ATLAS ID to Acts surfaces (Pixel and SCT)

Definition at line 169 of file ActsToTrkConverterTool.cxx.

170 {
171
172 Identifier atlasID = atlasSurface.associatedDetectorElementIdentifier();
173 auto it = m_actsSurfaceMap.find(atlasID);
174 if (it != m_actsSurfaceMap.end()) {
175 return *it->second;
176 }
177 ATH_MSG_ERROR("No Acts surface corresponding to this ATLAS surface: "<<atlasID);
178 ATH_MSG_ERROR(atlasSurface);
179 throw std::domain_error("No Acts surface corresponding to the ATLAS one");
180}
Identifier associatedDetectorElementIdentifier() const
return Identifier of the associated Detector Element

◆ trkTrackCollectionToActsTrackContainer()

void ActsTrk::ActsToTrkConverterTool::trkTrackCollectionToActsTrackContainer ( ActsTrk::MutableTrackContainer & tc,
const TrackCollection & trackColl,
const Acts::GeometryContext & gctx ) const
overridevirtual

Convert TrackCollection to Acts track container.

Parameters
tcThe track container to fill

Definition at line 425 of file ActsToTrkConverterTool.cxx.

427 {
428 ATH_MSG_VERBOSE("Calling trkTrackCollectionToActsTrackContainer with "
429 << trackColl.size() << " tracks.");
430 unsigned int trkCount = 0;
431 std::vector<Identifier> failedIds; // Keep track of Identifiers of failed conversions
432 for (const Trk::Track* trk : trackColl) {
433 // Do conversions!
434 const Trk::TrackStates *trackStates = trk->trackStateOnSurfaces();
435
436 auto actsTrack = tc.getTrack(tc.addTrack());
437 auto& trackStateContainer = tc.trackStateContainer();
438
439 ATH_MSG_VERBOSE("Track "<<trkCount++<<" has " << trackStates->size()
440 << " track states on surfaces.");
441 // basic quantities copy
442 actsTrack.chi2() = trk->fitQuality()->chiSquared();
443 actsTrack.nDoF() = trk->fitQuality()->numberDoF();
444
445 // loop over track states on surfaces, convert and add them to the ACTS
446 // container
447 bool first_tsos = true; // We need to handle the first one differently
448 int measurementsCount = 0;
449 for (const Trk::TrackStateOnSurface* tsos : *trackStates) {
450
451 // Setup the mask
452 Acts::TrackStatePropMask mask = Acts::TrackStatePropMask::None;
453 if (tsos->measurementOnTrack()) {
454 mask |= Acts::TrackStatePropMask::Calibrated;
455 }
456 if (tsos->trackParameters()) {
457 mask |= Acts::TrackStatePropMask::Smoothed;
458 }
459
460 // Setup the index of the trackstate
461 auto index = Acts::MultiTrajectoryTraits::kInvalid;
462 if (!first_tsos) {
463 index = actsTrack.tipIndex();
464 }
465 auto actsTSOS = trackStateContainer.getTrackState(trackStateContainer.addTrackState(mask, index));
466 ATH_MSG_VERBOSE("TipIndex: " << actsTrack.tipIndex() << " TSOS index within trajectory: "<< actsTSOS.index());
467 actsTrack.tipIndex() = actsTSOS.index();
468
469 if (tsos->trackParameters()) {
470 // TODO This try/catch is temporary and should be removed once the sTGC problem is fixed.
471 try {
472 ATH_MSG_VERBOSE("Converting track parameters.");
473 // TODO - work out whether we should set predicted, filtered, smoothed
474 const Acts::BoundTrackParameters parameters =
475 trkTrackParametersToActsParameters(*(tsos->trackParameters()), gctx);
476 ATH_MSG_VERBOSE("Track parameters: " << parameters.parameters());
477 // Sanity check on positions
478 if (!actsTrackParameterPositionCheck(parameters, *(tsos->trackParameters()), gctx)){
479 failedIds.push_back(tsos->trackParameters()->associatedSurface().associatedDetectorElementIdentifier());
480 }
481
482 if (first_tsos) {
483 // This is the first track state, so we need to set the track
484 // parameters
485 actsTrack.parameters() = parameters.parameters();
486 actsTrack.covariance() = *parameters.covariance();
487 actsTrack.setReferenceSurface(parameters.referenceSurface().getSharedPtr());
488 first_tsos = false;
489 } else {
490 actsTSOS.setReferenceSurface(parameters.referenceSurface().getSharedPtr());
491 // Since we're converting final Trk::Tracks, let's assume they're smoothed
492 actsTSOS.smoothed() = parameters.parameters();
493 actsTSOS.smoothedCovariance() = *parameters.covariance();
494 // Not yet implemented in MultiTrajectory.icc
495 // actsTSOS.typeFlags() |= Acts::TrackStateFlag::ParameterFlag;
496 if (!(actsTSOS.hasSmoothed() && actsTSOS.hasReferenceSurface())) {
497 ATH_MSG_WARNING("TrackState does not have smoothed state ["
498 << actsTSOS.hasSmoothed()
499 << "] or reference surface ["
500 << actsTSOS.hasReferenceSurface() << "].");
501 } else {
502 ATH_MSG_VERBOSE("TrackState has smoothed state and reference surface.");
503 }
504 }
505 } catch (const std::exception& e){
506 ATH_MSG_ERROR("Unable to convert TrackParameter with exception ["<<e.what()<<"]. Will be missing from ACTS track."
507 <<(*tsos->trackParameters()));
508 }
509 }
510 if (tsos->measurementOnTrack()) {
511 auto &measurement = *(tsos->measurementOnTrack());
512
513 measurementsCount++;
514 // const Acts::Surface &surface =
515 // trkSurfaceToActsSurface(measurement.associatedSurface());
516 // Commented for the moment because Surfaces not yet implemented in
517 // MultiTrajectory.icc
518
519 int dim = measurement.localParameters().dimension();
520 actsTSOS.allocateCalibrated(dim);
521 if (dim == 1) {
522 actsTSOS.calibrated<1>() = measurement.localParameters();
523 actsTSOS.calibratedCovariance<1>() = measurement.localCovariance();
524 } else if (dim == 2) {
525 actsTSOS.calibrated<2>() = measurement.localParameters();
526 actsTSOS.calibratedCovariance<2>() = measurement.localCovariance();
527 } else {
528 throw std::domain_error("Cannot handle measurement dim>2");
529 }
530 actsTSOS.setUncalibratedSourceLink(detail::TrkMeasurementCalibrator::pack(tsos->measurementOnTrack()));
531
532 } // end if measurement
533 } // end loop over track states
534 actsTrack.nMeasurements() = measurementsCount;
535 ATH_MSG_VERBOSE("TrackProxy has " << actsTrack.nTrackStates()
536 << " track states on surfaces.");
537 }
538 ATH_MSG_VERBOSE("Finished converting " << trackColl.size() << " tracks.");
539
540 if (!failedIds.empty()){
541 ATH_MSG_WARNING("Failed to convert "<<failedIds.size()<<" track parameters.");
542 for (auto id : failedIds){
543 ATH_MSG_WARNING("-> Failed for Identifier "<<m_idHelperSvc->toString(id));
544 }
545 }
546 ATH_MSG_VERBOSE("ACTS Track container has " << tc.size() << " tracks.");
547}
static Double_t tc
bool actsTrackParameterPositionCheck(const Acts::BoundTrackParameters &actsParameter, const Trk::TrackParameters &tsos, const Acts::GeometryContext &gctx) const
virtual const Acts::BoundTrackParameters trkTrackParametersToActsParameters(const Trk::TrackParameters &atlasParameter, const Acts::GeometryContext &gctx, Trk::ParticleHypothesis=Trk::pion) const override
Create Acts TrackParameter from ATLAS one.
size_type size() const noexcept
Returns the number of elements in the collection.
str index
Definition DeMoScan.py:362
DataVector< const Trk::TrackStateOnSurface > TrackStates

◆ trkTrackParametersToActsParameters()

const Acts::BoundTrackParameters ActsTrk::ActsToTrkConverterTool::trkTrackParametersToActsParameters ( const Trk::TrackParameters & atlasParameter,
const Acts::GeometryContext & gctx,
Trk::ParticleHypothesis hypothesis = Trk::pion ) const
overridevirtual

Create Acts TrackParameter from ATLAS one.

Take care of unit conversion between the two.

Definition at line 213 of file ActsToTrkConverterTool.cxx.

215 {
216
217 using namespace Acts::UnitLiterals;
218 std::shared_ptr<const Acts::Surface> actsSurface;
219 Acts::BoundVector params;
220
221 // get the associated surface
222 if (atlasParameter.hasSurface() &&
224 try {
225 actsSurface = trkSurfaceToActsSurface(atlasParameter.associatedSurface()).getSharedPtr();
226 } catch (const std::exception &e) {
227 ATH_MSG_ERROR("Could not find ACTS detector surface for this TrackParameter:");
228 ATH_MSG_ERROR(atlasParameter);
229 throw; // Nothing we can do, so just pass exception on...
230 }
231 }
232 // no associated surface create a perigee one
233 else {
235 "trkTrackParametersToActsParameters:: No associated surface found (owner: "<<atlasParameter.associatedSurface().owner()<<
236 "). Creating a free surface. Trk parameters:");
237 ATH_MSG_VERBOSE(atlasParameter);
238 const Amg::Transform3D& trf{atlasParameter.associatedSurface().transform()};
239 switch (atlasParameter.associatedSurface().type()){
241 actsSurface = Acts::Surface::makeShared<const Acts::PlaneSurface>(trf);
242 break;
244 actsSurface = Acts::Surface::makeShared<const Acts::PerigeeSurface>(trf);
245 break;
247 actsSurface = Acts::Surface::makeShared<const Acts::StrawSurface>(trf);
248 break;
249 // TODO - implement the missing types?
250 default: {
251 std::stringstream surfStr{};
252 atlasParameter.dump(surfStr);
253 throw std::domain_error(std::format("Failed to translate parameters {:}", surfStr.str()));
254 }
255 }
256 }
257
258 // Construct track parameters
259 const auto& atlasParam{atlasParameter.parameters()};
260 if (actsSurface->bounds().type() == Acts::SurfaceBounds::BoundsType::eAnnulus) {
261 // Annulus surfaces are constructed differently in Acts/Trk so we need to
262 // convert local coordinates
263 const Amg::Vector3D& position{atlasParameter.position()};
264 auto result = actsSurface->globalToLocal(gctx, position, atlasParameter.momentum());
265 if (result.ok()) {
266 params << (*result)[0], (*result)[1], atlasParam[Trk::phi0],
267 atlasParam[Trk::theta],
268 atlasParameter.charge() / (atlasParameter.momentum().mag() * 1_MeV),
269 0.;
270 } else {
271 ATH_MSG_WARNING("Unable to convert annulus surface - globalToLocal failed");
272 }
273 } else {
274 params << atlasParam[Trk::locX], atlasParam[Trk::locY],
275 atlasParam[Trk::phi0], atlasParam[Trk::theta],
276 atlasParameter.charge() / (atlasParameter.momentum().mag() * 1_MeV), 0.;
277 }
278
279 Acts::BoundSquareMatrix cov = Acts::BoundSquareMatrix::Identity();
280 if (atlasParameter.covariance()) {
281 cov.topLeftCorner(5, 5) = *atlasParameter.covariance();
282
283 // Convert the covariance matrix from MeV
284 // FIXME: This needs to handle the annulus case as well - currently the cov
285 // is wrong for annulus surfaces
286 for (int i = 0; i < cov.rows(); i++) {
287 cov(i, 4) = cov(i, 4) / 1_MeV;
288 }
289 for (int i = 0; i < cov.cols(); i++) {
290 cov(4, i) = cov(4, i) / 1_MeV;
291 }
292 }
293
294 return Acts::BoundTrackParameters(actsSurface, params,cov,
295 ParticleHypothesis::convert(hypothesis));
296}
Scalar mag() const
mag method
virtual const Acts::Surface & trkSurfaceToActsSurface(const Trk::Surface &atlasSurface) const override
Find the Acts surface corresponding to the ATLAS surface Use a map associating ATLAS ID to Acts surfa...
virtual MsgStream & dump(MsgStream &out) const
Dumps relevant information about the track parameters into the ostream.
const Amg::Vector3D & momentum() const
Access method for the momentum.
const Amg::Vector3D & position() const
Access method for the position.
double charge() const
Returns the charge.
virtual bool hasSurface() const override=0
Test to see if there's a not null surface ptr.
virtual const Surface & associatedSurface() const override=0
Access to the Surface associated to the Parameters.
const Amg::Transform3D & transform() const
Returns HepGeom::Transform3D by reference.
SurfaceOwner owner() const
return ownership
xAOD::ParticleHypothesis convert(Acts::ParticleHypothesis h)
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
@ locY
local cartesian
Definition ParamDefs.h:38
@ locX
Definition ParamDefs.h:37
@ phi0
Definition ParamDefs.h:65
@ theta
Definition ParamDefs.h:66

◆ trkTrackToSourceLinks()

std::vector< Acts::SourceLink > ActsTrk::ActsToTrkConverterTool::trkTrackToSourceLinks ( const Trk::Track & track) const
overridevirtual

Transform an ATLAS track into a vector of SourceLink to be use in the avts tracking Transform both measurement and outliers.

Definition at line 183 of file ActsToTrkConverterTool.cxx.

183 {
184 std::vector<Acts::SourceLink> sourceLinks{};
185 sourceLinks.reserve(track.measurementsOnTrack()->size() +
186 track.outliersOnTrack()->size());
187 toSourceLinks(track.measurementsOnTrack()->stdcont(), sourceLinks);
188 toSourceLinks(track.outliersOnTrack()->stdcont(), sourceLinks);
189 return sourceLinks;
190}
virtual void toSourceLinks(const std::vector< const Trk::MeasurementBase * > &measSet, std::vector< Acts::SourceLink > &links) const override final

Member Data Documentation

◆ m_actsSurfaceMap

std::unordered_map<Identifier, const Acts::Surface*> ActsTrk::ActsToTrkConverterTool::m_actsSurfaceMap {}
private

Definition at line 105 of file ActsToTrkConverterTool.h.

105{};

◆ m_boundaryCheckTool

ToolHandle<Trk::IBoundaryCheckTool> ActsTrk::ActsToTrkConverterTool::m_boundaryCheckTool {this, "BoundaryCheckTool", "", "Boundary checking tool for detector sensitivities"}
private

Definition at line 101 of file ActsToTrkConverterTool.h.

101{this, "BoundaryCheckTool", "", "Boundary checking tool for detector sensitivities"};

◆ m_extractMuonSurfaces

Gaudi::Property<bool> ActsTrk::ActsToTrkConverterTool::m_extractMuonSurfaces
private
Initial value:
{
this, "ExtractMuonSurfaces", false,
"If True, use the MuonDetectorManager to extract the Muon surfaces"}

Definition at line 112 of file ActsToTrkConverterTool.h.

112 {
113 this, "ExtractMuonSurfaces", false,
114 "If True, use the MuonDetectorManager to extract the Muon surfaces"};

◆ m_idHelperSvc

ServiceHandle<Muon::IMuonIdHelperSvc> ActsTrk::ActsToTrkConverterTool::m_idHelperSvc {this, "MuonIdHelperSvc", "Muon::MuonIdHelperSvc/MuonIdHelperSvc"}
private

Definition at line 116 of file ActsToTrkConverterTool.h.

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

◆ m_muonMgrKey

SG::ReadCondHandleKey<MuonGM::MuonDetectorManager> ActsTrk::ActsToTrkConverterTool::m_muonMgrKey {this, "MuonManagerKey", "MuonDetectorManager"}
private

Detector manager to fetch the legacy Trk surfaces.

Definition at line 119 of file ActsToTrkConverterTool.h.

119{this, "MuonManagerKey", "MuonDetectorManager"};

◆ m_ROTcreator

ToolHandle<Trk::IRIO_OnTrackCreator> ActsTrk::ActsToTrkConverterTool::m_ROTcreator {this, "RotCreatorTool", ""}
private

Definition at line 102 of file ActsToTrkConverterTool.h.

102{this, "RotCreatorTool", ""};

◆ m_trackingGeometry

std::shared_ptr<const Acts::TrackingGeometry> ActsTrk::ActsToTrkConverterTool::m_trackingGeometry {}
private

Definition at line 104 of file ActsToTrkConverterTool.h.

104{};

◆ m_trackingGeometryTool

PublicToolHandle<ActsTrk::ITrackingGeometryTool> ActsTrk::ActsToTrkConverterTool::m_trackingGeometryTool {this, "TrackingGeometryTool", "ActsTrackingGeometryTool"}
private

Definition at line 97 of file ActsToTrkConverterTool.h.

97{this, "TrackingGeometryTool", "ActsTrackingGeometryTool"};

◆ m_trkSummaryTool

ToolHandle<Trk::IExtendedTrackSummaryTool> ActsTrk::ActsToTrkConverterTool::m_trkSummaryTool {this, "SummaryTool", "", "ToolHandle for track summary tool"}
private

Tools needed to create Trk::Tracks from the ACts fit result.

Definition at line 100 of file ActsToTrkConverterTool.h.

100{this, "SummaryTool", "", "ToolHandle for track summary tool"};

◆ m_visualDebugOutput

Gaudi::Property<bool> ActsTrk::ActsToTrkConverterTool::m_visualDebugOutput
private
Initial value:
{
this, "VisualDebugOutput", false,
"Print additional output for debug plots"}

Definition at line 107 of file ActsToTrkConverterTool.h.

107 {
108 this, "VisualDebugOutput", false,
109 "Print additional output for debug plots"};

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