ATLAS Offline Software
Loading...
Searching...
No Matches
FastVertexFitter.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 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 xAOD::Vertex * FastVertexFitter::fit ( const std::vector<const Trk::TrackParameters*> & originalPerigees,
101 const Amg::Vector3D& firstStartingPoint ) const
102 {
103 xAOD::Vertex constraint;
104 constraint.makePrivateStore();
105 constraint.setPosition( firstStartingPoint );
106 constraint.setCovariancePosition( AmgSymMatrix(3)::Zero(3,3) );
107 constraint.setFitQuality( 0.,0.);
108 return fit ( originalPerigees, constraint );
109 }
110
113 xAOD::Vertex * FastVertexFitter::fit ( const std::vector<const Trk::TrackParameters*> & originalPerigees,
114 const xAOD::Vertex& firstStartingPoint ) const
115 {
116 if ( originalPerigees.empty() )
117 {
118 ATH_MSG_VERBOSE("No tracks to fit in this event.");
119 return nullptr;
120 }
121
122 /* Initialisation of variables */
123 double chi2 = 2000000000000.;
124 unsigned int nRP = originalPerigees.size(); // Number of tracks to fit
125 int ndf = nRP * ( 5-3 ) - 3; // Number of degrees of freedom
126 if ( ndf == -1 ) ndf = 1;
127
128 /* Determine if we are doing a constraint fit.*/
129 bool constraint = false;
130 if ( firstStartingPoint.covariancePosition().trace() != 0. )
131 {
132 constraint = true;
133 ndf += 3;
134 ATH_MSG_DEBUG("Fitting with constraint.");
135 ATH_MSG_VERBOSE(firstStartingPoint.covariancePosition().inverse().eval());
136 }
137
138 double chi2New=0.;double chi2Old=0.;
139
140 Amg::Vector3D linPoint ( firstStartingPoint.position() ); // linearization point for track parameters (updated for every iteration)
141
142 auto fittedVertex = std::make_unique<xAOD::Vertex>();
143 fittedVertex->makePrivateStore(); // xAOD::VertexContainer will take ownership of AuxStore when ActualVertex is added to it
144
145 std::vector<VxTrackAtVertex> tracksAtVertex;
146 std::vector<BilloirTrack> billoirTracks;
147
148 /* Iterate fits until the fit criteria are met, or the number of max
149 iterations is reached. */
150 for ( unsigned int niter=0; niter < m_maxIterations; ++niter )
151 {
152 // msg(MSG::VERBOSE) << "Start of iteration " << niter << ", starting point ("
153 // << linPoint [0] << ", " << linPoint [1] << ", " << linPoint [2]
154 // << ") and " << originalPerigees.size() << " tracks." << endmsg;
155
156 billoirTracks.clear();
157 chi2Old = chi2New;
158 chi2New = 0.;
159
160 AmgMatrix(2,3) D;
161
162 /* Linearize the track parameters wrt. starting point of the fit */
163 Amg::Vector3D globalPosition = linPoint;
164 Trk::PerigeeSurface perigeeSurface ( globalPosition );
165
166 BilloirVertex billoirVertex;
167 // unsigned int count(0);
168 for (const auto *originalPerigee : originalPerigees)
169 {
170 LinearizedTrack* linTrack = m_linFactory->linearizedTrack ( originalPerigee, linPoint );
171 if ( linTrack==nullptr )
172 {
173 ATH_MSG_DEBUG("Could not linearize track! Skipping this track!");
174 }
175 else
176 {
177 // local position
178 Amg::Vector3D locXpVec = linTrack->expectedPositionAtPCA();
179 locXpVec[0] = locXpVec[0] - linPoint[0];
180 locXpVec[1] = locXpVec[1] - linPoint[1];
181 locXpVec[2] = locXpVec[2] - linPoint[2];
182
183 // msg(MSG::VERBOSE) << "Track: " << count << endmsg;
184 // count++;
185 // const Trk::MeasuredPerigee* tmpPerigee = dynamic_cast<const Trk::MeasuredPerigee*>(*iter);
186 //AmgVector(5) expParameters = linTrack->expectedParametersAtPCA();
187
188 // msg(MSG::VERBOSE) << "locXp: " << locXpVec[0] << "\t" << locXpVec[1] << "\t" << locXpVec[2] << endmsg;
189
190 // first get the cov 2x2 sub matrix and then invert (don't get the 2x2 sub matrix of the 5x5 already inverted cov matrix)
191 AmgMatrix(2,2) billoirCovMat = linTrack->expectedCovarianceAtPCA().block<2,2>(0,0);
192 // msg(MSG::VERBOSE) << "CovMatrix: " << billoirCovMat[0][0] << "\t" << billoirCovMat[0][1] << endmsg;
193 // msg(MSG::VERBOSE) << " " << billoirCovMat[1][0] << "\t" << billoirCovMat[1][1] << endmsg;
194 AmgMatrix(2,2) billoirWeightMat = billoirCovMat.inverse().eval();
195 // msg(MSG::VERBOSE) << "WeightMatrix: " << billoirWeightMat[0][0] << "\t" << billoirWeightMat[0][1] << endmsg;
196 // msg(MSG::VERBOSE) << " " << billoirWeightMat[1][0] << "\t" << billoirWeightMat[1][1] << endmsg;
197 // D matrix for d0 and z0
198 D = linTrack->positionJacobian().block<2,3>(0,0);
199 // msg(MSG::VERBOSE) << "DMatrix: " << D[0][0] << "\t" << D[0][1] << endmsg;
200 // msg(MSG::VERBOSE) << " " << D[1][0] << "\t" << D[1][1] << endmsg;
201
202 // Calculate DtWD and DtWD*x and sum them
203 BilloirTrack locBilloirTrack;
204 locBilloirTrack.xpVec = locXpVec;
205 locBilloirTrack.DtWD = (D.transpose())*billoirWeightMat*D;
206 locBilloirTrack.chi2 = -1.0;
207 billoirVertex.DtWD_Sum += locBilloirTrack.DtWD;
208 locBilloirTrack.DtWDx = ((D.transpose())*billoirWeightMat*D)*locXpVec;
209 billoirVertex.DtWDx_Sum += locBilloirTrack.DtWDx;
210 locBilloirTrack.originalPerigee = originalPerigee;
211 billoirTracks.push_back ( locBilloirTrack );
212 }
213 delete linTrack; linTrack=nullptr;
214 }
215 if ( billoirTracks.empty() )
216 {
217 ATH_MSG_DEBUG("No linearized tracks left after linearization! Should not happen!");
218 return nullptr;
219 }
220 if ( constraint )
221 {
222 // add V_del += wgtconst * (linPoint.position() - Vconst) and V_wgt +=wgtconst
223 Amg::Vector3D constraintPosInBilloirFrame;
224 constraintPosInBilloirFrame.setZero();
225 // this will be 0 for first iteration but != 0 from second on
226 constraintPosInBilloirFrame[0] = firstStartingPoint.position() [0]-linPoint [0];
227 constraintPosInBilloirFrame[1] = firstStartingPoint.position() [1]-linPoint [1];
228 constraintPosInBilloirFrame[2] = firstStartingPoint.position() [2]-linPoint [2];
229 billoirVertex.DtWDx_Sum += firstStartingPoint.covariancePosition().inverse().eval() *constraintPosInBilloirFrame;
230 billoirVertex.DtWD_Sum += firstStartingPoint.covariancePosition().inverse().eval();
231 }
232
233 AmgMatrix(3,3) cov_delta_V_mat = billoirVertex.DtWD_Sum.inverse( ) ;
234
235 Amg::Vector3D delta_V = cov_delta_V_mat * billoirVertex.DtWDx_Sum;
236
237 std::vector<BilloirTrack>::iterator BTIter;
238 for ( BTIter = billoirTracks.begin(); BTIter != billoirTracks.end() ; ++BTIter )
239 {
240 // calculate chi2PerTrack = (xpVec - vtxPosInBilloirFrame).T * DtWD(track) * (xpVec - vtxPosInBilloirFrame); )
242 diff.setZero();
243 diff[0] = ( *BTIter ).xpVec[0] - delta_V[0];
244 diff[1] = ( *BTIter ).xpVec[1] - delta_V[1];
245 diff[2] = ( *BTIter ).xpVec[2] - delta_V[2];
246 ( *BTIter ).chi2 = diff.dot(( *BTIter ).DtWD* diff );
247 if ( ( *BTIter ).chi2 < 0 )
248 {
249 std::cout << "VxFastFit::calculate: error in chi2_per_track: "<<( *BTIter ).chi2<<"\n";
250 return nullptr;
251 }
252 chi2New += ( *BTIter ).chi2;
253 }
254
255 if ( constraint )
256 {
257 Amg::Vector3D deltaTrk;
258 deltaTrk.setZero();
259 // last term will also be 0 again but only in the first iteration
260 // = calc. vtx in billoir frame - ( constraint pos. in billoir frame )
261 deltaTrk[0] = delta_V[0] - ( firstStartingPoint.position() [0] - linPoint [0] );
262 deltaTrk[1] = delta_V[1] - ( firstStartingPoint.position() [1] - linPoint [1] );
263 deltaTrk[2] = delta_V[2] - ( firstStartingPoint.position() [2] - linPoint [2] );
264 chi2New += Amg::chi2(firstStartingPoint.covariancePosition().inverse().eval(), deltaTrk);
265 }
266
267 /* assign new linearization point (= new vertex position in global frame) */
268 Amg::Vector3D tmpPos ( linPoint );
269 tmpPos[0] += delta_V[0]; tmpPos[1] += delta_V[1]; tmpPos[2] += delta_V[2];
270 linPoint = tmpPos;
271
272 // msg(MSG::VERBOSE) << "Vertex of Iteration " << niter << " with chi2: " << chi2New << "\t old chi2: " << chi2 << endmsg;
273 // msg(MSG::VERBOSE) << "deltaV: (" << delta_V[0] << ", " << delta_V[1] << ", " << delta_V[2] << ")" << endmsg;
274 // msg(MSG::VERBOSE) << linPoint << endmsg;
275
276 if ( chi2New < chi2 )
277 {
278 /* Store the vertex */
279 chi2 = chi2New;
280 //const AmgMatrix(3,3) * newCovarianceMatrix = &cov_delta_V_mat ;
281 //const AmgMatrix(3,3) newErrorMatrix = newCovarianceMatrix->inverse().eval();
282 //fittedVertex = RecVertex ( linPoint.position(), newErrorMatrix, ndf, chi2 );
283
284 // The cov_delta_V_mat does not need to be inverted. -katy 2/3/16
285 fittedVertex->setPosition( linPoint );
286 fittedVertex->setCovariancePosition( cov_delta_V_mat );
287 fittedVertex->setFitQuality( chi2, ndf );
288
289 /* new go through vector and delete entries */
290 /* // TODO: not needed anymore, tracksAtVertex doesn't store pointers - just the objects themselves <David Shope> (EDM Migration) 03/21/16
291 for ( std::vector<Trk::VxTrackAtVertex*>::const_iterator itr = tracksAtVertex.begin();
292 itr != tracksAtVertex.end(); ++itr )
293 {
294 delete ( *itr );
295 }
296 */
297
298 tracksAtVertex.clear();
299
300 Amg::Vector3D pointToExtrapolateTo ( linPoint [0], linPoint [1], linPoint [2] );
301 Trk::PerigeeSurface perigeeSurface ( pointToExtrapolateTo );
302 for ( BTIter = billoirTracks.begin(); BTIter != billoirTracks.end() ; ++BTIter )
303 {
304 // you need to extrapolate the original perigee ((*BTIter).originalPerigee) really to the
305 // found vertex. The first propagation above is only to the starting point. But here we
306 // want to store it wrt. to the last fitted vertex
307 auto extrapolatedPerigee = std::unique_ptr<const Trk::TrackParameters> ( m_extrapolator->extrapolate (
308 Gaudi::Hive::currentContext(),
309 * ( *BTIter ).originalPerigee,
310 perigeeSurface ) );
311 if ( extrapolatedPerigee==nullptr )
312 {
313 extrapolatedPerigee = std::unique_ptr<const Trk::TrackParameters>(((*BTIter).originalPerigee)->clone());
314 ATH_MSG_DEBUG("Could not extrapolate these track parameters to final vertex position! Storing original position as final one ...");
315 }
316 //VxTrackAtVertex will own the clone of the extrapolatedPerigee
317 Trk::VxTrackAtVertex* tmpVxTrkAtVtx = new Trk::VxTrackAtVertex ( ( *BTIter ).chi2, extrapolatedPerigee->clone(),
318 ( *BTIter ).originalPerigee ) ;
319 tracksAtVertex.push_back ( *tmpVxTrkAtVtx );
320 // TODO: here is where the vxTracksAtVertex pointers are deleted
321 delete tmpVxTrkAtVtx; // TODO: is this ok?
322 }
323 }
324
325 if ( fabs ( chi2Old-chi2New ) < m_maxDchi2PerNdf * ndf )
326 {
327 break;
328 }
329 } // end of iteration
330 fittedVertex->vxTrackAtVertex() = tracksAtVertex;
331 //ATH_MSG_VERBOSE("Final Vertex Fitted: " << fittedVxCandidate->recVertex()); // TODO: can no longer print vertex after converting to xAOD
332 return fittedVertex.release();
333 }
334
335 xAOD::Vertex * FastVertexFitter::fit ( const std::vector<const Trk::TrackParameters*>& perigeeList ) const
336 {
337 Amg::Vector3D tmpVtx(0.,0.,0.);
338 return fit ( perigeeList, tmpVtx );
339 }
340
341 //xAOD interfaced methods. Required to un-block the current situation
342 // with the xAOD tracking design.
343 xAOD::Vertex * FastVertexFitter::fit(const std::vector<const xAOD::TrackParticle*>& vectorTrk,const Amg::Vector3D& startingPoint) const
344 {
345 xAOD::Vertex constraint;
346 constraint.makePrivateStore();
347 constraint.setPosition( startingPoint );
348 constraint.setCovariancePosition( AmgSymMatrix(3)::Zero(3,3) );
349 constraint.setFitQuality( 0.,0.);
350 return fit(vectorTrk, constraint);
351 }//end of the xAOD starting point fit method
352
353
354 xAOD::Vertex * FastVertexFitter::fit(const std::vector<const xAOD::TrackParticle*>& vectorTrk, const xAOD::Vertex& constraint) const
355 {
356 if(vectorTrk.empty())
357 {
358 msg(MSG::INFO)<<"Empty vector of tracks passed"<<endmsg;
359 return nullptr;
360 }
361
362 //making a list of perigee out of the vector of tracks
363 std::vector<const Trk::TrackParameters*> measuredPerigees;
364
365 for(const auto *i : vectorTrk)
366 {
367 const Trk::TrackParameters * tmpMeasPer = &(i->perigeeParameters());
368
369 if(tmpMeasPer!=nullptr) measuredPerigees.push_back(tmpMeasPer);
370 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?
371 }
372
373
374 xAOD::Vertex* fittedVertex = fit( measuredPerigees, constraint );
375 // fit() may return nullptr, need to protect
376 if (fittedVertex == nullptr){
377 ATH_MSG_WARNING("Failed fit, returning null vertex");
378 return nullptr;
379 }
380 //assigning the input tracks to the fitted vertex through VxTrackAtVertices
381 {
382 if( fittedVertex->vxTrackAtVertexAvailable() ) // TODO: I don't think vxTrackAtVertexAvailable() does the same thing as a null pointer check!
383 // Regretful Hindsight 8 years later: No, it doesn't!
384 {
385 if(!fittedVertex->vxTrackAtVertex().empty())
386 {
387 for(unsigned int i = 0; i <vectorTrk.size(); ++i)
388 {
389
391 linkTT->setElement(vectorTrk[i]);
392
393 // vxtrackatvertex takes ownership!
394 ( fittedVertex->vxTrackAtVertex() )[i].setOrigTrack(linkTT);
395 }//end of loop for setting orig tracks in.
396 }//end of protection against unsuccessfull updates (no tracks were added)
397 }//end of vector of tracks check
398 }//end of pointer check
399
400 //now set links to xAOD::TrackParticles directly in the xAOD::Vertex
401 unsigned int VTAVsize = fittedVertex->vxTrackAtVertex().size();
402 for (unsigned int i = 0 ; i < VTAVsize ; ++i)
403 {
404 Trk::VxTrackAtVertex* VTAV = &( fittedVertex->vxTrackAtVertex().at(i) );
405 //TODO: Will this pointer really hold 0 if no VxTrackAtVertex is found?
406 if (not VTAV){
407 ATH_MSG_WARNING (" Trying to set link to xAOD::TrackParticle. The VxTrackAtVertex is not found");
408 continue;
409 }
410
411 Trk::ITrackLink* trklink = VTAV->trackOrParticleLink();
412
413 // See if the trklink is to an xAOD::TrackParticle
414 Trk::LinkToXAODTrackParticle* linkToXAODTP = dynamic_cast<Trk::LinkToXAODTrackParticle*>(trklink);
415 if (linkToXAODTP)
416 {
417
418 //Now set the new link to the xAOD vertex
419 fittedVertex->addTrackAtVertex(*linkToXAODTP, VTAV->weight());
420
421 } else {
422 ATH_MSG_WARNING ("Skipping track. Trying to set link to something else than xAOD::TrackParticle. Neutrals not supported.");
423 }
424 } //end of loop
425
426 return fittedVertex;
427
428 }//end of the xAOD constrained fit method
429
430
431
432
433}
434
#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
void makePrivateStore()
Create a new (empty) private store for this object.
virtual StatusCode initialize() override
ToolHandle< Trk::IExtrapolator > m_extrapolator
ToolHandle< Trk::IVertexLinearizedTrackFactory > m_linFactory
virtual ~FastVertexFitter()
standard destructor
virtual xAOD::Vertex * fit(const std::vector< const Trk::TrackParameters * > &perigeeList, const Amg::Vector3D &startingPoint) const override
Interface for ParametersBase with starting point.
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 addTrackAtVertex(const ElementLink< TrackParticleContainer > &tr, float weight=1.0)
Add a new track to the vertex.
void setPosition(const Amg::Vector3D &position)
Sets the 3-position.
bool vxTrackAtVertexAvailable() const
Check if VxTrackAtVertices are attached to the object.
std::vector< Trk::VxTrackAtVertex > & vxTrackAtVertex()
Non-const access to the VxTrackAtVertex vector.
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