ATLAS Offline Software
NewtonTrkDistanceFinder.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 /*********************************************************************
6  NewtonTrkDistanceFinder.cxx - Description in header file
7 *********************************************************************/
8 
9 //#define TrkDistance_DEBUG
10 
11 #include "GaudiKernel/EventContext.h"
12 
15 
17 
19 #include <cmath>
20 
21 
22 
23 namespace {
24  inline double getRadiusOfCurvature(const Trk::Perigee & myPerigee,const double Bzfield) {
25  return sin(myPerigee.parameters()[Trk::theta])/(Bzfield*myPerigee.parameters()[Trk::qOverP]);
26  }
27 }
28 
29 namespace Trk
30 {
31  NewtonTrkDistanceFinder::NewtonTrkDistanceFinder(const std::string& t, const std::string& n, const IInterface* p) :
32  AthAlgTool(t,n,p),
33  m_precision(1e-8),
34  m_maxloopnumber(20)
35  {
36  declareProperty("Precision",m_precision);
37  declareProperty("MaxLoops",m_maxloopnumber);
38  declareInterface<NewtonTrkDistanceFinder>(this);
39  }
40 
42 
44  {
47  ATH_MSG_DEBUG( "Initialize successful" );
48  return StatusCode::SUCCESS;
49  }
51  {
52  ATH_MSG_DEBUG( "Finalize successful" );
53  return StatusCode::SUCCESS;
54  }
55 
56 std::variant<TwoPoints, std::string>
58  const PointOnTrack & secondtrack) const
59 {
60  //Now the direction of momentum at point of closest approach (but only direction, not versus)
61  const double a_phi0 = firsttrack.getPerigee().parameters()[Trk::phi0];
62  const double a_cosphi0 = -sin(a_phi0);//do i need it?
63  const double a_sinphi0 = cos(a_phi0);//~?
64 
65  //Now initialize the variable you need to go on
66  const double a_x0=firsttrack.getPerigee().associatedSurface().center().x() +
67  firsttrack.getPerigee().parameters()[Trk::d0]*a_cosphi0;
68  const double a_y0=firsttrack.getPerigee().associatedSurface().center().y() +
69  firsttrack.getPerigee().parameters()[Trk::d0]*a_sinphi0;
70  const double a_z0=firsttrack.getPerigee().associatedSurface().center().z() +
71  firsttrack.getPerigee().parameters()[Trk::z0];
72 
73 #ifdef TrkDistance_DEBUG
74  ATH_MSG_DEBUG( "a_x0 " << a_x0 << " a_y0 " << a_y0 << " a_z0 " << a_z0 );
75  ATH_MSG_DEBUG( "m_a_phi0 " << a_phi0 );
76 #endif
77 
78  // Setup magnetic field retrieval
79  SG::ReadCondHandle<AtlasFieldCacheCondObj> readHandle{m_fieldCacheCondObjInputKey, Gaudi::Hive::currentContext()};
80  const AtlasFieldCacheCondObj* fieldCondObj{*readHandle};
81 
82  MagField::AtlasFieldCache fieldCache;
83  fieldCondObj->getInitializedCache (fieldCache);
84 
85  double magnFieldVect[3];
86  double posXYZ[3];
87  posXYZ[0] = firsttrack.getPerigee().associatedSurface().center().x();
88  posXYZ[1] = firsttrack.getPerigee().associatedSurface().center().y();
89  posXYZ[2] = firsttrack.getPerigee().associatedSurface().center().z();
90  fieldCache.getField(posXYZ,magnFieldVect);
91 
92 
93  //Magnetic field at (x0,y0,z0)
94  const double a_Bz=magnFieldVect[2]*299.792;//B field in Gev/mm
95  //EvaluateMagneticField(a_x0,b_y0,b_z0);
96 
97  const double a_Rt = getRadiusOfCurvature(firsttrack.getPerigee(),a_Bz);
98  const double a_cotantheta = 1./tan(firsttrack.getPerigee().parameters()[Trk::theta]);
99 
100 #ifdef TrkDistance_DEBUG
101  ATH_MSG_DEBUG( "a_Rt" << a_Rt << " a_cotantheta " << a_cotantheta );
102  ATH_MSG_DEBUG( "Magnetic field at perigee is " << a_Bz << "GeV/mm " );
103 #endif
104 
105  //Now the direction of momentum at point of closest approach (but only direction, not versus)
106  const double b_phi0 = secondtrack.getPerigee().parameters()[Trk::phi0];
107  const double b_cosphi0 = -sin(b_phi0);//do i need it?
108  const double b_sinphi0 = cos(b_phi0);//~?
109 
110  //Now initialize the variable you need to go on
111  const double b_x0=secondtrack.getPerigee().associatedSurface().center().x() +
112  secondtrack.getPerigee().parameters()[Trk::d0]*b_cosphi0;
113  const double b_y0=secondtrack.getPerigee().associatedSurface().center().y() +
114  secondtrack.getPerigee().parameters()[Trk::d0]*b_sinphi0;
115  const double b_z0=secondtrack.getPerigee().associatedSurface().center().z() +
116  secondtrack.getPerigee().parameters()[Trk::z0];
117 
118 #ifdef TrkDistance_DEBUG
119  ATH_MSG_DEBUG( "b_x0 " << b_x0 << " b_y0 " << b_y0 << " b_z0 " << b_z0 );
120  ATH_MSG_DEBUG( "b_phi0 " << b_phi0 );
121 #endif
122 
123 
124  posXYZ[0] = secondtrack.getPerigee().associatedSurface().center().x();
125  posXYZ[1] = secondtrack.getPerigee().associatedSurface().center().y();
126  posXYZ[2] = secondtrack.getPerigee().associatedSurface().center().z();
127  fieldCache.getField(posXYZ,magnFieldVect);
128 
129  //Magnetic field at (x0,y0,z0)
130  const double b_Bz = magnFieldVect[2]*299.792;//B field in Gev/mm - for the moment use a constant field offline
131  //use the right value expressed in GeV
132  //EvaluateMagneticField(b_x0,b_y0,b_z0);
133 
134  const double b_Rt = getRadiusOfCurvature(secondtrack.getPerigee(),b_Bz);
135  const double b_cotantheta = 1./tan(secondtrack.getPerigee().parameters()[Trk::theta]);
136 
137 #ifdef TrkDistance_DEBUG
138  ATH_MSG_DEBUG( "b_Rt" << b_Rt << " b_cotantheta " << b_cotantheta );
139  ATH_MSG_DEBUG( "Magnetic field at perigee is " << b_Bz << " GeV/mm " );
140 #endif
141 
142 
143  //Now prepare some more elaborate pieces for later
144  const double ab_Dx0 = a_x0-b_x0-a_Rt*a_cosphi0+b_Rt*b_cosphi0;
145  const double ab_Dy0 = a_y0-b_y0-a_Rt*a_sinphi0+b_Rt*b_sinphi0;
146  const double ab_Dz0 = a_z0-b_z0+a_Rt*a_cotantheta*a_phi0-b_Rt*b_cotantheta*b_phi0;
147 
148 #ifdef TrkDistance_DEBUG
149  ATH_MSG_DEBUG( "ab_Dx0 " << ab_Dx0 << " ab_Dy0 " << ab_Dy0 << " ab_Dz0 " << ab_Dz0 );
150 #endif
151 
152 
153  //Prepare the initial point that can be different from point of closest approach
154  //If you don't specify any point the default will be the point of closest approach!!
155  //Another subroutine will be implemented if you want to use
156  //a certain seed
157  double a_phi = firsttrack.getPhiPoint();//this has to be corrected as soon as you adjust the Trk2dDistanceSeeder...
158  double b_phi = secondtrack.getPhiPoint();
159 
160  //store cos and sin of phi
161  double a_cosphi = -sin(a_phi);
162  double a_sinphi = cos(a_phi);
163  double b_cosphi = -sin(b_phi);
164  double b_sinphi = cos(b_phi);
165 
166 
167 #ifdef TrkDistance_DEBUG
168  ATH_MSG_DEBUG( "Beginning phi is a_phi: " << a_phi << " b_phi " << b_phi );
169  ATH_MSG_DEBUG( "LOOP number 0" );
170 #endif
171 
172 
173  int loopsnumber = 0;
174 
175  bool isok=false;
176 
177  while (!isok) {
178 
179 #ifdef TrkDistance_DEBUG
180  ATH_MSG_DEBUG( "Entered LOOP number: " << loopsnumber );
181  ATH_MSG_DEBUG( "actual value of a_phi: " << a_phi << " of b_phi " << b_phi );
182 #endif
183 
184 
185  //count the loop number
186  ++loopsnumber;
187 
188 
189 #ifdef TrkDistance_DEBUG
190  ATH_MSG_DEBUG( "First point x: " << GetClosestPoints().first.x()
191  << "y: " << GetClosestPoints().first.y()
192  << "z: " << GetClosestPoints().first.z() );
193  ATH_MSG_DEBUG( << "Second point x: " << GetClosestPoints().second.x()
194  << "y: " << GetClosestPoints().second.y()
195  << "z: " << GetClosestPoints().second.z() );
196 
197  ATH_MSG_DEBUG( "ActualDistance: " << GetDistance() );
198  ATH_MSG_DEBUG( "real Dx0 " << ab_Dx0+a_Rt*a_cosphi-b_Rt*b_cosphi );
199  ATH_MSG_DEBUG( "real Dy0 " << ab_Dy0+a_Rt*a_sinphi-b_Rt*b_sinphi );
200 #endif
201 
202  //I remove the factor two from the formula
203  const double d1da_phi =
204  (ab_Dx0-b_Rt*b_cosphi)*(-a_Rt*a_sinphi)+
205  (ab_Dy0-b_Rt*b_sinphi)*a_cosphi*a_Rt+
206  (ab_Dz0-a_Rt*a_cotantheta*a_phi+b_Rt*b_cotantheta*b_phi)*(-a_Rt*a_cotantheta);
207 
208 
209  //same for second deriv respective to phi
210  const double d1db_phi =
211  (ab_Dx0+a_Rt*a_cosphi)*b_Rt*b_sinphi-//attention!MINUS here
212  (ab_Dy0+a_Rt*a_sinphi)*b_cosphi*b_Rt+
213  (ab_Dz0-a_Rt*a_cotantheta*a_phi+b_Rt*b_cotantheta*b_phi)*(+b_Rt*b_cotantheta);
214 
215  //second derivatives (d^2/d^2(a) d^2/d^2(b) d^2/d(a)d(b) )
216 
217  const double d2da_phi2 =
218  (ab_Dx0-b_Rt*b_cosphi)*(-a_Rt*a_cosphi)+
219  (ab_Dy0-b_Rt*b_sinphi)*(-a_Rt*a_sinphi)+
220  +a_Rt*a_Rt*(a_cotantheta*a_cotantheta);
221 
222  const double d2db_phi2 =
223  (ab_Dx0+a_Rt*a_cosphi)*(+b_Rt*b_cosphi)+
224  (ab_Dy0+a_Rt*a_sinphi)*(+b_Rt*b_sinphi)+
225  +b_Rt*b_Rt*(b_cotantheta*b_cotantheta);
226 
227 
228  const double d2da_phib_phi = -a_Rt*b_Rt*(a_sinphi*b_sinphi+a_cosphi*b_cosphi+a_cotantheta*b_cotantheta);
229 
230  //Calculate the determinant of the Jacobian
231 
232  const double det = d2da_phi2*d2db_phi2-d2da_phib_phi*d2da_phib_phi;
233 
234 
235 #ifdef TrkDistance_DEBUG
236  ATH_MSG_DEBUG( "d1da_phi " << d1da_phi << " d1db_phi " << d1db_phi << " d2da_phi2 " << d2da_phi2 << " d2db_phi2 " << d2db_phi2
237  << " d2da_phib_phi " << d2da_phib_phi << " det " << det );
238 #endif
239 
240  //if the quadratic form is defined negative or is semidefined, throw the event
241  //(you are in a maximum or in a saddle point)
242  if (det<0) {
243  ATH_MSG_DEBUG( "Hessian is negative: saddle point" );
244  return "Hessian is negative";
245  }
246  if (det>0&&d2da_phi2<0) {
247  ATH_MSG_DEBUG( "Hessian indicates a maximum: derivative will be zero but result incorrect" );
248  return "Maximum point found";
249  }
250 
251  //Now apply the Newton formula in more than one dimension
252  const double deltaa_phi = -(d2db_phi2*d1da_phi-d2da_phib_phi*d1db_phi)/det;
253  const double deltab_phi = -(-d2da_phib_phi*d1da_phi+d2da_phi2*d1db_phi)/det;
254 
255 #ifdef TrkDistance_DEBUG
256  ATH_MSG_DEBUG( "deltaa_phi: " << deltaa_phi );
257  ATH_MSG_DEBUG( "deltab_phi: " << deltab_phi );
258 #endif
259 
260 
261  a_phi += deltaa_phi;
262  b_phi += deltab_phi;
263 
264  //store cos and sin of phi
265  a_cosphi = -sin(a_phi);
266  a_sinphi = cos(a_phi);
267  b_cosphi = -sin(b_phi);
268  b_sinphi = cos(b_phi);
269 
270  if (std::sqrt(std::pow(deltaa_phi,2)+std::pow(deltab_phi,2))<m_precision ||
271  loopsnumber>m_maxloopnumber) isok=true;
272 
273  }
274 
275  if (loopsnumber>m_maxloopnumber) {
276  return "Could not find minimum distance: max loops number reached"; //now return error, see how to do it...
277  }
278 
279 
280  return TwoPoints(Amg::Vector3D(a_x0+a_Rt*(a_cosphi-a_cosphi0),
281  a_y0+a_Rt*(a_sinphi-a_sinphi0),
282  a_z0-a_Rt*(a_phi-a_phi0)*a_cotantheta),
283  Amg::Vector3D(b_x0+b_Rt*(b_cosphi-b_cosphi0),
284  b_y0+b_Rt*(b_sinphi-b_sinphi0),
285  b_z0-b_Rt*(b_phi-b_phi0)*b_cotantheta));
286 }
287 
288 
289 } // namespace Trk
python.SystemOfUnits.second
int second
Definition: SystemOfUnits.py:120
Trk::NewtonTrkDistanceFinder::m_precision
double m_precision
Definition: NewtonTrkDistanceFinder.h:76
python.PerfMonSerializer.p
def p
Definition: PerfMonSerializer.py:743
SG::ReadCondHandle
Definition: ReadCondHandle.h:44
AtlasFieldCacheCondObj
Definition: AtlasFieldCacheCondObj.h:19
AthCommonDataStore< AthCommonMsg< AlgTool > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
Trk::ParametersT
Dummy class used to allow special convertors to be called for surfaces owned by a detector element.
Definition: EMErrorDetail.h:25
initialize
void initialize()
Definition: run_EoverP.cxx:894
Trk::PointOnTrack::getPhiPoint
double getPhiPoint() const
Definition: PointOnTrack.cxx:24
Trk::NewtonTrkDistanceFinder::NewtonTrkDistanceFinder
NewtonTrkDistanceFinder(const std::string &t, const std::string &n, const IInterface *p)
Definition: NewtonTrkDistanceFinder.cxx:31
conifer::pow
constexpr int pow(int x)
Definition: conifer.h:20
Trk::z0
@ z0
Definition: ParamDefs.h:70
Trk::TwoPoints
std::pair< Amg::Vector3D, Amg::Vector3D > TwoPoints
Definition: SeedFinderParamDefs.h:20
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
drawFromPickle.cos
cos
Definition: drawFromPickle.py:36
ParamDefs.h
Trk::NewtonTrkDistanceFinder::finalize
virtual StatusCode finalize() override
Definition: NewtonTrkDistanceFinder.cxx:50
Trk::NewtonTrkDistanceFinder::~NewtonTrkDistanceFinder
virtual ~NewtonTrkDistanceFinder()
Trk::ParametersT::associatedSurface
virtual const S & associatedSurface() const override final
Access to the Surface method.
Trk::NewtonTrkDistanceFinder::GetClosestPoints
std::variant< TwoPoints, std::string > GetClosestPoints(const Perigee &a, const Perigee &b) const
Definition: NewtonTrkDistanceFinder.h:55
beamspotman.n
n
Definition: beamspotman.py:731
Trk::theta
@ theta
Definition: ParamDefs.h:72
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
WritePulseShapeToCool.det
det
Definition: WritePulseShapeToCool.py:204
AtlasFieldCache.h
NewtonTrkDistanceFinder.h
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
drawFromPickle.tan
tan
Definition: drawFromPickle.py:36
python.compareTCTs.isok
isok
Definition: compareTCTs.py:350
Trk
Ensure that the ATLAS eigen extensions are properly loaded.
Definition: FakeTrackBuilder.h:9
Trk::d0
@ d0
Definition: ParamDefs.h:69
SeedFinderParamDefs.h
SG::CondHandleKey::initialize
StatusCode initialize(bool used=true)
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
Trk::PointOnTrack::getPerigee
const Perigee & getPerigee() const
Definition: PointOnTrack.cxx:20
Trk::NewtonTrkDistanceFinder::m_fieldCacheCondObjInputKey
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_fieldCacheCondObjInputKey
Definition: NewtonTrkDistanceFinder.h:81
Trk::PointOnTrack
Definition: PointOnTrack.h:13
DiTauMassTools::MaxHistStrategyV2::e
e
Definition: PhysicsAnalysis/TauID/DiTauMassTools/DiTauMassTools/HelperFunctions.h:26
Trk::NewtonTrkDistanceFinder::m_maxloopnumber
double m_maxloopnumber
Definition: NewtonTrkDistanceFinder.h:77
DeMoScan.first
bool first
Definition: DeMoScan.py:534
Trk::NewtonTrkDistanceFinder::initialize
virtual StatusCode initialize() override
Definition: NewtonTrkDistanceFinder.cxx:43
MagField::AtlasFieldCache
Local cache for magnetic field (based on MagFieldServices/AtlasFieldSvcTLS.h)
Definition: AtlasFieldCache.h:43
Trk::qOverP
@ qOverP
perigee
Definition: ParamDefs.h:73
MagField::AtlasFieldCache::getField
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,...
Definition: AtlasFieldCache.cxx:42
drawFromPickle.sin
sin
Definition: drawFromPickle.py:36
AthAlgTool
Definition: AthAlgTool.h:26
Trk::phi0
@ phi0
Definition: ParamDefs.h:71