ATLAS Offline Software
Loading...
Searching...
No Matches
KalmanVertexOnJetAxisUpdator.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3*/
4
12#include <algorithm>
13#include <utility>
14
15
16namespace Trk{
17
18 namespace {
19 int numRow(int numVertex) {
20 return numVertex+5;
21 }
22 }
23
24
25 KalmanVertexOnJetAxisUpdator::KalmanVertexOnJetAxisUpdator(const std::string& t, const std::string& n, const IInterface* p):
26 AthAlgTool(t,n,p),
28 {
29 declareInterface<KalmanVertexOnJetAxisUpdator>(this);
30 declareProperty("initialMomentumError",m_initialMomentumError);
31 }
32
33
35 {
36 StatusCode sc = AthAlgTool::initialize();
37 if(sc.isFailure()){
38 ATH_MSG_ERROR (" Unable to initialize the AlgTool");
39 return StatusCode::FAILURE;
40 }
41 return StatusCode::SUCCESS;
42 }
43
44
46 const VxVertexOnJetAxis* vertexToUpdate,
47 VxJetCandidate* candidateToUpdate) const {
48 update(trackToAdd,vertexToUpdate,candidateToUpdate,1,false);
49 }
50
51
53 const VxVertexOnJetAxis* vertexToUpdate,
54 VxJetCandidate* candidateToUpdate) const {
55 update(trackToAdd,vertexToUpdate,candidateToUpdate,1,true);
56 }
57
58
60 const VxVertexOnJetAxis* vertexToUpdate,
61 VxJetCandidate* candidateToUpdate) const {
62 update(trackToRemove,vertexToUpdate,candidateToUpdate,-1,false);
63 }
64
65
67 const VxVertexOnJetAxis* vertexToUpdate,
68 VxJetCandidate* candidateToUpdate) const {
69 update(trackToRemove,vertexToUpdate,candidateToUpdate,-1,true);
70 }
71
72
74 const VxVertexOnJetAxis* vertexToUpdate,
75 VxJetCandidate* candidateToUpdate,
76 int sign,bool doFastUpdate) const {
77
78 //check that all pointers are there...
79 if (trackToUpdate==nullptr || vertexToUpdate==nullptr ||
80 candidateToUpdate==nullptr || std::abs(sign)!=1) {
81 ATH_MSG_WARNING (" Empty pointers then calling fit method update. No fit will be done...");
82 return;
83 }
84
85 //getting tracks at vertex and verify if your trackToUpdate is there
86 bool found = false;
87 const std::vector<Trk::VxTrackAtVertex*> & tracksAtVertex(vertexToUpdate->getTracksAtVertex());
88 for (const auto& track : tracksAtVertex){
89 if (track==nullptr) {
90 ATH_MSG_WARNING (" Empty pointer in vector of VxTrackAtVertex of the VxVertexOnJetAxis which is being fitted. No fit will be done...");
91 return;
92 }
93 if (track==trackToUpdate) {
94 found=true;
95 break;
96 }
97 }
98
99 if (!found) {
100 ATH_MSG_WARNING ("Track was not found in the VxVertexOnJetAxis's list. No fit will be done...");
101 return;
102 }
103
104 double trkWeight = trackToUpdate->weight();
105 ATH_MSG_VERBOSE ("Weight is: " << trkWeight);
106
107 const Trk::RecVertexPositions & old_vrt = candidateToUpdate->getRecVertexPositions();
108
109 if (trackToUpdate->linState()==nullptr) {
110 ATH_MSG_WARNING ("Linearized state not associated to track. Aborting fit... " << old_vrt);
111 return;
112 }
113
114 RecVertexPositions fit_vrt;
115 if (vertexToUpdate!=candidateToUpdate->getPrimaryVertex()) {
116 //if not in primary vertex, then special update
117 fit_vrt = positionUpdate(*candidateToUpdate, trackToUpdate->linState(),
118 trkWeight, sign,
119 vertexToUpdate->getNumVertex(), false,
120 doFastUpdate);
121 } else {
122 //if in primary vertex, use dist=0
123 fit_vrt = positionUpdate(*candidateToUpdate, trackToUpdate->linState(),
124 trkWeight, sign,
125 vertexToUpdate->getNumVertex(), true,
126 doFastUpdate);
127 }
128
129 //forming a final candidate
130 candidateToUpdate->setRecVertexPositions(fit_vrt);
131
132 trackToUpdate->setTrackQuality(FitQuality(fit_vrt.fitQuality().chiSquared()-old_vrt.fitQuality().chiSquared(), 2));
133
134
135 }//end of update method
136
137
138 //actual method where the position update happens
141 const LinearizedTrack * trk,
142 double trackWeight, int sign,
143 int numVertex, bool isPrimary,
144 bool doFastUpdate) const {
145
146 //linearized track information
147
148 const int numrow_toupdate = isPrimary ? 4 : numRow(numVertex);
149
150 const VertexPositions & linearizationPositions = candidateToUpdate.getLinearizationVertexPositions();
151
152 const Amg::VectorX & initialjetdir = linearizationPositions.position();
153
154 //calculate 3-dim position on jet axis from linearizationPositionVector and calculate Jacobian of transformation
155 std::pair<Amg::Vector3D,Eigen::Matrix3Xd> PosOnJetAxisAndTransformMatrix =
156 createTransformJacobian(initialjetdir, numVertex, isPrimary,
157 /*truncate=*/ !doFastUpdate); // original fast updator didn't have feature
158
159 //only position jacobian changed from A ->oldA
160 const AmgMatrix(5,3)& oldA = trk->positionJacobian();
161
162 ATH_MSG_DEBUG("the old jacobian xyz d0z0phithetaqoverp vs xyz " << oldA);
163
164 //now create the new jacobian which you should use
165 Eigen::Matrix<double,5,Eigen::Dynamic> A = oldA*PosOnJetAxisAndTransformMatrix.second;
166
167 ATH_MSG_DEBUG("the new jacobian " << A);
168
169 const AmgMatrix(5,3)& B = trk->momentumJacobian();
170 const AmgVector(5)& trackParameters = trk->expectedParametersAtPCA();
171
172 // the constant term has to be recalculated because of the use of the new parameters
173
174 const AmgVector(5) constantTerm = trk->constantTerm()
175 + oldA*PosOnJetAxisAndTransformMatrix.first
176 - A*initialjetdir.segment(0,numrow_toupdate+1);
177
178 //vertex to be updated, needs to be copied
179 RecVertexPositions myPosition = candidateToUpdate.getRecVertexPositions();
180
181 if (doFastUpdate) {
182
183 const AmgSymMatrix(5)& trackParametersCovariance = trk->expectedCovarianceAtPCA();
184
185 // old jetvertex in covariance formalism
186 const Amg::VectorX & old_vrt_pos = myPosition.position();
187 const Amg::MatrixX & old_vrt_cov = myPosition.covariancePosition();
188
189 //now create three additional variables for the momenta error
190 // (which is nearly infinite... use a big number here... then pay attention to numerical instabilities...)
191 AmgSymMatrix(3) old_vrt_cov_momentum; old_vrt_cov_momentum.setZero();
192 old_vrt_cov_momentum(0,0) = m_initialMomentumError*m_initialMomentumError;
193 old_vrt_cov_momentum(1,1) = m_initialMomentumError*m_initialMomentumError;
194 old_vrt_cov_momentum(2,2) = m_initialMomentumError*m_initialMomentumError/10000.;
195
196 //R_k_k-1 = V_k + A C_k-1 A_T + B D_k-1 B_T
197 AmgSymMatrix(5) old_residual_cov =
198 trackParametersCovariance + A * old_vrt_cov * A.transpose() +
199 B * old_vrt_cov_momentum * B.transpose();
200
201 //the nice thing of the method is that the matrix to invert (old_residual) is just 5x5,
202 //which is much better than n.track+5 x n.track+5 !!!
203 if (old_residual_cov.determinant() == 0. ) {
204 ATH_MSG_WARNING ("The old_residual matrix inversion failed");
205 ATH_MSG_WARNING ("same vertex as before is returned");
206 return Trk::RecVertexPositions(myPosition);
207 }
208
209 AmgSymMatrix(5) old_residual_cov_inv = old_residual_cov.inverse().eval();
210
211 Eigen::Matrix<double,Eigen::Dynamic,5> Kk1 = old_vrt_cov*A.transpose()*old_residual_cov_inv;
212 AmgVector(5) residual_vector=trackParameters-constantTerm-A*old_vrt_pos;
213
214 //obtain new position
215 Amg::VectorX new_vrt_pos=old_vrt_pos+Kk1*residual_vector;
216 Amg::MatrixX new_vrt_cov=old_vrt_cov+Kk1*old_residual_cov*Kk1.transpose()-2.*Kk1*A*old_vrt_cov;
217
218 double chi2 = myPosition.fitQuality().chiSquared() +
219 residual_vector.transpose()*old_residual_cov_inv*residual_vector;
220
221 //NOT SO NICE: BUT: if there was already a track at this vertex,
222 //then add 2, otherwise add 1 (additional parameter in the fit decreases +2 ndf)
223 double ndf=myPosition.fitQuality().numberDoF()+sign*2.;
224 return Trk::RecVertexPositions(new_vrt_pos,new_vrt_cov,ndf,chi2);
225 }
226
227 const AmgSymMatrix(5) & trackParametersWeight = trk->expectedWeightAtPCA();
228
229 if (trackParametersWeight.determinant()<=0) {
230 ATH_MSG_WARNING(" The determinant of the inverse of the track covariance matrix is negative: " << trackParametersWeight.determinant());
231 if(trk->expectedCovarianceAtPCA().determinant()<=0) {
232 ATH_MSG_WARNING(" As well as the determinant of the track covariance matrix: " << trk->expectedCovarianceAtPCA().determinant());
233 }
234 }
235
236 //vertex to be updated, needs to be copied
237 myPosition = candidateToUpdate.getRecVertexPositions();
238 const Amg::MatrixX & old_full_vrt_cov = myPosition.covariancePosition();
239 Eigen::FullPivLU<Amg::MatrixX> lu_decomp(old_full_vrt_cov);
240 if(!lu_decomp.isInvertible()){
241 ATH_MSG_DEBUG ("The vertex-positions covariance matrix is not invertible");
242 ATH_MSG_DEBUG ("The copy of initial vertex returned");
243 return Trk::RecVertexPositions(myPosition);
244 }
245
246 const Amg::VectorX & old_full_vrt_pos = myPosition.position();
247 Amg::VectorX old_vrt_pos = old_full_vrt_pos.segment(0,numrow_toupdate+1);
248
249 const Amg::MatrixX & old_full_vrt_weight = old_full_vrt_cov.inverse();
250
251 if (trackParametersWeight.determinant()<=0) {
252 ATH_MSG_WARNING(" The determinant of the track covariance matrix is zero or negative: " << trackParametersWeight.determinant());
253 }
254
255 Amg::MatrixX old_vrt_weight(numrow_toupdate+1,numrow_toupdate+1);
256 old_vrt_weight = old_full_vrt_weight.block(0,0,numrow_toupdate+1,numrow_toupdate+1);
257
258 //making the intermediate quantities:
259 //W_k = (B^T*G*B)^(-1)
260 AmgSymMatrix(3) S = B.transpose()*(trackParametersWeight*B);
261
262 if (S.determinant() == 0.0) {
263 ATH_MSG_WARNING ("The S matrix is not invertible");
264 ATH_MSG_WARNING ("A copy of initial vertex returned");
265 return Trk::RecVertexPositions(myPosition);
266 }
267 S = S.inverse().eval();
268
269 //G_b = G_k - G_k*B_k*W_k*B_k^(T)*G_k
270 AmgSymMatrix(5) gB = trackParametersWeight - trackParametersWeight*(B*(S*B.transpose()))*trackParametersWeight.transpose();
271
272 ATH_MSG_DEBUG("Gain factor obtained: "<<trackParametersWeight*(B*(S*B.transpose()))*trackParametersWeight.transpose());
273 ATH_MSG_DEBUG("Resulting Gain Matrix: "<<gB);
274
275 //new vertex weight matrix, called "cov" for later inversion
276 Amg::MatrixX new_vrt_cov = old_vrt_weight + trackWeight * sign * A.transpose() * ( gB * A );
277
278 if (sign<0) {
279 ATH_MSG_WARNING(" ATTENTION! Sign is " << sign);
280 }
281
282 if (new_vrt_cov.determinant()<=0) {
283 ATH_MSG_WARNING(std::scientific << "The new vtx weight matrix determinant is negative: "<< new_vrt_cov.determinant());
284 }
285
286 // now invert back to covariance
287 try {
288 // Temporarily remove smart inversion as it seems to cause negative errors from time to time
289 // Symmetrize the matix before inversion, to give ride of the precision problem of Eigen.
290 new_vrt_cov = (new_vrt_cov+new_vrt_cov.transpose().eval())/2.0;
291 smartInvert(new_vrt_cov);
292 if (new_vrt_cov.determinant() == 0.0) {
293 ATH_MSG_WARNING ("The reduced weight matrix is not invertible, returning copy of initial vertex.");
294 const Trk::RecVertexPositions& r_vtx(myPosition);
295 return r_vtx;
296 }
297 }
298
299 catch (std::string a) {
300 ATH_MSG_WARNING( a << " Previous vertex returned " );
301 const Trk::RecVertexPositions& r_vtx(myPosition);
302 return r_vtx;
303 }
304
305 ATH_MSG_DEBUG(" new vertex covariance " << new_vrt_cov);
306
307 if (new_vrt_cov.determinant()<=0) {
308 ATH_MSG_DEBUG("The new vtx cov. matrix determinant is negative: "<< new_vrt_cov.determinant());
309 }
310
311 //new vertex position
312 Amg::VectorX new_vrt_position =
313 new_vrt_cov*(old_vrt_weight * old_vrt_pos + trackWeight * sign * (A.transpose() * (gB *(trackParameters - constantTerm))));
314 ATH_MSG_DEBUG(" new position " << new_vrt_position);
315
316 //refitted track momentum
317 Amg::Vector3D newTrackMomentum = S*B.transpose()*trackParametersWeight*
318 (trackParameters - constantTerm - A*new_vrt_position);
319 ATH_MSG_DEBUG(" new momentum : " << newTrackMomentum);
320
321 //refitted track parameters
322 AmgVector(5) refTrackParameters = constantTerm + A * new_vrt_position + B * newTrackMomentum;
323
324 //parameters difference
325 AmgVector(5) paramDifference = trackParameters - refTrackParameters;
326 Amg::VectorX posDifference = new_vrt_position - old_vrt_pos;
327
328 double chi2 = myPosition.fitQuality().chiSquared()+
329 (paramDifference.transpose()*trackParametersWeight*paramDifference)(0,0)*trackWeight*sign+
330 (posDifference.transpose()*old_vrt_weight*posDifference)(0,0); // matrices are 1x1 but make scalar through (0,0)
331
332 ATH_MSG_DEBUG(" new chi2 : " << chi2);
333
334 //NOT SO NICE: BUT: if there was already a track at this vertex,
335 //then add 2, otherwise add 1 (additional parameter in the fit decreases +2 ndf)
336 double ndf=myPosition.fitQuality().numberDoF()+sign*2.;
337
338 for (int i=0; i<new_vrt_cov.rows(); i++){
339 bool negative(false);
340 if (new_vrt_cov(i,i)<=0.) {
341 ATH_MSG_WARNING(" Diagonal element ("<<i<<","<<i<<") of covariance matrix after update negative: "<<new_vrt_cov(i,i) <<". Giving back previous vertex.");
342 negative=true;
343 }
344 if (negative) {
345 const Trk::RecVertexPositions& r_vtx(myPosition);
346 return r_vtx;
347 }
348 }
349
350 Amg::VectorX new_full_vrt_pos(old_full_vrt_pos);
351 new_full_vrt_pos.segment(0,new_vrt_position.rows()) = new_vrt_position;
352 Amg::MatrixX new_full_vrt_cov(myPosition.covariancePosition());
353 new_full_vrt_cov.block(0,0,new_vrt_cov.rows(),new_vrt_cov.cols()) = new_vrt_cov;
354
355 Trk::RecVertexPositions r_vtx(new_full_vrt_pos,new_full_vrt_cov,ndf, chi2);
356 return r_vtx;
357
358 //method which avoids inverting huge covariance matrix still needs to be implemented
359
360 } //end of position update method
361
363 const VxVertexOnJetAxis* vertexToUpdate,
364 VxJetCandidate* vertexCandidate) const {
365
366 //check that all pointers are there...
367 if (vertexCandidate==nullptr || trackToUpdate==nullptr) {
368 ATH_MSG_WARNING( " Empty pointers then calling fit method updateChi2NdfInfo. No update will be done..." );
369 return;
370 }
371
372 //getting tracks at vertex and verify if your trackToUpdate is there
373 bool found = false;
374 const std::vector<Trk::VxTrackAtVertex*> & tracksAtVertex(vertexToUpdate->getTracksAtVertex());
375
376 for (const auto& track : tracksAtVertex) {
377 if (track==nullptr) {
378 ATH_MSG_WARNING( " Empty pointer in vector of VxTrackAtVertex of the VxVertexOnJetAxis whose chi2 is being updated. No update will be done..." );
379 return;
380 }
381 if (track==trackToUpdate) {
382 found=true;
383 break;
384 }
385 }
386
387 if (!found) {
388 ATH_MSG_WARNING( " Track was not found in the VxVertexOnJetAxis's list. No update will be done..." );
389 return;
390 }
391
392 double trkWeight = trackToUpdate->weight();
393 ATH_MSG_VERBOSE ("Weight is: " << trkWeight);
394
395 Trk::RecVertexPositions vertexPositions = vertexCandidate->getRecVertexPositions();
396
397 if (trackToUpdate->linState()==nullptr) {
398 ATH_MSG_WARNING( "Linearized state not associated to track. Aborting chi2 update... " << vertexPositions );
399 return;
400 }
401
402 double chi2(vertexPositions.fitQuality().chiSquared());
403 ATH_MSG_VERBOSE ("old chi2: " << chi2);
404
405 if (vertexToUpdate!=vertexCandidate->getPrimaryVertex()) {
406 //if not in primary vertex, then special update
407 chi2+=calculateTrackChi2(*vertexCandidate, trackToUpdate->linState(),
408 trkWeight,
409 vertexToUpdate->getNumVertex(), false);
410 } else {
411 chi2+=calculateTrackChi2(*vertexCandidate, trackToUpdate->linState(),
412 trkWeight,
413 vertexToUpdate->getNumVertex(), true);
414 }
415
416 vertexPositions.setFitQuality(FitQuality(chi2,vertexPositions.fitQuality().numberDoF()));
417
418 ATH_MSG_VERBOSE (" new chi2: " << chi2);
419
420
421 trackToUpdate->setTrackQuality(FitQuality(chi2-vertexPositions.fitQuality().chiSquared(),
422 trackToUpdate->trackQuality().numberDoF()));
423
424 vertexCandidate->setRecVertexPositions(vertexPositions);
425
426 }
427
428
430 const LinearizedTrack * trk,
431 double trackWeight,
432 int numVertex, bool isPrimary) const {
433
434
435 //linearized track information
436 const VertexPositions & linearizationPositions = vertexCandidate.getLinearizationVertexPositions();
437 const Amg::VectorX & initialjetdir = linearizationPositions.position();
438
439 //calculate 3-dim position on jet axis from linearizationPositionVector and calculate Jacobian of transformation
440 std::pair<Amg::Vector3D,Eigen::Matrix3Xd> PosOnJetAxisAndTransformMatrix =
441 createTransformJacobian(initialjetdir, numVertex, isPrimary, true);
442
443 //only position jacobian changed from A ->oldA
444 const AmgMatrix(5,3)& oldA = trk->positionJacobian();
445
446 //now create the new jacobian which you should use
447 Eigen::Matrix<double,5,Eigen::Dynamic> A=oldA*PosOnJetAxisAndTransformMatrix.second;
448
449 const AmgMatrix(5,3)& B = trk->momentumJacobian();
450 const AmgVector(5) & trackParameters = trk->expectedParametersAtPCA();
451
452 AmgVector(5) constantTerm = trk->constantTerm() + oldA*PosOnJetAxisAndTransformMatrix.first
453 -A*initialjetdir;
454
455 const AmgSymMatrix(5) & trackParametersWeight = trk->expectedWeightAtPCA();
456
457 const RecVertexPositions & myPosition = vertexCandidate.getRecVertexPositions();
458 const Amg::VectorX & new_vrt_position = myPosition.position();
459
460 AmgSymMatrix(3) S = B.transpose()*trackParametersWeight*B;
461 if (S.determinant() == 0.0) {
462 ATH_MSG_WARNING ("The matrix S is not invertible, return chi2 0");
463 return -0.;
464 }
465 S = S.inverse().eval();
466
467 //refitted track momentum
468 Amg::Vector3D newTrackMomentum = S*B.transpose()*trackParametersWeight*(trackParameters - constantTerm - A*new_vrt_position);
469
470 //refitted track parameters
471 AmgVector(5) refTrackParameters = constantTerm + A * new_vrt_position + B * newTrackMomentum;
472
473 //parameters difference
474 AmgVector(5) paramDifference = trackParameters - refTrackParameters;
475
476 return (paramDifference.transpose()*trackParametersWeight*paramDifference)(0,0)*trackWeight;
477
478 }
479
480
482
483 //check that all pointers are there...
484 if (vertexCandidate==nullptr) {
485 ATH_MSG_WARNING( " Empty pointers then calling chi2 update method updateVertexChi2. No update will be done..." );
486 return;
487 }
488
489 const Trk::RecVertexPositions & OldPosition = vertexCandidate->getConstraintVertexPositions();
490 const Amg::VectorX & old_vrt_position = OldPosition.position();
491 const Amg::MatrixX & old_vrt_weight = OldPosition.covariancePosition().inverse();
492
493 const RecVertexPositions & myPosition = vertexCandidate->getRecVertexPositions();
494 const Amg::VectorX & new_vrt_position = myPosition.position();
495
496 AmgVector(5) posDifference = (new_vrt_position - old_vrt_position).segment(0,5);
497
498 double chi2 = (posDifference.transpose()*old_vrt_weight.block<5,5>(0,0)*posDifference)(0,0);
499
500#ifdef Updator_DEBUG
501 std::cout << " vertex diff chi2 : " << chi2 << std::endl;
502#endif
503
504 Trk::RecVertexPositions vertexPositions = vertexCandidate->getRecVertexPositions();
505
506 vertexPositions.setFitQuality(FitQuality(vertexPositions.fitQuality().chiSquared()+chi2,
507 vertexPositions.fitQuality().numberDoF()));
508
509 vertexCandidate->setRecVertexPositions(vertexPositions);
510
511 }
512
513
514 std::pair<Amg::Vector3D,Eigen::Matrix3Xd>
516 int numVertex,
517 bool isPrimary,
518 bool truncateDimensions) const {
519
520 //now modify the position jacobian in the way you need!
521 const unsigned int numrow_toupdate = isPrimary ? 4: numRow(numVertex);
522 const unsigned int matrixdim = truncateDimensions ?
523 numrow_toupdate+1 :
524 initialjetdir.rows();
525
526 //store values of RecVertexOnJetAxis
527 double xv = initialjetdir[Trk::jet_xv];
528 double yv = initialjetdir[Trk::jet_yv];
529 double zv = initialjetdir[Trk::jet_zv];
530 double phi = initialjetdir[Trk::jet_phi];
531 double theta = initialjetdir[Trk::jet_theta];
532 double dist = 0;
533 if (!isPrimary) {
534 dist = initialjetdir[numrow_toupdate];
535 }
536
537 ATH_MSG_VERBOSE ("actual initialjetdir values : xv " << xv << " yv " << yv << " zv " << zv << " phi " << phi << " theta " << theta << " dist " << dist);
538 ATH_MSG_VERBOSE ("numrow_toupdate " << numrow_toupdate << " when primary it's -5");
539
540 //now create matrix transformation to go from vertex position jacobian to vertex in jet jacobian
541 //(essentially Jacobian of spherical coordinate system transformation)
542 Eigen::Matrix3Xd transform(3,matrixdim);
543 transform.setZero();
544 transform(0,Trk::jet_xv) = 1;
545 transform(1,Trk::jet_yv) = 1;
546 transform(2,Trk::jet_zv) = 1;
547 if (!isPrimary) {
548 transform(0,Trk::jet_phi) = -dist*sin(theta)*sin(phi);
549 transform(0,Trk::jet_theta) = dist*cos(theta)*cos(phi);
550 transform(0,numrow_toupdate)= sin(theta)*cos(phi);
551 transform(1,Trk::jet_phi) = dist*sin(theta)*cos(phi);
552 transform(1,Trk::jet_theta) = dist*cos(theta)*sin(phi);
553 transform(1,numrow_toupdate)= sin(theta)*sin(phi);
554 transform(2,Trk::jet_theta) = -dist*sin(theta);
555 transform(2,numrow_toupdate)= cos(theta);
556 }
557
558 ATH_MSG_DEBUG ("The transform matrix xyzphitheta is: " << transform);
559
560 Amg::Vector3D posOnJetAxis;
561 posOnJetAxis(0) = xv+dist*cos(phi)*sin(theta);
562 posOnJetAxis(1) = yv+dist*sin(phi)*sin(theta);
563 posOnJetAxis(2) = zv+dist*cos(theta);
564
565 ATH_MSG_DEBUG("the lin position on jet axis x " << xv+dist*cos(phi)*sin(theta) << " y " << yv+dist*sin(phi)*sin(theta) << " z " << zv+dist*cos(theta));
566
567 return std::pair<Amg::Vector3D,Eigen::Matrix3Xd>(posOnJetAxis,transform);
568 }
569
570
572 {
573
574 int numRows = new_vrt_weight.rows();
575 if (numRows<=6) {
576 if (new_vrt_weight.determinant() ==0) {
577 throw std::string("The reduced weight matrix is not invertible. Previous vertex returned ");
578 }
579 new_vrt_weight = new_vrt_weight.inverse().eval();
580 return;
581 }
582
583 AmgSymMatrix(5) A = new_vrt_weight.block<5,5>(0,0);
584 //Eigen::Dynamic we are not sure about the number of Row minus 5, so a dynamic one is given here.
585 Eigen::Matrix<double,5,Eigen::Dynamic> B(5,numRows-5);
586 B.setZero();
587 for (int i=0; i<5; ++i) {
588 for (int j=5; j<numRows; ++j) {
589 B(i,j-5)=new_vrt_weight(i,j);
590 }
591 }
592
593 // will be of dim (numrows-5)
594 Amg::MatrixX D = new_vrt_weight.block(5,5,numRows-5,numRows-5);
595
596 // Eigen's diagonal matrices don't have the full MatrixBase members like determinant(),
597 // similarity() etc needed later -> therefore do not use them and invert by hand.
598 // The inverse of D is a diagonal matrix of the inverted diagonal elements -WL
599 // Eigen::DiagonalMatrix<double,Eigen::Dynamic> DdiagINV(D); do something...
600 for (unsigned int i=0; i<D.rows(); i++) {
601 if ( D(i,i) == 0.) {
602 throw std::string("Cannot invert diagonal matrix...");
603 break;
604 }
605
606 //Set the non-diagonal elements of D to be zero, which is as expected; the numerical proplem will change them into non-zero.
607 for(unsigned int j=0; j<i; j++){
608 D(i,j) = 0;
609 D(j,i) = 0;
610 }
611 D(i,i) = 1./D(i,i);
612 }
613
614 Amg::MatrixX E = A - B*(D*B.transpose());
615 if (E.determinant() == 0.) {
616 throw std::string("Cannot invert E matrix...");
617 }
618 E = E.inverse().eval();
619
620 Amg::MatrixX finalWeight(numRows,numRows);
621 finalWeight.setZero();
622 finalWeight.block<5,5>(0,0) = E;
623 Eigen::Matrix<double,5,Eigen::Dynamic> F = -E*(B*D);
624 finalWeight.block(0,5,5,D.rows()) = F;
625 finalWeight.block(5,0,D.rows(),5) = F.transpose();
626 finalWeight.block(5,5,D.rows(),D.rows()) =
627 D+(D*((B.transpose()*(E*B))*D.transpose()));
628
629 new_vrt_weight = finalWeight;
630
631 if (new_vrt_weight.determinant()<=0) {
632 ATH_MSG_DEBUG("smartInvert() new_vrt_weight FINAL det. is: " << new_vrt_weight.determinant());
633 }
634
635 }
636
637}//end of namespace definition
#define ATH_MSG_ERROR(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
#define AmgSymMatrix(dim)
#define AmgVector(rows)
#define AmgMatrix(rows, cols)
static Double_t a
static Double_t sc
#define F(x, y, z)
Definition MD5.cxx:112
int sign(int a)
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)
Class to represent and store fit qualities from track reconstruction in terms of and number of degre...
Definition FitQuality.h:97
int numberDoF() const
returns the number of degrees of freedom of the overall track or vertex fit as integer
Definition FitQuality.h:60
double chiSquared() const
returns the of the overall track fit
Definition FitQuality.h:56
void updateChi2NdfInfo(VxTrackAtVertex *trackToUpdate, const VxVertexOnJetAxis *vertexToUpdate, VxJetCandidate *vertexCandidate) const
Obsolete (will be removed - not in use, however migrated to eigen before finding out -WL) Updates onl...
void addWithFastUpdate(VxTrackAtVertex *trackToAdd, const VxVertexOnJetAxis *vertexToUpdate, VxJetCandidate *candidateToUpdate) const
void remove(VxTrackAtVertex *trackToRemove, const VxVertexOnJetAxis *vertexToUpdate, VxJetCandidate *candidateToUpdate) const
Method removing already added track from the fit along the flight axis, where you specify from what v...
void add(VxTrackAtVertex *trackToAdd, const VxVertexOnJetAxis *vertexToUpdate, VxJetCandidate *candidateToUpdate) const
Method updating the fit along the flight axis (VxJetCandidate) with a track (VxTrackOnJetAxis) which ...
void updateVertexChi2(VxJetCandidate *vertexCandidate) const
Obsolete (will be removed - not in use, however moved to eigen before finding out -WL).
void smartInvert(Amg::MatrixX &new_vrt_cov) const
void removeWithFastUpdate(VxTrackAtVertex *trackToRemove, const VxVertexOnJetAxis *vertexToUpdate, VxJetCandidate *candidateToUpdate) const
KalmanVertexOnJetAxisUpdator(const std::string &t, const std::string &n, const IInterface *p)
Constructor.
void update(VxTrackAtVertex *trackToUpdate, const VxVertexOnJetAxis *vertexToUpdate, VxJetCandidate *candidateToUpdate, int sign, bool doFastUpdate) const
Internal method to do the Kalman Update.
Trk::RecVertexPositions positionUpdate(VxJetCandidate &vertexCandidate, const LinearizedTrack *trk, double trackWeight, int sign, int numVertex, bool isPrimary, bool doFastUpdate) const
Method to do the Kalman Update of the positions of the fit along the flight axis with a single new tr...
double calculateTrackChi2(const VxJetCandidate &vertexCandidate, const LinearizedTrack *trk, double trackWeight, int numVertex, bool isPrimary=false) const
Internal method where the chi2/ndf update is actually done.
std::pair< Amg::Vector3D, Eigen::Matrix3Xd > createTransformJacobian(const Amg::VectorX &initialjetdir, int numVertex, bool isPrimary, bool truncate) const
Method to create the Jacobian needed to go to the space of single vertices to the space of the variab...
Amg::MatrixX const & covariancePosition() const
return the covDeltaV matrix of the vertex fit
void setFitQuality(const Trk::FitQuality &)
const Trk::FitQuality & fitQuality() const
Fit quality access method.
VertexPositions class to represent and store a vertex.
const Amg::VectorX & position() const
return position of vertex
const Trk::VertexPositions & getLinearizationVertexPositions() const
const Trk::RecVertexPositions & getConstraintVertexPositions() const
const VxVertexOnJetAxis * getPrimaryVertex(void) const
const Trk::RecVertexPositions & getRecVertexPositions() const
void setRecVertexPositions(const Trk::RecVertexPositions &)
The VxTrackAtVertex is a common class for all present TrkVertexFitters The VxTrackAtVertex is designe...
void setTrackQuality(const FitQuality &trkQuality)
Set methods for various components.
LinearizedTrack * linState(void)
Access method for the perigee linearized track.
FitQuality trackQuality(void) const
Returns a pointer to the original track if any.
double weight(void) const
Information about the weight of track in fit (given back by annealing): weight=ndf/2.
VxVertexOnJetAxis inherits from Vertex.
int getNumVertex(void) const
Get Method for NumVertex.
const std::vector< VxTrackAtVertex * > & getTracksAtVertex(void) const
get Tracks At Vertex Method
double chi2(TH1 *h0, TH1 *h1)
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic Matrix - dynamic allocation.
Eigen::Matrix< double, 3, 1 > Vector3D
Eigen::Matrix< double, Eigen::Dynamic, 1 > VectorX
Dynamic Vector - dynamic allocation.
Ensure that the ATLAS eigen extensions are properly loaded.
@ theta
Definition ParamDefs.h:66
@ phi
Definition ParamDefs.h:75
@ jet_zv
position x,y,z of primary vertex
hold the test vectors and ease the comparison