ATLAS Offline Software
Loading...
Searching...
No Matches
ExtrapolatorComparisonTest.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 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{
57 // cleanup of the Trk::Surfaces
58 for (const auto& surfaceTriple : m_atlasReferenceSurfaceTriples) {
59 for (const auto* surface : surfaceTriple) {
60 delete surface;
61 }
62 }
63}
64
65
66//================ Initialisation =================================================
67
69{
70 // Code entered here will be executed once at program start.
71
72 ATH_MSG_INFO(" initialize()");
73
74 ATH_CHECK( m_extrapolationTool.retrieve() );
75 ATH_CHECK( m_atlasExtrapolator.retrieve() );
77
78 // Create the destination surfaces for extrapolation
79 // --> you need the Trk::Surfaces and the Acts::Surfaces
81 // assign the size
83 // loop over it and create the
84 for (unsigned int surface = 0; surface < m_referenceSurfaces; surface++) {
85
86 double radius = m_referenceSurfaceRadius[surface];
87 double halfZ = m_referenceSurfaceHalflength[surface];
88
89 // create the Surface triplet
90 std::vector< const Trk::Surface*> trkSurfaceTriplet;
91 trkSurfaceTriplet.push_back(new Trk::DiscSurface (Amg::Transform3D(Amg::Translation3D(0.,0., halfZ)), 0.,radius));
92 trkSurfaceTriplet.push_back(new Trk::CylinderSurface(Amg::Transform3D(Amg::Translation3D(0.,0., 0.)),radius, halfZ));
93 trkSurfaceTriplet.push_back(new Trk::DiscSurface (Amg::Transform3D(Amg::Translation3D(0.,0.,-halfZ)), 0.,radius));
94 ATH_MSG_INFO("Creating Trk::Surface at: R " << radius << " Z " << halfZ);
95 m_atlasReferenceSurfaceTriples.push_back(trkSurfaceTriplet);
96
97 // create the Surface triplet
98 std::vector<std::shared_ptr<const Acts::Surface>> actsSurfaceTriplet;
99
100 Acts::Transform3 posTransf(Acts::Transform3::Identity()*Acts::Translation3(Acts::Vector3(0.,0., halfZ)));
101 Acts::Transform3 cTransf(Acts::Transform3::Identity()*Acts::Translation3(Acts::Vector3(0.,0., 0.)));
102 Acts::Transform3 negTransf(Acts::Transform3::Identity()*Acts::Translation3(Acts::Vector3(0.,0.,-halfZ)));
103
104 auto posSurface = Acts::Surface::makeShared<Acts::DiscSurface> (posTransf , 0.,radius);
105 auto cSurface = Acts::Surface::makeShared<Acts::CylinderSurface>( cTransf ,radius, halfZ);
106 auto negSurface = Acts::Surface::makeShared<Acts::DiscSurface> (negTransf , 0.,radius);
107
108 actsSurfaceTriplet.push_back(posSurface);
109 actsSurfaceTriplet.push_back(cSurface );
110 actsSurfaceTriplet.push_back(negSurface);
111 ATH_MSG_INFO("Creating Acts::Surface at: R " << radius << " Z " << halfZ);
112 m_actsReferenceSurfaceTriples.push_back(actsSurfaceTriplet);
113
114 m_referenceSurfaceNegativeBoundary.push_back(atan2(radius,-halfZ));
115 m_referenceSurfacePositiveBoundary.push_back(atan2(radius, halfZ));
116 }
117 } else {
118 ATH_MSG_WARNING("Not compatible size of ReferenceSurfaceRadius and ReferenceSurfaceHalfZ!! Returning FAILURE!");
119 return StatusCode::FAILURE;
120 }
121
124 ATH_CHECK( m_rndmSvc.retrieve() );
125 m_randomEngine = m_rndmSvc->getEngine (this, "ExtrapolatorComparisonTest");
126
127 return StatusCode::SUCCESS;
128}
129
130//================ Finalisation =================================================
131
133{
134 // Code entered here will be executed once at the end of the program run.
135 return StatusCode::SUCCESS;
136}
137
138//================ Execution ====================================================
139
140StatusCode Trk::ExtrapolatorComparisonTest::execute(const EventContext& ctx) const {
141
142 float milliseconds_to_seconds = 1000.;
143
144 // generate perigees with random number generator
145 CLHEP::HepRandomEngine* engine = m_randomEngine->getEngine(ctx);
146
147 std::vector<perigeeParameters> parameters = {};
148 for (int ext = 0; ext<m_eventsPerExecute; ext++) {
149 // generate with random number generator
150 double d0 = CLHEP::RandGauss::shoot(engine) * m_sigmaD0;
151 double z0 = CLHEP::RandGauss::shoot(engine) * m_sigmaZ0;
152 double phi = m_minPhi + (m_maxPhi-m_minPhi)* CLHEP::RandFlat::shoot(engine);
153 double eta = m_minEta + CLHEP::RandFlat::shoot(engine)*(m_maxEta-m_minEta);
154 double pt = m_minPt + CLHEP::RandFlat::shoot(engine)*(m_maxPt-m_minPt);
155 double charge = (CLHEP::RandFlat::shoot(engine) > 0.5 ) ? -1. : 1.;
156 parameters.emplace_back(d0, z0, phi, eta, pt, charge);
157 }
158
159 int n_extraps = 0;
160 auto start = xclock::now();
161 for (auto& perigee : parameters) {
162
163 Acts::Vector3 momentum(perigee.m_pt * std::cos(perigee.m_phi), perigee.m_pt * std::sin(perigee.m_phi), perigee.m_pt * std::sinh(perigee.m_eta));
164 double theta = Acts::VectorHelpers::theta(momentum);
165 double qOverP = perigee.m_charge / momentum.norm();
166
167 const Trk::PerigeeSurface atlPerigeeSurface;
168 auto atlPerigee = std::make_unique<Trk::Perigee>(perigee.m_d0, perigee.m_z0, perigee.m_phi, theta, qOverP, atlPerigeeSurface);
169
170 for (unsigned int surface = 0; surface < m_atlasReferenceSurfaceTriples.size(); surface++) {
171 n_extraps++;
172
173 double negRef = m_referenceSurfaceNegativeBoundary.at(surface);
174 double posRef = m_referenceSurfacePositiveBoundary.at(surface);
175
176 // decide which reference surface to take
177 int refSurface = theta < posRef ? 2 : 1;
178 refSurface = theta > negRef ? 0 : 1;
179
180 const Trk::Surface* destinationSurface = m_atlasReferenceSurfaceTriples.at(surface).at(refSurface);
181
182 ATH_MSG_VERBOSE("Starting extrapolation " << n_extraps << " from : " << *atlPerigee << " to : " << *destinationSurface);
183
184 auto start_fwd = xclock::now();
185 auto destParameters =
186 m_atlasExtrapolator->extrapolate(
187 ctx,
188 *atlPerigee,
189 *destinationSurface,
191 true,
192 static_cast<Trk::ParticleHypothesis>(m_particleType.value()));
193 auto end_fwd = xclock::now();
194 float ms_fwd = std::chrono::duration_cast<std::chrono::milliseconds>(end_fwd-start_fwd).count();
195
196 if (destParameters) {
197 ATH_MSG_VERBOSE(" ATLAS Extrapolator succeded!! --> Forward" );
198 ATH_MSG_VERBOSE(" [ intersection ] with surface at (x,y,z) = " << destParameters->position().x() << ", " << destParameters->position().y() << ", " << destParameters->position().z() );
199 ATH_MSG_VERBOSE(" [ intersection ] parameters: " << destParameters->parameters() );
200 ATH_MSG_VERBOSE(" [ intersection ] cov matrix: " << destParameters->covariance() );
201
202 // now try backward extrapolation
203 auto start_bkw = xclock::now();
204 auto finalperigee =
205 m_atlasExtrapolator->extrapolate(
206 ctx,
207 *destParameters,
208 atlPerigee->associatedSurface(),
210 true,
211 static_cast<Trk::ParticleHypothesis>(m_particleType.value()));
212 auto end_bkw = xclock::now();
213 float ms_bkw = std::chrono::duration_cast<std::chrono::milliseconds>(end_bkw-start_bkw).count();
214
215 if (finalperigee) {
216 ATH_MSG_VERBOSE(" ATLAS Extrapolator succeded!! --> Backward" );
217 ATH_MSG_VERBOSE(" [extrapolation to perigee] input: " << atlPerigee->parameters() );
218 ATH_MSG_VERBOSE(" [extrapolation to perigee] output: " << finalperigee->parameters() );
219 ATH_MSG_VERBOSE(" [extrapolation to perigee] cov matrix: " << finalperigee->covariance() );
220
221 } else if (!finalperigee) {
222 ATH_MSG_DEBUG(" ATLAS Extrapolation to perigee failed for input parameters: " << destParameters->parameters());
223 }
224
225 m_atlasPropResultWriterSvc->write<Trk::TrackParameters>(atlPerigee.get(), destParameters.get(), ms_fwd, finalperigee.get(), ms_bkw);
226 } else if (!destParameters) {
227 ATH_MSG_DEBUG(" ATLAS Extrapolation not successful! " );
228 m_atlasPropResultWriterSvc->write<Trk::TrackParameters>(atlPerigee.get());
229 }
230 }
231 }
232 auto end = xclock::now();
233 auto secs = std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count() / milliseconds_to_seconds;
234 double secs_per_ex = secs / n_extraps;
235
236 ATH_MSG_INFO("ATLAS : Time for " << n_extraps << " iterations: " << secs << "s (" << secs_per_ex << "s per extrapolation)");
237
238 n_extraps = 0;
239 start = xclock::now();
240 for (auto& perigee : parameters) {
241 Acts::Vector3 momentum(perigee.m_pt * std::cos(perigee.m_phi), perigee.m_pt * std::sin(perigee.m_phi), perigee.m_pt * std::sinh(perigee.m_eta));
242 double theta = Acts::VectorHelpers::theta(momentum);
243 double qOverP = perigee.m_charge / momentum.norm();
244
245 std::shared_ptr<Acts::PerigeeSurface> actsPerigeeSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(Acts::Vector3(0, 0, 0));
246 double t = 0.;
247 Acts::BoundVector pars;
248 //cppcheck-suppress constStatement
249 pars << perigee.m_d0, perigee.m_z0, perigee.m_phi, theta, qOverP, t;
250 std::optional<Acts::BoundSquareMatrix> cov = std::nullopt;
251
252 // Perigee, no alignment -> default geo context
253 const ActsTrk::GeometryContext& gctx = m_trackingGeometryTool->getNominalGeometryContext();
254 auto anygctx = gctx.context();
255 const auto* startParameters = new const Acts::GenericBoundTrackParameters(std::move(actsPerigeeSurface), pars, std::move(cov), Acts::ParticleHypothesis::pion());
256
257 for (unsigned int surface = 0; surface < m_actsReferenceSurfaceTriples.size(); surface++) {
258 n_extraps++;
259
260 double negRef = m_referenceSurfaceNegativeBoundary.at(surface);
261 double posRef = m_referenceSurfacePositiveBoundary.at(surface);
262
263 // decide which reference surface to take
264 int refSurface = theta < posRef ? 2 : 1;
265 refSurface = theta > negRef ? 0 : 1;
266
267 auto destinationSurface = m_actsReferenceSurfaceTriples.at(surface).at(refSurface);
268
269 ATH_MSG_VERBOSE("Starting extrapolation " << n_extraps << " from : " << pars << " to : " << destinationSurface);
270
271 auto start_fwd = xclock::now();
272 auto destParameters = m_extrapolationTool->propagate(ctx, *startParameters, *destinationSurface, Acts::Direction::Forward());
273 auto end_fwd = xclock::now();
274 float ms_fwd = std::chrono::duration_cast<std::chrono::milliseconds>(end_fwd-start_fwd).count();
275
276 if (destParameters) {
277 ATH_MSG_VERBOSE(" ACTS Extrapolator succeded!! --> Forward" );
278 ATH_MSG_VERBOSE(" [ intersection ] with surface at (x,y,z) = " << destParameters->position(anygctx).x() << ", " << destParameters->position(anygctx).y() << ", " << destParameters->position(anygctx).z() );
279 ATH_MSG_VERBOSE(" [ intersection ] parameters: " << destParameters->parameters() );
280 ATH_MSG_VERBOSE(" [ intersection ] cov matrix: " << *destParameters->covariance() );
281
282 // now try backward extrapolation
283 auto start_bkw = xclock::now();
284 auto finalperigee = m_extrapolationTool->propagate(ctx, *destParameters, startParameters->referenceSurface(), Acts::Direction::Backward());
285 auto end_bkw = xclock::now();
286 float ms_bkw = std::chrono::duration_cast<std::chrono::milliseconds>(end_bkw-start_bkw).count();
287
288 if (finalperigee) {
289 ATH_MSG_VERBOSE(" ACTS Extrapolator succeded!! --> Backward" );
290 ATH_MSG_VERBOSE(" [extrapolation to perigee] input: " << startParameters->parameters() );
291 ATH_MSG_VERBOSE(" [extrapolation to perigee] output: " << finalperigee->parameters() );
292 ATH_MSG_VERBOSE(" [extrapolation to perigee] cov matrix: " << *finalperigee->covariance() );
293
294 } else if (!finalperigee) {
295 ATH_MSG_DEBUG(" ACTS Extrapolation to perigee failed for input parameters: " << destParameters->parameters());
296 }
297
298 // Construct wrappers for Acts track parameters
299 auto startWrapper = std::make_unique<ActsTrackWrapper>(startParameters, anygctx);
300 auto destWrapper = std::make_unique<ActsTrackWrapper>(&destParameters.value(), anygctx);
301 auto finalWrapper = std::make_unique<ActsTrackWrapper>(&finalperigee.value(), anygctx);
302
303 m_actsPropResultWriterSvc->write<ActsTrackWrapper>(startWrapper.get(), destWrapper.get(), ms_fwd, finalWrapper.get(), ms_bkw);
304
305 } else if (!destParameters) {
306 ATH_MSG_DEBUG(" ACTS Extrapolation not successful! " );
307 auto startWrapper = std::make_unique<ActsTrackWrapper>(startParameters, anygctx);
308 m_actsPropResultWriterSvc->write<ActsTrackWrapper>(startWrapper.get());
309 }
310 }
311 delete startParameters;
312 }
313
314 end = xclock::now();
315 secs = std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count() / milliseconds_to_seconds;
316 secs_per_ex = secs / n_extraps;
317
318 ATH_MSG_INFO("ACTS : Time for " << n_extraps << " iterations: " << secs << "s (" << secs_per_ex << "s per extrapolation)");
319
320 return StatusCode::SUCCESS;
321}
322
323//============================================================================================
324
325
326
Scalar eta() const
pseudorapidity method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
double charge(const T &p)
Definition AtlasPID.h:997
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
PublicToolHandle< ActsTrk::ITrackingGeometryTool > m_trackingGeometryTool
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.
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.
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
Wrapper code for Acts track parameters, to provide a position() method without the need of explicitly...