12 #include "GaudiKernel/IInterface.h"
30 #include "Acts/Definitions/Units.hpp"
31 #include "Acts/EventData/TrackParameters.hpp"
32 #include "Acts/EventData/VectorTrackContainer.hpp"
33 #include "Acts/EventData/TransformationHelpers.hpp"
34 #include "Acts/Geometry/TrackingGeometry.hpp"
35 #include "Acts/Propagator/detail/JacobianEngine.hpp"
36 #include "Acts/Surfaces/PerigeeSurface.hpp"
37 #include "Acts/Surfaces/Surface.hpp"
39 #include "Acts/EventData/TrackStatePropMask.hpp"
40 #include "Acts/EventData/SourceLink.hpp"
53 #pragma GCC diagnostic push
54 #pragma GCC diagnostic ignored "-Wunused-function"
55 static void ActsMeasurementCheck(
const Acts::GeometryContext &gctx,
57 const Acts::Surface &surface,
58 const Acts::BoundVector &loc);
59 #pragma GCC diagnostic pop
61 static void ActsTrackParameterCheck(
62 const Acts::BoundTrackParameters &actsParameter,
63 const Acts::GeometryContext &gctx,
const Acts::BoundSquareMatrix &covpc,
64 const Acts::BoundVector &targetPars,
const Acts::BoundSquareMatrix &targetCov,
70 const std::string &
type,
const std::string &
name,
const IInterface *
parent)
75 if (m_extractMuonSurfaces){
78 if (!m_trackingGeometryTool.empty()) {
79 ATH_CHECK(m_trackingGeometryTool.retrieve());
80 m_trackingGeometry = m_trackingGeometryTool->trackingGeometry();
82 m_trackingGeometry->visitSurfaces([&](
const Acts::Surface *surface) {
87 surface->associatedDetectorElement());
93 actsElement->upstreamDetectorElement()) !=
nullptr);
98 m_actsSurfaceMap.insert({actsElement->identify(), surface});
101 <<
" has two ACTS surfaces: "
102 <<
it->second->geometryId() <<
" and "
103 << surface->geometryId());
108 if (m_extractMuonSurfaces){
111 unsigned int mapSize = m_actsSurfaceMap.size();
114 for (
const auto& surf : reSurfaces) {
116 m_actsSurfaceMap.insert(std::make_pair(
id, surf.get()));
119 ATH_MSG_VERBOSE(
"After adding muon surfaces, the map has grown from "<<mapSize<<
" to "<<m_actsSurfaceMap.size());
121 return StatusCode::SUCCESS;
125 const Acts::Surface &actsSurface)
const {
128 actsSurface.associatedDetectorElement());
132 throw std::domain_error(
"No ATLAS surface corresponding to to the Acts one");
139 auto it = m_actsSurfaceMap.find(atlasID);
140 if (
it != m_actsSurfaceMap.end()) {
143 ATH_MSG_ERROR(
"No Acts surface corresponding to this ATLAS surface:");
145 throw std::domain_error(
"No Acts surface corresponding to the ATLAS one");
149 [[maybe_unused]]
const Acts::GeometryContext& gctx,
152 return Acts::SourceLink(&measurement);
156 std::vector<Acts::SourceLink>
158 const Acts::GeometryContext &gctx,
const Trk::Track &track)
const {
159 auto hits = track.measurementsOnTrack();
160 auto outliers = track.outliersOnTrack();
162 std::vector<Acts::SourceLink> sourceLinks;
163 sourceLinks.reserve(
hits->size() + outliers->size());
166 sourceLinks.push_back(trkMeasurementToSourceLink(gctx, **
it));
168 for (
auto it = outliers->begin();
it != outliers->end(); ++
it) {
169 sourceLinks.push_back(trkMeasurementToSourceLink(gctx, **
it));
175 const Acts::BoundTrackParameters
179 using namespace Acts::UnitLiterals;
180 std::shared_ptr<const Acts::Surface> actsSurface;
190 ATH_MSG_ERROR(
"Could not find ACTS detector surface for this TrackParameter:");
198 "trkTrackParametersToActsParameters:: No associated surface found (owner: "<<atlasParameter.
associatedSurface().
owner()<<
199 "). Creating a free surface. Trk parameters:");
204 actsSurface = Acts::Surface::makeShared<const Acts::PlaneSurface>(
208 actsSurface = Acts::Surface::makeShared<const Acts::PerigeeSurface>(
213 ATH_MSG_WARNING(
"No surface type found for this Trk::Surface. Creating a perigee surface.");
214 actsSurface = Acts::Surface::makeShared<const Acts::PerigeeSurface>(
220 auto atlasParam = atlasParameter.parameters();
221 if (actsSurface->bounds().type() ==
222 Acts::SurfaceBounds::BoundsType::eAnnulus) {
225 auto position = atlasParameter.
position();
227 actsSurface->globalToLocal(gctx, position, atlasParameter.
momentum());
231 atlasParameter.
charge() / (atlasParameter.
momentum().mag() * 1_MeV),
235 "Unable to convert annulus surface - globalToLocal failed");
240 atlasParameter.
charge() / (atlasParameter.
momentum().mag() * 1_MeV), 0.;
243 Acts::BoundSquareMatrix
cov = Acts::BoundSquareMatrix::Identity();
244 if (atlasParameter.covariance()) {
245 cov.topLeftCorner(5, 5) = *atlasParameter.covariance();
250 for (
int i = 0;
i <
cov.rows();
i++) {
253 for (
int i = 0;
i <
cov.cols();
i++) {
260 Acts::PdgParticle absPdg = Acts::makeAbsolutePdgParticle(
261 static_cast<Acts::PdgParticle
>(
262 m_pdgToParticleHypothesis.convert(hypothesis, atlasParameter.
charge())));
264 absPdg,
mass, Acts::AnyCharge{std::abs(
static_cast<float>(atlasParameter.
charge()))}};
266 return Acts::BoundTrackParameters(actsSurface,
params,
267 cov, actsHypothesis);
270 std::unique_ptr<Trk::TrackParameters>
272 const Acts::BoundTrackParameters &actsParameter,
273 const Acts::GeometryContext &gctx)
const {
275 using namespace Acts::UnitLiterals;
277 if (actsParameter.covariance()) {
279 newcov(actsParameter.covariance()->topLeftCorner<5, 5>());
281 for (
int i = 0;
i < newcov.rows();
i++) {
282 newcov(
i, 4) = newcov(
i, 4) * 1_MeV;
284 for (
int i = 0;
i < newcov.cols();
i++) {
285 newcov(4,
i) = newcov(4,
i) * 1_MeV;
287 cov = std::optional<AmgSymMatrix(5)>(newcov);
290 const Acts::Surface &actsSurface = actsParameter.referenceSurface();
292 switch (actsSurface.type()) {
297 actsSurfaceToTrkSurface(actsSurface));
298 return std::make_unique<Trk::AtaCone>(
299 actsParameter.get<Acts::eBoundLoc0>(),
300 actsParameter.get<Acts::eBoundLoc1>(),
301 actsParameter.get<Acts::eBoundPhi>(),
302 actsParameter.get<Acts::eBoundTheta>(),
303 actsParameter.get<Acts::eBoundQOverP>() * 1_MeV, coneSurface,
cov);
310 actsSurfaceToTrkSurface(actsSurface));
311 return std::make_unique<Trk::AtaCylinder>(
312 actsParameter.get<Acts::eBoundLoc0>(),
313 actsParameter.get<Acts::eBoundLoc1>(),
314 actsParameter.get<Acts::eBoundPhi>(),
315 actsParameter.get<Acts::eBoundTheta>(),
316 actsParameter.get<Acts::eBoundQOverP>() * 1_MeV, cylSurface,
cov);
321 &actsSurfaceToTrkSurface(actsSurface));
322 discSurface !=
nullptr) {
323 return std::make_unique<Trk::AtaDisc>(
324 actsParameter.get<Acts::eBoundLoc0>(),
325 actsParameter.get<Acts::eBoundLoc1>(),
326 actsParameter.get<Acts::eBoundPhi>(),
327 actsParameter.get<Acts::eBoundTheta>(),
328 actsParameter.get<Acts::eBoundQOverP>() * 1_MeV, *discSurface,
cov);
329 }
else if (
const auto *planeSurface =
331 &actsSurfaceToTrkSurface(actsSurface));
332 planeSurface !=
nullptr) {
334 auto helperSurface = Acts::Surface::makeShared<Acts::PlaneSurface>(
335 planeSurface->transform());
337 auto covpc = actsParameter.covariance().value();
339 Acts::FreeVector freePars =
340 Acts::transformBoundToFreeParameters(
341 actsSurface, gctx, actsParameter.parameters());
343 Acts::BoundVector targetPars =
344 Acts::transformFreeToBoundParameters(freePars,
345 *helperSurface, gctx)
348 Acts::FreeMatrix freeTransportJacobian = Acts::FreeMatrix::Identity();
351 freeToPathDerivatives.head<3>() = freePars.segment<3>(Acts::eFreeDir0);
353 auto boundToFreeJacobian = actsSurface.boundToFreeJacobian(
354 gctx, freePars.segment<3>(Acts::eFreePos0),
355 freePars.segment<3>(Acts::eFreeDir0));
357 Acts::BoundMatrix boundToBoundJac = Acts::detail::boundToBoundTransportJacobian(
358 gctx, freePars, boundToFreeJacobian, freeTransportJacobian,
359 freeToPathDerivatives, *helperSurface);
361 Acts::BoundMatrix targetCov =
362 boundToBoundJac * covpc * boundToBoundJac.transpose();
364 auto pars = std::make_unique<Trk::AtaPlane>(
365 targetPars[Acts::eBoundLoc0], targetPars[Acts::eBoundLoc1],
366 targetPars[Acts::eBoundPhi], targetPars[Acts::eBoundTheta],
367 targetPars[Acts::eBoundQOverP] * 1_MeV, *planeSurface,
368 targetCov.topLeftCorner<5, 5>());
370 if (m_visualDebugOutput) {
371 ActsTrackParameterCheck(actsParameter, gctx, covpc, targetPars,
372 targetCov, planeSurface);
378 throw std::runtime_error{
379 "Acts::DiscSurface is not associated with ATLAS disc or plane "
384 case Acts::Surface::SurfaceType::Perigee: {
386 return std::make_unique<Trk::Perigee>(
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, perSurface,
cov);
398 actsSurfaceToTrkSurface(actsSurface));
399 return std::make_unique<Trk::AtaPlane>(
400 actsParameter.get<Acts::eBoundLoc0>(),
401 actsParameter.get<Acts::eBoundLoc1>(),
402 actsParameter.get<Acts::eBoundPhi>(),
403 actsParameter.get<Acts::eBoundTheta>(),
404 actsParameter.get<Acts::eBoundQOverP>() * 1_MeV, plaSurface,
cov);
410 actsSurfaceToTrkSurface(actsSurface));
411 return std::make_unique<Trk::AtaStraightLine>(
412 actsParameter.get<Acts::eBoundLoc0>(),
413 actsParameter.get<Acts::eBoundLoc1>(),
414 actsParameter.get<Acts::eBoundPhi>(),
415 actsParameter.get<Acts::eBoundTheta>(),
416 actsParameter.get<Acts::eBoundQOverP>() * 1_MeV, lineSurface,
cov);
420 return std::make_unique<Trk::CurvilinearParameters>(
421 actsParameter.position(gctx), actsParameter.get<Acts::eBoundPhi>(),
422 actsParameter.get<Acts::eBoundTheta>(),
423 actsParameter.get<Acts::eBoundQOverP>() * 1_MeV,
cov);
426 case Acts::Surface::SurfaceType::Other: {
431 throw std::domain_error(
"Surface type not found");
437 const Acts::GeometryContext & gctx)
const {
439 << trackColl.size() <<
" tracks.");
440 unsigned int trkCount = 0;
441 std::vector<Identifier> failedIds;
442 for (
auto trk : trackColl) {
445 trk->trackStateOnSurfaces();
451 auto actsTrack = tc.getTrack(tc.addTrack());
452 auto& trackStateContainer = tc.trackStateContainer();
455 <<
" track states on surfaces.");
457 actsTrack.chi2() = trk->fitQuality()->chiSquared();
458 actsTrack.nDoF() = trk->fitQuality()->numberDoF();
462 bool first_tsos =
true;
463 int measurementsCount = 0;
464 for (
auto tsos : *trackStates) {
468 if (tsos->measurementOnTrack()) {
469 mask |= Acts::TrackStatePropMask::Calibrated;
471 if (tsos->trackParameters()) {
472 mask |= Acts::TrackStatePropMask::Smoothed;
476 auto index = Acts::MultiTrajectoryTraits::kInvalid;
478 index = actsTrack.tipIndex();
480 auto actsTSOS = trackStateContainer.getTrackState(
481 trackStateContainer.addTrackState(
mask,
index));
483 <<
" TSOS index within trajectory: "
484 << actsTSOS.index());
485 actsTrack.tipIndex() = actsTSOS.index();
487 if (tsos->trackParameters()) {
493 trkTrackParametersToActsParameters(*(tsos->trackParameters()), gctx);
496 if (!actsTrackParameterPositionCheck(
parameters, *(tsos->trackParameters()), gctx)){
497 failedIds.push_back(tsos->trackParameters()->associatedSurface().associatedDetectorElementIdentifier());
503 actsTrack.parameters() =
parameters.parameters();
504 actsTrack.covariance() = *
parameters.covariance();
505 actsTrack.setReferenceSurface(
506 parameters.referenceSurface().getSharedPtr());
509 actsTSOS.setReferenceSurface(
parameters.referenceSurface().getSharedPtr());
511 actsTSOS.smoothed() =
parameters.parameters();
512 actsTSOS.smoothedCovariance() = *
parameters.covariance();
515 if (!(actsTSOS.hasSmoothed() && actsTSOS.hasReferenceSurface())) {
517 << actsTSOS.hasSmoothed()
518 <<
"] or reference surface ["
519 << actsTSOS.hasReferenceSurface() <<
"].");
521 ATH_MSG_VERBOSE(
"TrackState has smoothed state and reference surface.");
525 ATH_MSG_ERROR(
"Unable to convert TrackParameter with exception ["<<
e.what()<<
"]. Will be missing from ACTS track."
526 <<(*tsos->trackParameters()));
529 if (tsos->measurementOnTrack()) {
530 auto &measurement = *(tsos->measurementOnTrack());
538 int dim = measurement.localParameters().dimension();
539 actsTSOS.allocateCalibrated(
dim);
541 actsTSOS.calibrated<1>() = measurement.localParameters();
542 actsTSOS.calibratedCovariance<1>() = measurement.localCovariance();
543 }
else if (
dim == 2) {
544 actsTSOS.calibrated<2>() = measurement.localParameters();
545 actsTSOS.calibratedCovariance<2>() = measurement.localCovariance();
547 throw std::domain_error(
"Cannot handle measurement dim>2");
549 actsTSOS.setUncalibratedSourceLink(Acts::SourceLink(
static_cast<ActsTrk::ATLASSourceLink>(tsos->measurementOnTrack())));
553 actsTrack.nMeasurements() = measurementsCount;
555 <<
" track states on surfaces.");
557 ATH_MSG_VERBOSE(
"Finished converting " << trackColl.size() <<
" tracks.");
559 if (!failedIds.empty()){
560 ATH_MSG_WARNING(
"Failed to convert "<<failedIds.size()<<
" track parameters.");
561 for (
auto id : failedIds){
562 ATH_MSG_WARNING(
"-> Failed for Identifier "<<m_idHelperSvc->toString(
id));
565 ATH_MSG_VERBOSE(
"ACTS Track container has " << tc.size() <<
" tracks.");
571 const Acts::GeometryContext &gctx)
const {
579 if (std::fabs(actsPos.x() - trkparameters.
position().x()) >
581 std::fabs(actsPos.y() - trkparameters.
position().y()) >
583 std::fabs(actsPos.z() - trkparameters.
position().z()) >
586 << actsPos <<
" vs Trk \n"
599 #pragma GCC diagnostic push
600 #pragma GCC diagnostic ignored "-Wunused-function"
601 static void ActsTrk::ActsMeasurementCheck(
603 const Acts::Surface &surface,
const Acts::BoundVector &loc) {
610 if (bounds ==
nullptr) {
611 throw std::runtime_error{
"Annulus but not XY"};
620 if (
auto res = surface.globalToLocal(gctx,
global, Acts::Vector3{});
624 throw std::runtime_error{
"Global position not on target surface"};
630 Acts::Surface::makeShared<Acts::PlaneSurface>(surf.
transform());
631 Acts::BoundVector locxypar;
632 locxypar.head<2>() = locxy;
634 locxypar[3] = M_PI_2;
637 Acts::FreeVector globalxypar = Acts::transformBoundToFreeParameters(
638 *planeSurface, gctx, locxypar);
639 auto boundToFree = planeSurface->boundToFreeJacobian(
640 gctx, globalxypar.segment<3>(Acts::eFreePos0),
641 globalxypar.segment<3>(Acts::eFreeDir0));
642 Acts::ActsSquareMatrix<2> xyToXyzJac = boundToFree.topLeftCorner<2, 2>();
644 Acts::BoundVector locpcpar;
645 locpcpar.head<2>() = locpc;
647 locpcpar[3] = M_PI_2;
650 Acts::FreeVector globalpcpar = Acts::transformBoundToFreeParameters(
651 surface, gctx, locpcpar);
653 boundToFree = surface.boundToFreeJacobian(
654 gctx, globalpcpar.segment<3>(Acts::eFreePos0),
655 globalpcpar.segment<3>(Acts::eFreeDir0));
656 Acts::ActsSquareMatrix<2> pcToXyzJac = boundToFree.topLeftCorner<2, 2>();
657 Acts::ActsSquareMatrix<2> xyzToPcJac = pcToXyzJac.inverse();
660 Acts::ActsMatrix<2, 2> covpc = covxy;
661 covpc = xyToXyzJac * covpc * xyToXyzJac.transpose();
662 covpc = xyzToPcJac * covpc * xyzToPcJac.transpose();
664 std::mt19937
gen{42 + surface.geometryId().value()};
665 std::normal_distribution<double> normal{0, 1};
666 std::uniform_real_distribution<double>
uniform{-1, 1};
668 Acts::ActsMatrix<2, 2> lltxy = covxy.llt().matrixL();
669 Acts::ActsMatrix<2, 2> lltpc = covpc.llt().matrixL();
671 for (
size_t i = 0;
i < 1
e4;
i++) {
672 std::cout <<
"ANNULUS COV: ";
673 std::cout << surface.geometryId();
681 std::cout <<
"," << xy.x() <<
"," << xy.y();
682 std::cout <<
"," <<
xyz.x() <<
"," <<
xyz.y() <<
"," <<
xyz.z();
692 std::cout <<
"," << rt.x() <<
"," << rt.y();
693 std::cout <<
"," <<
xyz.x() <<
"," <<
xyz.y() <<
"," <<
xyz.z();
696 std::cout << std::endl;
699 #pragma GCC diagnostic pop
701 void ActsTrk::ActsTrackParameterCheck(
702 const Acts::BoundTrackParameters &actsParameter,
703 const Acts::GeometryContext &gctx,
const Acts::BoundSquareMatrix &covpc,
704 const Acts::BoundVector &targetPars,
const Acts::BoundSquareMatrix &targetCov,
707 std::cout <<
"ANNULUS PAR COV: ";
708 std::cout << actsParameter.referenceSurface().geometryId();
709 for (
unsigned int i = 0;
i < 5;
i++) {
710 for (
unsigned int j = 0; j < 5; j++) {
711 std::cout <<
"," << covpc(
i, j);
714 for (
unsigned int i = 0;
i < 5;
i++) {
715 for (
unsigned int j = 0; j < 5; j++) {
716 std::cout <<
"," << targetCov(
i, j);
719 std::cout << std::endl;
721 std::mt19937
gen{4242 +
722 actsParameter.referenceSurface().geometryId().value()};
723 std::normal_distribution<double> normal{0, 1};
725 Acts::ActsMatrix<2, 2> lltxy =
726 targetCov.topLeftCorner<2, 2>().llt().matrixL();
727 Acts::ActsMatrix<2, 2> lltpc = covpc.topLeftCorner<2, 2>().llt().matrixL();
729 for (
size_t i = 0;
i < 1
e4;
i++) {
730 std::cout <<
"ANNULUS PAR: ";
731 std::cout << actsParameter.referenceSurface().geometryId();
733 Acts::ActsVector<2> rnd;
734 rnd << normal(
gen), normal(
gen);
738 Acts::ActsVector<2> xy =
739 lltxy.topLeftCorner<2, 2>() * rnd + targetPars.head<2>();
743 for (
unsigned int i = 0;
i < 2;
i++) {
744 std::cout <<
"," << xy[
i];
746 std::cout <<
"," <<
xyz.x() <<
"," <<
xyz.y() <<
"," <<
xyz.z();
750 Acts::ActsVector<2> rt = lltpc.topLeftCorner<2, 2>() * rnd +
751 actsParameter.parameters().head<2>();
753 gctx, Acts::Vector2{rt.head<2>()}, Acts::Vector3{});
755 for (
unsigned int i = 0;
i < 2;
i++) {
756 std::cout <<
"," << rt[
i];
758 std::cout <<
"," <<
xyz.x() <<
"," <<
xyz.y() <<
"," <<
xyz.z();
761 std::cout << std::endl;