ATLAS Offline Software
Loading...
Searching...
No Matches
ExtrapolatorComparisonTest.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// ExtrapolatorComparisonTest.cxx, (c) ATLAS Detector software
8
10
11// Tracking
18
19#include "GaudiKernel/ISvcLocator.h"
20
21// ACTS
22#include "Acts/Definitions/Algebra.hpp"
23#include "Acts/Definitions/TrackParametrization.hpp"
24#include "Acts/EventData/ParticleHypothesis.hpp"
25#include "Acts/Geometry/GeometryContext.hpp"
26#include "Acts/Propagator/detail/SteppingLogger.hpp"
27#include "Acts/Surfaces/CylinderSurface.hpp"
28#include "Acts/Surfaces/DiscSurface.hpp"
29#include "Acts/Surfaces/PerigeeSurface.hpp"
30#include "Acts/Surfaces/Surface.hpp"
31#include "Acts/Utilities/Helpers.hpp"
32#include "Acts/Utilities/Logger.hpp"
34#include "ActsInterop/Logger.h"
35
36// OTHER
37#include "CLHEP/Random/RandomEngine.h"
38#include "CLHEP/Random/Randomize.h"
39
40// STL
41#include <string>
42#include <fstream>
43#include <chrono>
44#include <cmath>
45
46using xclock = std::chrono::steady_clock;
47
48//================ Constructor =================================================
49
50Trk::ExtrapolatorComparisonTest::ExtrapolatorComparisonTest(const std::string& name, ISvcLocator* pSvcLocator) :
51 AthReentrantAlgorithm(name, pSvcLocator) {}
52
53//================ Destructor =================================================
54
56 // cleanup of the Trk::Surfaces
57 for (const auto& surfaceTriple : m_atlasReferenceSurfaceTriples) {
58 for (const auto* surface : surfaceTriple) {
59 delete surface;
60 }
61 }
62}
63
64//================ Initialisation =================================================
65
67 // Code entered here will be executed once at program start.
68
69 ATH_MSG_INFO(" initialize()");
70
74
75 // Create the destination surfaces for extrapolation
76 // --> you need the Trk::Surfaces and the Acts::Surfaces
78 // assign the size
80 // loop over it and create the
81 for (unsigned int surface = 0; surface < m_referenceSurfaces; surface++) {
82 double radius = m_referenceSurfaceRadius[surface];
83 double halfZ = m_referenceSurfaceHalflength[surface];
84
85 // create the Surface triplet
86 std::vector< const Trk::Surface*> trkSurfaceTriplet;
87 trkSurfaceTriplet.push_back(new Trk::DiscSurface(Amg::Transform3D(Amg::Translation3D(0., 0., halfZ)), 0.,
88 radius));
89 trkSurfaceTriplet.push_back(new Trk::CylinderSurface(Amg::Transform3D(Amg::Translation3D(0., 0., 0.)), radius,
90 halfZ));
91 trkSurfaceTriplet.push_back(new Trk::DiscSurface(Amg::Transform3D(Amg::Translation3D(0., 0., -halfZ)), 0.,
92 radius));
93 ATH_MSG_INFO("Creating Trk::Surface at: R " << radius << " Z " << halfZ);
94 m_atlasReferenceSurfaceTriples.push_back(std::move(trkSurfaceTriplet));
95
96 // create the Surface triplet
97 std::vector<std::shared_ptr<const Acts::Surface> > actsSurfaceTriplet;
98
99 Acts::Transform3 posTransf(Acts::Transform3::Identity() * Acts::Translation3(Acts::Vector3(0., 0., halfZ)));
100 Acts::Transform3 cTransf(Acts::Transform3::Identity() * Acts::Translation3(Acts::Vector3(0., 0., 0.)));
101 Acts::Transform3 negTransf(Acts::Transform3::Identity() * Acts::Translation3(Acts::Vector3(0., 0., -halfZ)));
102
103 auto posSurface = Acts::Surface::makeShared<Acts::DiscSurface> (posTransf, 0., radius);
104 auto cSurface = Acts::Surface::makeShared<Acts::CylinderSurface>(cTransf, radius, halfZ);
105 auto negSurface = Acts::Surface::makeShared<Acts::DiscSurface> (negTransf, 0., radius);
106
107 actsSurfaceTriplet.push_back(posSurface);
108 actsSurfaceTriplet.push_back(cSurface);
109 actsSurfaceTriplet.push_back(negSurface);
110 ATH_MSG_INFO("Creating Acts::Surface at: R " << radius << " Z " << halfZ);
111 m_actsReferenceSurfaceTriples.push_back(std::move(actsSurfaceTriplet));
112
113 m_referenceSurfaceNegativeBoundary.push_back(atan2(radius, -halfZ));
114 m_referenceSurfacePositiveBoundary.push_back(atan2(radius, halfZ));
115 }
116 } else {
117 ATH_MSG_WARNING("Not compatible size of ReferenceSurfaceRadius and ReferenceSurfaceHalfZ!! Returning FAILURE!");
118 return StatusCode::FAILURE;
119 }
120
123 ATH_CHECK(m_rndmSvc.retrieve());
124 m_randomEngine = m_rndmSvc->getEngine(this, "ExtrapolatorComparisonTest");
125
126 return StatusCode::SUCCESS;
127}
128
129//================ Finalisation =================================================
130
132 // Code entered here will be executed once at the end of the program run.
133 return StatusCode::SUCCESS;
134}
135
136//================ Execution ====================================================
137
138StatusCode Trk::ExtrapolatorComparisonTest::execute(const EventContext& ctx) const {
139 float milliseconds_to_seconds = 1000.;
140
141 // generate perigees with random number generator
142 CLHEP::HepRandomEngine* engine = m_randomEngine->getEngine(ctx);
143
144 std::vector<perigeeParameters> parameters = {};
145 for (int ext = 0; ext < m_eventsPerExecute; ext++) {
146 // generate with random number generator
147 double d0 = CLHEP::RandGauss::shoot(engine) * m_sigmaD0;
148 double z0 = CLHEP::RandGauss::shoot(engine) * m_sigmaZ0;
149 double phi = m_minPhi + (m_maxPhi - m_minPhi) * CLHEP::RandFlat::shoot(engine);
150 double eta = m_minEta + CLHEP::RandFlat::shoot(engine) * (m_maxEta - m_minEta);
151 double pt = m_minPt + CLHEP::RandFlat::shoot(engine) * (m_maxPt - m_minPt);
152 double charge = (CLHEP::RandFlat::shoot(engine) > 0.5) ? -1. : 1.;
153 parameters.emplace_back(d0, z0, phi, eta, pt, charge);
154 }
155
156 int n_extraps = 0;
157 auto start = xclock::now();
158 for (auto& perigee : parameters) {
159 Acts::Vector3 momentum(perigee.m_pt * std::cos(perigee.m_phi), perigee.m_pt * std::sin(
160 perigee.m_phi), perigee.m_pt * std::sinh(perigee.m_eta));
161 double theta = Acts::VectorHelpers::theta(momentum);
162 double qOverP = perigee.m_charge / momentum.norm();
163
164 const Trk::PerigeeSurface atlPerigeeSurface;
165 auto atlPerigee = std::make_unique<Trk::Perigee>(perigee.m_d0, perigee.m_z0, perigee.m_phi, theta, qOverP,
166 atlPerigeeSurface);
167
168 for (unsigned int surface = 0; surface < m_atlasReferenceSurfaceTriples.size(); surface++) {
169 n_extraps++;
170
171 double negRef = m_referenceSurfaceNegativeBoundary.at(surface);
172 double posRef = m_referenceSurfacePositiveBoundary.at(surface);
173
174 // decide which reference surface to take
175 int refSurface = theta < posRef ? 2 : 1;
176 refSurface = theta > negRef ? 0 : 1;
177
178 const Trk::Surface* destinationSurface = m_atlasReferenceSurfaceTriples.at(surface).at(refSurface);
179
181 "Starting extrapolation " << n_extraps << " from : " << *atlPerigee << " to : " << *destinationSurface);
182
183 auto start_fwd = xclock::now();
184 auto destParameters =
185 m_atlasExtrapolator->extrapolate(
186 ctx,
187 *atlPerigee,
188 *destinationSurface,
190 true,
191 static_cast<Trk::ParticleHypothesis>(m_particleType.value()));
192 auto end_fwd = xclock::now();
193 float ms_fwd = std::chrono::duration_cast<std::chrono::milliseconds>(end_fwd - start_fwd).count();
194
195 if (destParameters) {
196 ATH_MSG_VERBOSE(" ATLAS Extrapolator succeded!! --> Forward");
198 " [ intersection ] with surface at (x,y,z) = " << destParameters->position().x() << ", " << destParameters->position().y() << ", " <<
199 destParameters->position().z());
200 ATH_MSG_VERBOSE(" [ intersection ] parameters: " << destParameters->parameters());
201 ATH_MSG_VERBOSE(" [ intersection ] cov matrix: " << destParameters->covariance());
202
203 // now try backward extrapolation
204 auto start_bkw = xclock::now();
205 auto finalperigee =
206 m_atlasExtrapolator->extrapolate(
207 ctx,
208 *destParameters,
209 atlPerigee->associatedSurface(),
211 true,
212 static_cast<Trk::ParticleHypothesis>(m_particleType.value()));
213 auto end_bkw = xclock::now();
214 float ms_bkw = std::chrono::duration_cast<std::chrono::milliseconds>(end_bkw - start_bkw).count();
215
216 if (finalperigee) {
217 ATH_MSG_VERBOSE(" ATLAS Extrapolator succeded!! --> Backward");
218 ATH_MSG_VERBOSE(" [extrapolation to perigee] input: " << atlPerigee->parameters());
219 ATH_MSG_VERBOSE(" [extrapolation to perigee] output: " << finalperigee->parameters());
220 ATH_MSG_VERBOSE(" [extrapolation to perigee] cov matrix: " << finalperigee->covariance());
221 } else if (!finalperigee) {
222 ATH_MSG_DEBUG(" ATLAS Extrapolation to perigee failed for input parameters: " <<
223 destParameters->parameters());
224 }
225
226 m_atlasPropResultWriterSvc->write<Trk::TrackParameters>(atlPerigee.get(),
227 destParameters.get(), ms_fwd, finalperigee.get(),
228 ms_bkw);
229 } else if (!destParameters) {
230 ATH_MSG_DEBUG(" ATLAS Extrapolation not successful! ");
231 m_atlasPropResultWriterSvc->write<Trk::TrackParameters>(atlPerigee.get());
232 }
233 }
234 }
235 auto end = xclock::now();
236 auto secs = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() / milliseconds_to_seconds;
237 if (n_extraps == 0) [[unlikely]] {
238 ATH_MSG_ERROR("n_extraps is zero");
239 } else {
240 double secs_per_ex = secs / n_extraps;
242 "ATLAS : Time for " << n_extraps << " iterations: " << secs << "s (" << secs_per_ex << "s per extrapolation)");
243 }
244 n_extraps = 0;
245 start = xclock::now();
246 for (auto& perigee : parameters) {
247 Acts::Vector3 momentum(perigee.m_pt * std::cos(perigee.m_phi), perigee.m_pt * std::sin(
248 perigee.m_phi), perigee.m_pt * std::sinh(perigee.m_eta));
249 double theta = Acts::VectorHelpers::theta(momentum);
250 double qOverP = perigee.m_charge / momentum.norm();
251
252 std::shared_ptr<Acts::PerigeeSurface> actsPerigeeSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(Acts::Vector3(
253 0, 0,
254 0));
255 double t = 0.;
256 Acts::BoundVector pars;
257 //cppcheck-suppress constStatement
258 pars << perigee.m_d0, perigee.m_z0, perigee.m_phi, theta, qOverP, t;
259 std::optional<Acts::BoundMatrix> cov = std::nullopt;
260
261 // Perigee, no alignment -> default geo context
262 const ActsTrk::GeometryContext& gctx = m_trackingGeometrySvc->getNominalContext();
263 auto anygctx = gctx.context();
264 const auto* startParameters =
265 new const Acts::BoundTrackParameters(std::move(actsPerigeeSurface), pars, std::move(
266 cov), Acts::ParticleHypothesis::pion());
267
268 for (unsigned int surface = 0; surface < m_actsReferenceSurfaceTriples.size(); surface++) {
269 n_extraps++;
270
271 double negRef = m_referenceSurfaceNegativeBoundary.at(surface);
272 double posRef = m_referenceSurfacePositiveBoundary.at(surface);
273
274 // decide which reference surface to take
275 int refSurface = theta < posRef ? 2 : 1;
276 refSurface = theta > negRef ? 0 : 1;
277
278 auto destinationSurface = m_actsReferenceSurfaceTriples.at(surface).at(refSurface);
279
280 ATH_MSG_VERBOSE("Starting extrapolation " << n_extraps << " from : " << pars << " to : " << destinationSurface);
281
282 auto start_fwd = xclock::now();
283 auto destParameters = m_extrapolationTool->propagate(ctx, *startParameters, *destinationSurface,
284 Acts::Direction::Forward());
285 auto end_fwd = xclock::now();
286 float ms_fwd = std::chrono::duration_cast<std::chrono::milliseconds>(end_fwd - start_fwd).count();
287
288 if (destParameters.ok()) {
289 ATH_MSG_VERBOSE(" ACTS Extrapolator succeded!! --> Forward");
290 ATH_MSG_VERBOSE(" [ intersection ] with surface at (x,y,z) = " << destParameters->position(
291 anygctx).x() << ", " << destParameters->position(anygctx).y() << ", " <<
292 destParameters->position(anygctx).z());
293 ATH_MSG_VERBOSE(" [ intersection ] parameters: " << destParameters->parameters());
294 ATH_MSG_VERBOSE(" [ intersection ] cov matrix: " << *destParameters->covariance());
295
296 // now try backward extrapolation
297 auto start_bkw = xclock::now();
298 auto finalperigee = m_extrapolationTool->propagate(ctx, *destParameters,
299 startParameters->referenceSurface(),
300 Acts::Direction::Backward());
301 auto end_bkw = xclock::now();
302 float ms_bkw = std::chrono::duration_cast<std::chrono::milliseconds>(end_bkw - start_bkw).count();
303
304 if (finalperigee.ok()) {
305 ATH_MSG_VERBOSE(" ACTS Extrapolator succeded!! --> Backward");
306 ATH_MSG_VERBOSE(" [extrapolation to perigee] input: " << startParameters->parameters());
307 ATH_MSG_VERBOSE(" [extrapolation to perigee] output: " << finalperigee->parameters());
308 ATH_MSG_VERBOSE(" [extrapolation to perigee] cov matrix: " << *finalperigee->covariance());
309 } else if (!finalperigee.ok()) {
310 ATH_MSG_DEBUG(" ACTS Extrapolation to perigee failed for input parameters: " << destParameters->parameters());
311 }
312
313 // Construct wrappers for Acts track parameters
314 auto startWrapper = std::make_unique<ActsTrackWrapper>(startParameters, anygctx);
315 auto destWrapper = std::make_unique<ActsTrackWrapper>(&destParameters.value(), anygctx);
316 auto finalWrapper = std::make_unique<ActsTrackWrapper>(&finalperigee.value(), anygctx);
317
318 m_actsPropResultWriterSvc->write<ActsTrackWrapper>(startWrapper.get(),
319 destWrapper.get(), ms_fwd, finalWrapper.get(), ms_bkw);
320 } else if (!destParameters.ok()) {
321 ATH_MSG_DEBUG(" ACTS Extrapolation not successful! ");
322 auto startWrapper = std::make_unique<ActsTrackWrapper>(startParameters, anygctx);
323 m_actsPropResultWriterSvc->write<ActsTrackWrapper>(startWrapper.get());
324 }
325 }
326 delete startParameters;
327 }
328
329 end = xclock::now();
330 secs = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() / milliseconds_to_seconds;
331 if (n_extraps == 0) [[unlikely]] {
332 ATH_MSG_ERROR("n_extraps is zero");
333 } else {
334 double secs_per_ex = secs / n_extraps;
336 "ATLAS : Time for " << n_extraps << " iterations: " << secs << "s (" << secs_per_ex << "s per extrapolation)");
337 }
338 return StatusCode::SUCCESS;
339}
340
341//============================================================================================
Scalar eta() const
pseudorapidity method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_VERBOSE(x,...)
#define ATH_MSG_INFO(x,...)
double charge(const T &p)
Definition AtlasPID.h:1003
std::chrono::steady_clock xclock
Acts::GeometryContext context() const
An algorithm that can be simultaneously executed in multiple threads.
Class for a CylinderSurface in the ATLAS detector.
Class for a DiscSurface in the ATLAS detector.
Definition DiscSurface.h:54
ToolHandle< ActsTrk::IExtrapolationTool > m_extrapolationTool
The ACTS ExtrapolationTool to be retrieved.
ServiceHandle< PropResultRootWriterSvc > m_actsPropResultWriterSvc
StatusCode execute(const EventContext &ctx) const override
standard Athena-Algorithm method
ServiceHandle< PropResultRootWriterSvc > m_atlasPropResultWriterSvc
StatusCode initialize() override
standard Athena-Algorithm method
StatusCode finalize() override
standard Athena-Algorithm method
std::vector< double > m_referenceSurfacePositiveBoundary
std::vector< std::vector< std::shared_ptr< const Acts::Surface > > > m_actsReferenceSurfaceTriples
std::vector< double > m_referenceSurfaceNegativeBoundary
ToolHandle< Trk::IExtrapolator > m_atlasExtrapolator
The ATLAS Extrapolator to be retrieved.
unsigned int m_referenceSurfaces
member variables for algorithm properties:
ExtrapolatorComparisonTest(const std::string &name, ISvcLocator *pSvcLocator)
Standard Athena-Algorithm Constructor.
ServiceHandle< ActsTrk::ITrackingGeometrySvc > m_trackingGeometrySvc
std::vector< std::vector< const Trk::Surface * > > m_atlasReferenceSurfaceTriples
Class describing the Line to which the Perigee refers to.
Abstract Base Class for tracking surfaces.
Definition Surface.h:79
Eigen::Affine3d Transform3D
Eigen::Translation< double, 3 > Translation3D
@ oppositeMomentum
@ alongMomentum
@ theta
Definition ParamDefs.h:66
@ qOverP
perigee
Definition ParamDefs.h:67
@ phi
Definition ParamDefs.h:75
@ d0
Definition ParamDefs.h:63
@ z0
Definition ParamDefs.h:64
ParticleHypothesis
Enumeration for Particle hypothesis respecting the interaction with material.
ParametersBase< TrackParametersDim, Charged > TrackParameters
#define unlikely(x)
Wrapper code for Acts track parameters, to provide a position() method without the need of explicitly...