ATLAS Offline Software
Loading...
Searching...
No Matches
ActsToTrkConverterTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7// Trk
10#include "TrkSurfaces/Surface.h"
11#include "TrkTrack/Track.h"
12
13// ATHENA
14#include "GaudiKernel/IInterface.h"
19#include "TrkSurfaces/Surface.h"
21
24
30// PACKAGE
39
40// ACTS
41#include "Acts/Surfaces/StrawSurface.hpp"
42#include "Acts/Surfaces/PerigeeSurface.hpp"
43#include "Acts/Surfaces/PlaneSurface.hpp"
44
45#include "Acts/Surfaces/RectangleBounds.hpp"
46#include "Acts/Surfaces/TrapezoidBounds.hpp"
47#include "Acts/Surfaces/CylinderBounds.hpp"
48#include "Acts/Surfaces/DiscBounds.hpp"
49#include "Acts/Surfaces/LineBounds.hpp"
50#include "Acts/Surfaces/RadialBounds.hpp"
51
52#include "Acts/Definitions/Units.hpp"
53#include "Acts/EventData/BoundTrackParameters.hpp"
54#include "Acts/EventData/VectorTrackContainer.hpp"
55#include "Acts/EventData/TransformationHelpers.hpp"
56#include "Acts/Geometry/TrackingGeometry.hpp"
57#include "Acts/Propagator/detail/JacobianEngine.hpp"
58#include "Acts/Surfaces/detail/PlanarHelper.hpp"
59
61#include "Acts/EventData/TrackStatePropMask.hpp"
62#include "Acts/EventData/SourceLink.hpp"
63
64
65
66
73
74// STL
75#include <cmath>
76#include <iostream>
77#include <memory>
78#include <random>
79#include <format>
80
81namespace ActsTrk {
82
83using namespace Acts::UnitLiterals;
84
85using SurfacePtr_t = ActsToTrkConverterTool::SurfacePtr_t;
86
87// Forward definitions of local functions
88// @TODO unused, remove ?
89#pragma GCC diagnostic push
90#pragma GCC diagnostic ignored "-Wunused-function"
91static void ActsMeasurementCheck(const Acts::GeometryContext &gctx,
92 const Trk::MeasurementBase &measurement,
93 const Acts::Surface &surface,
94 const Acts::BoundVector &loc);
95#pragma GCC diagnostic pop
96
97static void ActsTrackParameterCheck(
98 const Acts::BoundTrackParameters &actsParameter,
99 const Acts::GeometryContext &gctx, const Acts::BoundMatrix &covpc,
100 const Acts::BoundVector &targetPars, const Acts::BoundMatrix &targetCov,
101 const Trk::PlaneSurface *planeSurface);
102
103
104std::unique_ptr<Trk::TrackParameters> rotateParams(const Trk::TrackParameters& inPars,
105 const Trk::Surface& target) {
106 const Amg::Vector3D& pos = inPars.position();
107 const Amg::Vector3D& mom = inPars.momentum();
108 using namespace Acts::PlanarHelper;
109
110 const auto isect = intersectPlane(pos, mom.normalized(), target.normal(), target.center());
111 std::optional<AmgSymMatrix(5)> cov{};
112 if (inPars.covariance()) {
113 AmgSymMatrix(5) rot {AmgSymMatrix(5)::Identity()};
114 rot.block<2,2>(0,0) = AmgSymMatrix(2){Eigen::Rotation2D{90._degree}};
115 cov = rot.transpose() * (*inPars.covariance()) * rot;
116 }
117 return target.createUniqueTrackParameters(isect.position(), mom,
118 std::copysign(1., inPars.parameters()[Trk::qOverP]),
119 std::move(cov));
120}
121
122
124 ATH_MSG_DEBUG("Initializing ACTS to ATLAS converter tool");
125 if (!m_trackingGeometryTool.empty()) {
127 m_trackingGeometry = m_trackingGeometryTool->trackingGeometry();
128
129 m_trackingGeometry->visitSurfaces([&](const Acts::Surface *surface) {
130 // find acts surface with the same detector element ID
131 if (!surface)
132 return;
133 const auto *actsElement = dynamic_cast<const IDetectorElementBase*>(
134 surface->surfacePlacement());
135 if (!actsElement) {
136 return;
137 }
138 // Conversion from Acts to ATLAS surface impossible for the TRT so the TRT
139 // surfaces are not stored in this map
140 if (actsElement->detectorType() == DetectorType::Trt) {
141 return;
142 }
143
144 auto [it, ok] = m_actsSurfaceMap.insert(std::make_pair(actsElement->identify(), surface->getSharedPtr()));
145 if (!ok) {
146 ATH_MSG_WARNING("ATLAS ID " << actsElement->identify()
147 << " has two ACTS surfaces: "
148 << it->second->geometryId() << " and "
149 << surface->geometryId());
150 }
151 });
152 }
153
154 ATH_CHECK(m_trkSummaryTool.retrieve());
155 ATH_CHECK(m_ROTcreator.retrieve());
157 m_slType = static_cast<detail::SourceLinkType>(m_sourceLinkType.value());
159 ATH_CHECK(m_keyMdt.initialize(SG::AllowEmpty));
160 ATH_CHECK(m_keyRpc.initialize(SG::AllowEmpty));
161 ATH_CHECK(m_keyTgc.initialize(SG::AllowEmpty));
162 ATH_CHECK(m_keyMm.initialize(SG::AllowEmpty));
164 ATH_CHECK(m_compRotCreator.retrieve(EnableTool{!m_keyRpc.empty() || !m_keyTgc.empty()}));
166 ATH_CHECK(m_idHelperSvc.retrieve());
167 const MuonGMR4::MuonDetectorManager* muonMgr{nullptr};
168 ATH_CHECK(detStore()->retrieve(muonMgr));
169 unsigned int mapSize = m_actsSurfaceMap.size(); // For debugging message later
170 for (auto readoutElement : muonMgr->getAllReadoutElements()) {
171 std::vector<std::shared_ptr<Acts::Surface>> reSurfaces = readoutElement->getSurfaces();
172 for ( const auto& surf : reSurfaces) {
173 const Identifier id = static_cast<const SurfaceCache*>(surf->surfacePlacement())->identify();
174 m_actsSurfaceMap.insert(std::make_pair(id, surf));
175 }
176 }
177 ATH_MSG_VERBOSE("After adding muon surfaces, the map has grown from "<<mapSize<<" to "<<m_actsSurfaceMap.size());
178 }
179 return StatusCode::SUCCESS;
180}
181
183 const ActsTrk::GeometryContext gctx{};
184 const Amg::Transform3D& trf{surface.localToGlobalTransform(gctx.context())};
185 switch (surface.type()) {
186 using enum Acts::Surface::SurfaceType;
187 case Plane:
188 return SurfacePtr_t{new Trk::PlaneSurface(trf, translateBounds(surface.bounds()))};
189 case Cylinder:
190 return SurfacePtr_t{new Trk::CylinderSurface(trf,
191 std::dynamic_pointer_cast<Trk::CylinderBounds>(translateBounds(surface.bounds())))};
192 case Perigee:
193 return SurfacePtr_t{new Trk::PerigeeSurface(trf)};
194 case Disc:
195 return SurfacePtr_t{new Trk::DiscSurface(trf,
196 std::dynamic_pointer_cast<Trk::DiscBounds>(translateBounds(surface.bounds())))};
197 case Straw: {
198 auto bounds = std::dynamic_pointer_cast<Trk::CylinderBounds>(translateBounds(surface.bounds()));
199 return SurfacePtr_t{new Trk::StraightLineSurface(trf, bounds->r(), bounds->halflengthZ())};
200 } default:
201 break;
202
203 }
204 THROW_EXCEPTION("ActsToTrkConverterTool() - Surface cannot be translated "
205 <<surface.toString(gctx.context()));
206
207 return nullptr;
208}
209
211 const Acts::Surface &actsSurface) const {
212
213 const auto *detEleBase= dynamic_cast<const IDetectorElementBase*>(actsSurface.surfacePlacement());
214 if (!detEleBase) {
215 return translateFreeSurface(actsSurface);
216 }
217 switch (detEleBase->detectorType()) {
218 using enum DetectorType;
219 case Pixel:
220 case Sct:
221 case Hgtd:
222 case Trt: {
223 const auto actsElement = dynamic_cast<const ActsDetectorElement*>(detEleBase);
224 if (actsElement) {
225 return SurfacePtr_t{&actsElement->atlasSurface()};
226 }
227 break;
228 }
229 case Mdt:
230 case Rpc:
231 case Tgc:
232 case Csc:
233 case sTgc:
234 case Mm: {
235 const MuonGM::MuonDetectorManager* detMgr{nullptr};
236 if (!SG::get(detMgr, m_muonMgrKey, ctx).isSuccess() || !detMgr) {
237 THROW_EXCEPTION("Failed to retrieve the muon detector manager");
238 }
239 return SurfacePtr_t{&detMgr->getReadoutElement(detEleBase->identify())->surface(detEleBase->identify())};
240
241 } default:
242 break;
243 }
245 return translateFreeSurface(actsSurface);
246}
247
248std::shared_ptr<const Acts::Surface>
250
251 Identifier atlasID = atlasSurface.associatedDetectorElementIdentifier();
252 auto it = m_actsSurfaceMap.find(atlasID);
253 if (it != m_actsSurfaceMap.end()) {
254 return it->second;
255 }
256 const Amg::Transform3D& trf{atlasSurface.transform()};
257 switch (atlasSurface.type()){
258 using enum Trk::SurfaceType;
259 case Plane:
260 return Acts::Surface::makeShared<Acts::PlaneSurface>(trf);
261 case Perigee:
262 return Acts::Surface::makeShared<Acts::PerigeeSurface>(trf);
263 case Line:
264 return Acts::Surface::makeShared<Acts::StrawSurface>(trf);
265 // TODO - implement the missing types?
266 default: {
267 break;
268 }
269 }
270 std::stringstream surfStr{};
271 atlasSurface.dump(surfStr);
272 throw std::domain_error(std::format("Failed to translate surface {:}", surfStr.str()));
273}
274
275std::vector<Acts::SourceLink>
277 std::vector<Acts::SourceLink> sourceLinks{};
278 sourceLinks.reserve(track.measurementsOnTrack()->size() +
279 track.outliersOnTrack()->size());
280 toSourceLinks(track.measurementsOnTrack()->stdcont(), sourceLinks);
281 toSourceLinks(track.outliersOnTrack()->stdcont(), sourceLinks);
282 return sourceLinks;
283}
284
285
286void ActsToTrkConverterTool::toSourceLinks(const std::vector<const Trk::MeasurementBase*>& measSet,
287 std::vector<Acts::SourceLink>& sourceLinks) const{
288 if (sourceLinks.capacity() < sourceLinks.size() + measSet.size()) {
289 sourceLinks.reserve(sourceLinks.size() + measSet.size());
290 }
291 std::ranges::transform(measSet, std::back_inserter(sourceLinks), [](const Trk::MeasurementBase* meas) {
293 });
294}
295void ActsToTrkConverterTool::toSourceLinks(const std::vector<const Trk::PrepRawData*>& prdSet,
296 std::vector<Acts::SourceLink>& links) const {
297 if (links.capacity() < links.size() + prdSet.size()) {
298 links.reserve(links.size() + prdSet.size());
299 }
300 std::ranges::transform(prdSet, std::back_inserter(links), [](const Trk::PrepRawData* prd) {
302 });
303}
304
305const Acts::BoundTrackParameters
307 const Acts::GeometryContext & gctx,
308 Trk::ParticleHypothesis hypothesis) const {
309
310 std::shared_ptr<const Acts::Surface> actsSurface{};
311 Acts::BoundVector params;
312
313 // get the associated surface
314 try {
315 actsSurface = trkSurfaceToActsSurface(atlasParameter.associatedSurface());
316 } catch (const std::exception &e) {
317 ATH_MSG_ERROR("Could not find ACTS detector surface for this TrackParameter:");
318 ATH_MSG_ERROR(atlasParameter);
319 throw; // Nothing we can do, so just pass exception on...
320 }
321
322 // Construct track parameters
323 const auto& atlasParam{atlasParameter.parameters()};
324 if (actsSurface->bounds().type() == Acts::SurfaceBounds::BoundsType::eAnnulus) {
325 // Annulus surfaces are constructed differently in Acts/Trk so we need to
326 // convert local coordinates
327 const Amg::Vector3D& position{atlasParameter.position()};
328 auto result = actsSurface->globalToLocal(gctx, position, atlasParameter.momentum());
329 if (result.ok()) {
330 params << (*result)[0], (*result)[1], atlasParam[Trk::phi0],
331 atlasParam[Trk::theta],
332 atlasParameter.charge() / (atlasParameter.momentum().mag() * 1_MeV),
333 0.;
334 } else {
335 ATH_MSG_WARNING("Unable to convert annulus surface - globalToLocal failed");
336 }
337 } else {
338 params << atlasParam[Trk::locX], atlasParam[Trk::locY],
339 atlasParam[Trk::phi0], atlasParam[Trk::theta],
340 atlasParameter.charge() / (atlasParameter.momentum().mag() * 1_MeV), 0.;
341 }
342
343 Acts::BoundMatrix cov = Acts::BoundMatrix::Identity();
344 if (atlasParameter.covariance()) {
345 cov.topLeftCorner(5, 5) = *atlasParameter.covariance();
346
347 // Convert the covariance matrix from MeV
348 // FIXME: This needs to handle the annulus case as well - currently the cov
349 // is wrong for annulus surfaces
350 for (int i = 0; i < cov.rows(); i++) {
351 cov(i, 4) = cov(i, 4) / 1_MeV;
352 }
353 for (int i = 0; i < cov.cols(); i++) {
354 cov(4, i) = cov(4, i) / 1_MeV;
355 }
356 }
357
358 return Acts::BoundTrackParameters(actsSurface, params,cov,
359 ParticleHypothesis::convert(hypothesis));
360}
361
362std::unique_ptr<Trk::TrackParameters>
364 const EventContext& ctx,
365 const Acts::BoundTrackParameters &actsParameter,
366 const Acts::GeometryContext &gctx) const {
367
368 std::optional<AmgSymMatrix(5)> cov = std::nullopt;
369 if (actsParameter.covariance()) {
370 AmgSymMatrix(5) newcov(actsParameter.covariance()->topLeftCorner<5, 5>());
371 // Convert the covariance matrix to GeV
372 for (int i = 0; i < newcov.rows(); i++) {
373 newcov(i, 4) = newcov(i, 4) * 1_MeV;
374 }
375 for (int i = 0; i < newcov.cols(); i++) {
376 newcov(4, i) = newcov(4, i) * 1_MeV;
377 }
378 cov = newcov;
379 }
380
381 const Acts::Surface &actsSurface = actsParameter.referenceSurface();
382 SurfacePtr_t trkSurface = actsSurfaceToTrkSurface(ctx, actsSurface);
383 switch (actsSurface.type()) {
384 case Acts::Surface::SurfaceType::Cone: {
385 const auto &coneSurface = static_cast<const Trk::ConeSurface&>(*trkSurface);
386 return std::make_unique<Trk::AtaCone>(
387 actsParameter.get<Acts::eBoundLoc0>(),
388 actsParameter.get<Acts::eBoundLoc1>(),
389 actsParameter.get<Acts::eBoundPhi>(),
390 actsParameter.get<Acts::eBoundTheta>(),
391 actsParameter.get<Acts::eBoundQOverP>() * 1_MeV, coneSurface, cov);
392 } case Acts::Surface::SurfaceType::Cylinder: {
393 const auto &cylSurface{static_cast<const Trk::CylinderSurface&>(*trkSurface)};
394 return std::make_unique<Trk::AtaCylinder>(
395 actsParameter.get<Acts::eBoundLoc0>(),
396 actsParameter.get<Acts::eBoundLoc1>(),
397 actsParameter.get<Acts::eBoundPhi>(),
398 actsParameter.get<Acts::eBoundTheta>(),
399 actsParameter.get<Acts::eBoundQOverP>() * 1_MeV, cylSurface, cov);
400 } case Acts::Surface::SurfaceType::Disc: {
401 if (trkSurface->type() == Trk::SurfaceType::Disc) {
402 const auto& discSurface{static_cast<const Trk::DiscSurface&>(*trkSurface)};
403 return std::make_unique<Trk::AtaDisc>(
404 actsParameter.get<Acts::eBoundLoc0>(),
405 actsParameter.get<Acts::eBoundLoc1>(),
406 actsParameter.get<Acts::eBoundPhi>(),
407 actsParameter.get<Acts::eBoundTheta>(),
408 actsParameter.get<Acts::eBoundQOverP>() * 1_MeV, discSurface, cov);
409 } else if (trkSurface->type() == Trk::SurfaceType::Plane) {
410 auto& planeSurface{static_cast<const Trk::PlaneSurface&>(*trkSurface)};
411 // need to convert to plane position on plane surface (annulus bounds)
412 auto helperSurface = Acts::Surface::makeShared<Acts::PlaneSurface>(planeSurface.transform());
413
414 auto covpc = actsParameter.covariance().value();
416 Acts::FreeVector freePars = Acts::transformBoundToFreeParameters(actsSurface, gctx,
417 actsParameter.parameters());
418
420 Acts::BoundVector targetPars = Acts::transformFreeToBoundParameters(freePars,
421 *helperSurface, gctx).value();
422
423 Acts::FreeMatrix freeTransportJacobian{Acts::FreeMatrix::Identity()};
424
425 Acts::FreeVector freeToPathDerivatives{Acts::FreeVector::Zero()};
426 freeToPathDerivatives.head<3>() = freePars.segment<3>(Acts::eFreeDir0);
427
428 auto boundToFreeJacobian = actsSurface.boundToFreeJacobian(gctx, freePars.segment<3>(Acts::eFreePos0),
429 freePars.segment<3>(Acts::eFreeDir0));
430
431 Acts::BoundMatrix boundToBoundJac = Acts::detail::boundToBoundTransportJacobian(gctx, freePars,
432 boundToFreeJacobian, freeTransportJacobian, freeToPathDerivatives, *helperSurface);
433
434 Acts::BoundMatrix targetCov{boundToBoundJac * covpc * boundToBoundJac.transpose()};
435
436 auto pars = std::make_unique<Trk::AtaPlane>(
437 targetPars[Acts::eBoundLoc0], targetPars[Acts::eBoundLoc1],
438 targetPars[Acts::eBoundPhi], targetPars[Acts::eBoundTheta],
439 targetPars[Acts::eBoundQOverP] * 1_MeV, planeSurface,
440 targetCov.topLeftCorner<5, 5>());
441
443 ActsTrackParameterCheck(actsParameter, gctx, covpc, targetPars,
444 targetCov, &planeSurface);
445 }
446 return pars;
447
448 } else {
449 throw std::domain_error("Acts::DiscSurface is not associated with ATLAS disc or plane surface");
450 }
451 break;
452 } case Acts::Surface::SurfaceType::Perigee: {
453 const auto& perSurface = static_cast<const Trk::PerigeeSurface&>(*trkSurface);
454 return std::make_unique<Trk::Perigee>(
455 actsParameter.get<Acts::eBoundLoc0>(),
456 actsParameter.get<Acts::eBoundLoc1>(),
457 actsParameter.get<Acts::eBoundPhi>(),
458 actsParameter.get<Acts::eBoundTheta>(),
459 actsParameter.get<Acts::eBoundQOverP>() * 1_MeV, perSurface, cov);
460 } case Acts::Surface::SurfaceType::Plane: {
461 auto &plaSurface{static_cast<const Trk::PlaneSurface&>(*trkSurface)};
462 return std::make_unique<Trk::AtaPlane>(
463 actsParameter.get<Acts::eBoundLoc0>(),
464 actsParameter.get<Acts::eBoundLoc1>(),
465 actsParameter.get<Acts::eBoundPhi>(),
466 actsParameter.get<Acts::eBoundTheta>(),
467 actsParameter.get<Acts::eBoundQOverP>() * 1_MeV, plaSurface, cov);
468 } case Acts::Surface::SurfaceType::Straw: {
469 auto& lineSurface{static_cast<const Trk::StraightLineSurface&>(*trkSurface)};
470 return std::make_unique<Trk::AtaStraightLine>(
471 actsParameter.get<Acts::eBoundLoc0>(),
472 actsParameter.get<Acts::eBoundLoc1>(),
473 actsParameter.get<Acts::eBoundPhi>(),
474 actsParameter.get<Acts::eBoundTheta>(),
475 actsParameter.get<Acts::eBoundQOverP>() * 1_MeV, lineSurface, cov);
476 } case Acts::Surface::SurfaceType::Curvilinear: {
477 return std::make_unique<Trk::CurvilinearParameters>(
478 actsParameter.position(gctx), actsParameter.get<Acts::eBoundPhi>(),
479 actsParameter.get<Acts::eBoundTheta>(),
480 actsParameter.get<Acts::eBoundQOverP>() * 1_MeV, cov);
481 } case Acts::Surface::SurfaceType::Other: {
482 break;
483 }
484 }
485 throw std::domain_error("Surface type not found");
486}
487
489 const TrackCollection &trackColl,
490 const Acts::GeometryContext & gctx) const {
491 ATH_MSG_VERBOSE("Calling trkTrackCollectionToActsTrackContainer with "
492 << trackColl.size() << " tracks.");
493 unsigned int trkCount = 0;
494 std::vector<Identifier> failedIds; // Keep track of Identifiers of failed conversions
495 for (const Trk::Track* trk : trackColl) {
496 // Do conversions!
497 const Trk::TrackStates *trackStates = trk->trackStateOnSurfaces();
498
499 auto actsTrack = tc.getTrack(tc.addTrack());
500 auto& trackStateContainer = tc.trackStateContainer();
501
502 ATH_MSG_VERBOSE("Track "<<trkCount++<<" has " << trackStates->size()
503 << " track states on surfaces.");
504 // basic quantities copy
505 actsTrack.chi2() = trk->fitQuality()->chiSquared();
506 actsTrack.nDoF() = trk->fitQuality()->numberDoF();
507
508 // loop over track states on surfaces, convert and add them to the ACTS
509 // container
510 bool first_tsos = true; // We need to handle the first one differently
511 int measurementsCount = 0;
512 for (const Trk::TrackStateOnSurface* tsos : *trackStates) {
513
514 // Setup the mask
515 Acts::TrackStatePropMask mask = Acts::TrackStatePropMask::None;
516 if (tsos->measurementOnTrack()) {
517 mask |= Acts::TrackStatePropMask::Calibrated;
518 }
519 if (tsos->trackParameters()) {
520 mask |= Acts::TrackStatePropMask::Smoothed;
521 }
522
523 // Setup the index of the trackstate
524 auto index = Acts::kTrackIndexInvalid;
525 if (!first_tsos) {
526 index = actsTrack.tipIndex();
527 }
528 auto actsTSOS = trackStateContainer.getTrackState(trackStateContainer.addTrackState(mask, index));
529 ATH_MSG_VERBOSE("TipIndex: " << actsTrack.tipIndex() << " TSOS index within trajectory: "<< actsTSOS.index());
530 actsTrack.tipIndex() = actsTSOS.index();
531
532 if (tsos->trackParameters()) {
533 // TODO This try/catch is temporary and should be removed once the sTGC problem is fixed.
534 try {
535 ATH_MSG_VERBOSE("Converting track parameters.");
536 // TODO - work out whether we should set predicted, filtered, smoothed
537 const Acts::BoundTrackParameters parameters =
538 trkTrackParametersToActsParameters(*(tsos->trackParameters()), gctx);
539 ATH_MSG_VERBOSE("Track parameters: " << parameters.parameters());
540 // Sanity check on positions
541 if (!actsTrackParameterPositionCheck(parameters, *(tsos->trackParameters()), gctx)){
542 failedIds.push_back(tsos->trackParameters()->associatedSurface().associatedDetectorElementIdentifier());
543 }
544
545 if (first_tsos) {
546 // This is the first track state, so we need to set the track
547 // parameters
548 actsTrack.parameters() = parameters.parameters();
549 actsTrack.covariance() = *parameters.covariance();
550 actsTrack.setReferenceSurface(parameters.referenceSurface().getSharedPtr());
551 first_tsos = false;
552 } else {
553 actsTSOS.setReferenceSurface(parameters.referenceSurface().getSharedPtr());
554 // Since we're converting final Trk::Tracks, let's assume they're smoothed
555 actsTSOS.smoothed() = parameters.parameters();
556 actsTSOS.smoothedCovariance() = *parameters.covariance();
557 // Not yet implemented in MultiTrajectory.icc
558 // actsTSOS.typeFlags().setHasParameters();
559 if (!(actsTSOS.hasSmoothed() && actsTSOS.hasReferenceSurface())) {
560 ATH_MSG_WARNING("TrackState does not have smoothed state ["
561 << actsTSOS.hasSmoothed()
562 << "] or reference surface ["
563 << actsTSOS.hasReferenceSurface() << "].");
564 } else {
565 ATH_MSG_VERBOSE("TrackState has smoothed state and reference surface.");
566 }
567 }
568 } catch (const std::exception& e){
569 ATH_MSG_ERROR("Unable to convert TrackParameter with exception ["<<e.what()<<"]. Will be missing from ACTS track."
570 <<(*tsos->trackParameters()));
571 }
572 }
573 if (tsos->measurementOnTrack()) {
574 auto &measurement = *(tsos->measurementOnTrack());
575
576 measurementsCount++;
577 // const Acts::Surface &surface =
578 // trkSurfaceToActsSurface(measurement.associatedSurface());
579 // Commented for the moment because Surfaces not yet implemented in
580 // MultiTrajectory.icc
581
582 int dim = measurement.localParameters().dimension();
583 actsTSOS.allocateCalibrated(dim);
584 if (dim == 1) {
585 actsTSOS.calibrated<1>() = measurement.localParameters();
586 actsTSOS.calibratedCovariance<1>() = measurement.localCovariance();
587 } else if (dim == 2) {
588 actsTSOS.calibrated<2>() = measurement.localParameters();
589 actsTSOS.calibratedCovariance<2>() = measurement.localCovariance();
590 } else {
591 throw std::domain_error("Cannot handle measurement dim>2");
592 }
593 actsTSOS.setUncalibratedSourceLink(detail::TrkMeasurementCalibrator::pack(tsos->measurementOnTrack()));
594
595 } // end if measurement
596 } // end loop over track states
597 actsTrack.nMeasurements() = measurementsCount;
598 ATH_MSG_VERBOSE("TrackProxy has " << actsTrack.nTrackStates()
599 << " track states on surfaces.");
600 }
601 ATH_MSG_VERBOSE("Finished converting " << trackColl.size() << " tracks.");
602
603 if (!failedIds.empty()){
604 ATH_MSG_WARNING("Failed to convert "<<failedIds.size()<<" track parameters.");
605 for (auto id : failedIds){
606 ATH_MSG_WARNING("-> Failed for Identifier "<<m_idHelperSvc->toString(id));
607 }
608 }
609 ATH_MSG_VERBOSE("ACTS Track container has " << tc.size() << " tracks.");
610}
611
612std::shared_ptr<Trk::SurfaceBounds>
613 ActsToTrkConverterTool::translateBounds(const Acts::SurfaceBounds& bounds) const {
614 switch (bounds.type()) {
615 using enum Acts::SurfaceBounds::BoundsType;
616 case eRectangle:{
617 using ParEnum_t = Acts::RectangleBounds::BoundValues;
618 const auto& cBounds = static_cast<const Acts::RectangleBounds&>(bounds);
619 return std::make_shared<Trk::RectangleBounds>(cBounds.get(ParEnum_t::eMaxX),
620 cBounds.get(ParEnum_t::eMaxY));
621 } case eTrapezoid: {
622 using ParEnum_t = Acts::TrapezoidBounds::BoundValues;
623 const auto& cBounds = static_cast<const Acts::TrapezoidBounds&>(bounds);
624 return std::make_shared<Trk::TrapezoidBounds>(cBounds.get(ParEnum_t::eHalfLengthXnegY),
625 cBounds.get(ParEnum_t::eHalfLengthXposY),
626 cBounds.get(ParEnum_t::eHalfLengthY));
627
628 } case eDisc: {
629 using ParEnum_t = Acts::RadialBounds::BoundValues;
630 const auto& cBounds = static_cast<const Acts::RadialBounds&>(bounds);
631 return std::make_shared<Trk::DiscBounds>(cBounds.get(ParEnum_t::eMinR),
632 cBounds.get(ParEnum_t::eMaxR),
633 cBounds.get(ParEnum_t::eAveragePhi),
634 cBounds.get(ParEnum_t::eHalfPhiSector));
635
636 } case eCylinder: {
637 using ParEnum_t = Acts::CylinderBounds::BoundValues;
638 const auto& cBounds = static_cast<const Acts::CylinderBounds&>(bounds);
639 return std::make_shared<Trk::CylinderBounds>(cBounds.get(ParEnum_t::eR),
640 cBounds.get(ParEnum_t::eHalfPhiSector),
641 cBounds.get(ParEnum_t::eAveragePhi),
642 cBounds.get(ParEnum_t::eHalfLengthZ));
643 } case eLine: {
644 using ParEnum_t = Acts::LineBounds::BoundValues;
645 const auto& cBounds = static_cast<const Acts::LineBounds&>(bounds);
646 return std::make_shared<Trk::CylinderBounds>(cBounds.get(ParEnum_t::eR),
647 cBounds.get(ParEnum_t::eHalfLengthZ));
648 } default:
649 break;
650
651 }
652 THROW_EXCEPTION("The bounds "<<bounds<<" cannot be translated");
653 return nullptr;
654}
655
656
658 const Acts::BoundTrackParameters &parameters,
659 const Trk::TrackParameters &trkparameters,
660 const Acts::GeometryContext &gctx) const {
661 auto actsPos = parameters.position(gctx);
662 // ATH_MSG_VERBOSE("Acts position: \n"
663 // << actsPos << " vs trk position: \n"
664 // << trkparameters.position());
665 // ATH_MSG_VERBOSE(parameters.referenceSurface().toString(gctx));
666 // ATH_MSG_VERBOSE("GeometryId "<<parameters.referenceSurface().geometryId().value());
667
668 if ( (actsPos - trkparameters.position()).mag() > 0.1) {
669 ATH_MSG_WARNING("Parameter position mismatch. Acts \n"
670 << actsPos << " vs Trk \n"
671 << trkparameters.position());
672 ATH_MSG_WARNING("Acts surface:");
673 ATH_MSG_WARNING(parameters.referenceSurface().toString(gctx));
674 ATH_MSG_WARNING("Trk surface:");
675 ATH_MSG_WARNING(trkparameters.associatedSurface());
676 return false;
677 }
678 return true;
679}
680
681// Local functions to check/debug Annulus bounds
682
683#pragma GCC diagnostic push
684#pragma GCC diagnostic ignored "-Wunused-function"
686 const Acts::GeometryContext &gctx, const Trk::MeasurementBase &measurement,
687 const Acts::Surface &surface, const Acts::BoundVector &loc) {
688 const Trk::Surface &surf = measurement.associatedSurface();
689 // only check Annulus for the moment
690 if (surf.bounds().type() != Trk::SurfaceBounds::Annulus) {
691 return;
692 }
693 const auto *bounds = dynamic_cast<const Trk::AnnulusBounds *>(&surf.bounds());
694 if (bounds == nullptr) {
695 throw std::runtime_error{"Annulus but not XY"};
696 }
697
698 Amg::Vector2D locxy = loc.head<2>();
699
700 Acts::Matrix<2, 2> covxy = measurement.localCovariance();
701
702 Amg::Vector3D global = surf.localToGlobal(locxy, Amg::Vector3D{});
703 Acts::Vector2 locpc;
704 if (auto res = surface.globalToLocal(gctx, global, Acts::Vector3{});
705 res.ok()) {
706 locpc = *res;
707 } else {
708 throw std::runtime_error{"Global position not on target surface"};
709 }
710
711 // use ACTS jacobian math to convert cluster covariance from cartesian to
712 // polar
713 auto planeSurface =
714 Acts::Surface::makeShared<Acts::PlaneSurface>(surf.transform());
715 Acts::BoundVector locxypar;
716 locxypar.head<2>() = locxy;
717 locxypar[2] = 0;
718 locxypar[3] = M_PI_2;
719 locxypar[4] = 1;
720 locxypar[5] = 1;
721 Acts::FreeVector globalxypar = Acts::transformBoundToFreeParameters(
722 *planeSurface, gctx, locxypar);
723 auto boundToFree = planeSurface->boundToFreeJacobian(
724 gctx, globalxypar.segment<3>(Acts::eFreePos0),
725 globalxypar.segment<3>(Acts::eFreeDir0));
726 Acts::SquareMatrix<2> xyToXyzJac = boundToFree.topLeftCorner<2, 2>();
727
728 Acts::BoundVector locpcpar;
729 locpcpar.head<2>() = locpc;
730 locpcpar[2] = 0;
731 locpcpar[3] = M_PI_2;
732 locpcpar[4] = 1;
733 locpcpar[5] = 1;
734 Acts::FreeVector globalpcpar = Acts::transformBoundToFreeParameters(
735 surface, gctx, locpcpar);
736
737 boundToFree = surface.boundToFreeJacobian(
738 gctx, globalpcpar.segment<3>(Acts::eFreePos0),
739 globalpcpar.segment<3>(Acts::eFreeDir0));
740 Acts::SquareMatrix<2> pcToXyzJac = boundToFree.topLeftCorner<2, 2>();
741 Acts::SquareMatrix<2> xyzToPcJac = pcToXyzJac.inverse();
742
743 // convert cluster covariance
744 Acts::SquareMatrix<2> covpc = covxy;
745 covpc = xyToXyzJac * covpc * xyToXyzJac.transpose();
746 covpc = xyzToPcJac * covpc * xyzToPcJac.transpose();
747
748 std::mt19937 gen{42 + surface.geometryId().value()};
749 std::normal_distribution<double> normal{0, 1};
750 std::uniform_real_distribution<double> uniform{-1, 1};
751
752 Acts::SquareMatrix<2> lltxy = covxy.llt().matrixL();
753 Acts::SquareMatrix<2> lltpc = covpc.llt().matrixL();
754
755 for (size_t i = 0; i < 1e4; i++) {
756 std::cout << "ANNULUS COV: ";
757 std::cout << surface.geometryId();
758
759 Amg::Vector2D rnd{normal(gen), normal(gen)};
760
761 // XY
762 {
763 Amg::Vector2D xy = lltxy * rnd + locxy;
765 std::cout << "," << xy.x() << "," << xy.y();
766 std::cout << "," << xyz.x() << "," << xyz.y() << "," << xyz.z();
767 }
768 // PC
769 {
770 // Amg::Vector2D xy = lltpc * rnd + loc.head<2>();
771 Amg::Vector2D rt = lltpc * rnd + locpc;
772 Amg::Vector3D xyz = surface.localToGlobal(gctx, rt, Acts::Vector3{});
773 // Amg::Vector3D xyz = surface.transform(gctx).rotation() *
774 // Acts::Vector3{rt.x(), rt.y(), 0};
775
776 std::cout << "," << rt.x() << "," << rt.y();
777 std::cout << "," << xyz.x() << "," << xyz.y() << "," << xyz.z();
778 }
779
780 std::cout << std::endl;
781 }
782}
783#pragma GCC diagnostic pop
784
786 const Acts::BoundTrackParameters &actsParameter,
787 const Acts::GeometryContext &gctx, const Acts::BoundMatrix &covpc,
788 const Acts::BoundVector &targetPars, const Acts::BoundMatrix &targetCov,
789 const Trk::PlaneSurface *planeSurface) {
790
791 std::cout << "ANNULUS PAR COV: ";
792 std::cout << actsParameter.referenceSurface().geometryId();
793 for (unsigned int i = 0; i < 5; i++) {
794 for (unsigned int j = 0; j < 5; j++) {
795 std::cout << "," << covpc(i, j);
796 }
797 }
798 for (unsigned int i = 0; i < 5; i++) {
799 for (unsigned int j = 0; j < 5; j++) {
800 std::cout << "," << targetCov(i, j);
801 }
802 }
803 std::cout << std::endl;
804
805 std::mt19937 gen{4242 +
806 actsParameter.referenceSurface().geometryId().value()};
807 std::normal_distribution<double> normal{0, 1};
808
809 Acts::SquareMatrix<2> lltxy =
810 targetCov.topLeftCorner<2, 2>().llt().matrixL();
811 Acts::SquareMatrix<2> lltpc = covpc.topLeftCorner<2, 2>().llt().matrixL();
812
813 for (size_t i = 0; i < 1e4; i++) {
814 std::cout << "ANNULUS PAR: ";
815 std::cout << actsParameter.referenceSurface().geometryId();
816
817 Acts::Vector<2> rnd;
818 rnd << normal(gen), normal(gen);
819
820 // XY
821 {
822 Acts::Vector<2> xy =
823 lltxy.topLeftCorner<2, 2>() * rnd + targetPars.head<2>();
825 planeSurface->localToGlobal(Amg::Vector2D{xy.head<2>()}, Amg::Vector3D{},
826 xyz);
827 for (unsigned int i = 0; i < 2; i++) {
828 std::cout << "," << xy[i];
829 }
830 std::cout << "," << xyz.x() << "," << xyz.y() << "," << xyz.z();
831 }
832 // PC
833 {
834 Acts::Vector<2> rt = lltpc.topLeftCorner<2, 2>() * rnd +
835 actsParameter.parameters().head<2>();
836 Amg::Vector3D xyz = actsParameter.referenceSurface().localToGlobal(
837 gctx, Acts::Vector2{rt.head<2>()}, Acts::Vector3{});
838
839 for (unsigned int i = 0; i < 2; i++) {
840 std::cout << "," << rt[i];
841 }
842 std::cout << "," << xyz.x() << "," << xyz.y() << "," << xyz.z();
843 }
844
845 std::cout << std::endl;
846 }
847}
848
849std::unique_ptr<Trk::Track> ActsToTrkConverterTool::convertFitResult(const EventContext& ctx,
850 TrackFitResult_t& fitResult,
851 const Trk::TrackInfo::TrackFitter fitAuthor,
852 const detail::SourceLinkType slType) const {
853
854 if (not fitResult.ok()) {
855 ATH_MSG_VERBOSE("Fit did not converge");
856 return nullptr;
857 }
858 return convertActsTrack(ctx, fitResult.value(), fitAuthor, slType);
859}
860
861template <typename Proxy_t>
862 std::unique_ptr<Trk::Track>
864 const Proxy_t& acts_track,
865 const Trk::TrackInfo::TrackFitter fitAuthor,
866 const detail::SourceLinkType slType) const{
867
868
869 const Acts::CalibrationContext cctx{getCalibrationContext(ctx)};
870 const Acts::GeometryContext gctx{m_trackingGeometryTool->getGeometryContext(ctx).context()};
871
872 auto finalTrajectory = std::make_unique<Trk::TrackStates>();
873 int nDoF{0};
874
875 double chi2{0};
876
877 // Loop over all the output state to create track state
878 acts_track.container().trackStateContainer().visitBackwards(acts_track.tipIndex(),
879 [&] (const auto &state) -> void {
880 if (!state.hasReferenceSurface()) {
881 return;
882 }
883 // First only consider state with an associated detector element
884 if (!m_convertMaterial && !state.referenceSurface().isSensitive()) {
885 return;
886 }
887
888 if (const auto* associatedDetEl = dynamic_cast<const IDetectorElementBase*>(
889 state.referenceSurface().surfacePlacement());
890 associatedDetEl != nullptr) {
891 ATH_MSG_VERBOSE("Associated det: "<<associatedDetEl->detectorType());
892 }
893
894 auto flag = state.typeFlags();
895
896 // We need to determine the type of state
897 TrkTSOSMask typePattern;
898 std::unique_ptr<Trk::TrackParameters> trkPars = actsTrackParametersToTrkParameters(ctx,
899 acts_track.createParametersFromState(state), gctx);
900 std::unique_ptr<Trk::MeasurementBase> trkMeasurement{};
901
902 // State is a hole (no associated measurement), use predicted parameters
903 if (flag.isHole()) {
904 if (!m_convertHoles) { return; }
905 typePattern.set(Trk::TrackStateOnSurface::Hole);
906 } if (flag.isOutlier()) {
907 if (!m_convertOutliers) { return; }
908 typePattern.set(Trk::TrackStateOnSurface::Outlier);
909 } if (flag.hasMeasurement()) {
910 typePattern.set(Trk::TrackStateOnSurface::Measurement);
911 nDoF = state.calibratedSize();
912 chi2 = state.chi2();
913 switch (slType) {
914 using enum detail::SourceLinkType;
915 case TrkMeasurement:
916 trkMeasurement = m_measCalib.unpack(state.getUncalibratedSourceLink())->uniqueClone();
917 break;
918 case TrkPrepRawData:
919 trkMeasurement = m_prdCalib.createROT(gctx, cctx, state.getUncalibratedSourceLink(), state);
920 break;
921 case xAODUnCalibMeas:
922 appendMeasTSOS(ctx, detail::xAODUncalibMeasCalibrator::unpack(state.getUncalibratedSourceLink()),
923 typePattern, Trk::FitQualityOnSurface{chi2, nDoF},
924 std::move(trkPars), *finalTrajectory);
925 return;
926 default:
927 THROW_EXCEPTION("Invalid "<<slType<<" type parsed.");
928 }
929 }
930 auto perState = std::make_unique<Trk::TrackStateOnSurface>(Trk::FitQualityOnSurface{chi2, nDoF},
931 std::move(trkMeasurement),
932 std::move(trkPars), nullptr, typePattern);
933 // If a state was succesfully created add it to the trajectory
934 ATH_MSG_VERBOSE("State succesfully created, adding it to the trajectory");
935 finalTrajectory->insert(finalTrajectory->begin(), std::move(perState));
936 });
937 // Convert the perigee state and add it to the trajectory
938 std::unique_ptr<Trk::TrackParameters> per = actsTrackParametersToTrkParameters(ctx, acts_track.createParametersAtReference(), gctx);
939 TrkTSOSMask typePattern;
940 typePattern.set(Trk::TrackStateOnSurface::Perigee);
941 finalTrajectory->insert(finalTrajectory->begin(),
942 std::make_unique<Trk::TrackStateOnSurface>(nullptr, std::move(per), nullptr, typePattern));
943
944 // Create the track using the states
945 Trk::TrackInfo newInfo{fitAuthor, ParticleHypothesis::convertTrk(acts_track.particleHypothesis())};
946 auto newtrack = std::make_unique<Trk::Track>(newInfo, std::move(finalTrajectory), nullptr);
947 constexpr bool suppressHoleSearch = false;
948 m_trkSummaryTool->updateTrackSummary(ctx, *newtrack, suppressHoleSearch);
949 return newtrack;
950 }
951
952 std::unique_ptr<TrackCollection>
954 const ActsTrk::TrackContainer& trackCont) const {
955 auto outColl = std::make_unique<TrackCollection>();
956 for (const ActsTrk::TrackContainer::ConstTrackProxy& trk : trackCont) {
957 outColl->push_back(convertActsTrack(ctx, trk, m_fitAuthor, m_slType));
958 }
959 return outColl;
960 }
961 void ActsToTrkConverterTool::appendMeasTSOS(const EventContext& ctx,
963 const TrkTSOSMask typePattern,
964 Trk::FitQualityOnSurface&& quality,
965 std::unique_ptr<Trk::TrackParameters> trkPars,
966 Trk::TrackStates& states) const {
967 std::unique_ptr<Trk::MeasurementBase> rot{};
968 switch (meas->type()) {
969 using enum xAOD::UncalibMeasType;
970 case PixelClusterType: {
971 static const SG::AuxElement::ConstAccessor<ElementLink<InDet::PixelClusterCollection>> acc_pixelLink("pixelClusterLink");
972 if (acc_pixelLink.isAvailable(*meas) && acc_pixelLink(*meas).isValid()) {
973 rot.reset(m_ROTcreator->correct(**acc_pixelLink(*meas), *trkPars, ctx));
974 }
975 break;
976 } case StripClusterType: {
977 static const SG::AuxElement::ConstAccessor<ElementLink<InDet::SCT_ClusterCollection>> acc_stripLink("sctClusterLink");
978 if (acc_stripLink.isAvailable(*meas) && acc_stripLink(*meas).isValid()) {
979 rot.reset(m_ROTcreator->correct(**acc_stripLink(*meas), *trkPars, ctx));
980 }
981 break;
982 } case MdtDriftCircleType:
983 case MMClusterType: {
984 const Identifier& id = static_cast<const xAOD::MuonMeasurement*>(meas)->identify();
985 const IdentifierHash modHash = m_idHelperSvc->moduleHash(id);
986 const auto* prd = meas->type() == MdtDriftCircleType ? fetchPrd(ctx, m_keyMdt, id, modHash)
987 : fetchPrd(ctx, m_keyMm, id, modHash);
988 assert(prd != nullptr);
989 rot.reset(m_ROTcreator->correct(*prd, *trkPars, ctx));
990 break;
991 } case TgcStripType:
992 case RpcStripType:
993 case sTgcStripType: {
994 const Identifier& id = static_cast<const xAOD::MuonMeasurement*>(meas)->identify();
995 const IdentifierHash modHash = m_idHelperSvc->moduleHash(id);
997 const Trk::PrepRawData* prd{nullptr}, *prd1{nullptr};
998
999 if (meas->numDimensions() == 0) {
1000 const auto* muonMeas = static_cast<const xAOD::CombinedMuonStrip*>(meas);
1001 if (meas->type() == RpcStripType) {
1002 prd = fetchPrd(ctx, m_keyRpc, id, modHash);
1003 prd1 = fetchPrd(ctx, m_keyRpc, muonMeas->secondaryStrip()->identify(), modHash);
1004 } else if (meas->type() == TgcStripType) {
1005 prd = fetchPrd(ctx, m_keyTgc, id, modHash);
1006 prd1 = fetchPrd(ctx, m_keyTgc, muonMeas->secondaryStrip()->identify(), modHash);
1007 } else {
1008 prd = fetchPrd(ctx, m_keyStgc, id, modHash);
1009 prd1 = fetchPrd(ctx, m_keyStgc, muonMeas->secondaryStrip()->identify(), modHash);
1010 }
1011 assert(prd != nullptr);
1012 assert(prd1 != nullptr);
1013
1015 const Trk::Surface& phiSurface = prd1->detectorElement()->surface(prd1->identify());
1016 auto phiPars = rotateParams(*trkPars, phiSurface);
1017 assert(phiPars != nullptr);
1018 std::unique_ptr<Trk::MeasurementBase> phiRot{};
1019 if (meas->type() != sTgcStripType) {
1020 phiRot = m_compRotCreator->createBroadCluster(std::list{prd1}, 1.);
1021 rot = m_compRotCreator->createBroadCluster(std::list{prd}, 1.);
1022 } else {
1023 phiRot.reset(m_ROTcreator->correct(*prd1, *phiPars, ctx));
1024 rot.reset(m_ROTcreator->correct(*prd, *trkPars, ctx));
1025 }
1026 assert(phiRot != nullptr);
1027 states.insert(states.begin(),
1028 std::make_unique<Trk::TrackStateOnSurface>(quality,
1029 std::move(phiRot),
1030 std::move(phiPars), nullptr, typePattern));
1031 } else {
1032 const auto* prd = meas->type() == RpcStripType ? fetchPrd(ctx, m_keyRpc, id, modHash)
1033 :
1034 meas->type() == TgcStripType ? fetchPrd(ctx, m_keyTgc, id, modHash)
1035 : fetchPrd(ctx, m_keyStgc, id, modHash);
1036 assert(prd != nullptr);
1037 // Track parameter representation needs to change towards a phi surface
1038 if (m_idHelperSvc->measuresPhi(id)) {
1039 ATH_MSG_VERBOSE("Convert the track parameters "<<m_idHelperSvc->toString(id)
1040 <<", "<<m_idHelperSvc->toStringDetEl(prd->detectorElement()->identify()));
1041 const Trk::Surface& target = prd->detectorElement()->surface(id);
1042 trkPars = rotateParams(*trkPars, target);
1043 }
1045 rot.reset(m_ROTcreator->correct(*prd, *trkPars, ctx));
1046 }
1047 break;
1048 } default:
1049 ATH_MSG_WARNING("Measurement type "<<meas->type()<<" is not implemented");
1050 return;
1051 }
1052 assert(rot != nullptr);
1053 assert(trkPars != nullptr);
1054 states.insert(states.begin(),
1055 std::make_unique<Trk::TrackStateOnSurface>(std::move(quality), std::move(rot),
1056 std::move(trkPars), nullptr, typePattern));
1057
1058 }
1059 template <typename PrdType_t>
1062 const Identifier& prdId,
1063 const IdentifierHash& hash) const{
1064 const PrdType_t* container{nullptr};
1065 if (key.empty() || !SG::get(container, key, ctx).isSuccess()) {
1066 THROW_EXCEPTION("Failed to retrieve container "<<key.fullKey());
1067 }
1068 const auto* coll = container->indexFindPtr(hash);
1069 if (coll == nullptr){
1070 ATH_MSG_WARNING("fetchPrd() - Failed to find a valid collection for "<<prdId.getString()<<", key: "<<key.fullKey());
1071 return nullptr;
1072 }
1073 for (const Trk::PrepRawData* prd : *coll) {
1074 if (prd->identify() == prdId) {
1075 return prd;
1076 }
1077 }
1078 ATH_MSG_WARNING("fetchPrd() - Prep data object "<<prdId.getString()<<" is not in "<<key.fullKey());
1079 return nullptr;
1080 }
1081} // namespace ActsTrk
Scalar mag() const
mag 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)
#define AmgSymMatrix(dim)
std::pair< std::vector< unsigned int >, bool > res
static Double_t tc
static TRandom * rnd
if(pathvar)
DataVector< Trk::Track > TrackCollection
This typedef represents a collection of Trk::Track objects.
#define xyz
std::bitset< Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes > TrkTSOSMask
Abrivate the state mask for the TSOS.
virtual void toSourceLinks(const std::vector< const Trk::MeasurementBase * > &measSet, std::vector< Acts::SourceLink > &links) const override final
virtual std::unique_ptr< Trk::Track > convertFitResult(const EventContext &ctx, TrackFitResult_t &fitResult, const Trk::TrackInfo::TrackFitter fitAuthor, const detail::SourceLinkType slType) const override final
virtual SurfacePtr_t actsSurfaceToTrkSurface(const EventContext &ctx, const Acts::Surface &actsSurface) const override
Find the ATLAS surface corresponding to the Acts surface Only work if the Acts surface has an associa...
bool actsTrackParameterPositionCheck(const Acts::BoundTrackParameters &actsParameter, const Trk::TrackParameters &tsos, const Acts::GeometryContext &gctx) const
ToolHandle< Trk::IExtendedTrackSummaryTool > m_trkSummaryTool
Tools needed to create Trk::Tracks from the ACts fit result.
SG::ReadCondHandleKey< MuonGM::MuonDetectorManager > m_muonMgrKey
Detector manager to fetch the legacy Trk surfaces.
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
SG::ReadHandleKey< Muon::RpcPrepDataContainer > m_keyRpc
virtual StatusCode initialize() override
std::shared_ptr< Trk::SurfaceBounds > translateBounds(const Acts::SurfaceBounds &bounds) const
std::unique_ptr< Trk::Track > convertActsTrack(const EventContext &ctx, const Proxy_t &track, const Trk::TrackInfo::TrackFitter fitAuthor, const detail::SourceLinkType slType) const
Helper function to convert a Acts TrackPoxy (which may be const or not) into a Trk::Track.
ToolHandle< Muon::IMuonCompetingClustersOnTrackCreator > m_compRotCreator
Gaudi::Property< bool > m_visualDebugOutput
detail::TrkPrepRawDataCalibrator m_prdCalib
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.
SurfacePtr_t translateFreeSurface(const Acts::Surface &surface) const
Translate a surface that is not associated with any detector element.
virtual std::unique_ptr< TrackCollection > convertActsToTrkContainer(const EventContext &ctx, const ActsTrk::TrackContainer &trackCont) const override final
ToolHandle< Trk::IRIO_OnTrackCreator > m_ROTcreator
Gaudi::Property< bool > m_extractMuonSurfaces
virtual std::unique_ptr< Trk::TrackParameters > actsTrackParametersToTrkParameters(const EventContext &ctx, const Acts::BoundTrackParameters &actsParameter, const Acts::GeometryContext &gctx) const override
Create ATLAS TrackParameter from Acts one.
SG::ReadHandleKey< Muon::MMPrepDataContainer > m_keyMm
SG::ReadHandleKey< Muon::MdtPrepDataContainer > m_keyMdt
SG::ReadHandleKey< Muon::TgcPrepDataContainer > m_keyTgc
std::shared_ptr< const Acts::TrackingGeometry > m_trackingGeometry
virtual void trkTrackCollectionToActsTrackContainer(ActsTrk::MutableTrackContainer &tc, const TrackCollection &trackColl, const Acts::GeometryContext &gctx) const override
Convert TrackCollection to Acts track container.
std::unordered_map< Identifier, std::shared_ptr< const Acts::Surface > > m_actsSurfaceMap
const Trk::PrepRawData * fetchPrd(const EventContext &ctx, const SG::ReadHandleKey< PrdType_t > &key, const Identifier &prdId, const IdentifierHash &hash) const
Searches a Prd object from a collection according to the measurement's Identifier and the container's...
Gaudi::Property< int > m_sourceLinkType
Source link sepcification used when the ActTrk container -> Trk container conversion is called.
void appendMeasTSOS(const EventContext &ctx, const xAOD::UncalibratedMeasurement *meas, const TrkTSOSMask typePattern, Trk::FitQualityOnSurface &&quality, std::unique_ptr< Trk::TrackParameters > trkPars, Trk::TrackStates &states) const
Append the translated TSOS at the beginning of the states container corresponding to the parsed measu...
Trk::TrackInfo::TrackFitter m_fitAuthor
SG::ReadHandleKey< Muon::sTgcPrepDataContainer > m_keyStgc
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 me...
virtual std::shared_ptr< 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...
Gaudi::Property< bool > m_convertMaterial
Flag to convert the material states (non sensitive) Acts -> Trk conversion.
PublicToolHandle< ActsTrk::ITrackingGeometryTool > m_trackingGeometryTool
Acts::GeometryContext context() const
base class interface providing the bare minimal interface extension.
: Helper class to connect the aligned transformations of each active sensor(layer) with the Acts::Sur...
Identifier identify() const override final
Returns the identifier of the Surface.
static Acts::SourceLink pack(const Trk::MeasurementBase *meas)
Packs the pointer to the track measurement into an Acts::SouceLink.
Class to calibrate the Acts track states with uncalibrated Trk::PrepRaw data objects.
static Acts::SourceLink pack(const SourceLink_t prd)
Pack the PrepRaw data measurement into a source link.
size_type size() const noexcept
Returns the number of elements in the collection.
This is a "hash" representation of an Identifier.
std::string getString() const
Provide a string form of the identifier - hexadecimal.
std::vector< const MuonReadoutElement * > getAllReadoutElements(const ActsTrk::DetectorType type=ActsTrk::DetectorType::UnDefined) const
Returns all readout elements.
The MuonDetectorManager stores the transient representation of the Muon Spectrometer geometry and pro...
const MuonReadoutElement * getReadoutElement(const Identifier &id) const
Get any read out element.
Property holding a SG store/key/clid from which a ReadHandle is made.
Bounds for a annulus-like, planar Surface.
Class for a conical surface in the ATLAS detector.
Definition ConeSurface.h:51
Class for a CylinderSurface in the ATLAS detector.
Class for a DiscSurface in the ATLAS detector.
Definition DiscSurface.h:54
This class is the pure abstract base class for all fittable tracking measurements.
virtual const Surface & associatedSurface() const =0
Interface method to get the associated Surface.
const Amg::MatrixX & localCovariance() const
Interface method to get the localError.
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 const Surface & associatedSurface() const override=0
Access to the Surface associated to the Parameters.
Class describing the Line to which the Perigee refers to.
Class for a planaer rectangular or trapezoidal surface in the ATLAS detector.
virtual void localToGlobal(const Amg::Vector2D &locp, const Amg::Vector3D &mom, Amg::Vector3D &glob) const override final
Specified for PlaneSurface: LocalToGlobal method without dynamic memory allocation.
virtual const TrkDetElementBase * detectorElement() const =0
return the detector element corresponding to this PRD The pointer will be zero if the det el is not d...
Class for a StraightLineSurface in the ATLAS detector to describe dirft tube and straw like detectors...
virtual BoundsType type() const =0
Return the bounds type - for persistency optimization.
Abstract Base Class for tracking surfaces.
Definition Surface.h:79
virtual MsgStream & dump(MsgStream &sl) const
Output Method for MsgStream, to be overloaded by child classes.
Definition Surface.cxx:157
const Amg::Transform3D & transform() const
Returns HepGeom::Transform3D by reference.
Identifier associatedDetectorElementIdentifier() const
return Identifier of the associated Detector Element
virtual constexpr SurfaceType type() const =0
Returns the Surface type to avoid dynamic casts.
virtual const SurfaceBounds & bounds() const =0
Surface Bounds method.
virtual void localToGlobal(const Amg::Vector2D &locp, const Amg::Vector3D &mom, Amg::Vector3D &glob) const =0
Specified by each surface type: LocalToGlobal method without dynamic memory allocation.
Contains information about the 'fitter' of this track.
TrackFitter
enums to identify who created this track and what propertis does it have.
represents the track state (measurement, material, fit parameters and quality) at a surface.
@ Perigee
This represents a perigee, and so will contain a Perigee object only.
@ Outlier
This TSoS contains an outlier, that is, it contains a MeasurementBase/RIO_OnTrack which was not used ...
@ Hole
A hole on the track - this is defined in the following way.
virtual Identifier identify() const =0
Identifier.
virtual const Surface & surface() const =0
Return surface associated with this detector element.
virtual unsigned int numDimensions() const =0
Returns the number of dimensions of the measurement.
virtual xAOD::UncalibMeasType type() const =0
Returns the type of the measurement type as a simple enumeration.
double chi2(TH1 *h0, TH1 *h1)
xAOD::ParticleHypothesis convert(Acts::ParticleHypothesis h)
SourceLinkType
Enumeration to distinguish between the ATLAS EDM -> Acts::SourceLink variants.
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...
ActsToTrkConverterTool::SurfacePtr_t SurfacePtr_t
DetectorType
Simple enum to Identify the Type of the ACTS sub detector.
@ Mm
Maybe not needed in the migration.
@ Tgc
Resitive Plate Chambers.
@ sTgc
Micromegas (NSW).
@ Rpc
Monitored Drift Tubes.
@ Csc
Thin gap champers.
@ Trt
Maybe the Sct / Pixel for Itk become seperate entries?
@ Mdt
MuonSpectrometer.
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...
static void ActsTrackParameterCheck(const Acts::BoundTrackParameters &actsParameter, const Acts::GeometryContext &gctx, const Acts::BoundMatrix &covpc, const Acts::BoundVector &targetPars, const Acts::BoundMatrix &targetCov, const Trk::PlaneSurface *planeSurface)
static void ActsMeasurementCheck(const Acts::GeometryContext &gctx, const Trk::MeasurementBase &measurement, const Acts::Surface &surface, const Acts::BoundVector &loc)
std::unique_ptr< Trk::TrackParameters > rotateParams(const Trk::TrackParameters &inPars, const Trk::Surface &target)
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
SurfaceType
This enumerator simplifies the persistency & calculations,.
DataVector< const Trk::TrackStateOnSurface > TrackStates
@ locY
local cartesian
Definition ParamDefs.h:38
@ locX
Definition ParamDefs.h:37
@ phi0
Definition ParamDefs.h:65
@ theta
Definition ParamDefs.h:66
@ qOverP
perigee
Definition ParamDefs.h:67
ParticleHypothesis
Enumeration for Particle hypothesis respecting the interaction with material.
ParametersBase< TrackParametersDim, Charged > TrackParameters
Definition index.py:1
MuonMeasurement_v1 MuonMeasurement
UncalibMeasType
Define the type of the uncalibrated measurement.
CombinedMuonStrip_v1 CombinedMuonStrip
UncalibratedMeasurement_v1 UncalibratedMeasurement
Define the version of the uncalibrated measurement class.
#define THROW_EXCEPTION(MESSAGE)
Definition throwExcept.h:10