ATLAS Offline Software
Loading...
Searching...
No Matches
TrackPropagationHelper.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5
7 // //
8 // Implementation of class TrackPropagationHelper //
9 // //
10 // Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) //
11 // Initial extrapolation code by Thijs Cornelissen //
12 // Initial version: February 2008 //
13 // //
15
17#include "GaudiKernel/ThreadLocalContext.h"
19#include "TrkTrack/Track.h"
22#include <stdexcept>
25#include "TrkVolumes/Volume.h"
28
29#include "CLHEP/Units/PhysicalConstants.h"
30
31#include "VP1Base/VP1QtUtils.h"
32#include "VP1Base/VP1Msg.h"
33#include <limits>
34#include <memory>
35
36//____________________________________________________________________
38public:
40 : theclass(tc),
41 tracksanity(new VP1TrackSanity(tc?tc->systemBase():nullptr)),
42 maxInDetr(1.1*CLHEP::m),
44 maxz(3.5*CLHEP::m),
46 showExtrapSurfaces(VP1QtUtils::environmentVariableIsOn("VP1_TRKSYS_SHOWEXTRAPSURFACES"))
47 {
48 }
49
51 std::unique_ptr<VP1TrackSanity> tracksanity{};
52 const double maxInDetr{};
53 const double maxInDetrsq{};
54 const double maxz{};
55 const double fallback_flydist{};
56
57 bool outsideIDVolume(const Amg::Vector3D& p) const {
58 return fabs(p.z())>maxz||p.perp2()>maxInDetrsq;
59 }
60
61 //Fixme: These are similar to internal methods in InDetProjHelper in guideline system!!:
62 void movePoint1ToZPlaneAndPoint2( Amg::Vector3D& p1, const Amg::Vector3D& p2, const double& z ) const;
63 void movePoint1ToInfiniteCylinderAndPoint2( Amg::Vector3D&p1, const Amg::Vector3D&p2, const double& r ) const;
64
65 bool makePointsNeutral_SinglePar( std::vector<Amg::Vector3D >& points, const Trk::Track* );
66 bool makePointsCharged_SinglePar( std::vector<Amg::Vector3D >& points, const Trk::Track*,
67 Trk::IExtrapolator * extrapolator, Trk::ParticleHypothesis hypo );
68 bool addPointsBetweenParameters_Charged( std::vector<Amg::Vector3D >& points, const Trk::Track*,
69 const Trk::TrackParameters * par1, const Trk::TrackParameters * par2,
70 Trk::IExtrapolator * extrapolator, Trk::ParticleHypothesis hypo );
71
72 //Will create new track par:
74 const Trk::Track* trk,
75 const Trk::TrackParameters * prevpars,
77 const double& dist );
78 //Granularity:
79 static double maxPointDistSq(const Amg::Vector3D& /* p */){
80 //Vertex region:
90 return 2*CLHEP::cm;//Outside ID
91 }
92
93 std::vector<Trk::PlaneSurface> surfaces;
95};
96
97std::vector<Trk::PlaneSurface>& TrackPropagationHelper::getExtrapolationSurfaces() const {
98 return m_d->surfaces;
99}
100
101//____________________________________________________________________
103{
104 double dx(p2.x()-p1.x()), dy(p2.y()-p1.y()), dz(p2.z()-p1.z());
105 if (dz==0.0) {
106 theclass->message("movePoint1ToZPlaneAndPoint2 Error: Points have same z!!");
107 return;
108 }
109 double s( (z-p1.z())/dz );
110 // p1.set( p1.x()+dx*s, p1.y()+dy*s, z );
111 p1[0]= p1.x()+dx*s;
112 p1[1]= p1.y()+dy*s;
113 p1[2]= z;
114
115}
116
117 //____________________________________________________________________
119{
120 //Fixme: what happens here if we don't cross? And how can we be sure
121 //that we don't move FURTHER than the other point? (i.e. if the
122 //infinite line with p1 and p2 crosses, but the segment p1p2 does
123 //not!?
124 double p1r(p1.perp());
125 double dr(p2.perp()-p1r);
126 if (dr==0.0) {
127 theclass->message("movePoint1ToInfiniteCylinderAndPoint2 Error: Points have same r!!");
128 return;
129 }
130 double s((r-p1r)/dr);
131 double t(1.0-s);
132 // p1.set( p1.x()*t + p2.x()*s, p1.y()*t + p2.y()*s, p1.z()*t + p2.z()*s );
133 p1[0]= p1.x()*t + p2.x()*s;
134 //p1[1]= p2.y()*s, p1.z()*t; original
135 p1[1]= p1.y()*t + p2.y()*s; //sroe, compiler warning fix
136 p1[2]= p1.z()*t + p2.z()*s;
137}
138
139 //____________________________________________________________________
141 : VP1HelperClassBase(sys,"TrackPropagationHelper"), m_d(new Imp(this))
142{
143}
144
145 //____________________________________________________________________
150
151 //____________________________________________________________________
152bool TrackPropagationHelper::makePointsNeutral( std::vector<Amg::Vector3D >& points, const Trk::Track* track )
153{
154 if (VP1Msg::verbose())
155 messageVerbose("makePointsNeutral start");
156
157 points.clear();
158 if (!track) {
159 message("makePointsNeutral called with null track pointer");
160 return false;
161 }
162 const unsigned npars = track->trackParameters()->size();
163 if (npars==0) {
164 message("makePointsNeutral Error: No TrackParameters on track!");
165 return false;
166 }
167 if (npars==1)
168 return m_d->makePointsNeutral_SinglePar(points,track);
169
170 points.reserve(track->trackParameters()->size());
171
172
173 Trk::TrackStates::const_iterator tsos_iter = track->trackStateOnSurfaces()->begin();
174 Trk::TrackStates::const_iterator tsos_end = track->trackStateOnSurfaces()->end();
175 bool problems(false);
176 for (; tsos_iter != tsos_end; ++tsos_iter) {
177 if (!m_d->tracksanity->isSafe(*tsos_iter)) {
178 problems = true;
179 continue;
180 }
181 //if ((*tsos_iter)->materialEffectsOnTrack())
182 // continue;
183 const Trk::TrackParameters* trackParam = (*tsos_iter)->trackParameters();
184 if (!m_d->tracksanity->isSafe(trackParam)) {
185 problems = true;
186 continue;
187 }
188 points.push_back(trackParam->position());
189 }
190 if (problems) {
191 messageDebug("makePointsNeutral WARNING: Track had one or more track parameters which is unsafe to use in job.");
192 if (points.size()<2) {
193 messageDebug("makePointsNeutral ERROR: Track did not have at least two safe parameters.");
194 points.clear();
195 return false;
196 }
197 }
198
199 if (VP1Msg::verbose())
200 messageVerbose("makePointsNeutral_SinglePar end");
201 return true;
202}
203
204 //____________________________________________________________________
205bool TrackPropagationHelper::Imp::makePointsNeutral_SinglePar( std::vector<Amg::Vector3D >& points, const Trk::Track* track )
206{
207 if (VP1Msg::verbose())
208 theclass->messageVerbose("makePointsNeutral_SinglePar start");
209 points.clear();
210 const Trk::TrackParameters * par = *(track->trackParameters()->begin());
211 if (!tracksanity->isSafe(par)) {
212 theclass->messageDebug("makePointsNeutral_SinglePar called with unsafe track parameter");
213 return false;
214 }
215 Amg::Vector3D u(par->momentum().unit());
216 Amg::Vector3D a(par->position()),b;
217 if (outsideIDVolume(a)) {
218 //We start outside. We just add fallback_flydist. (fixme: warn?)
219 b = a +fallback_flydist*u;
220 } else {
221 //Make a second point, where trajectory hits maxInDetr,maxz
222 b = a +999*CLHEP::m*u;
223 if (b.z()<-maxz)
225 else
226 if (b.z()>maxz)
228 if (b.perp2()>maxInDetrsq)
230 }
231 points.reserve(2);
232 points.push_back(a);
233 points.push_back(b);
234 if (VP1Msg::verbose())
235 theclass->messageVerbose("makePointsNeutral_SinglePar (single track parameter) end");
236 return true;
237}
238
239 //____________________________________________________________________
240bool TrackPropagationHelper::makePointsCharged( std::vector<Amg::Vector3D >& points, const Trk::Track* track,
241 Trk::IExtrapolator * extrapolator, Trk::ParticleHypothesis hypo, bool useMEOT,const Trk::Volume* volume )
242{
243 if (VP1Msg::verbose())
244 messageVerbose("makePointsCharged start with hypo="+str(hypo)+", useMEOT="+str(useMEOT)+", volume=" +str(volume));
245 // if (volume) std::cout<<volume->volumeBounds()<<std::endl;
247 // Clear input points, check/sanitise input and initialise //
249
250 points.clear();
251 if (!extrapolator) {
252 message("makePointsCharged ERROR: Null extrapolator tool provided!");
253 return false;
254 }
255 if (!track) {
256 message("makePointsCharged ERROR: Called with null track pointer");
257 return false;
258 }
259 const unsigned npars = track->trackParameters()->size();
260 if (npars==0) {
261 message("makePointsCharged ERROR: No TrackParameters on track!");
262 return false;
263 }
264 if (npars==1)
265 return m_d->makePointsCharged_SinglePar(points,track,extrapolator,hypo);
266
267 points.reserve(npars);//At least we need this.
268 const EventContext& ctx = Gaudi::Hive::currentContext();
269 //Add a point for each parameter, and add extra points between them where appropriate.
270 Trk::TrackStates::const_iterator tsos_iter = track->trackStateOnSurfaces()->begin();
271 Trk::TrackStates::const_iterator tsos_end = track->trackStateOnSurfaces()->end();
272 const Trk::TrackParameters* prevpar(nullptr);
273 const Trk::TrackParameters* trackParam(nullptr);
274 bool problems(false);
275 for (; tsos_iter != tsos_end; ++tsos_iter) {
276 if (!m_d->tracksanity->isSafe(*tsos_iter))
277 continue;
278 if ((*tsos_iter)->measurementOnTrack()==nullptr && ( (*tsos_iter)->materialEffectsOnTrack()&&!useMEOT ) )
279 continue;
280 trackParam = (*tsos_iter)->trackParameters();
281 if (!m_d->tracksanity->isSafe(trackParam))
282 continue;
283 if (!prevpar) {
284 //first time.
285 prevpar = trackParam;
286 points.push_back(prevpar->position());
287 continue;
288 }
289 if (!m_d->addPointsBetweenParameters_Charged(points,track,prevpar,trackParam,extrapolator,hypo))
290 problems = true;
291 points.push_back(trackParam->position());
292 prevpar = trackParam;
293 }
294
295 if (problems)
296 messageDebug("WARNING: Problems encountered adding point(s) between track parameters");
297
298// restrict to ID tracks for now.
299 if (volume && trackParam && !m_d->outsideIDVolume(trackParam->position())) {
300 messageVerbose("Extending to Volume");
301 //get individual surfaces
302
303 // TODO - optimise this!
304 const std::vector<std::unique_ptr<Trk::Surface>> bsurfs =
305 const_cast<Trk::VolumeBounds&>(volume->volumeBounds())
306 .decomposeToSurfaces(volume->transform());
307
308 if (!bsurfs.empty()){
309 messageVerbose("Has this many surfaces:"+str(bsurfs.size()));
310
311 auto bSurfsIt = bsurfs.begin();
312 for (;bSurfsIt!= bsurfs.end(); ++bSurfsIt){
313
314 messageVerbose("Extrap value:"+str((extrapolator)));
315 messageVerbose("trackParam:"+str((trackParam)));
316 const Trk::TrackParameters* trackPar = extrapolator->extrapolate(ctx,
317 *trackParam,
318 **bSurfsIt,
319 Trk::alongMomentum,true,hypo).release(); // change this to extrapolate current param to surface.
320
321 if (trackPar){
322 messageVerbose("Extrapolation succeeded");
323
324 if (!m_d->addPointsBetweenParameters_Charged(points,track,trackParam,trackPar,extrapolator,hypo))
325 messageDebug("WARNING: Problems encountered adding point(s) between track parameters in extending to Volume");
326 }
327 }
328 } else {
329 messageDebug("WARNING: Problems encountered getting boundary surfaces from Volume");
330 }
331 }
332 if (VP1Msg::verbose())
333 messageVerbose("makePointsCharged end with "+str(points.size())+"points");
334 return true;
335}
336
337 //____________________________________________________________________
339 const Trk::Track* trk,
340 const Trk::TrackParameters * prevpars,
342 const double& dist )
343{
344 if (!trk||!prevpars||!extrapolator)
345 return nullptr;
346
347 Trk::CurvilinearUVT uvt(prevpars->momentum().unit());
348
349
350 Amg::Transform3D t(uvt.curvU(),uvt.curvV(),uvt.curvT(), prevpars->position()+(prevpars->momentum().unit()*dist));
351
352 Trk::PlaneSurface surf(t);
353
354
355 if (showExtrapSurfaces) surfaces.push_back(surf);
356
357
358 const Trk::TrackParameters *newpars(nullptr);
359 try {
360 newpars = extrapolator->extrapolate(Gaudi::Hive::currentContext(),
361 *prevpars,
362 surf,
363 Trk::alongMomentum,false,hypo).release(); // change this to extrapolate current param to surface.
364 } catch (const std::runtime_error& e) {
365 theclass->message("Failure trying to use extrapolator for track (Exception thrown: " + QString(e.what())+")");
366 return nullptr;
367 }
368 if (!newpars) {
369 theclass->message("Failure trying to use extrapolator for track");
370 return nullptr;
371 }
372 if (!newpars) {
373 theclass->message("Failure trying to use extrapolator for track");
374 return nullptr;
375 }
376 return newpars;
377}
378
380 return m_d->showExtrapSurfaces;
381}
382
383
384 //____________________________________________________________________
385bool TrackPropagationHelper::Imp::makePointsCharged_SinglePar( std::vector<Amg::Vector3D >& points, const Trk::Track* track,
386 Trk::IExtrapolator * extrapolator, Trk::ParticleHypothesis hypo )
387{
388 if (VP1Msg::verbose())
389 theclass->messageVerbose("makePointsCharged_SinglePar start");
390 points.clear();
391 if (!extrapolator) {
392 theclass->message("makePointsCharged_SinglePar ERROR: Null extrapolator tool provided!");
393 return false;
394 }
395 const Trk::TrackParameters * par = *(track->trackParameters()->begin());
396 if (!tracksanity->isSafe(par)) {
397 theclass->messageDebug("makePointsCharged_SinglePar called with unsafe track parameter");
398 return false;
399 }
400
401 Amg::Vector3D p0(par->position());
402 points.push_back(p0);
403 const bool startoutsideID(outsideIDVolume(p0));
404
405 double distadded(0);
406 const double maxdistadded = 2*CLHEP::m;
407 points.reserve(20);//skip a few reallocs
408 const Trk::TrackParameters * prevpars = par;
409 const Trk::TrackParameters * temppars(nullptr);
410
411 while (distadded<maxdistadded) {
412 temppars = extrapolateToNewPar( extrapolator, track, prevpars, hypo, maxPointDistSq(prevpars->position()));
413 if (temppars)
414 distadded += (temppars->position()-prevpars->position()).mag();
415 if (prevpars!=par)
416 delete prevpars;
417 prevpars = nullptr;
418 if (!temppars) {
419 theclass->messageDebug("makePointsCharged_SinglePar ERROR: Failed to use extrapolator for next point");
420 if (points.size()<2) {
421 points.clear();
422 return false;
423 }
424 return true;//Fixme??
425 }
426 Amg::Vector3D p(temppars->position());
427 points.push_back(p);
428 prevpars = temppars;
429 temppars = nullptr;
430 if (!startoutsideID && outsideIDVolume(p)) {
431 if (prevpars!=par)
432 delete prevpars;
433 prevpars = nullptr;
434 break;
435 }
436 }
437 if (prevpars!=par)
438 delete prevpars;
439
440 if (VP1Msg::verbose())
441 theclass->messageVerbose("makePointsCharged_SinglePar end");
442 return true;
443
444}
445
446 //____________________________________________________________________
447bool TrackPropagationHelper::Imp::addPointsBetweenParameters_Charged( std::vector<Amg::Vector3D >& points, const Trk::Track* trk,
448 const Trk::TrackParameters * par1, const Trk::TrackParameters * par2,
449 Trk::IExtrapolator * extrapolator, Trk::ParticleHypothesis hypo )
450{
451 double distbetween = sqrt((par2->position()-par1->position()).mag2());
452 if (distbetween<0.001) {
453 theclass->messageVerbose("TrackPropagationHelper::Imp::addPointsBetweenParameters_Charged: parameters on top of each other. Skip, but no error.");
454 return true;
455 }
456 // theclass->messageVerbose("TrackPropagationHelper::Imp::addPointsBetweenParameters_Charged: par1="
457 // +str(par1->position())+", par2=" +str(par2->position())+", dist="+str(distbetween));
458
459 Amg::Vector3D p2(par2->position());
460 const Trk::TrackParameters * prevpars = par1;
461
462 double olddistsq(1.0e99);
463 double distadded(0);
464 const double maxdistadded = std::max(2*CLHEP::m,(par1->position()-p2).mag()*1.5);
465 while ( (prevpars->position()-p2).mag()> maxPointDistSq(prevpars->position()) && distadded<maxdistadded ) {
466
467 // theclass->messageVerbose("distadded: "+str(distadded)+", distance left="+str(sqrt((prevpars->position()-p2).mag2()))+", jump="+str(maxPointDistSq(prevpars->position())));
468 const Trk::TrackParameters * newpars = extrapolateToNewPar( extrapolator, trk, prevpars, hypo, maxPointDistSq(prevpars->position()) );
469 if (!newpars){
470 if (VP1Msg::verbose())
471 theclass->messageVerbose("TrackPropagationHelper::Imp::addPointsBetweenParameters_Charged: Extrapolation failed.");
472 return false;
473 }
474 const double distsq = (par2->position()-newpars->position()).mag2();
475 if (distsq>olddistsq) {
476 delete newpars;
477 if (VP1Msg::verbose())
478 theclass->messageVerbose("TrackPropagationHelper::Imp::addPointsBetweenParameters_Charged: distq("+str(distsq)+")>olddistsq ("+str(olddistsq)+") so overshot?");
479 return false;
480 }
481 olddistsq = distsq;
482 // if ((prevpars->position()-newpars->position()).mag2() > 4*maxpointdistsq) {
483 // delete newpars;
484 // return false;
485 // }
486 points.push_back(newpars->position());
487 distadded += (newpars->position()-prevpars->position()).mag();
488 if (prevpars!=par1)
489 delete prevpars;
490 prevpars = newpars;
491 }
492 if (prevpars!=par1)
493 delete prevpars;
494 return (distadded<maxdistadded);
495}
static Double_t a
static Double_t tc
#define z
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:838
const Trk::TrackParameters * extrapolateToNewPar(Trk::IExtrapolator *extrapolator, const Trk::Track *trk, const Trk::TrackParameters *prevpars, Trk::ParticleHypothesis hypo, const double &dist)
std::vector< Trk::PlaneSurface > surfaces
For debugging.
bool addPointsBetweenParameters_Charged(std::vector< Amg::Vector3D > &points, const Trk::Track *, const Trk::TrackParameters *par1, const Trk::TrackParameters *par2, Trk::IExtrapolator *extrapolator, Trk::ParticleHypothesis hypo)
bool makePointsCharged_SinglePar(std::vector< Amg::Vector3D > &points, const Trk::Track *, Trk::IExtrapolator *extrapolator, Trk::ParticleHypothesis hypo)
TrackPropagationHelper * theclass
void movePoint1ToZPlaneAndPoint2(Amg::Vector3D &p1, const Amg::Vector3D &p2, const double &z) const
bool outsideIDVolume(const Amg::Vector3D &p) const
Imp(TrackPropagationHelper *tc)
std::unique_ptr< VP1TrackSanity > tracksanity
bool makePointsNeutral_SinglePar(std::vector< Amg::Vector3D > &points, const Trk::Track *)
static double maxPointDistSq(const Amg::Vector3D &)
void movePoint1ToInfiniteCylinderAndPoint2(Amg::Vector3D &p1, const Amg::Vector3D &p2, const double &r) const
bool makePointsCharged(std::vector< Amg::Vector3D > &points, const Trk::Track *, Trk::IExtrapolator *extrapolator, Trk::ParticleHypothesis hypo=Trk::nonInteracting, bool useMEOT=false, const Trk::Volume *volume=0)
bool makePointsNeutral(std::vector< Amg::Vector3D > &points, const Trk::Track *)
std::vector< Trk::PlaneSurface > & getExtrapolationSurfaces() const
simple class that constructs the curvilinear vectors curvU and curvV from a given momentum direction ...
const Amg::Vector3D & curvU() const
Access methods.
const Amg::Vector3D & curvT() const
const Amg::Vector3D & curvV() const
Interface class for the extrapolation AlgTool, it inherits from IAlgTool Detailed information about p...
virtual std::unique_ptr< NeutralParameters > extrapolate(const NeutralParameters &parameters, const Surface &sf, PropDirection dir=anyDirection, const BoundaryCheck &bcheck=true) const =0
Main extrapolation Interface starting from neutral parameters and aiming at surface.
const Amg::Vector3D & momentum() const
Access method for the momentum.
const Amg::Vector3D & position() const
Access method for the position.
Class for a planaer rectangular or trapezoidal surface in the ATLAS detector.
Pure Absract Base Class for Volume bounds.
virtual std::vector< std::unique_ptr< Trk::Surface > > decomposeToSurfaces(const Amg::Transform3D &transform)=0
Method to decompose the Bounds into Surfaces, the Volume can turn them into BoundarySurfaces.
Base class for all volumes inside the tracking realm, it defines the interface for inherited Volume c...
Definition Volume.h:36
const Amg::Transform3D & transform() const
Return methods for geometry transform.
Definition Volume.h:83
const VolumeBounds & volumeBounds() const
returns the volumeBounds()
Definition Volume.h:96
VP1HelperClassBase(IVP1System *sys=0, QString helpername="")
void messageVerbose(const QString &) const
void message(const QString &) const
IVP1System * systemBase() const
void messageDebug(const QString &) const
static bool verbose()
Definition VP1Msg.h:31
int r
Definition globals.cxx:22
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
@ alongMomentum
ParticleHypothesis
Enumeration for Particle hypothesis respecting the interaction with material.
ParametersBase< TrackParametersDim, Charged > TrackParameters