ATLAS Offline Software
Loading...
Searching...
No Matches
Trk2dDistanceSeeder.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/*********************************************************************
6 Trk2dDistanceSeeder.cxx - Description in header file
7*********************************************************************/
8
9//#define TRK2DDISTANCESEEDER_DEBUG
10
12#include "GaudiKernel/EventContext.h"
13#include "GaudiKernel/SystemOfUnits.h"
17#include <cmath>
18
19namespace {
20 inline double dist2d(const Amg::Vector3D & a, const Amg::Vector3D & b) {
21 return std::sqrt(std::pow(a.x()-b.x(),2)+std::pow(a.y()-b.y(),2));
22 }
23 inline double takenearest(const double of, const double to) {
24 if (of-to>=M_PI) return of-2*M_PI;
25 if (of-to<-M_PI) return of+2*M_PI;
26 return of;
27 }
28
29 inline double
30 safeAtan2(const double y, const double x)
31 {
32 //This is basically what TMath::Atan2 does
33 //up until 6.24 at least.
34 if (x != 0){
35 return std::atan2(y, x);
36 }
37 //x ==0 cases
38 if (y == 0){
39 return 0;
40 }
41 if (y > 0){
42 return M_PI_2;
43 }
44 else{
45 return -M_PI_2;
46 }
47 }
48
49 inline double
50 safeAcos(const double x)
51 {
52 // This is what TMath::Acos did up to 6.22 but not
53 // from 6.24 onwards...
54 if (x < -1.) {
55 return M_PI;
56 }
57 if (x > 1.) {
58 return 0;
59 }
60 return std::acos(x);
61 }
62
63 inline double
64 oppositeangle(const double angle)
65 {
66 return angle > 0. ? angle - M_PI : angle + M_PI;
67 }
68 inline double
69 square(const double tosquare)
70 {
71 return std::pow(tosquare, 2);
72 }
73 inline double
74 getphipoca(const Trk::Perigee& myPerigee)
75 {
76 return myPerigee.parameters()[Trk::phi0] + M_PI / 2;
77 }
78 inline double
79 setphipoca(const double phi)
80 {
81 return phi - M_PI / 2.;
82 }
83 inline double
84 goFromPhipocaToPhi(const double phipoca)
85 {
86 return phipoca + M_PI / 2.;
87 }
88
89 inline double
90 getRadiusOfCurvature(const Trk::Perigee& myPerigee, const double Bzfield)
91 {
92 return sin(myPerigee.parameters()[Trk::theta]) /
93 (Bzfield * myPerigee.parameters()[Trk::qOverP]);
94 }
95 inline Amg::Vector3D
96 getCenterOfCurvature(const Trk::Perigee& myPerigee,
97 const double RadiusOfCurvature,
98 const double phipoca)
99 {
100 return Amg::Vector3D(myPerigee.associatedSurface().center().x() +
101 myPerigee.parameters()[Trk::d0] * cos(phipoca) -
102 RadiusOfCurvature * cos(phipoca),
103 myPerigee.associatedSurface().center().y() +
104 myPerigee.parameters()[Trk::d0] * sin(phipoca) -
105 RadiusOfCurvature * sin(phipoca),
106 myPerigee.associatedSurface().center().z() +
107 myPerigee.parameters()[Trk::z0] +
108 RadiusOfCurvature *
109 myPerigee.parameters()[Trk::phi0] /
110 tan(myPerigee.parameters()[Trk::theta]));
111 }
112 inline Amg::Vector3D
113 getSeedPoint(const Trk::Perigee& myPerigee,
114 const Amg::Vector3D& center,
115 const double radius,
116 const double newphi)
117 {
118 // short int sgnd0=(short
119 // int)(myPerigee.parameters()[Trk::d0]/fabs(myPerigee.parameters()[Trk::d0]));
120 return Amg::Vector3D(
121 center.x() + radius * cos(newphi + M_PI / 2.),
122 center.y() + radius * sin(newphi + M_PI / 2.),
123 // eliminated sgnd0 from
124 // center.z()-radius*(newphi-sgnd0*M_PI/2.)/tan(myPerigee.parameters()[Trk::theta]));
125 center.z() - radius * newphi / tan(myPerigee.parameters()[Trk::theta]));
126 }
127 inline Amg::Vector3D
128 getSeedPoint(const Amg::Vector3D& center,
129 const double radius,
130 const double newphi)
131 {
132 // short int sgnd0=(short
133 // int)(myPerigee.parameters()[Trk::d0]/fabs(myPerigee.parameters()[Trk::d0]));
134 return Amg::Vector3D(center.x() + radius * cos(newphi + M_PI / 2.),
135 center.y() + radius * sin(newphi + M_PI / 2.),
136 0.);
137 }
138
139}//end anonymous namespace
140
141namespace Trk
142{
143 Trk2dDistanceSeeder::Trk2dDistanceSeeder(const std::string& t, const std::string& n, const IInterface* p) :
144 AthAlgTool(t,n,p),
146 {
147 declareProperty("SolveAmbiguityUsingZ",m_solveAmbiguityUsingZ);
148 declareInterface<Trk2dDistanceSeeder>(this);
149 }
150
152
154 {
155 ATH_CHECK( AlgTool::initialize() );
157 ATH_MSG_DEBUG( "Initialize successful" );
158 return StatusCode::SUCCESS;
159 }
160
162 {
163 ATH_MSG_DEBUG( "Finalize successful" );
164 return StatusCode::SUCCESS;
165 }
166
167
170 TwoPoints* twopoints /*=nullptr*/) const
171 {
172 SG::ReadCondHandle<AtlasFieldCacheCondObj> readHandle{m_fieldCacheCondObjInputKey, Gaudi::Hive::currentContext()};
173 const AtlasFieldCacheCondObj* fieldCondObj{*readHandle};
174 if (!fieldCondObj)[[unlikely]]{
175 ATH_MSG_ERROR("GetSeed: fieldCondObj is nullptr.");
176 return {};
177 }
178 MagField::AtlasFieldCache fieldCache;
179 fieldCondObj->getInitializedCache (fieldCache);
180
181 const double bfield1 = getBField (mytracks.getFirstPerigee(), fieldCache);
182 const double bfield2 = getBField (mytracks.getSecondPerigee(), fieldCache);
183
184 //phitanpoca here means not the tan to poca (which is phi0) but the direction from perigee to the center of curvature (I don't know
185 //why I chose this strange name, sorry!)
186 const double phitanpoca1=getphipoca(mytracks.getFirstPerigee());
187 const double phitanpoca2=getphipoca(mytracks.getSecondPerigee());
188
189 //Temporary abs1 and abs2 are the signed radius quantities (later we will reduce it to unsigned quantities)
190 double abs1 = getRadiusOfCurvature(mytracks.getFirstPerigee(), bfield1);
191 double abs2 = getRadiusOfCurvature(mytracks.getSecondPerigee(),bfield2);
192
193 const double sgnr1 = abs1>0 ? 1. : -1.;
194 const double sgnr2 = abs2>0 ? 1. : -1.;
195
196 //component x of center of curv of first particle
197 const std::pair<Amg::Vector3D,Amg::Vector3D> centersofcurv
198 (getCenterOfCurvature(mytracks.getFirstPerigee(),abs1,phitanpoca1),
199 getCenterOfCurvature(mytracks.getSecondPerigee(),abs2,phitanpoca2));
200
201#ifdef TRK2DDISTANCESEEDER_DEBUG
202 ATH_MSG_DEBUG( " Center of track number 1: " << centersofcurv.first << " center of track 2 " << centersofcurv.second );
203#endif
204
205 const double distance2d = dist2d(centersofcurv.first,centersofcurv.second);
206
207 abs1 = std::abs(abs1);
208 abs2 = std::abs(abs2);
209
210
211#ifdef TRK2DDISTANCESEEDER_DEBUG
212 ATH_MSG_DEBUG( "abs1: " << abs1 << " abs2: " << abs2 );
213 ATH_MSG_DEBUG( "phitanpoca1: " << phitanpoca1 << " phitanpoca2: " << phitanpoca2 );
214 ATH_MSG_DEBUG( "distance2d " << distance2d );
215#endif
216
217 double phi1 = 0;
218 double phi2 = 0;
219
220 // Strictly redundant with phi1 and phi2 above, but needed to get results
221 // that are rounded identically with the pre-MT version.
222 double phi1poca = 0;
223 double phi2poca = 0;
224
225 //first case (the two circles are the one distinct from the other)
226 if (distance2d > (abs1+abs2)) {
227
228#ifdef TRK2DDISTANCESEEDER_DEBUG
229 ATH_MSG_DEBUG ("Distinct circles " );
230#endif
231
232 phi1 = safeAtan2(centersofcurv.second.y()-centersofcurv.first.y(),
233 centersofcurv.second.x()-centersofcurv.first.x());
234
235 if (sgnr2<0) {
236 phi2=phi1;
237 } else {
238 phi2=oppositeangle(phi1);
239 }
240
241 if (sgnr1<0) {
242 phi1=oppositeangle(phi1);
243 }
244
245 //Now you are worried that the solution has to be the one nearest to the original phi...
246 phi1=takenearest(phi1,phitanpoca1);
247 phi2=takenearest(phi2,phitanpoca2);
248 }
249 else {
250 //second case(if distance2d<abs1+abs2 we have still two cases
251 //1) one circle inside the other (nobody is touched) (if |abs2-abs1|>d)
252 //2) two intersections (if |abs2-abs1|<d)
253 // -->(case with one intersection seems me of no physical interest)
254 if (fabs(abs2-abs1)>=distance2d) {
255
256#ifdef TRK2DDISTANCESEEDER_DEBUG
257 ATH_MSG_DEBUG( " one circle inside the other " );
258#endif
259
260 //1)
261 if (abs2<abs1) {
262
263#ifdef TRK2DDISTANCESEEDER_DEBUG
264 ATH_MSG_DEBUG(" second radius smaller than first " );
265#endif
266 phi1 = safeAtan2(centersofcurv.second.y()-centersofcurv.first.y(),
267 centersofcurv.second.x()-centersofcurv.first.x());
268 phi2=phi1;
269 }
270 else {
271
272#ifdef TRK2DDISTANCESEEDER_DEBUG
273 ATH_MSG_DEBUG( " first radius smaller than second " );
274#endif
275
276
277 phi1 = safeAtan2(-(centersofcurv.second.y()-centersofcurv.first.y()),
278 -(centersofcurv.second.x()-centersofcurv.first.x()));
279 phi2=phi1;
280 }
281
282 //adjust the sign, taking into account possible q(1,2)<0
283 if (sgnr2<0) {
284 phi2=oppositeangle(phi2);
285 }
286
287 if (sgnr1<0) {
288 phi1=oppositeangle(phi1);
289 }
290
291 phi1=takenearest(setphipoca(phi1),setphipoca(phitanpoca1));
292 phi2=takenearest(setphipoca(phi2),setphipoca(phitanpoca2));
293 phi1poca = setphipoca(phi1);
294 phi2poca = setphipoca(phi2);
295 }
296 else {
297
298 //Do it easier...
299 const double projection2=(square(abs1)-square(abs2)-square(distance2d))/2./distance2d;
300 const double cosinus2=projection2/sgnr2/abs2;
301
302
303#ifdef TRK2DDISTANCESEEDER_DEBUG
304 const double projection1=(square(abs2)-square(abs1)-square(distance2d))/2./distance2d;
305 const double cosinus1=projection1/sgnr1/abs1;
306 ATH_MSG_DEBUG( "projection1: " << projection1 << " cosinus1 " << cosinus1
307 << "projection2: " << projection2 << " cosinus2 " << cosinus2 );
308#endif
309
310 const double phibase2 =
311 safeAtan2(centersofcurv.second.y() - centersofcurv.first.y(),
312 centersofcurv.second.x() - centersofcurv.first.x());
313
314 const double addtophi2=
315 safeAcos(cosinus2);
316
317#ifdef TRK2DDISTANCESEEDER_DEBUG
318 ATH_MSG_DEBUG( " phibase2 is : " << phibase2 << " add to phi " << addtophi2 );
319#endif
320
321 const std::pair<double,double> possiblephiontrack2(phibase2+addtophi2,phibase2-addtophi2);
322
323#ifdef TRK2DDISTANCESEEDER_DEBUG
324 ATH_MSG_DEBUG( "the two phis are: " << possiblephiontrack2.first << " and " << possiblephiontrack2.second );
325#endif
326
327 const std::pair<double,double>
328 possiblecosphitrack1((centersofcurv.second.x()-centersofcurv.first.x()
329 +sgnr2*abs2*std::cos(possiblephiontrack2.first))/sgnr1/abs1,
330 (centersofcurv.second.x()-centersofcurv.first.x()
331 +sgnr2*abs2*std::cos(possiblephiontrack2.second))/sgnr1/abs1);
332
333 const std::pair<double,double>
334 possiblesigntrack1(sgnr1*(centersofcurv.second.y()-centersofcurv.first.y()
335 +sgnr2*abs2*std::sin(possiblephiontrack2.first))>0?1.:-1.,
336 sgnr1*(centersofcurv.second.y()-centersofcurv.first.y()
337 +sgnr2*abs2*std::sin(possiblephiontrack2.second))>0?1.:-1.);
338
339 const std::pair<double,double>
340 possiblephiontrack1(possiblesigntrack1.first*safeAcos(possiblecosphitrack1.first),
341 possiblesigntrack1.second*safeAcos(possiblecosphitrack1.second));
342
343
344 const std::pair<PointOnTrack,PointOnTrack>
345 possiblepointsontrack1(PointOnTrack(mytracks.getFirstPerigee(),
346 takenearest(setphipoca(possiblephiontrack1.first),
347 setphipoca(phitanpoca1))),
348 PointOnTrack(mytracks.getFirstPerigee(),
349 takenearest(setphipoca(possiblephiontrack1.second),
350 setphipoca(phitanpoca1))));
351
352 const std::pair<PointOnTrack,PointOnTrack>
353 possiblepointsontrack2(PointOnTrack(mytracks.getSecondPerigee(),
354 takenearest(setphipoca(possiblephiontrack2.first),
355 setphipoca(phitanpoca2))),
357 takenearest(setphipoca(possiblephiontrack2.second),
358 setphipoca(phitanpoca2))));
359
360
361 const std::pair<Amg::Vector3D,Amg::Vector3D>
362 possiblepoints1(getSeedPoint(possiblepointsontrack1.first.getPerigee(),centersofcurv.first,
363 abs1*sgnr1,possiblepointsontrack1.first.getPhiPoint()),
364 getSeedPoint(possiblepointsontrack1.second.getPerigee(),centersofcurv.first,
365 abs1*sgnr1,possiblepointsontrack1.second.getPhiPoint()));
366
367 const std::pair<Amg::Vector3D,Amg::Vector3D>
368 possiblepoints2(getSeedPoint(possiblepointsontrack2.first.getPerigee(),centersofcurv.second,
369 abs2*sgnr2,possiblepointsontrack2.first.getPhiPoint()),
370 getSeedPoint(possiblepointsontrack2.second.getPerigee(),centersofcurv.second,
371 abs2*sgnr2,possiblepointsontrack2.second.getPhiPoint()));
372
373
374#ifdef TRK2DDISTANCESEEDER_DEBUG
375 ATH_MSG_DEBUG( "Point 1a: x " << possiblepoints1.first.x() << " y " << possiblepoints1.first.y() );
376 ATH_MSG_DEBUG( "Point 2a: x " << possiblepoints2.first.x() << " y " << possiblepoints2.first.y() );
377 ATH_MSG_DEBUG( "Point 1b: x " << possiblepoints1.second.x() << " y " << possiblepoints1.second.y() );
378 ATH_MSG_DEBUG( "Point 2b: x " << possiblepoints2.second.x() << " y " << possiblepoints2.second.y() );
379 ATH_MSG_DEBUG( "Distance between 1a and 2a:" << fabs(possiblepoints1.first.z()-possiblepoints2.first.z()) <<
380 "Distance between 1a and 2a:" << fabs(possiblepoints1.second.z()-possiblepoints2.second.z()) );
381#endif
382
383
384 //now discover what couple of points are the nearest ones
386 {
387 if (fabs(possiblepoints1.first.z()-possiblepoints2.first.z())<
388 fabs(possiblepoints1.second.z()-possiblepoints2.second.z()))
389 {
390 phi1poca = possiblepointsontrack1.first.getPhiPoint();
391 phi2poca = possiblepointsontrack2.first.getPhiPoint();
392 } else {
393 phi1poca = possiblepointsontrack1.second.getPhiPoint();
394 phi2poca = possiblepointsontrack2.second.getPhiPoint();
395 }
396 }
397 else
398 {
399 if (sqrt(possiblepoints1.first.x()*possiblepoints1.first.x()+possiblepoints1.first.y()*possiblepoints1.first.y())<
400 sqrt(possiblepoints2.first.x()*possiblepoints2.first.x()+possiblepoints2.first.y()*possiblepoints2.first.y()))
401 {
402 phi1poca = possiblepointsontrack1.first.getPhiPoint();
403 phi2poca = possiblepointsontrack2.first.getPhiPoint();
404 } else {
405 phi1poca = possiblepointsontrack1.second.getPhiPoint();
406 phi2poca = possiblepointsontrack2.second.getPhiPoint();
407 }
408 }
409 phi1=goFromPhipocaToPhi(phi1poca);
410 phi2=goFromPhipocaToPhi(phi2poca);
411 }
412 }
413
414 if (twopoints) {
415 *twopoints = TwoPoints (getSeedPoint(centersofcurv.first,
416 abs1*sgnr1,setphipoca(phi1)),
417 getSeedPoint(centersofcurv.second,
418 abs2*sgnr2,setphipoca(phi2)));
419 }
420
421 return std::make_pair (PointOnTrack (mytracks.getFirstPerigee(), phi1poca),
422 PointOnTrack (mytracks.getSecondPerigee(),phi2poca));
423 }
424
425
427 {
428 double magnFieldVect[3];
429 double posXYZ[3];
430 posXYZ[0] = p.associatedSurface().center().x();
431 posXYZ[1] = p.associatedSurface().center().y();
432 posXYZ[2] = p.associatedSurface().center().z();
433
434 cache.getField(posXYZ,magnFieldVect);
435 const double bfield = magnFieldVect[2]*299.792;//should be in GeV/mm
436 if (bfield==0. || std::isnan(bfield)) {
437 ATH_MSG_DEBUG( "Could not find a magnetic field different from zero: very very strange" );
438 return 0.60407; //Value in GeV/mm (ATLAS units)
439 }
440 ATH_MSG_DEBUG( "Magnetic field projection of z axis in the perigee position is: " << bfield << " GeV/mm " );
441
442 return bfield;
443 }
444
445
446} // namespace Trk
#define M_PI
Scalar phi() const
phi method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_DEBUG(x)
static Double_t a
double angle(const GeoTrf::Vector2D &a, const GeoTrf::Vector2D &b)
#define y
#define x
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
void getInitializedCache(MagField::AtlasFieldCache &cache) const
get B field cache for evaluation as a function of 2-d or 3-d position.
Local cache for magnetic field (based on MagFieldServices/AtlasFieldSvcTLS.h).
virtual const S & associatedSurface() const override final
Access to the Surface method.
const Amg::Vector3D & center() const
Returns the center position of the Surface.
double getBField(const Perigee &p, MagField::AtlasFieldCache &cache) const
virtual StatusCode finalize() override
TwoPointOnTrack GetSeed(const TwoTracks &mytracks, TwoPoints *twopoints=nullptr) const
virtual StatusCode initialize() override
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_fieldCacheCondObjInputKey
Trk2dDistanceSeeder(const std::string &t, const std::string &n, const IInterface *p)
const Perigee & getSecondPerigee() const
Definition TwoTracks.cxx:21
const Perigee & getFirstPerigee() const
Definition TwoTracks.cxx:17
Eigen::Matrix< double, 3, 1 > Vector3D
Ensure that the ATLAS eigen extensions are properly loaded.
ParametersT< TrackParametersDim, Charged, PerigeeSurface > Perigee
@ phi0
Definition ParamDefs.h:65
@ theta
Definition ParamDefs.h:66
@ qOverP
perigee
Definition ParamDefs.h:67
@ d0
Definition ParamDefs.h:63
@ z0
Definition ParamDefs.h:64
std::pair< PointOnTrack, PointOnTrack > TwoPointOnTrack
std::pair< Amg::Vector3D, Amg::Vector3D > TwoPoints
const IIntersectionCache * cache() const
Retrieve the associated cache block, if it exists.
#define unlikely(x)