ATLAS Offline Software
Loading...
Searching...
No Matches
FullLinearizedTrackFactory.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 FullPerigeeLinearizedTrackFactory.cxx - Description in header file
7*********************************************************************/
8
10
13
16
20#include <numbers>
21
22namespace Trk
23{
24
25 FullLinearizedTrackFactory::FullLinearizedTrackFactory(const std::string& t, const std::string& n, const IInterface* p) :
26 AthAlgTool(t,n,p),m_extrapolator("Trk::Extrapolator", this)
27 {
28 declareProperty("Extrapolator", m_extrapolator);
29 declareInterface<IVertexLinearizedTrackFactory>(this);
30 }
31
33
35 {
36
37 ATH_CHECK( m_extrapolator.retrieve() );
39
40 return StatusCode::SUCCESS;
41 }
42
44 {
45 if (theTrack.initialPerigee())
46 theTrack.setLinTrack(linearizedTrack(theTrack.initialPerigee(),linPoint));
47 else
48 theTrack.setLinTrack(linearizedTrack(theTrack.initialNeutralPerigee(),linPoint));
49 }
50
52 const Amg::Vector3D& linPoint) const {
53 if (!trackPars) return nullptr;
54 //perigee surface
55 Amg::Vector3D lp =linPoint;
56 const PerigeeSurface perigeeSurface(lp);
57
58//Remove matherial changes. Trying to understand where the perigee currently is and
59//whether we need to add or remove material during extrapolation.
60//Obvious case is the extrapolation form the perigee point: add in the direction
61//opposite to momentum; remove along the momentum.
62
63 const Amg::Vector3D gMomentum = trackPars->momentum();
64 const Amg::Vector3D gDirection = trackPars->position() - lp;
65 const double extrapolationDirection = gMomentum.dot( gDirection);
66 MaterialUpdateMode mode = (extrapolationDirection < 0) ?
67 Trk::addNoise : // parameters upstream of vertex
68 Trk::removeNoise ; // parameters downstream of vertex -> go back
69
70 const TrackParameters* parsAtVertex =
71 m_extrapolator->extrapolate(
72 Gaudi::Hive::currentContext(),
73 *trackPars,
74 perigeeSurface, Trk::anyDirection, true, Trk::pion, mode).release();
75
76 if (dynamic_cast<const Trk::Perigee*>(parsAtVertex)==nullptr ||
77 parsAtVertex->covariance()==nullptr ) {
78 ATH_MSG_INFO ("Could not extrapolate Perigee to vertex pos: x " << lp.x() << " y " <<
79 lp.y() << " z " << lp.z() << ". Normal if outside ID acceptance ");
80
81 if (dynamic_cast<const Trk::Perigee*>(trackPars) && trackPars->covariance()) {
82 if (parsAtVertex) delete parsAtVertex; // in case extrapolation made other parameters
83 parsAtVertex = trackPars->clone();
84 } else {
85 delete parsAtVertex; return nullptr;
86 }
87 }
88
89 if (parsAtVertex && parsAtVertex->covariance() && parsAtVertex->covariance()->determinant()<=0)
90 {
91 ATH_MSG_DEBUG ("The track covariance matrix det after extrapolation is: " << parsAtVertex->covariance()->determinant() <<
92 " --> Using non extrapolated track parameters");
93 delete parsAtVertex;
94 parsAtVertex=trackPars->clone();
95 }
96 if (!parsAtVertex)[[unlikely]]{
97 ATH_MSG_ERROR("parsAtVertex is nullptr.");
98 return nullptr;
99 }
100 // positions
101 AmgVector(5) param = parsAtVertex->parameters();
102 Amg::Vector3D expPoint = parsAtVertex->position();
103
104 //phi_v and functions
105 double phi_v = param(Trk::phi);
106 double sin_phi_v = sin(phi_v);
107 double cos_phi_v = cos(phi_v);
108
109 //theta and functions
110 double th = param(Trk::theta);
111 double sin_th = sin(th);
112 double tan_th = tan(th);
113
114 //q over p
115 double q_ov_p = param(Trk::qOverP);
116 int sgn_h = (q_ov_p<0.)? -1:1;
117 Amg::Vector3D expMomentum(phi_v, th, q_ov_p);
118
119 // magnetic field
120
121 SG::ReadCondHandle<AtlasFieldCacheCondObj> readHandle{m_fieldCacheCondObjInputKey, Gaudi::Hive::currentContext()};
122 const AtlasFieldCacheCondObj* fieldCondObj{*readHandle};
123 if (!fieldCondObj)[[unlikely]]{
124 ATH_MSG_ERROR("fieldCondObj is nullptr");
125 delete parsAtVertex;
126 return nullptr;
127 }
128 MagField::AtlasFieldCache fieldCache;
129 fieldCondObj->getInitializedCache (fieldCache);
130
131 double mField[3];
132 fieldCache.getField(expPoint.data(),mField);
133
134 double B_z=mField[2]*299.792;//Magnetic field is returned in kT.
135 //The scaling is a factor of c needed for computing rho.
136
137 // signed radius and rotation variables
138 // (if momentum or mag field is absent, the curvature radius is infinite)
139
140 double rho;
141 if(mField[2] == 0. || fabs(q_ov_p) <= 1e-15) rho = 1e+15 ;
142 else rho = sin_th / (q_ov_p * B_z);
143
144 // std:: cout<<"calculated rho "<< rho<<std::endl;
145 double X = expPoint(0) - lp.x() + rho*sin_phi_v;
146 double Y = expPoint(1) - lp.y() - rho*cos_phi_v;
147 double SS = (X * X + Y * Y);
148 double S = sqrt(SS);
149
150 //calculated parameters at expansion point
151 //q_over_p and theta stay constant along trajectory
152 AmgVector(5) parAtExpansionPoint; parAtExpansionPoint.setZero();
153 parAtExpansionPoint[0] = rho - sgn_h * S;
154
155//calculation of phi at expansion point
156 double phiAtEp;
157 int sgnY = (Y<0)? -1:1;
158 int sgnX = (X<0)? -1:1;
159 static constexpr double pi = std::numbers::pi_v<double>;
160
161 if(fabs(X)>fabs(Y)) phiAtEp = sgn_h*sgnX* acos(-sgn_h * Y / S);
162 else
163 {
164 phiAtEp = asin(sgn_h * X / S);
165 if( (sgn_h * sgnY)> 0) phiAtEp = sgn_h * sgnX * pi - phiAtEp;
166 }
167
168 parAtExpansionPoint[2] = phiAtEp;
169 parAtExpansionPoint[1] = expPoint(2) - lp.z() + rho*(phi_v - parAtExpansionPoint[2])/tan_th;
170 parAtExpansionPoint[3] = th;
171 parAtExpansionPoint[4] = q_ov_p;
172// std::cout<<"Calculated parameters at expansion point: "<<parAtExpansionPoint<<std::endl;
173// std::cout<<"Difference: "<<predStateParameters-parAtExpansionPoint<<std::endl;
174
175 //jacobian elements
176 AmgMatrix(5,3) positionJacobian; positionJacobian.setZero();
177
178 //first row
179 positionJacobian(0,0) = -sgn_h * X / S;
180 positionJacobian(0,1) = -sgn_h * Y / S;
181
182 //second row
183 positionJacobian(1,0) = rho * Y / (tan_th * SS);
184 positionJacobian(1,1) = -rho * X / (tan_th * SS);
185 positionJacobian(1,2) = 1.;
186
187 //third row
188 positionJacobian(2,0) = -Y / SS;
189 positionJacobian(2,1) = X / SS;
190// std::cout<<"My position Jacobian: "<<positionJacobian<<std::endl;
191
192 //momentum jacobian and related stuff
193 AmgMatrix(5,3) momentumJacobian; momentumJacobian.setZero();
194 double R = X*cos_phi_v + Y * sin_phi_v;
195 double Q = X*sin_phi_v - Y * cos_phi_v;
196 double d_phi = parAtExpansionPoint[2] - phi_v;
197
198 //first row
199 momentumJacobian(0,0) = -sgn_h * rho * R / S ;
200
201 double qOvS_red = 1 - sgn_h * Q / S;
202 momentumJacobian(0,1) = qOvS_red * rho / tan_th;
203 momentumJacobian(0,2) = - qOvS_red * rho / q_ov_p;
204
205 //second row
206 momentumJacobian(1,0) = (1 - rho*Q/SS )*rho/tan_th;
207 momentumJacobian(1,1) = (d_phi + rho * R / (SS * tan_th * tan_th) ) * rho;
208 momentumJacobian(1,2) = (d_phi - rho * R /SS ) * rho / (q_ov_p*tan_th);
209
210 //third row
211 momentumJacobian(2,0) = rho * Q / SS;
212 momentumJacobian(2,1) = -rho * R / (SS*tan_th);
213 momentumJacobian(2,2) = rho * R / (q_ov_p*SS);
214
215 //last two rows:
216 momentumJacobian(3,1) = 1.;
217 momentumJacobian(4,2) = 1.;
218// std::cout<<"My momentum Jacobian "<<momentumJacobian<<std::endl;
219
220 AmgVector(5) constantTerm = parAtExpansionPoint - positionJacobian*expPoint - momentumJacobian*expMomentum;
221// std::cout<<"My constant term: "<<constantTerm<<std::endl;
222
223 LinearizedTrack* toreturn=new LinearizedTrack(parsAtVertex->parameters(),
224 *parsAtVertex->covariance(),
225 lp,
226 positionJacobian,
227 momentumJacobian,
228 expPoint,
229 expMomentum,
230 constantTerm);
231
232 //delete Perigee object created by the Extrapolator
233 delete parsAtVertex;
234 //return new linearized track
235 return toreturn;
236 }
237
239 const Amg::Vector3D& linPoint) const
240 {
241 if (!neutralPars) return nullptr;
242 Amg::Vector3D lp =linPoint;
243 PerigeeSurface perigeeSurface(lp);
244
245 //no material effects for neutral particles
246 /*
247 const Amg::Vector3D gMomentum = neutralPars->momentum();
248 const Amg::Vector3D gDirection = neutralPars->position() - lp;
249 const double extrapolationDirection = gMomentum.dot( gDirection);
250 MaterialUpdateMode mode = (extrapolationDirection < 0) ?
251 Trk::addNoise : // parameters upstream of vertex
252 Trk::removeNoise ; // parameters downstream of vertex -> go back
253 */
254 const NeutralParameters* parsAtVertex =
255 m_extrapolator->extrapolate(*neutralPars,
256 perigeeSurface, Trk::anyDirection, true).release();
257
258 if (dynamic_cast<const Trk::NeutralPerigee*>(parsAtVertex)==nullptr ||
259 parsAtVertex->covariance()==nullptr ) {
260 ATH_MSG_INFO ("Could not extrapolate Perigee to vertex pos: x " << lp.x() << " y " <<
261 lp.y() << " z " << lp.z() << ". Should not happen. ");
262
263 if (dynamic_cast<const Trk::NeutralPerigee*>(neutralPars) && neutralPars->covariance()) {
264 if (parsAtVertex) delete parsAtVertex; // in case extrapolation made other parameters
265 parsAtVertex = neutralPars->clone();
266 } else {
267 delete parsAtVertex; return nullptr;
268 }
269 }
270
271 // positions, phi, theta
272 AmgVector(5) param = parsAtVertex->parameters();
273 Amg::Vector3D expPoint = parsAtVertex->position();
274
275 double phi_v = param(Trk::phi);
276 double sin_phi_v = sin(phi_v);
277 double cos_phi_v = cos(phi_v);
278 double th = param(Trk::theta);
279 double tan_th = tan(th);
280 double q_ov_p = param(Trk::qOverP);
281
282 //momentum
283 Amg::Vector3D expMomentum(phi_v, th, q_ov_p);
284 double X = expPoint(0) - lp.x();
285 double Y = expPoint(1) - lp.y();
286
287 AmgVector(5) parAtExpansionPoint; parAtExpansionPoint.setZero();
288 parAtExpansionPoint[0] = Y*cos_phi_v-X*sin_phi_v;
289
290 //very easy for a neutral track!
291 //phi doesn't change...
292
293 double phiAtEp=phi_v;
294 parAtExpansionPoint[2] = phiAtEp;
295 parAtExpansionPoint[1] = expPoint[2] - lp.z() - 1./tan_th*(X*cos_phi_v+Y*sin_phi_v);
296 parAtExpansionPoint[3] = th;
297 parAtExpansionPoint[4] = q_ov_p;
298
299 //jacobian elements
300 AmgMatrix(5,3) positionJacobian; positionJacobian.setZero();
301
302 //first row
303 positionJacobian(0,0) = -sin_phi_v;
304 positionJacobian(0,1) = +cos_phi_v;
305
306 //second raw
307 positionJacobian(1,0) = -cos_phi_v/tan_th;
308 positionJacobian(1,1) = -sin_phi_v/tan_th;
309 positionJacobian(1,2) = 1.;
310
311// std::cout<<"My position Jacobian: "<<positionJacobian<<std::endl;
312
313 //momentum jacobian and related stuff
314 AmgMatrix(5,3) momentumJacobian; momentumJacobian.setZero();
315 momentumJacobian(2,0) = 1.;
316 momentumJacobian(3,1) = 1.;
317 momentumJacobian(4,2) = 1.;
318// std::cout<<"My momentum Jacobian "<<momentumJacobian<<std::endl;
319
320 AmgVector(5) constantTerm = parAtExpansionPoint - positionJacobian*expPoint - momentumJacobian*expMomentum;
321// std::cout<<"My constant term: "<<constantTerm<<std::endl;
322
323 LinearizedTrack* toreturn=new LinearizedTrack(parsAtVertex->parameters(),
324 *parsAtVertex->covariance(),
325 lp,
326 positionJacobian,
327 momentumJacobian,
328 expPoint,
329 expMomentum,
330 constantTerm);
331
332 //delete MeasuredPerigee object created by the Extrapolator
333 delete parsAtVertex;
334 //return new linearized track
335 return toreturn;
336 }
337
338
339}//end of namespace definitions
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_DEBUG(x)
#define AmgVector(rows)
#define AmgMatrix(rows, cols)
#define pi
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 LinearizedTrack * linearizedTrack(const TrackParameters *param, const Amg::Vector3D &linPoint) const override
Linearization method: Takes a MeasuredPerigee and a LinearizationPoint.
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_fieldCacheCondObjInputKey
~FullLinearizedTrackFactory()
Destructor.
virtual void linearize(VxTrackAtVertex &theTrack, const Amg::Vector3D &linPoint) const override
Interface for VxTrackAtVertex: Takes a MeasuredPerigee from VxTrackAtVertex and a Lineariztion point.
ToolHandle< Trk::IExtrapolator > m_extrapolator
virtual StatusCode initialize() override
Standard AlgToolMethods.
FullLinearizedTrackFactory(const std::string &t, const std::string &n, const IInterface *p)
Default constructor due to Athena interface.
const Amg::Vector3D & momentum() const
Access method for the momentum.
virtual ParametersBase< DIM, T > * clone() const override=0
clone method for polymorphic deep copy
const Amg::Vector3D & position() const
Access method for the position.
Class describing the Line to which the Perigee refers to.
The VxTrackAtVertex is a common class for all present TrkVertexFitters The VxTrackAtVertex is designe...
const NeutralParameters * initialNeutralPerigee(void) const
Access to the initial perigee parameters of trajectory.
const TrackParameters * initialPerigee(void) const
Access to the initial perigee parameters of trajectory.
void setLinTrack(LinearizedTrack *myLinTrack)
Setting up the linearized track.
Eigen::Matrix< double, 3, 1 > Vector3D
Ensure that the ATLAS eigen extensions are properly loaded.
@ anyDirection
ParametersT< TrackParametersDim, Charged, PerigeeSurface > Perigee
ParametersBase< NeutralParametersDim, Neutral > NeutralParameters
ParametersT< NeutralParametersDim, Neutral, PerigeeSurface > NeutralPerigee
@ theta
Definition ParamDefs.h:66
@ qOverP
perigee
Definition ParamDefs.h:67
@ phi
Definition ParamDefs.h:75
MaterialUpdateMode
This is a steering enum to force the material update it can be: (1) addNoise (-1) removeNoise Second ...
ParametersBase< TrackParametersDim, Charged > TrackParameters
#define unlikely(x)