ATLAS Offline Software
Loading...
Searching...
No Matches
Trk2dDistanceSeeder.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2021 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
175 MagField::AtlasFieldCache fieldCache;
176 fieldCondObj->getInitializedCache (fieldCache);
177
178 const double bfield1 = getBField (mytracks.getFirstPerigee(), fieldCache);
179 const double bfield2 = getBField (mytracks.getSecondPerigee(), fieldCache);
180
181 //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
182 //why I chose this strange name, sorry!)
183 const double phitanpoca1=getphipoca(mytracks.getFirstPerigee());
184 const double phitanpoca2=getphipoca(mytracks.getSecondPerigee());
185
186 //Temporary abs1 and abs2 are the signed radius quantities (later we will reduce it to unsigned quantities)
187 double abs1 = getRadiusOfCurvature(mytracks.getFirstPerigee(), bfield1);
188 double abs2 = getRadiusOfCurvature(mytracks.getSecondPerigee(),bfield2);
189
190 const double sgnr1 = abs1>0 ? 1. : -1.;
191 const double sgnr2 = abs2>0 ? 1. : -1.;
192
193 //component x of center of curv of first particle
194 const std::pair<Amg::Vector3D,Amg::Vector3D> centersofcurv
195 (getCenterOfCurvature(mytracks.getFirstPerigee(),abs1,phitanpoca1),
196 getCenterOfCurvature(mytracks.getSecondPerigee(),abs2,phitanpoca2));
197
198#ifdef TRK2DDISTANCESEEDER_DEBUG
199 ATH_MSG_DEBUG( " Center of track number 1: " << centersofcurv.first << " center of track 2 " << centersofcurv.second );
200#endif
201
202 const double distance2d = dist2d(centersofcurv.first,centersofcurv.second);
203
204 abs1 = std::abs(abs1);
205 abs2 = std::abs(abs2);
206
207
208#ifdef TRK2DDISTANCESEEDER_DEBUG
209 ATH_MSG_DEBUG( "abs1: " << abs1 << " abs2: " << abs2 );
210 ATH_MSG_DEBUG( "phitanpoca1: " << phitanpoca1 << " phitanpoca2: " << phitanpoca2 );
211 ATH_MSG_DEBUG( "distance2d " << distance2d );
212#endif
213
214 double phi1 = 0;
215 double phi2 = 0;
216
217 // Strictly redundant with phi1 and phi2 above, but needed to get results
218 // that are rounded identically with the pre-MT version.
219 double phi1poca = 0;
220 double phi2poca = 0;
221
222 //first case (the two circles are the one distinct from the other)
223 if (distance2d > (abs1+abs2)) {
224
225#ifdef TRK2DDISTANCESEEDER_DEBUG
226 ATH_MSG_DEBUG ("Distinct circles " );
227#endif
228
229 phi1 = safeAtan2(centersofcurv.second.y()-centersofcurv.first.y(),
230 centersofcurv.second.x()-centersofcurv.first.x());
231
232 if (sgnr2<0) {
233 phi2=phi1;
234 } else {
235 phi2=oppositeangle(phi1);
236 }
237
238 if (sgnr1<0) {
239 phi1=oppositeangle(phi1);
240 }
241
242 //Now you are worried that the solution has to be the one nearest to the original phi...
243 phi1=takenearest(phi1,phitanpoca1);
244 phi2=takenearest(phi2,phitanpoca2);
245 }
246 else {
247 //second case(if distance2d<abs1+abs2 we have still two cases
248 //1) one circle inside the other (nobody is touched) (if |abs2-abs1|>d)
249 //2) two intersections (if |abs2-abs1|<d)
250 // -->(case with one intersection seems me of no physical interest)
251 if (fabs(abs2-abs1)>=distance2d) {
252
253#ifdef TRK2DDISTANCESEEDER_DEBUG
254 ATH_MSG_DEBUG( " one circle inside the other " );
255#endif
256
257 //1)
258 if (abs2<abs1) {
259
260#ifdef TRK2DDISTANCESEEDER_DEBUG
261 ATH_MSG_DEBUG(" second radius smaller than first " );
262#endif
263 phi1 = safeAtan2(centersofcurv.second.y()-centersofcurv.first.y(),
264 centersofcurv.second.x()-centersofcurv.first.x());
265 phi2=phi1;
266 }
267 else {
268
269#ifdef TRK2DDISTANCESEEDER_DEBUG
270 ATH_MSG_DEBUG( " first radius smaller than second " );
271#endif
272
273
274 phi1 = safeAtan2(-(centersofcurv.second.y()-centersofcurv.first.y()),
275 -(centersofcurv.second.x()-centersofcurv.first.x()));
276 phi2=phi1;
277 }
278
279 //adjust the sign, taking into account possible q(1,2)<0
280 if (sgnr2<0) {
281 phi2=oppositeangle(phi2);
282 }
283
284 if (sgnr1<0) {
285 phi1=oppositeangle(phi1);
286 }
287
288 phi1=takenearest(setphipoca(phi1),setphipoca(phitanpoca1));
289 phi2=takenearest(setphipoca(phi2),setphipoca(phitanpoca2));
290 phi1poca = setphipoca(phi1);
291 phi2poca = setphipoca(phi2);
292 }
293 else {
294
295 //Do it easier...
296 const double projection2=(square(abs1)-square(abs2)-square(distance2d))/2./distance2d;
297 const double cosinus2=projection2/sgnr2/abs2;
298
299
300#ifdef TRK2DDISTANCESEEDER_DEBUG
301 const double projection1=(square(abs2)-square(abs1)-square(distance2d))/2./distance2d;
302 const double cosinus1=projection1/sgnr1/abs1;
303 ATH_MSG_DEBUG( "projection1: " << projection1 << " cosinus1 " << cosinus1
304 << "projection2: " << projection2 << " cosinus2 " << cosinus2 );
305#endif
306
307 const double phibase2 =
308 safeAtan2(centersofcurv.second.y() - centersofcurv.first.y(),
309 centersofcurv.second.x() - centersofcurv.first.x());
310
311 const double addtophi2=
312 safeAcos(cosinus2);
313
314#ifdef TRK2DDISTANCESEEDER_DEBUG
315 ATH_MSG_DEBUG( " phibase2 is : " << phibase2 << " add to phi " << addtophi2 );
316#endif
317
318 const std::pair<double,double> possiblephiontrack2(phibase2+addtophi2,phibase2-addtophi2);
319
320#ifdef TRK2DDISTANCESEEDER_DEBUG
321 ATH_MSG_DEBUG( "the two phis are: " << possiblephiontrack2.first << " and " << possiblephiontrack2.second );
322#endif
323
324 const std::pair<double,double>
325 possiblecosphitrack1((centersofcurv.second.x()-centersofcurv.first.x()
326 +sgnr2*abs2*std::cos(possiblephiontrack2.first))/sgnr1/abs1,
327 (centersofcurv.second.x()-centersofcurv.first.x()
328 +sgnr2*abs2*std::cos(possiblephiontrack2.second))/sgnr1/abs1);
329
330 const std::pair<double,double>
331 possiblesigntrack1(sgnr1*(centersofcurv.second.y()-centersofcurv.first.y()
332 +sgnr2*abs2*std::sin(possiblephiontrack2.first))>0?1.:-1.,
333 sgnr1*(centersofcurv.second.y()-centersofcurv.first.y()
334 +sgnr2*abs2*std::sin(possiblephiontrack2.second))>0?1.:-1.);
335
336 const std::pair<double,double>
337 possiblephiontrack1(possiblesigntrack1.first*safeAcos(possiblecosphitrack1.first),
338 possiblesigntrack1.second*safeAcos(possiblecosphitrack1.second));
339
340
341 const std::pair<PointOnTrack,PointOnTrack>
342 possiblepointsontrack1(PointOnTrack(mytracks.getFirstPerigee(),
343 takenearest(setphipoca(possiblephiontrack1.first),
344 setphipoca(phitanpoca1))),
345 PointOnTrack(mytracks.getFirstPerigee(),
346 takenearest(setphipoca(possiblephiontrack1.second),
347 setphipoca(phitanpoca1))));
348
349 const std::pair<PointOnTrack,PointOnTrack>
350 possiblepointsontrack2(PointOnTrack(mytracks.getSecondPerigee(),
351 takenearest(setphipoca(possiblephiontrack2.first),
352 setphipoca(phitanpoca2))),
354 takenearest(setphipoca(possiblephiontrack2.second),
355 setphipoca(phitanpoca2))));
356
357
358 const std::pair<Amg::Vector3D,Amg::Vector3D>
359 possiblepoints1(getSeedPoint(possiblepointsontrack1.first.getPerigee(),centersofcurv.first,
360 abs1*sgnr1,possiblepointsontrack1.first.getPhiPoint()),
361 getSeedPoint(possiblepointsontrack1.second.getPerigee(),centersofcurv.first,
362 abs1*sgnr1,possiblepointsontrack1.second.getPhiPoint()));
363
364 const std::pair<Amg::Vector3D,Amg::Vector3D>
365 possiblepoints2(getSeedPoint(possiblepointsontrack2.first.getPerigee(),centersofcurv.second,
366 abs2*sgnr2,possiblepointsontrack2.first.getPhiPoint()),
367 getSeedPoint(possiblepointsontrack2.second.getPerigee(),centersofcurv.second,
368 abs2*sgnr2,possiblepointsontrack2.second.getPhiPoint()));
369
370
371#ifdef TRK2DDISTANCESEEDER_DEBUG
372 ATH_MSG_DEBUG( "Point 1a: x " << possiblepoints1.first.x() << " y " << possiblepoints1.first.y() );
373 ATH_MSG_DEBUG( "Point 2a: x " << possiblepoints2.first.x() << " y " << possiblepoints2.first.y() );
374 ATH_MSG_DEBUG( "Point 1b: x " << possiblepoints1.second.x() << " y " << possiblepoints1.second.y() );
375 ATH_MSG_DEBUG( "Point 2b: x " << possiblepoints2.second.x() << " y " << possiblepoints2.second.y() );
376 ATH_MSG_DEBUG( "Distance between 1a and 2a:" << fabs(possiblepoints1.first.z()-possiblepoints2.first.z()) <<
377 "Distance between 1a and 2a:" << fabs(possiblepoints1.second.z()-possiblepoints2.second.z()) );
378#endif
379
380
381 //now discover what couple of points are the nearest ones
383 {
384 if (fabs(possiblepoints1.first.z()-possiblepoints2.first.z())<
385 fabs(possiblepoints1.second.z()-possiblepoints2.second.z()))
386 {
387 phi1poca = possiblepointsontrack1.first.getPhiPoint();
388 phi2poca = possiblepointsontrack2.first.getPhiPoint();
389 } else {
390 phi1poca = possiblepointsontrack1.second.getPhiPoint();
391 phi2poca = possiblepointsontrack2.second.getPhiPoint();
392 }
393 }
394 else
395 {
396 if (sqrt(possiblepoints1.first.x()*possiblepoints1.first.x()+possiblepoints1.first.y()*possiblepoints1.first.y())<
397 sqrt(possiblepoints2.first.x()*possiblepoints2.first.x()+possiblepoints2.first.y()*possiblepoints2.first.y()))
398 {
399 phi1poca = possiblepointsontrack1.first.getPhiPoint();
400 phi2poca = possiblepointsontrack2.first.getPhiPoint();
401 } else {
402 phi1poca = possiblepointsontrack1.second.getPhiPoint();
403 phi2poca = possiblepointsontrack2.second.getPhiPoint();
404 }
405 }
406 phi1=goFromPhipocaToPhi(phi1poca);
407 phi2=goFromPhipocaToPhi(phi2poca);
408 }
409 }
410
411 if (twopoints) {
412 *twopoints = TwoPoints (getSeedPoint(centersofcurv.first,
413 abs1*sgnr1,setphipoca(phi1)),
414 getSeedPoint(centersofcurv.second,
415 abs2*sgnr2,setphipoca(phi2)));
416 }
417
418 return std::make_pair (PointOnTrack (mytracks.getFirstPerigee(), phi1poca),
419 PointOnTrack (mytracks.getSecondPerigee(),phi2poca));
420 }
421
422
424 {
425 double magnFieldVect[3];
426 double posXYZ[3];
427 posXYZ[0] = p.associatedSurface().center().x();
428 posXYZ[1] = p.associatedSurface().center().y();
429 posXYZ[2] = p.associatedSurface().center().z();
430
431 cache.getField(posXYZ,magnFieldVect);
432 const double bfield = magnFieldVect[2]*299.792;//should be in GeV/mm
433 if (bfield==0. || std::isnan(bfield)) {
434 ATH_MSG_DEBUG( "Could not find a magnetic field different from zero: very very strange" );
435 return 0.60407; //Value in GeV/mm (ATLAS units)
436 }
437 ATH_MSG_DEBUG( "Magnetic field projection of z axis in the perigee position is: " << bfield << " GeV/mm " );
438
439 return bfield;
440 }
441
442
443} // namespace Trk
#define M_PI
Scalar phi() const
phi method
#define ATH_CHECK
Evaluate an expression and check for errors.
#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)
void getField(const double *ATH_RESTRICT xyz, double *ATH_RESTRICT bxyz, double *ATH_RESTRICT deriv=nullptr)
get B field value at given position xyz[3] is in mm, bxyz[3] is in kT if deriv[9] is given,...
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