ATLAS Offline Software
ActsToTrkConverterTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 
7 // Trk
8 #include "TrkSurfaces/Surface.h"
9 #include "TrkTrack/Track.h"
10 
11 // ATHENA
12 #include "GaudiKernel/IInterface.h"
17 #include "TrkSurfaces/Surface.h"
20 
21 // PACKAGE
27 
28 // ACTS
29 #include "Acts/Definitions/Units.hpp"
30 #include "Acts/EventData/TrackParameters.hpp"
31 #include "Acts/EventData/VectorTrackContainer.hpp"
32 #include "Acts/EventData/TransformationHelpers.hpp"
33 #include "Acts/Geometry/TrackingGeometry.hpp"
34 #include "Acts/Propagator/detail/JacobianEngine.hpp"
35 #include "Acts/Surfaces/PerigeeSurface.hpp"
36 #include "Acts/Surfaces/Surface.hpp"
38 #include "Acts/EventData/TrackStatePropMask.hpp"
39 #include "Acts/EventData/SourceLink.hpp"
41 
42 // STL
43 #include <cmath>
44 #include <iostream>
45 #include <memory>
46 #include <random>
47 
48 namespace ActsTrk {
49 
50 // Forward definitions of local functions
51 // @TODO unused, remove ?
52 #pragma GCC diagnostic push
53 #pragma GCC diagnostic ignored "-Wunused-function"
54 static void ActsMeasurementCheck(const Acts::GeometryContext &gctx,
55  const Trk::MeasurementBase &measurement,
56  const Acts::Surface &surface,
57  const Acts::BoundVector &loc);
58 #pragma GCC diagnostic pop
59 
60 static void ActsTrackParameterCheck(
61  const Acts::BoundTrackParameters &actsParameter,
62  const Acts::GeometryContext &gctx, const Acts::BoundSquareMatrix &covpc,
63  const Acts::BoundVector &targetPars, const Acts::BoundSquareMatrix &targetCov,
64  const Trk::PlaneSurface *planeSurface);
65 
66 } // namespace ActsTrk
67 
69  const std::string &type, const std::string &name, const IInterface *parent)
70  : base_class(type, name, parent) {}
71 
73  ATH_MSG_VERBOSE("Initializing ACTS to ATLAS converter tool");
74  if (m_extractMuonSurfaces){
75  ATH_CHECK(m_idHelperSvc.retrieve());
76  }
77  if (!m_trackingGeometryTool.empty()) {
78  ATH_CHECK(m_trackingGeometryTool.retrieve());
79  m_trackingGeometry = m_trackingGeometryTool->trackingGeometry();
80 
81  m_trackingGeometry->visitSurfaces([&](const Acts::Surface *surface) {
82  // find acts surface with the same detector element ID
83  if (!surface)
84  return;
85  const auto *actsElement = dynamic_cast<const ActsDetectorElement *>(
86  surface->associatedDetectorElement());
87  if (!actsElement)
88  return;
89  // Conversion from Acts to ATLAS surface impossible for the TRT so the TRT
90  // surfaces are not stored in this map
91  bool isTRT = (dynamic_cast<const InDetDD::TRT_BaseElement *>(
92  actsElement->upstreamDetectorElement()) != nullptr);
93  if (isTRT)
94  return;
95 
96  auto [it, ok] =
97  m_actsSurfaceMap.insert({actsElement->identify(), surface});
98  if (!ok) {
99  ATH_MSG_WARNING("ATLAS ID " << actsElement->identify()
100  << " has two ACTS surfaces: "
101  << it->second->geometryId() << " and "
102  << surface->geometryId());
103  }
104  });
105  }
106 
107  if (m_extractMuonSurfaces){
108  const MuonGMR4::MuonDetectorManager* muonMgr{nullptr};
109  ATH_CHECK(detStore()->retrieve(muonMgr));
110  unsigned int mapSize = m_actsSurfaceMap.size(); // For debugging message later
111  for (auto readoutElement : muonMgr->getAllReadoutElements()) {
112  std::map<Identifier, std::shared_ptr<Acts::Surface>> reSurfaces = readoutElement->getSurfaces();
113  for (auto [id, surf] : reSurfaces){
114  const Acts::Surface* tmp = surf.get();
115  m_actsSurfaceMap.insert(std::pair<Identifier, const Acts::Surface*>(id, tmp));
116  }
117  }
118  ATH_MSG_VERBOSE("After adding muon surfaces, the map has grown from "<<mapSize<<" to "<<m_actsSurfaceMap.size());
119  }
120  return StatusCode::SUCCESS;
121 }
122 
124  const Acts::Surface &actsSurface) const {
125 
126  const auto *actsElement = dynamic_cast<const ActsDetectorElement *>(
127  actsSurface.associatedDetectorElement());
128  if (actsElement) {
129  return actsElement->atlasSurface();
130  }
131  throw std::domain_error("No ATLAS surface corresponding to to the Acts one");
132 }
133 
135  const Trk::Surface &atlasSurface) const {
136 
137  Identifier atlasID = atlasSurface.associatedDetectorElementIdentifier();
138  auto it = m_actsSurfaceMap.find(atlasID);
139  if (it != m_actsSurfaceMap.end()) {
140  return *it->second;
141  }
142  ATH_MSG_ERROR("No Acts surface corresponding to this ATLAS surface:");
143  ATH_MSG_ERROR(atlasSurface);
144  throw std::domain_error("No Acts surface corresponding to the ATLAS one");
145 }
146 
148  [[maybe_unused]] const Acts::GeometryContext& gctx,
149  const Trk::MeasurementBase &measurement) const
150 {
151  return Acts::SourceLink(&measurement);
152 }
153 
154 
155 std::vector<Acts::SourceLink>
157  const Acts::GeometryContext &gctx, const Trk::Track &track) const {
158  auto hits = track.measurementsOnTrack();
159  auto outliers = track.outliersOnTrack();
160 
161  std::vector<Acts::SourceLink> sourceLinks;
162  sourceLinks.reserve(hits->size() + outliers->size());
163 
164  for (auto it = hits->begin(); it != hits->end(); ++it) {
165  sourceLinks.push_back(trkMeasurementToSourceLink(gctx, **it));
166  }
167  for (auto it = outliers->begin(); it != outliers->end(); ++it) {
168  sourceLinks.push_back(trkMeasurementToSourceLink(gctx, **it));
169  }
170  return sourceLinks;
171 }
172 
173 
174 const Acts::BoundTrackParameters
176  const Trk::TrackParameters &atlasParameter, const Acts::GeometryContext & gctx, Trk::ParticleHypothesis hypothesis) const {
177 
178  using namespace Acts::UnitLiterals;
179  std::shared_ptr<const Acts::Surface> actsSurface;
180  Acts::BoundVector params;
181 
182  // get the associated surface
183  if (atlasParameter.hasSurface() &&
184  atlasParameter.associatedSurface().owner() == Trk::SurfaceOwner::DetElOwn) {
185  try {
186  actsSurface = trkSurfaceToActsSurface(atlasParameter.associatedSurface())
187  .getSharedPtr();
188  } catch (const std::exception &e) {
189  ATH_MSG_ERROR("Could not find ACTS detector surface for this TrackParameter:");
190  ATH_MSG_ERROR(atlasParameter);
191  throw; // Nothing we can do, so just pass exception on...
192  }
193  }
194  // no associated surface create a perigee one
195  else {
197  "trkTrackParametersToActsParameters:: No associated surface found (owner: "<<atlasParameter.associatedSurface().owner()<<
198  "). Creating a free surface. Trk parameters:");
199  ATH_MSG_VERBOSE(atlasParameter);
200 
201  switch (atlasParameter.associatedSurface().type()){
203  actsSurface = Acts::Surface::makeShared<const Acts::PlaneSurface>(
204  atlasParameter.associatedSurface().transform());
205  break;
207  actsSurface = Acts::Surface::makeShared<const Acts::PerigeeSurface>(
208  atlasParameter.associatedSurface().transform());
209  break;
210  // TODO - implement the missing types?
211  default:
212  ATH_MSG_WARNING("No surface type found for this Trk::Surface. Creating a perigee surface.");
213  actsSurface = Acts::Surface::makeShared<const Acts::PerigeeSurface>(
214  atlasParameter.associatedSurface().center());
215  }
216  }
217 
218  // Construct track parameters
219  auto atlasParam = atlasParameter.parameters();
220  if (actsSurface->bounds().type() ==
221  Acts::SurfaceBounds::BoundsType::eAnnulus) {
222  // Annulus surfaces are constructed differently in Acts/Trk so we need to
223  // convert local coordinates
224  auto position = atlasParameter.position();
225  auto result =
226  actsSurface->globalToLocal(gctx, position, atlasParameter.momentum());
227  if (result.ok()) {
228  params << (*result)[0], (*result)[1], atlasParam[Trk::phi0],
229  atlasParam[Trk::theta],
230  atlasParameter.charge() / (atlasParameter.momentum().mag() * 1_MeV),
231  0.;
232  } else {
234  "Unable to convert annulus surface - globalToLocal failed");
235  }
236  } else {
237  params << atlasParam[Trk::locX], atlasParam[Trk::locY],
238  atlasParam[Trk::phi0], atlasParam[Trk::theta],
239  atlasParameter.charge() / (atlasParameter.momentum().mag() * 1_MeV), 0.;
240  }
241 
242  Acts::BoundSquareMatrix cov = Acts::BoundSquareMatrix::Identity();
243  if (atlasParameter.covariance()) {
244  cov.topLeftCorner(5, 5) = *atlasParameter.covariance();
245 
246  // Convert the covariance matrix from MeV
247  // FIXME: This needs to handle the annulus case as well - currently the cov
248  // is wrong for annulus surfaces
249  for (int i = 0; i < cov.rows(); i++) {
250  cov(i, 4) = cov(i, 4) / 1_MeV;
251  }
252  for (int i = 0; i < cov.cols(); i++) {
253  cov(4, i) = cov(4, i) / 1_MeV;
254  }
255  }
256 
257  // convert hypotheses
259  Acts::PdgParticle absPdg = Acts::makeAbsolutePdgParticle(
260  static_cast<Acts::PdgParticle>(
261  m_pdgToParticleHypothesis.convert(hypothesis, atlasParameter.charge())));
262  Acts::ParticleHypothesis actsHypothesis{
263  absPdg, mass, Acts::AnyCharge{std::abs(static_cast<float>(atlasParameter.charge()))}};
264 
265  return Acts::BoundTrackParameters(actsSurface, params,
266  cov, actsHypothesis);
267 }
268 
269 std::unique_ptr<Trk::TrackParameters>
271  const Acts::BoundTrackParameters &actsParameter,
272  const Acts::GeometryContext &gctx) const {
273 
274  using namespace Acts::UnitLiterals;
275  std::optional<AmgSymMatrix(5)> cov = std::nullopt;
276  if (actsParameter.covariance()) {
277  AmgSymMatrix(5)
278  newcov(actsParameter.covariance()->topLeftCorner<5, 5>());
279  // Convert the covariance matrix to GeV
280  for (int i = 0; i < newcov.rows(); i++) {
281  newcov(i, 4) = newcov(i, 4) * 1_MeV;
282  }
283  for (int i = 0; i < newcov.cols(); i++) {
284  newcov(4, i) = newcov(4, i) * 1_MeV;
285  }
286  cov = std::optional<AmgSymMatrix(5)>(newcov);
287  }
288 
289  const Acts::Surface &actsSurface = actsParameter.referenceSurface();
290 
291  switch (actsSurface.type()) {
292 
294  const Trk::ConeSurface &coneSurface =
295  dynamic_cast<const Trk::ConeSurface &>(
296  actsSurfaceToTrkSurface(actsSurface));
297  return std::make_unique<Trk::AtaCone>(
298  actsParameter.get<Acts::eBoundLoc0>(),
299  actsParameter.get<Acts::eBoundLoc1>(),
300  actsParameter.get<Acts::eBoundPhi>(),
301  actsParameter.get<Acts::eBoundTheta>(),
302  actsParameter.get<Acts::eBoundQOverP>() * 1_MeV, coneSurface, cov);
303 
304  break;
305  }
307  const Trk::CylinderSurface &cylSurface =
308  dynamic_cast<const Trk::CylinderSurface &>(
309  actsSurfaceToTrkSurface(actsSurface));
310  return std::make_unique<Trk::AtaCylinder>(
311  actsParameter.get<Acts::eBoundLoc0>(),
312  actsParameter.get<Acts::eBoundLoc1>(),
313  actsParameter.get<Acts::eBoundPhi>(),
314  actsParameter.get<Acts::eBoundTheta>(),
315  actsParameter.get<Acts::eBoundQOverP>() * 1_MeV, cylSurface, cov);
316  break;
317  }
319  if (const auto *discSurface = dynamic_cast<const Trk::DiscSurface *>(
320  &actsSurfaceToTrkSurface(actsSurface));
321  discSurface != nullptr) {
322  return std::make_unique<Trk::AtaDisc>(
323  actsParameter.get<Acts::eBoundLoc0>(),
324  actsParameter.get<Acts::eBoundLoc1>(),
325  actsParameter.get<Acts::eBoundPhi>(),
326  actsParameter.get<Acts::eBoundTheta>(),
327  actsParameter.get<Acts::eBoundQOverP>() * 1_MeV, *discSurface, cov);
328  } else if (const auto *planeSurface =
329  dynamic_cast<const Trk::PlaneSurface *>(
330  &actsSurfaceToTrkSurface(actsSurface));
331  planeSurface != nullptr) {
332  // need to convert to plane position on plane surface (annulus bounds)
333  auto helperSurface = Acts::Surface::makeShared<Acts::PlaneSurface>(
334  planeSurface->transform());
335 
336  auto covpc = actsParameter.covariance().value();
337 
338  Acts::FreeVector freePars =
339  Acts::transformBoundToFreeParameters(
340  actsSurface, gctx, actsParameter.parameters());
341 
342  Acts::BoundVector targetPars =
343  Acts::transformFreeToBoundParameters(freePars,
344  *helperSurface, gctx)
345  .value();
346 
347  Acts::FreeMatrix freeTransportJacobian = Acts::FreeMatrix::Identity();
348 
349  Acts::FreeVector freeToPathDerivatives = Acts::FreeVector::Zero();
350  freeToPathDerivatives.head<3>() = freePars.segment<3>(Acts::eFreeDir0);
351 
352  auto boundToFreeJacobian = actsSurface.boundToFreeJacobian(
353  gctx, freePars.segment<3>(Acts::eFreePos0),
354  freePars.segment<3>(Acts::eFreeDir0));
355 
356  Acts::BoundMatrix boundToBoundJac = Acts::detail::boundToBoundTransportJacobian(
357  gctx, freePars, boundToFreeJacobian, freeTransportJacobian,
358  freeToPathDerivatives, *helperSurface);
359 
360  Acts::BoundMatrix targetCov =
361  boundToBoundJac * covpc * boundToBoundJac.transpose();
362 
363  auto pars = std::make_unique<Trk::AtaPlane>(
364  targetPars[Acts::eBoundLoc0], targetPars[Acts::eBoundLoc1],
365  targetPars[Acts::eBoundPhi], targetPars[Acts::eBoundTheta],
366  targetPars[Acts::eBoundQOverP] * 1_MeV, *planeSurface,
367  targetCov.topLeftCorner<5, 5>());
368 
369  if (m_visualDebugOutput) {
370  ActsTrackParameterCheck(actsParameter, gctx, covpc, targetPars,
371  targetCov, planeSurface);
372  }
373 
374  return pars;
375 
376  } else {
377  throw std::runtime_error{
378  "Acts::DiscSurface is not associated with ATLAS disc or plane "
379  "surface"};
380  }
381  break;
382  }
383  case Acts::Surface::SurfaceType::Perigee: {
384  const Trk::PerigeeSurface perSurface(actsSurface.center(gctx));
385  return std::make_unique<Trk::Perigee>(
386  actsParameter.get<Acts::eBoundLoc0>(),
387  actsParameter.get<Acts::eBoundLoc1>(),
388  actsParameter.get<Acts::eBoundPhi>(),
389  actsParameter.get<Acts::eBoundTheta>(),
390  actsParameter.get<Acts::eBoundQOverP>() * 1_MeV, perSurface, cov);
391 
392  break;
393  }
395  const Trk::PlaneSurface &plaSurface =
396  dynamic_cast<const Trk::PlaneSurface &>(
397  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  break;
405  }
407  const Trk::StraightLineSurface &lineSurface =
408  dynamic_cast<const Trk::StraightLineSurface &>(
409  actsSurfaceToTrkSurface(actsSurface));
410  return std::make_unique<Trk::AtaStraightLine>(
411  actsParameter.get<Acts::eBoundLoc0>(),
412  actsParameter.get<Acts::eBoundLoc1>(),
413  actsParameter.get<Acts::eBoundPhi>(),
414  actsParameter.get<Acts::eBoundTheta>(),
415  actsParameter.get<Acts::eBoundQOverP>() * 1_MeV, lineSurface, cov);
416  break;
417  }
419  return std::make_unique<Trk::CurvilinearParameters>(
420  actsParameter.position(gctx), actsParameter.get<Acts::eBoundPhi>(),
421  actsParameter.get<Acts::eBoundTheta>(),
422  actsParameter.get<Acts::eBoundQOverP>() * 1_MeV, cov);
423  break;
424  }
425  case Acts::Surface::SurfaceType::Other: {
426  break;
427  }
428  }
429 
430  throw std::domain_error("Surface type not found");
431 }
432 
435  const TrackCollection &trackColl,
436  const Acts::GeometryContext & gctx) const {
437  ATH_MSG_VERBOSE("Calling trkTrackCollectionToActsTrackContainer with "
438  << trackColl.size() << " tracks.");
439  unsigned int trkCount = 0;
440  std::vector<Identifier> failedIds; // Keep track of Identifiers of failed conversions
441  for (auto trk : trackColl) {
442  // Do conversions!
443  const Trk::TrackStates *trackStates =
444  trk->trackStateOnSurfaces();
445  if (!trackStates) {
446  ATH_MSG_WARNING("No track states on surfaces found for this track.");
447  continue;
448  }
449 
450  auto actsTrack = tc.getTrack(tc.addTrack());
451  auto& trackStateContainer = tc.trackStateContainer();
452 
453  ATH_MSG_VERBOSE("Track "<<trkCount++<<" has " << trackStates->size()
454  << " track states on surfaces.");
455  // basic quantities copy
456  actsTrack.chi2() = trk->fitQuality()->chiSquared();
457  actsTrack.nDoF() = trk->fitQuality()->numberDoF();
458 
459  // loop over track states on surfaces, convert and add them to the ACTS
460  // container
461  bool first_tsos = true; // We need to handle the first one differently
462  int measurementsCount = 0;
463  for (auto tsos : *trackStates) {
464 
465  // Setup the mask
466  Acts::TrackStatePropMask mask = Acts::TrackStatePropMask::None;
467  if (tsos->measurementOnTrack()) {
468  mask |= Acts::TrackStatePropMask::Calibrated;
469  }
470  if (tsos->trackParameters()) {
471  mask |= Acts::TrackStatePropMask::Smoothed;
472  }
473 
474  // Setup the index of the trackstate
475  auto index = Acts::MultiTrajectoryTraits::kInvalid;
476  if (!first_tsos) {
477  index = actsTrack.tipIndex();
478  }
479  auto actsTSOS = trackStateContainer.getTrackState(
480  trackStateContainer.addTrackState(mask, index));
481  ATH_MSG_VERBOSE("TipIndex: " << actsTrack.tipIndex()
482  << " TSOS index within trajectory: "
483  << actsTSOS.index());
484  actsTrack.tipIndex() = actsTSOS.index();
485 
486  if (tsos->trackParameters()) {
487  // TODO This try/catch is temporary and should be removed once the sTGC problem is fixed.
488  try {
489  ATH_MSG_VERBOSE("Converting track parameters.");
490  // TODO - work out whether we should set predicted, filtered, smoothed
491  const Acts::BoundTrackParameters parameters =
492  trkTrackParametersToActsParameters(*(tsos->trackParameters()), gctx);
493  ATH_MSG_VERBOSE("Track parameters: " << parameters.parameters());
494  // Sanity check on positions
495  if (!actsTrackParameterPositionCheck(parameters, *(tsos->trackParameters()), gctx)){
496  failedIds.push_back(tsos->trackParameters()->associatedSurface().associatedDetectorElementIdentifier());
497  }
498 
499  if (first_tsos) {
500  // This is the first track state, so we need to set the track
501  // parameters
502  actsTrack.parameters() = parameters.parameters();
503  actsTrack.covariance() = *parameters.covariance();
504  actsTrack.setReferenceSurface(
505  parameters.referenceSurface().getSharedPtr());
506  first_tsos = false;
507  } else {
508  actsTSOS.setReferenceSurface(parameters.referenceSurface().getSharedPtr());
509  // Since we're converting final Trk::Tracks, let's assume they're smoothed
510  actsTSOS.smoothed() = parameters.parameters();
511  actsTSOS.smoothedCovariance() = *parameters.covariance();
512  // Not yet implemented in MultiTrajectory.icc
513  // actsTSOS.typeFlags() |= Acts::TrackStateFlag::ParameterFlag;
514  if (!(actsTSOS.hasSmoothed() && actsTSOS.hasReferenceSurface())) {
515  ATH_MSG_WARNING("TrackState does not have smoothed state ["
516  << actsTSOS.hasSmoothed()
517  << "] or reference surface ["
518  << actsTSOS.hasReferenceSurface() << "].");
519  } else {
520  ATH_MSG_VERBOSE("TrackState has smoothed state and reference surface.");
521  }
522  }
523  } catch (const std::exception& e){
524  ATH_MSG_ERROR("Unable to convert TrackParameter with exception ["<<e.what()<<"]. Will be missing from ACTS track."
525  <<(*tsos->trackParameters()));
526  }
527  }
528  if (tsos->measurementOnTrack()) {
529  auto &measurement = *(tsos->measurementOnTrack());
530 
531  measurementsCount++;
532  // const Acts::Surface &surface =
533  // trkSurfaceToActsSurface(measurement.associatedSurface());
534  // Commented for the moment because Surfaces not yet implemented in
535  // MultiTrajectory.icc
536 
537  int dim = measurement.localParameters().dimension();
538  actsTSOS.allocateCalibrated(dim);
539  if (dim == 1) {
540  actsTSOS.calibrated<1>() = measurement.localParameters();
541  actsTSOS.calibratedCovariance<1>() = measurement.localCovariance();
542  } else if (dim == 2) {
543  actsTSOS.calibrated<2>() = measurement.localParameters();
544  actsTSOS.calibratedCovariance<2>() = measurement.localCovariance();
545  } else {
546  throw std::domain_error("Cannot handle measurement dim>2");
547  }
548  actsTSOS.setUncalibratedSourceLink(Acts::SourceLink(static_cast<ActsTrk::ATLASSourceLink>(tsos->measurementOnTrack())));
549 
550  } // end if measurement
551  } // end loop over track states
552  actsTrack.nMeasurements() = measurementsCount;
553  ATH_MSG_VERBOSE("TrackProxy has " << actsTrack.nTrackStates()
554  << " track states on surfaces.");
555  }
556  ATH_MSG_VERBOSE("Finished converting " << trackColl.size() << " tracks.");
557 
558  if (!failedIds.empty()){
559  ATH_MSG_WARNING("Failed to convert "<<failedIds.size()<<" track parameters.");
560  for (auto id : failedIds){
561  ATH_MSG_WARNING("-> Failed for Identifier "<<m_idHelperSvc->toString(id));
562  }
563  }
564  ATH_MSG_VERBOSE("ACTS Track container has " << tc.size() << " tracks.");
565 }
566 
568  const Acts::BoundTrackParameters &parameters,
569  const Trk::TrackParameters &trkparameters,
570  const Acts::GeometryContext &gctx) const {
571  auto actsPos = parameters.position(gctx);
572  // ATH_MSG_VERBOSE("Acts position: \n"
573  // << actsPos << " vs trk position: \n"
574  // << trkparameters.position());
575  // ATH_MSG_VERBOSE(parameters.referenceSurface().toString(gctx));
576  // ATH_MSG_VERBOSE("GeometryId "<<parameters.referenceSurface().geometryId().value());
577 
578  if (std::fabs(actsPos.x() - trkparameters.position().x()) >
579  0.1 ||
580  std::fabs(actsPos.y() - trkparameters.position().y()) >
581  0.1 ||
582  std::fabs(actsPos.z() - trkparameters.position().z()) >
583  0.1) {
584  ATH_MSG_WARNING("Parameter position mismatch. Acts \n"
585  << actsPos << " vs Trk \n"
586  << trkparameters.position());
587  ATH_MSG_WARNING("Acts surface:");
588  ATH_MSG_WARNING(parameters.referenceSurface().toString(gctx));
589  ATH_MSG_WARNING("Trk surface:");
590  ATH_MSG_WARNING(trkparameters.associatedSurface());
591  return false;
592  }
593  return true;
594 }
595 
596 // Local functions to check/debug Annulus bounds
597 
598 #pragma GCC diagnostic push
599 #pragma GCC diagnostic ignored "-Wunused-function"
600 static void ActsTrk::ActsMeasurementCheck(
601  const Acts::GeometryContext &gctx, const Trk::MeasurementBase &measurement,
602  const Acts::Surface &surface, const Acts::BoundVector &loc) {
603  const Trk::Surface &surf = measurement.associatedSurface();
604  // only check Annulus for the moment
605  if (surf.bounds().type() != Trk::SurfaceBounds::Annulus) {
606  return;
607  }
608  const auto *bounds = dynamic_cast<const Trk::AnnulusBounds *>(&surf.bounds());
609  if (bounds == nullptr) {
610  throw std::runtime_error{"Annulus but not XY"};
611  }
612 
613  Amg::Vector2D locxy = loc.head<2>();
614 
615  Acts::ActsMatrix<2, 2> covxy = measurement.localCovariance();
616 
618  Acts::Vector2 locpc;
619  if (auto res = surface.globalToLocal(gctx, global, Acts::Vector3{});
620  res.ok()) {
621  locpc = *res;
622  } else {
623  throw std::runtime_error{"Global position not on target surface"};
624  }
625 
626  // use ACTS jacobian math to convert cluster covariance from cartesian to
627  // polar
628  auto planeSurface =
629  Acts::Surface::makeShared<Acts::PlaneSurface>(surf.transform());
630  Acts::BoundVector locxypar;
631  locxypar.head<2>() = locxy;
632  locxypar[2] = 0;
633  locxypar[3] = M_PI_2;
634  locxypar[4] = 1;
635  locxypar[5] = 1;
636  Acts::FreeVector globalxypar = Acts::transformBoundToFreeParameters(
637  *planeSurface, gctx, locxypar);
638  auto boundToFree = planeSurface->boundToFreeJacobian(
639  gctx, globalxypar.segment<3>(Acts::eFreePos0),
640  globalxypar.segment<3>(Acts::eFreeDir0));
641  Acts::ActsSquareMatrix<2> xyToXyzJac = boundToFree.topLeftCorner<2, 2>();
642 
643  Acts::BoundVector locpcpar;
644  locpcpar.head<2>() = locpc;
645  locpcpar[2] = 0;
646  locpcpar[3] = M_PI_2;
647  locpcpar[4] = 1;
648  locpcpar[5] = 1;
649  Acts::FreeVector globalpcpar = Acts::transformBoundToFreeParameters(
650  surface, gctx, locpcpar);
651 
652  boundToFree = surface.boundToFreeJacobian(
653  gctx, globalpcpar.segment<3>(Acts::eFreePos0),
654  globalpcpar.segment<3>(Acts::eFreeDir0));
655  Acts::ActsSquareMatrix<2> pcToXyzJac = boundToFree.topLeftCorner<2, 2>();
656  Acts::ActsSquareMatrix<2> xyzToPcJac = pcToXyzJac.inverse();
657 
658  // convert cluster covariance
659  Acts::ActsMatrix<2, 2> covpc = covxy;
660  covpc = xyToXyzJac * covpc * xyToXyzJac.transpose();
661  covpc = xyzToPcJac * covpc * xyzToPcJac.transpose();
662 
663  std::mt19937 gen{42 + surface.geometryId().value()};
664  std::normal_distribution<double> normal{0, 1};
665  std::uniform_real_distribution<double> uniform{-1, 1};
666 
667  Acts::ActsMatrix<2, 2> lltxy = covxy.llt().matrixL();
668  Acts::ActsMatrix<2, 2> lltpc = covpc.llt().matrixL();
669 
670  for (size_t i = 0; i < 1e4; i++) {
671  std::cout << "ANNULUS COV: ";
672  std::cout << surface.geometryId();
673 
674  Amg::Vector2D rnd{normal(gen), normal(gen)};
675 
676  // XY
677  {
678  Amg::Vector2D xy = lltxy * rnd + locxy;
679  Amg::Vector3D xyz = surf.localToGlobal(xy);
680  std::cout << "," << xy.x() << "," << xy.y();
681  std::cout << "," << xyz.x() << "," << xyz.y() << "," << xyz.z();
682  }
683  // PC
684  {
685  // Amg::Vector2D xy = lltpc * rnd + loc.head<2>();
686  Amg::Vector2D rt = lltpc * rnd + locpc;
687  Amg::Vector3D xyz = surface.localToGlobal(gctx, rt, Acts::Vector3{});
688  // Amg::Vector3D xyz = surface.transform(gctx).rotation() *
689  // Acts::Vector3{rt.x(), rt.y(), 0};
690 
691  std::cout << "," << rt.x() << "," << rt.y();
692  std::cout << "," << xyz.x() << "," << xyz.y() << "," << xyz.z();
693  }
694 
695  std::cout << std::endl;
696  }
697 }
698 #pragma GCC diagnostic pop
699 
700 void ActsTrk::ActsTrackParameterCheck(
701  const Acts::BoundTrackParameters &actsParameter,
702  const Acts::GeometryContext &gctx, const Acts::BoundSquareMatrix &covpc,
703  const Acts::BoundVector &targetPars, const Acts::BoundSquareMatrix &targetCov,
704  const Trk::PlaneSurface *planeSurface) {
705 
706  std::cout << "ANNULUS PAR COV: ";
707  std::cout << actsParameter.referenceSurface().geometryId();
708  for (unsigned int i = 0; i < 5; i++) {
709  for (unsigned int j = 0; j < 5; j++) {
710  std::cout << "," << covpc(i, j);
711  }
712  }
713  for (unsigned int i = 0; i < 5; i++) {
714  for (unsigned int j = 0; j < 5; j++) {
715  std::cout << "," << targetCov(i, j);
716  }
717  }
718  std::cout << std::endl;
719 
720  std::mt19937 gen{4242 +
721  actsParameter.referenceSurface().geometryId().value()};
722  std::normal_distribution<double> normal{0, 1};
723 
724  Acts::ActsMatrix<2, 2> lltxy =
725  targetCov.topLeftCorner<2, 2>().llt().matrixL();
726  Acts::ActsMatrix<2, 2> lltpc = covpc.topLeftCorner<2, 2>().llt().matrixL();
727 
728  for (size_t i = 0; i < 1e4; i++) {
729  std::cout << "ANNULUS PAR: ";
730  std::cout << actsParameter.referenceSurface().geometryId();
731 
732  Acts::ActsVector<2> rnd;
733  rnd << normal(gen), normal(gen);
734 
735  // XY
736  {
737  Acts::ActsVector<2> xy =
738  lltxy.topLeftCorner<2, 2>() * rnd + targetPars.head<2>();
740  planeSurface->localToGlobal(Amg::Vector2D{xy.head<2>()}, Amg::Vector3D{},
741  xyz);
742  for (unsigned int i = 0; i < 2; i++) {
743  std::cout << "," << xy[i];
744  }
745  std::cout << "," << xyz.x() << "," << xyz.y() << "," << xyz.z();
746  }
747  // PC
748  {
749  Acts::ActsVector<2> rt = lltpc.topLeftCorner<2, 2>() * rnd +
750  actsParameter.parameters().head<2>();
751  Amg::Vector3D xyz = actsParameter.referenceSurface().localToGlobal(
752  gctx, Acts::Vector2{rt.head<2>()}, Acts::Vector3{});
753 
754  for (unsigned int i = 0; i < 2; i++) {
755  std::cout << "," << rt[i];
756  }
757  std::cout << "," << xyz.x() << "," << xyz.y() << "," << xyz.z();
758  }
759 
760  std::cout << std::endl;
761  }
762 }
763 
python.PyKernel.retrieve
def retrieve(aClass, aKey=None)
Definition: PyKernel.py:110
make_hlt_rep.pars
pars
Definition: make_hlt_rep.py:90
UncalibratedMeasurement.h
ActsToTrkConverterTool.h
yodamerge_tmp.dim
dim
Definition: yodamerge_tmp.py:239
get_generator_info.result
result
Definition: get_generator_info.py:21
ActsTrk::ActsToTrkConverterTool::trkTrackToSourceLinks
virtual std::vector< Acts::SourceLink > trkTrackToSourceLinks(const Acts::GeometryContext &gctx, 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...
Definition: ActsToTrkConverterTool.cxx:156
ActsTrk::ActsToTrkConverterTool::trkTrackParametersToActsParameters
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.
Definition: ActsToTrkConverterTool.cxx:175
MeasurementBase.h
PerigeeSurface.h
Trk::locX
@ locX
Definition: ParamDefs.h:43
Trk::ParametersBase::charge
double charge() const
Returns the charge.
Trk::locY
@ locY
local cartesian
Definition: ParamDefs.h:44
Surface.h
Trk::Track
The ATLAS Track class.
Definition: Tracking/TrkEvent/TrkTrack/TrkTrack/Track.h:73
MuonGMR4::MuonDetectorManager
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/MuonDetectorManager.h:61
ActsGeometryContext.h
Trk::PerigeeSurface
Definition: PerigeeSurface.h:43
Trk::ParametersBase::position
const Amg::Vector3D & position() const
Access method for the position.
Amg::Vector2D
Eigen::Matrix< double, 2, 1 > Vector2D
Definition: GeoPrimitives.h:48
index
Definition: index.py:1
Trk::ParametersBase::associatedSurface
virtual const Surface & associatedSurface() const override=0
Access to the Surface associated to the Parameters.
IdentityHelper.h
ActsTrk::ActsToTrkConverterTool::trkMeasurementToSourceLink
virtual Acts::SourceLink trkMeasurementToSourceLink(const Acts::GeometryContext &gctx, const Trk::MeasurementBase &measurement) const override
Create an SourceLink from an ATLAS measurment Works for 1 and 2D measurmenent.
Definition: ActsToTrkConverterTool.cxx:147
Trk::AnnulusBounds
Definition: AnnulusBounds.h:45
Trk::Surface::associatedDetectorElementIdentifier
Identifier associatedDetectorElementIdentifier() const
return Identifier of the associated Detector Element
python.SystemOfUnits.MeV
int MeV
Definition: SystemOfUnits.py:154
skel.it
it
Definition: skel.GENtoEVGEN.py:423
plotBeamSpotVxVal.cov
cov
Definition: plotBeamSpotVxVal.py:201
ActsTrk::ActsToTrkConverterTool::actsTrackParameterPositionCheck
bool actsTrackParameterPositionCheck(const Acts::BoundTrackParameters &actsParameter, const Trk::TrackParameters &tsos, const Acts::GeometryContext &gctx) const
Definition: ActsToTrkConverterTool.cxx:567
xyz
#define xyz
Trk::SurfaceBounds::Annulus
@ Annulus
Definition: SurfaceBounds.h:70
Trk::DiscSurface
Definition: DiscSurface.h:54
InDetDD::global
@ global
Definition: InDetDD_Defs.h:16
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
ActsTrk::ActsToTrkConverterTool::trkSurfaceToActsSurface
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...
Definition: ActsToTrkConverterTool.cxx:134
Trk::Surface::center
const Amg::Vector3D & center() const
Returns the center position of the Surface.
AmgSymMatrix
#define AmgSymMatrix(dim)
Definition: EventPrimitives.h:52
dqt_zlumi_pandas.mass
mass
Definition: dqt_zlumi_pandas.py:170
python.utils.AtlRunQueryLookup.mask
string mask
Definition: AtlRunQueryLookup.py:460
master.gen
gen
Definition: master.py:32
Track.h
Trk::ParticleHypothesis
ParticleHypothesis
Definition: ParticleHypothesis.h:25
xAOD::Cone
@ Cone
Definition: TrackingPrimitives.h:552
Trk::SurfaceBounds::type
virtual BoundsType type() const =0
Return the bounds type - for persistency optimization.
CaloCellPos2Ntuple.None
None
Definition: CaloCellPos2Ntuple.py:23
Trk::Surface::owner
SurfaceOwner owner() const
return ownership
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
lumiFormat.i
int i
Definition: lumiFormat.py:92
TrackCollection
DataVector< Trk::Track > TrackCollection
This typedef represents a collection of Trk::Track objects.
Definition: TrackCollection.h:19
PixelAthClusterMonAlgCfg.e4
e4
Definition: PixelAthClusterMonAlgCfg.py:317
Trk::ParametersBase::hasSurface
virtual bool hasSurface() const override=0
Test to see if there's a not null surface ptr.
Identifier
Definition: DetectorDescription/Identifier/Identifier/Identifier.h:32
ActsTrackingGeometryTool.h
Trk::theta
@ theta
Definition: ParamDefs.h:72
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
Trk::CylinderSurface
Definition: CylinderSurface.h:55
LArG4ShowerLibProcessing.hits
hits
Definition: LArG4ShowerLibProcessing.py:136
ActsDetectorElement::atlasSurface
const Trk::Surface & atlasSurface() const
Return a shared pointer on the ATLAS surface associated with this identifier,.
Definition: ActsDetectorElement.cxx:259
calibdata.exception
exception
Definition: calibdata.py:496
res
std::pair< std::vector< unsigned int >, bool > res
Definition: JetGroupProductTest.cxx:14
MuonDetectorManager.h
test_pyathena.parent
parent
Definition: test_pyathena.py:15
xAOD::Disc
@ Disc
Definition: TrackingPrimitives.h:554
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
ActsTrk::ActsToTrkConverterTool::actsTrackParametersToTrkParameters
virtual std::unique_ptr< Trk::TrackParameters > actsTrackParametersToTrkParameters(const Acts::BoundTrackParameters &actsParameter, const Acts::GeometryContext &gctx) const override
Create ATLAS TrackParameter from Acts one.
Definition: ActsToTrkConverterTool.cxx:270
xAOD::readoutElement
const MuonGMR4::MuonReadoutElement * readoutElement(const UncalibratedMeasurement *meas)
Returns the associated readout element to the measurement.
Definition: MuonSpectrometer/MuonPhaseII/Event/xAOD/xAODMuonPrepData/Root/UtilFunctions.cxx:32
ActsDetectorElement
Definition: ActsDetectorElement.h:42
Trk::ParametersBase
Definition: ParametersBase.h:55
ActsTrk::ActsToTrkConverterTool::initialize
virtual StatusCode initialize() override
Definition: ActsToTrkConverterTool.cxx:72
ActsTrk::ActsToTrkConverterTool::ActsToTrkConverterTool
ActsToTrkConverterTool(const std::string &type, const std::string &name, const IInterface *parent)
Definition: ActsToTrkConverterTool.cxx:68
ActsDetectorElement.h
DeMoUpdate.tmp
string tmp
Definition: DeMoUpdate.py:1167
Trk::DetElOwn
@ DetElOwn
Definition: Tracking/TrkDetDescr/TrkSurfaces/TrkSurfaces/Surface.h:56
DataVector< const Trk::TrackStateOnSurface >
Trk::MeasurementBase::localCovariance
const Amg::MatrixX & localCovariance() const
Interface method to get the localError.
Definition: MeasurementBase.h:138
Trk::MeasurementBase
Definition: MeasurementBase.h:58
Trk::ParticleMasses::mass
constexpr double mass[PARTICLEHYPOTHESES]
the array of masses
Definition: ParticleHypothesis.h:53
python.PyKernel.detStore
detStore
Definition: PyKernel.py:41
Trk::SurfaceType::Perigee
@ Perigee
xAOD::Straw
@ Straw
Definition: TrackingPrimitives.h:557
Trk::Surface::bounds
virtual const SurfaceBounds & bounds() const =0
Surface Bounds method.
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
Trk::MeasurementBase::associatedSurface
virtual const Surface & associatedSurface() const =0
Interface method to get the associated Surface.
xAOD::Cylinder
@ Cylinder
Definition: TrackingPrimitives.h:553
MuonGMR4::MuonReadoutElement::getSurfaces
virtual std::map< Identifier, std::shared_ptr< Acts::Surface > > getSurfaces() const =0
Returns all surfaces that are associated with the active readout planes.
xAOD::Curvilinear
@ Curvilinear
Definition: TrackingPrimitives.h:558
SiDetectorElementCollection.h
xAOD::ParticleHypothesis
ParticleHypothesis
Definition: TrackingPrimitives.h:192
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
MultiTrajectory.h
Trk::ParametersBase::momentum
const Amg::Vector3D & momentum() const
Access method for the momentum.
H5Utils::internal::uniform
std::array< hsize_t, N > uniform(size_t val)
Definition: Writer.h:331
DiTauMassTools::MaxHistStrategyV2::e
e
Definition: PhysicsAnalysis/TauID/DiTauMassTools/DiTauMassTools/HelperFunctions.h:26
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
Trk::PlaneSurface
Definition: PlaneSurface.h:64
RungeKuttaUtils.h
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
physics_parameters.parameters
parameters
Definition: physics_parameters.py:144
Trk::ConeSurface
Definition: ConeSurface.h:51
Trk::SurfaceType::Plane
@ Plane
ActsTrk
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...
Definition: MuonDetectorBuilderTool.cxx:34
ActsTrk::ActsToTrkConverterTool::trkTrackCollectionToActsTrackContainer
virtual void trkTrackCollectionToActsTrackContainer(ActsTrk::MutableTrackContainer &tc, const TrackCollection &trackColl, const Acts::GeometryContext &gctx) const override
Convert TrackCollection to Acts track container.
Definition: ActsToTrkConverterTool.cxx:433
xAOD::track
@ track
Definition: TrackingPrimitives.h:512
PowhegControl_ttFCNC_NLO.params
params
Definition: PowhegControl_ttFCNC_NLO.py:226
Trk::PlaneSurface::localToGlobal
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.
Definition: PlaneSurface.cxx:204
xAOD::Plane
@ Plane
Definition: TrackingPrimitives.h:556
Trk::Surface
Definition: Tracking/TrkDetDescr/TrkSurfaces/TrkSurfaces/Surface.h:75
ActsTrk::MutableTrackContainer
Definition: TrackContainer.h:122
Trk::Surface::transform
const Amg::Transform3D & transform() const
Returns HepGeom::Transform3D by reference.
DataVector::size
size_type size() const noexcept
Returns the number of elements in the collection.
Trk::Surface::type
constexpr virtual SurfaceType type() const =0
Returns the Surface type to avoid dynamic casts.
Trk::phi0
@ phi0
Definition: ParamDefs.h:71
Trk::Surface::localToGlobal
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.
IActsTrackingGeometryTool.h
ActsTrk::ActsToTrkConverterTool::actsSurfaceToTrkSurface
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...
Definition: ActsToTrkConverterTool.cxx:123
Trk::StraightLineSurface
Definition: StraightLineSurface.h:51
generate::Zero
void Zero(TH1D *hin)
Definition: generate.cxx:32
InDetDD::TRT_BaseElement
Definition: TRT_BaseElement.h:57