ATLAS Offline Software
Loading...
Searching...
No Matches
FastVertexFitter.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 FastVertexFitter.cxx - Description
7 ***************************************************************************/
14#include "TrkTrack/Track.h"
21//xAOD includes
22#include "xAODTracking/Vertex.h"
24
25/* These are some local helper classes only needed for convenience, therefor
26within anonymous namespace. They do contain temporary calculations of matrices
27and vectors resulting from the Billoir calculation (Note: no transformation
28of the perigee parameters is done anymore). */
29namespace
30{
31 struct BilloirTrack
32 {
33 BilloirTrack() : originalPerigee(nullptr),chi2{} { DtWD.setZero(); DtWDx.setZero(); xpVec.setZero();}
34 virtual ~BilloirTrack() = default;
35 const Trk::TrackParameters * originalPerigee;
36 AmgMatrix(3,3) DtWD;
37 Amg::Vector3D DtWDx;
38 Amg::Vector3D xpVec;
39 double chi2;
40 };
41
42 struct BilloirVertex
43 {
44 BilloirVertex() : chi2{},ndf{} { DtWD_Sum.setZero(); DtWDx_Sum.setZero();}
45 virtual ~BilloirVertex() = default;
46 AmgMatrix(3,3) DtWD_Sum;
47 Amg::Vector3D DtWDx_Sum;
48 double chi2;
49 unsigned int ndf;
50 };
51}
52
53namespace Trk
54{
56 {
57
58 if ( m_extrapolator.retrieve().isFailure() )
59 {
60 msg(MSG::FATAL) << "Failed to retrieve tool " << m_extrapolator << endmsg;
61 return StatusCode::FAILURE;
62 }
63
64
65 msg(MSG::INFO) << "Retrieved tool " << m_extrapolator << endmsg;
66
67
68 if ( m_linFactory.retrieve().isFailure() )
69 {
70 msg(MSG::FATAL) << "Failed to retrieve tool " << m_linFactory << endmsg;
71 return StatusCode::FAILURE;
72 }
73
74
75 msg(MSG::INFO) << "Retrieved tool " << m_linFactory << endmsg;
76
77
78 return StatusCode::SUCCESS;
79 }
80
81
82 FastVertexFitter::FastVertexFitter ( const std::string& t, const std::string& n, const IInterface* p ) : base_class ( t,n,p ),
83 m_maxIterations ( 3 ),
84 m_maxDchi2PerNdf ( 0.000001 )
85
86
87 {
88 declareProperty ( "MaxIterations", m_maxIterations );
89 declareProperty ( "MaxChi2PerNdf", m_maxDchi2PerNdf );
90 declareInterface<IVertexFitter> ( this );
91 }
92
94
95
96
100 std::unique_ptr<xAOD::Vertex> FastVertexFitter::fit ( const EventContext& ctx,
101 const std::vector<const Trk::TrackParameters*> & originalPerigees,
102 const Amg::Vector3D& firstStartingPoint ) const
103 {
104 xAOD::Vertex constraint;
105 constraint.makePrivateStore();
106 constraint.setPosition( firstStartingPoint );
107 constraint.setCovariancePosition( AmgSymMatrix(3)::Zero(3,3) );
108 constraint.setFitQuality( 0.,0.);
109 return fit ( ctx, originalPerigees, constraint );
110 }
111
114 std::unique_ptr<xAOD::Vertex> FastVertexFitter::fit ( const EventContext& ctx,
115 const std::vector<const Trk::TrackParameters*> & originalPerigees,
116 const xAOD::Vertex& firstStartingPoint ) const
117 {
118 if ( originalPerigees.empty() )
119 {
120 ATH_MSG_VERBOSE("No tracks to fit in this event.");
121 return nullptr;
122 }
123
124 /* Initialisation of variables */
125 double chi2 = 2000000000000.;
126 unsigned int nRP = originalPerigees.size(); // Number of tracks to fit
127 int ndf = nRP * ( 5-3 ) - 3; // Number of degrees of freedom
128 if ( ndf == -1 ) ndf = 1;
129
130 /* Determine if we are doing a constraint fit.*/
131 bool constraint = false;
132 if ( firstStartingPoint.covariancePosition().trace() != 0. )
133 {
134 constraint = true;
135 ndf += 3;
136 ATH_MSG_DEBUG("Fitting with constraint.");
137 ATH_MSG_VERBOSE(firstStartingPoint.covariancePosition().inverse().eval());
138 }
139
140 double chi2New=0.;double chi2Old=0.;
141
142 Amg::Vector3D linPoint ( firstStartingPoint.position() ); // linearization point for track parameters (updated for every iteration)
143
144 auto fittedVertex = std::make_unique<xAOD::Vertex>();
145 fittedVertex->makePrivateStore(); // xAOD::VertexContainer will take ownership of AuxStore when ActualVertex is added to it
146
147 std::vector<VxTrackAtVertex> tracksAtVertex;
148 std::vector<BilloirTrack> billoirTracks;
149
150 /* Iterate fits until the fit criteria are met, or the number of max
151 iterations is reached. */
152 for ( unsigned int niter=0; niter < m_maxIterations; ++niter )
153 {
154 // msg(MSG::VERBOSE) << "Start of iteration " << niter << ", starting point ("
155 // << linPoint [0] << ", " << linPoint [1] << ", " << linPoint [2]
156 // << ") and " << originalPerigees.size() << " tracks." << endmsg;
157
158 billoirTracks.clear();
159 chi2Old = chi2New;
160 chi2New = 0.;
161
162 AmgMatrix(2,3) D;
163
164 /* Linearize the track parameters wrt. starting point of the fit */
165 Amg::Vector3D globalPosition = linPoint;
166 Trk::PerigeeSurface perigeeSurface ( globalPosition );
167
168 BilloirVertex billoirVertex;
169 // unsigned int count(0);
170 for (const auto *originalPerigee : originalPerigees)
171 {
172 LinearizedTrack* linTrack = m_linFactory->linearizedTrack ( originalPerigee, linPoint );
173 if ( linTrack==nullptr )
174 {
175 ATH_MSG_DEBUG("Could not linearize track! Skipping this track!");
176 }
177 else
178 {
179 // local position
180 Amg::Vector3D locXpVec = linTrack->expectedPositionAtPCA();
181 locXpVec[0] = locXpVec[0] - linPoint[0];
182 locXpVec[1] = locXpVec[1] - linPoint[1];
183 locXpVec[2] = locXpVec[2] - linPoint[2];
184
185 // msg(MSG::VERBOSE) << "Track: " << count << endmsg;
186 // count++;
187 // const Trk::MeasuredPerigee* tmpPerigee = dynamic_cast<const Trk::MeasuredPerigee*>(*iter);
188 //AmgVector(5) expParameters = linTrack->expectedParametersAtPCA();
189
190 // msg(MSG::VERBOSE) << "locXp: " << locXpVec[0] << "\t" << locXpVec[1] << "\t" << locXpVec[2] << endmsg;
191
192 // first get the cov 2x2 sub matrix and then invert (don't get the 2x2 sub matrix of the 5x5 already inverted cov matrix)
193 AmgMatrix(2,2) billoirCovMat = linTrack->expectedCovarianceAtPCA().block<2,2>(0,0);
194 // msg(MSG::VERBOSE) << "CovMatrix: " << billoirCovMat[0][0] << "\t" << billoirCovMat[0][1] << endmsg;
195 // msg(MSG::VERBOSE) << " " << billoirCovMat[1][0] << "\t" << billoirCovMat[1][1] << endmsg;
196 AmgMatrix(2,2) billoirWeightMat = billoirCovMat.inverse().eval();
197 // msg(MSG::VERBOSE) << "WeightMatrix: " << billoirWeightMat[0][0] << "\t" << billoirWeightMat[0][1] << endmsg;
198 // msg(MSG::VERBOSE) << " " << billoirWeightMat[1][0] << "\t" << billoirWeightMat[1][1] << endmsg;
199 // D matrix for d0 and z0
200 D = linTrack->positionJacobian().block<2,3>(0,0);
201 // msg(MSG::VERBOSE) << "DMatrix: " << D[0][0] << "\t" << D[0][1] << endmsg;
202 // msg(MSG::VERBOSE) << " " << D[1][0] << "\t" << D[1][1] << endmsg;
203
204 // Calculate DtWD and DtWD*x and sum them
205 BilloirTrack locBilloirTrack;
206 locBilloirTrack.xpVec = locXpVec;
207 locBilloirTrack.DtWD = (D.transpose())*billoirWeightMat*D;
208 locBilloirTrack.chi2 = -1.0;
209 billoirVertex.DtWD_Sum += locBilloirTrack.DtWD;
210 locBilloirTrack.DtWDx = ((D.transpose())*billoirWeightMat*D)*locXpVec;
211 billoirVertex.DtWDx_Sum += locBilloirTrack.DtWDx;
212 locBilloirTrack.originalPerigee = originalPerigee;
213 billoirTracks.push_back ( locBilloirTrack );
214 }
215 delete linTrack; linTrack=nullptr;
216 }
217 if ( billoirTracks.empty() )
218 {
219 ATH_MSG_DEBUG("No linearized tracks left after linearization! Should not happen!");
220 return nullptr;
221 }
222 if ( constraint )
223 {
224 // add V_del += wgtconst * (linPoint.position() - Vconst) and V_wgt +=wgtconst
225 Amg::Vector3D constraintPosInBilloirFrame;
226 constraintPosInBilloirFrame.setZero();
227 // this will be 0 for first iteration but != 0 from second on
228 constraintPosInBilloirFrame[0] = firstStartingPoint.position() [0]-linPoint [0];
229 constraintPosInBilloirFrame[1] = firstStartingPoint.position() [1]-linPoint [1];
230 constraintPosInBilloirFrame[2] = firstStartingPoint.position() [2]-linPoint [2];
231 billoirVertex.DtWDx_Sum += firstStartingPoint.covariancePosition().inverse().eval() *constraintPosInBilloirFrame;
232 billoirVertex.DtWD_Sum += firstStartingPoint.covariancePosition().inverse().eval();
233 }
234
235 AmgMatrix(3,3) cov_delta_V_mat = billoirVertex.DtWD_Sum.inverse( ) ;
236
237 Amg::Vector3D delta_V = cov_delta_V_mat * billoirVertex.DtWDx_Sum;
238
239 std::vector<BilloirTrack>::iterator BTIter;
240 for ( BTIter = billoirTracks.begin(); BTIter != billoirTracks.end() ; ++BTIter )
241 {
242 // calculate chi2PerTrack = (xpVec - vtxPosInBilloirFrame).T * DtWD(track) * (xpVec - vtxPosInBilloirFrame); )
244 diff.setZero();
245 diff[0] = ( *BTIter ).xpVec[0] - delta_V[0];
246 diff[1] = ( *BTIter ).xpVec[1] - delta_V[1];
247 diff[2] = ( *BTIter ).xpVec[2] - delta_V[2];
248 ( *BTIter ).chi2 = diff.dot(( *BTIter ).DtWD* diff );
249 if ( ( *BTIter ).chi2 < 0 )
250 {
251 std::cout << "VxFastFit::calculate: error in chi2_per_track: "<<( *BTIter ).chi2<<"\n";
252 return nullptr;
253 }
254 chi2New += ( *BTIter ).chi2;
255 }
256
257 if ( constraint )
258 {
259 Amg::Vector3D deltaTrk;
260 deltaTrk.setZero();
261 // last term will also be 0 again but only in the first iteration
262 // = calc. vtx in billoir frame - ( constraint pos. in billoir frame )
263 deltaTrk[0] = delta_V[0] - ( firstStartingPoint.position() [0] - linPoint [0] );
264 deltaTrk[1] = delta_V[1] - ( firstStartingPoint.position() [1] - linPoint [1] );
265 deltaTrk[2] = delta_V[2] - ( firstStartingPoint.position() [2] - linPoint [2] );
266 chi2New += Amg::chi2(firstStartingPoint.covariancePosition().inverse().eval(), deltaTrk);
267 }
268
269 /* assign new linearization point (= new vertex position in global frame) */
270 Amg::Vector3D tmpPos ( linPoint );
271 tmpPos[0] += delta_V[0]; tmpPos[1] += delta_V[1]; tmpPos[2] += delta_V[2];
272 linPoint = tmpPos;
273
274 // msg(MSG::VERBOSE) << "Vertex of Iteration " << niter << " with chi2: " << chi2New << "\t old chi2: " << chi2 << endmsg;
275 // msg(MSG::VERBOSE) << "deltaV: (" << delta_V[0] << ", " << delta_V[1] << ", " << delta_V[2] << ")" << endmsg;
276 // msg(MSG::VERBOSE) << linPoint << endmsg;
277
278 if ( chi2New < chi2 )
279 {
280 /* Store the vertex */
281 chi2 = chi2New;
282 //const AmgMatrix(3,3) * newCovarianceMatrix = &cov_delta_V_mat ;
283 //const AmgMatrix(3,3) newErrorMatrix = newCovarianceMatrix->inverse().eval();
284 //fittedVertex = RecVertex ( linPoint.position(), newErrorMatrix, ndf, chi2 );
285
286 // The cov_delta_V_mat does not need to be inverted. -katy 2/3/16
287 fittedVertex->setPosition( linPoint );
288 fittedVertex->setCovariancePosition( cov_delta_V_mat );
289 fittedVertex->setFitQuality( chi2, ndf );
290
291 /* new go through vector and delete entries */
292 /* // TODO: not needed anymore, tracksAtVertex doesn't store pointers - just the objects themselves <David Shope> (EDM Migration) 03/21/16
293 for ( std::vector<Trk::VxTrackAtVertex*>::const_iterator itr = tracksAtVertex.begin();
294 itr != tracksAtVertex.end(); ++itr )
295 {
296 delete ( *itr );
297 }
298 */
299
300 tracksAtVertex.clear();
301
302 Amg::Vector3D pointToExtrapolateTo ( linPoint [0], linPoint [1], linPoint [2] );
303 Trk::PerigeeSurface perigeeSurface ( pointToExtrapolateTo );
304 for ( BTIter = billoirTracks.begin(); BTIter != billoirTracks.end() ; ++BTIter )
305 {
306 // you need to extrapolate the original perigee ((*BTIter).originalPerigee) really to the
307 // found vertex. The first propagation above is only to the starting point. But here we
308 // want to store it wrt. to the last fitted vertex
309 auto extrapolatedPerigee = std::unique_ptr<const Trk::TrackParameters> ( m_extrapolator->extrapolate (
310 ctx,
311 * ( *BTIter ).originalPerigee,
312 perigeeSurface ) );
313 if ( extrapolatedPerigee==nullptr )
314 {
315 extrapolatedPerigee = std::unique_ptr<const Trk::TrackParameters>(((*BTIter).originalPerigee)->clone());
316 ATH_MSG_DEBUG("Could not extrapolate these track parameters to final vertex position! Storing original position as final one ...");
317 }
318 //VxTrackAtVertex will own the clone of the extrapolatedPerigee
319 Trk::VxTrackAtVertex* tmpVxTrkAtVtx = new Trk::VxTrackAtVertex ( ( *BTIter ).chi2, extrapolatedPerigee->clone(),
320 ( *BTIter ).originalPerigee ) ;
321 tracksAtVertex.push_back ( *tmpVxTrkAtVtx );
322 // TODO: here is where the vxTracksAtVertex pointers are deleted
323 delete tmpVxTrkAtVtx; // TODO: is this ok?
324 }
325 }
326
327 if ( fabs ( chi2Old-chi2New ) < m_maxDchi2PerNdf * ndf )
328 {
329 break;
330 }
331 } // end of iteration
332 fittedVertex->vxTrackAtVertex() = tracksAtVertex;
333 //ATH_MSG_VERBOSE("Final Vertex Fitted: " << fittedVxCandidate->recVertex()); // TODO: can no longer print vertex after converting to xAOD
334 return fittedVertex;
335 }
336
337 std::unique_ptr<xAOD::Vertex> FastVertexFitter::fit ( const EventContext& ctx,
338 const std::vector<const Trk::TrackParameters*>& perigeeList ) const
339 {
340 Amg::Vector3D tmpVtx(0.,0.,0.);
341 return fit ( ctx, perigeeList, tmpVtx );
342 }
343
344 //xAOD interfaced methods. Required to un-block the current situation
345 // with the xAOD tracking design.
346 std::unique_ptr<xAOD::Vertex> FastVertexFitter::fit(const EventContext& ctx,const std::vector<const xAOD::TrackParticle*>& vectorTrk,const Amg::Vector3D& startingPoint) const
347 {
348 xAOD::Vertex constraint;
349 constraint.makePrivateStore();
350 constraint.setPosition( startingPoint );
351 constraint.setCovariancePosition( AmgSymMatrix(3)::Zero(3,3) );
352 constraint.setFitQuality( 0.,0.);
353 return fit(ctx, vectorTrk, constraint);
354 }//end of the xAOD starting point fit method
355
356
357 std::unique_ptr<xAOD::Vertex> FastVertexFitter::fit(const EventContext& ctx, const std::vector<const xAOD::TrackParticle*>& vectorTrk, const xAOD::Vertex& constraint) const
358 {
359 if(vectorTrk.empty())
360 {
361 msg(MSG::INFO)<<"Empty vector of tracks passed"<<endmsg;
362 return nullptr;
363 }
364
365 //making a list of perigee out of the vector of tracks
366 std::vector<const Trk::TrackParameters*> measuredPerigees;
367
368 for(const auto *i : vectorTrk)
369 {
370 const Trk::TrackParameters * tmpMeasPer = &(i->perigeeParameters());
371
372 if(tmpMeasPer!=nullptr) measuredPerigees.push_back(tmpMeasPer);
373 else msg(MSG::INFO)<<"Failed to dynamic_cast this track parameters to perigee"<<endmsg; //TODO: Failed to implicit cast the perigee parameters to track parameters?
374 }
375
376
377 std::unique_ptr<xAOD::Vertex> fittedVertex = fit( ctx, measuredPerigees, constraint );
378 // fit() may return nullptr, need to protect
379 if (fittedVertex == nullptr){
380 ATH_MSG_WARNING("Failed fit, returning null vertex");
381 return nullptr;
382 }
383 //assigning the input tracks to the fitted vertex through VxTrackAtVertices
384 {
385 if( fittedVertex->vxTrackAtVertexAvailable() ) // TODO: I don't think vxTrackAtVertexAvailable() does the same thing as a null pointer check!
386 // Regretful Hindsight 8 years later: No, it doesn't!
387 {
388 if(!fittedVertex->vxTrackAtVertex().empty())
389 {
390 for(unsigned int i = 0; i <vectorTrk.size(); ++i)
391 {
392
394 linkTT->setElement(vectorTrk[i]);
395
396 // vxtrackatvertex takes ownership!
397 ( fittedVertex->vxTrackAtVertex() )[i].setOrigTrack(linkTT);
398 }//end of loop for setting orig tracks in.
399 }//end of protection against unsuccessfull updates (no tracks were added)
400 }//end of vector of tracks check
401 }//end of pointer check
402
403 //now set links to xAOD::TrackParticles directly in the xAOD::Vertex
404 unsigned int VTAVsize = fittedVertex->vxTrackAtVertex().size();
405 for (unsigned int i = 0 ; i < VTAVsize ; ++i)
406 {
407 Trk::VxTrackAtVertex* VTAV = &( fittedVertex->vxTrackAtVertex().at(i) );
408 //TODO: Will this pointer really hold 0 if no VxTrackAtVertex is found?
409 if (not VTAV){
410 ATH_MSG_WARNING (" Trying to set link to xAOD::TrackParticle. The VxTrackAtVertex is not found");
411 continue;
412 }
413
414 Trk::ITrackLink* trklink = VTAV->trackOrParticleLink();
415
416 // See if the trklink is to an xAOD::TrackParticle
417 Trk::LinkToXAODTrackParticle* linkToXAODTP = dynamic_cast<Trk::LinkToXAODTrackParticle*>(trklink);
418 if (linkToXAODTP)
419 {
420
421 //Now set the new link to the xAOD vertex
422 fittedVertex->addTrackAtVertex(*linkToXAODTP, VTAV->weight());
423
424 } else {
425 ATH_MSG_WARNING ("Skipping track. Trying to set link to something else than xAOD::TrackParticle. Neutrals not supported.");
426 }
427 } //end of loop
428
429 return fittedVertex;
430
431 }//end of the xAOD constrained fit method
432
433
434
435
436}
437
#define endmsg
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
#define AmgSymMatrix(dim)
#define AmgMatrix(rows, cols)
void diff(const Jet &rJet1, const Jet &rJet2, std::map< std::string, double > varDiff)
Difference between jets - Non-Class function required by trigger.
Definition Jet.cxx:631
Eigen::Matrix< double, 3, 1 > Vector3D
virtual StatusCode initialize() override
ToolHandle< Trk::IExtrapolator > m_extrapolator
virtual std::unique_ptr< xAOD::Vertex > fit(const EventContext &ctx, const std::vector< const Trk::TrackParameters * > &perigeeList, const Amg::Vector3D &startingPoint) const override
Interface for ParametersBase with starting point.
ToolHandle< Trk::IVertexLinearizedTrackFactory > m_linFactory
virtual ~FastVertexFitter()
standard destructor
FastVertexFitter(const std::string &t, const std::string &n, const IInterface *p)
const Amg::Vector3D & expectedPositionAtPCA() const
Access to the expected position at point of closet approach.
Element link to XAOD TrackParticle.
Class describing the Line to which the Perigee refers to.
The VxTrackAtVertex is a common class for all present TrkVertexFitters The VxTrackAtVertex is designe...
double weight(void) const
Information about the weight of track in fit (given back by annealing): weight=ndf/2.
const ITrackLink * trackOrParticleLink(void) const
void setCovariancePosition(const AmgSymMatrix(3)&covariancePosition)
Sets the vertex covariance matrix.
void setPosition(const Amg::Vector3D &position)
Sets the 3-position.
void setFitQuality(float chiSquared, float numberDoF)
Set the 'Fit Quality' information.
const Amg::Vector3D & position() const
Returns the 3-pos.
double chi2(TH1 *h0, TH1 *h1)
double chi2(const T &precision, const U &residual, const int sign=1)
Eigen::Matrix< double, 3, 1 > Vector3D
ParametersBase< TrackParametersDim, Charged > TrackParameters
Vertex_v1 Vertex
Define the latest version of the vertex class.
MsgStream & msg
Definition testRead.cxx:32