ATLAS Offline Software
Loading...
Searching...
No Matches
AnalyticalDerivCalcTool.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#include "TrkTrack/Track.h"
9
12
15
21
23
25
26#include <string>
27#include <memory>
28
29namespace Trk {
30
31 //________________________________________________________________________
33 const std::string & name,
34 const IInterface * parent)
35 : AthAlgTool(type,name,parent)
36 {
37 declareInterface<IDerivCalcTool>(this);
38 }
39
40 //________________________________________________________________________
42 {
43 if (m_alignModuleTool.retrieve().isFailure()) {
44 ATH_MSG_FATAL("Could not get " << m_alignModuleTool);
45 return StatusCode::FAILURE;
46 }
47 ATH_MSG_INFO("Retrieved " << m_alignModuleTool);
48
49 if (detStore()->retrieve(m_idHelper, "AtlasID").isFailure()) {
50 ATH_MSG_FATAL("Could not get AtlasDetectorID helper");
51 return StatusCode::FAILURE;
52 }
54
55 return StatusCode::SUCCESS;
56 }
57
58 //________________________________________________________________________
60 {
61 ATH_MSG_DEBUG("in AnalyticalDerivCalcTool::finalize()");
62 return StatusCode::SUCCESS;
63 }
64
65 //________________________________________________________________________
67 {
69 checkResidualType(alignTrack);
70
71 // create table of modules for checking whether the module
72 // is hit by the track or not
73 int nModules = m_alignModuleTool->alignModules1D()->size();
74 std::vector<bool> hitModules(nModules,false);
75
76 // loop over AlignTSOSCollection,
77 // find modules that are in the AlignModuleList,
78 std::vector<AlignModule *> alignModules;
79 AlignTSOSCollection::iterator atsosItr = alignTrack->firstAtsos();
80 for (; atsosItr != alignTrack->lastAtsos(); ++atsosItr) {
81 AlignModule * module=(*atsosItr)->module();
82 if (module)
83 ATH_MSG_DEBUG("have ATSOS for module "<<module->identify());
84 else
85 ATH_MSG_DEBUG("no module!");
86
87 if (!(*atsosItr)->isValid() || !module)
88 continue;
89
90 // if the module is not yet in the list for this track, add it
91 if(!hitModules[module->identifyHash()]) {
92 hitModules[module->identifyHash()] = true;
93 alignModules.push_back(module);
94 }
95 }
96
97 // Determine derivatives from shifting these modules
98 std::vector<AlignModuleDerivatives> * derivatives = new std::vector<AlignModuleDerivatives>;
99 std::vector<AlignModule *>::iterator moduleIt = alignModules.begin();
100 for ( ; moduleIt!=alignModules.end(); ++moduleIt) {
101 std::vector<Amg::VectorX> deriv_vec = getDerivatives(alignTrack,*moduleIt);
102 derivatives->push_back(make_pair(*moduleIt,deriv_vec));
103 }
104
105 // alignTrack takes care of deleting the derivatives
106 ATH_MSG_DEBUG("setting matrix derivatives");
107 alignTrack->setDerivatives(derivatives);
108
109 ATH_MSG_DEBUG("returning from setDerivatives");
110
111 return true;
112 }
113
114 //________________________________________________________________________
116 {
117 static std::once_flag flag;
118 std::call_once(flag, [&]() {
119 if(m_logStream) {
120 *m_logStream<<"*************************************************************"<<std::endl;
121 *m_logStream<<"*************************************************************"<<std::endl;
122 *m_logStream<<"*** *****"<<std::endl;
123
125 *m_logStream<<"*** Running full LOCAL Chi2 method *****"<<std::endl;
126 else
127 *m_logStream<<"*** Running full GLOBAL Chi2 method *****"<<std::endl;
128
129 *m_logStream<<"*** using analytical derivatives *****"<<std::endl;
130
132 std::string resType = "HitOnly ";
134 resType = "Unbiased";
135 *m_logStream<<"*** with residual type: "<<resType<<" *****"<<std::endl;
136 }
137
138 *m_logStream<<"*** *****"<<std::endl;
139 *m_logStream<<"*************************************************************"<<std::endl;
140 }
141 });
142
143 // get inverse local error matrix of the track
144 const Amg::MatrixX * Vinv = alignTrack->localErrorMatrixInv();
145 if(!checkValidity(*Vinv)) {
146 ATH_MSG_WARNING("Inverse local error matrix is invalid, skipping the track");
147 return false;
148 }
149 ATH_MSG_DEBUG("V inverse (diagonal only):");
150 if (msgLvl(MSG::DEBUG)) {
151 for (int i=0;i<Vinv->rows();i++) msg()<<(*Vinv)(i,i)<<" ";
152 msg()<<endmsg;
153 }
154
155 // ========================
156 // setup local chi2 method
157 // ========================
158 if (m_useLocalSetting) {
159 ATH_MSG_DEBUG("setting Residual covariance matrix for local method");
160
161 // for local method we only need the Vinv
162 const Amg::MatrixX * Vinv = alignTrack->localErrorMatrixInv();
163 Amg::MatrixX * W = new Amg::MatrixX(*Vinv);
164
165 // if we want to ignore the real errors of measurements for a particular subretector
166 // (we should add something similar for Muon detectors)
168
170 ATH_MSG_DEBUG("Ignoring measured errors for Pixel clusters, using intrinsic errors");
172 ATH_MSG_DEBUG("Ignoring measured errors for SCT clusters, using intrinsic errors");
174 ATH_MSG_DEBUG("Ignoring measured errors for TRT clusters, using intrinsic errors");
175
176 int index(0);
177 AlignTSOSCollection::const_iterator itAtsos = alignTrack->firstAtsos();
178 AlignTSOSCollection::const_iterator itAtsos_end = alignTrack->lastAtsos();
179 for ( ; itAtsos != itAtsos_end; ++itAtsos) {
180 const AlignTSOS * atsos = *itAtsos;
181 if (!atsos->isValid())
182 continue;
183
185 (*W)(index,index) = 1./(0.05*0.05/12);
186 (*W)(index+1,index+1) = 1./(0.4*0.4/12);
187 }
189 (*W)(index,index) = 1./(0.1*0.1/12);
191 (*W)(index,index) = 1./(0.5*0.5/12);
192
193 index += atsos->nResDim();
194 }
195 }
196
197 ATH_MSG_DEBUG("setting local weight matrix W ( "<<W->rows()<<" x "<<W->cols()<<" ) (diagonal only):");
198 if (msgLvl(MSG::DEBUG)) {
199 for (int i=0;i<W->rows();i++) msg()<<(*W)(i,i)<<" ";
200 msg()<<endmsg;
201 }
202 alignTrack->setWeightMatrix(W);
203
204 Amg::MatrixX * W1st = new Amg::MatrixX(*W);
205 alignTrack->setWeightMatrixFirstDeriv(W1st);
206
207 return true;
208 }
209
210 // ========================
211 // setup global chi2 method
212 // ========================
213
214 // get the ingredients for calculating R = V - Q
215 const Amg::MatrixX * V = alignTrack->localErrorMatrix();
216 ATH_MSG_DEBUG("V ( "<<V->rows()<<" x "<<V->cols()<<" ) (diagonal only):");
217 if (msgLvl(MSG::DEBUG)) {
218 for (int i=0;i<V->rows();i++) msg()<<(*V)(i,i)<<" ";
219 msg()<<endmsg;
220 }
221
222 const int outputdim = alignTrack->nAlignTSOSMeas();
223
224 Amg::MatrixX Q(outputdim, outputdim); //symmetric matrix
225 if (!getTrkParamCovMatrix(alignTrack, Q))
226 return false;
227 ATH_MSG_DEBUG("Q ( "<<Q.rows()<<" x "<<Q.cols()<<" )");
228 ATH_MSG_DEBUG("Q: "<<Q);
229
230 // calculate R
231 const Amg::MatrixX R = (*V) - Q;
232 if (!checkValidity(R)) {
233 ATH_MSG_WARNING("Matrix R = V - HCH is invalid, skipping the track");
234 return false;
235 }
236 ATH_MSG_DEBUG("R ( "<<R.rows()<<" x "<<R.cols()<<" )");
237 ATH_MSG_DEBUG("R: "<<R);
238
239 // calculate weight matrix and set it
240 Amg::MatrixX * W = new Amg::MatrixX(outputdim,outputdim); //symmetric matrix
241 *W = ((*Vinv) * R * (*Vinv));
242
243 if (!checkValidity(*W)) {
244 ATH_MSG_DEBUG("Weight matrix is invalid, skipping the track");
245 delete W;
246 return false;
247 }
248 ATH_MSG_DEBUG("setting weight: "<<(*W));
249 alignTrack->setWeightMatrix(W);
250
251 // for 1st derivatives the weight matrix is just the V^-1
252 // it has been chacked above so no need to do it again
253 Amg::MatrixX * W1st = new Amg::MatrixX(*Vinv); //symmetric matrix
254 ATH_MSG_DEBUG("setting weight for 1st derivatives (diagonal only): ");
255 if (msgLvl(MSG::DEBUG)) {
256 for (int i=0;i<W1st->rows();i++) msg()<<(*W1st)(i,i)<<" ";
257 msg()<<endmsg;
258 }
259 alignTrack->setWeightMatrixFirstDeriv(W1st);
260
261 return true;
262 }
263
264 //________________________________________________________________________
265 bool AnalyticalDerivCalcTool::getTrkParamCovMatrix(const AlignTrack * alignTrack, Amg::MatrixX & Q /*symmetric matrix*/) const
266 {
267
268 // get derivative matrices from fitter
269 const Amg::MatrixX * H0 = alignTrack->derivativeMatrix();
270 const Amg::MatrixX * C = alignTrack->fullCovarianceMatrix(); //symmetric matrix
271
272 // H0 is a q0 x p matrix,
273 // C is a p x p matrix,
274 // q0 = number of tsos measurements
275 // p = number perigee params+2*nscat+nbrem
276
277 if( H0==nullptr || C==nullptr) {
278 ATH_MSG_ERROR("no derivative matrix or cov matrix stored on AlignTrack!"
279 << "This should have been done in AlignTrackPreProcessor!"
280 << H0 << " " << C );
281 return false;
282 }
283
284 ATH_MSG_DEBUG("H0 ( "<<H0->rows()<<" x "<<H0->cols()<<" )");
285 ATH_MSG_DEBUG("H0: "<<(*H0));
286 ATH_MSG_DEBUG("C ( "<<C->rows()<<" x "<<C->cols()<<" )");
287 ATH_MSG_DEBUG("C: "<<(*C));
288
289
290 int Csize(C->rows());
291 Amg::MatrixX CC(*C); // take a copy of C //symmetric matrix
292 int ierr(0);
293 bool amendC( !(alignTrack->refitD0() && alignTrack->refitZ0() &&
294 alignTrack->refitPhi() && alignTrack->refitTheta() &&
295 alignTrack->refitQovP()) );
296
297 // amendC = true; // FUDGE!
298
299 if( amendC ) {
300 // test with AlSymMat:
301 // build AlSymMat instance from
302 auto CA = std::make_unique<AlSymMat>(Csize);
303
304 // take a copy of C:
305 for( int ii=0; ii<Csize; ++ii ) {
306 for( int jj=ii; jj<Csize; ++jj ) {
307 CA->elemr(ii,jj) = (*C)(ii,jj);
308 }
309 }
310
311 // first inversion:
312 ierr = CA->invert();
313 if( ierr ) {
314 ATH_MSG_ERROR("First inversion of matrix CA failed with LAPACK status flag " << ierr);
315 return false;
316 } else {
317 // disable selected track parametrs (remove from refit).
318 // It is your duty to assure that corresponding constraints have been imposed!
319 if( !(alignTrack->refitD0()) ) {
320 for(int ii=0; ii<(Csize); ++ii) CA->elemr(0,ii)=0.0; // should do the trick. It is a CLHEP::HepSymMatrix!
321 CA->elemr(0,0)=1.0;
322 }
323 if( !(alignTrack->refitZ0()) ) {
324 for(int ii=0; ii<(Csize); ++ii) CA->elemr(1,ii)=0.0; // should do the trick. It is a CLHEP::HepSymMatrix!
325 CA->elemr(1,1)=1.0;
326 }
327 if( !(alignTrack->refitPhi()) ) {
328 for(int ii=0; ii<(Csize); ++ii) CA->elemr(2,ii)=0.0; // should do the trick. It is a CLHEP::HepSymMatrix!
329 CA->elemr(2,2)=1.0;
330 }
331 if( !(alignTrack->refitTheta()) ) {
332 for(int ii=0; ii<(Csize); ++ii) CA->elemr(3,ii)=0.0; // should do the trick. It is a CLHEP::HepSymMatrix!
333 CA->elemr(3,3)=1.0;
334 }
335 if( !(alignTrack->refitQovP()) ) {
336 for(int ii=0; ii<(Csize); ++ii) CA->elemr(4,ii)=0.0; // should do the trick. It is a CLHEP::HepSymMatrix!
337 CA->elemr(4,4)=1.0;
338 }
339
340
341 // invert back:
342 ierr = CA->invert();
343 if( ierr ) {
344 ATH_MSG_ERROR("Second inversion of matrix CA failed with LAPACK status flag " << ierr);
345 return false;
346 }
347
348 // copy back to CC:
349 for( int ii=0; ii<Csize; ++ii ) {
350 for( int jj=ii; jj<Csize; ++jj ) {
351 CC(ii,jj) = CA->elemc(ii,jj);
352 }
353 }
354
355 // clear the disabled rows/collumns
356 if( !(alignTrack->refitD0()) ) for(int ii=0; ii<(Csize); ++ii){ CC(0,ii)=0.0; CC(ii,0)=0.0; }; // should do the trick.
357 if( !(alignTrack->refitZ0()) ) for(int ii=0; ii<(Csize); ++ii){ CC(1,ii)=0.0; CC(ii,1)=0.0; }; // should do the trick.
358 if( !(alignTrack->refitPhi()) ) for(int ii=0; ii<(Csize); ++ii){ CC(2,ii)=0.0; CC(ii,2)=0.0; }; // should do the trick.
359 if( !(alignTrack->refitTheta()) ) for(int ii=0; ii<(Csize); ++ii){ CC(3,ii)=0.0; CC(ii,3)=0.0; }; // should do the trick.
360 if( !(alignTrack->refitQovP()) ) for(int ii=0; ii<(Csize); ++ii){ CC(4,ii)=0.0; CC(ii,4)=0.0; }; // should do the trick.
361
362
363 }
364
365 }
366
367
368
369 int nMeas = H0->rows();
370 int nAtsos = alignTrack->nAlignTSOSMeas();
371 ATH_MSG_DEBUG("nMeas: "<<nMeas);
372
373 //CLHEP::HepSymMatrix HCH(nMeas,0);
374 Amg::MatrixX HCH(nAtsos,nAtsos);
375 HCH = CC.similarity( *H0 );
376
377 ATH_MSG_DEBUG("HCH ( "<<HCH.rows()<<" x "<<HCH.cols()<<" )");
378 ATH_MSG_DEBUG("HCH: "<<HCH);
379
380 //
381 // get indices of HCH matrix corresponding to alignTSOSs in alignTrack
382 const AlignTSOSCollection * alignTSOSCollection = alignTrack->alignTSOSCollection();
383
384 std::vector<int> matrixIndices(nMeas);
385
386 int imeas(-1);
387 for (const TrackStateOnSurface* tsos : *alignTrack->trackStateOnSurfaces()){
388
389 ATH_MSG_DEBUG("tsos: "<<tsos->dumpType());
390
391 // get tsos and make sure it is a RIO_OnTrack
392 if (tsos->type(TrackStateOnSurface::Outlier))
393 continue;
394
395 // RIO
396 if (!tsos->type(TrackStateOnSurface::Scatterer)) {
397 ATH_MSG_DEBUG("not scatterer, trying rio");
398
399 const MeasurementBase * mesb = tsos->measurementOnTrack();
400 const RIO_OnTrack * rio = dynamic_cast<const RIO_OnTrack *>(mesb);
401 const CompetingRIOsOnTrack * crio = dynamic_cast<const CompetingRIOsOnTrack *>(mesb);
402 if (!rio && crio)
403 rio=&crio->rioOnTrack(0);
404
405 if (rio==nullptr)
406 continue;
407
408 ++imeas;
409 matrixIndices[imeas]=-1;
410
411 Identifier tsosId = rio->identify();
412 ATH_MSG_DEBUG("have tsos with Id "<<tsosId);
413
414 // get matching alignTSOS and store track index in goodMatrixIndices
415 int iameas(0);
416 for (const AlignTSOS* atsos : *alignTSOSCollection) {
417
418 if (!atsos->isValid())
419 continue;
420
421 if (atsos->type(TrackStateOnSurface::Scatterer))
422 ATH_MSG_ERROR("can't use scatterers on AlignTrack yet for analytical derivatives!");
423
424 const RIO_OnTrack * atsos_rio = atsos->rio();
425 if (atsos_rio) {
426// ATH_MSG_DEBUG("tsosId / atsosId : "<<tsosId<<" / "<<atsos_rio->identify());
427
428 if (atsos_rio->identify()==tsosId) {
429 matrixIndices[imeas]=iameas;
430 ATH_MSG_DEBUG("matrixIndices["<<imeas<<"]="<<iameas);
431
432 // for Pixel we have two measurements
433 if (atsos->nResDim()>1)
434 {
435 imeas++;
436 iameas++;
437 matrixIndices[imeas]=iameas;
438 ATH_MSG_DEBUG("matrixIndices["<<imeas<<"]="<<iameas);
439 }
440 break;
441 }
442 // for Pixel we have two measurements
443 else if(atsos->nResDim()>1)
444 iameas++;
445 }
446 iameas++;
447 }
448
449 // even when the Pixel is not aligned we have to take into account
450 // that it has two measurements
451 if(matrixIndices[imeas]==-1 && m_measTypeIdHelper->defineType(mesb) == TrackState::Pixel) {
452 imeas++;
453 matrixIndices[imeas]=-1;
454 ATH_MSG_DEBUG("matrixIndices["<<imeas<<"]="<<matrixIndices[imeas]);
455 }
456
457 } // end tsos==rio
458
459 } // end loop over track tsos
460
461 // strip elements in the HCH matrix which don't correspond
462 // to AlignTSOS on alignTrack
463 ATH_MSG_DEBUG("Filling the Q matrix:");
464 for (int k=0;k<nMeas;k++) {
465
466 int iameas=matrixIndices[k];
467 if (iameas==-1)
468 continue;
469
470 for (int l=0;l<nMeas;l++) {
471 int jameas=matrixIndices[l];
472 if (jameas==-1)
473 continue;
474
475 Q(iameas,jameas) = HCH(k,l);
476
477 }
478 }
479
480 ATH_MSG_DEBUG("before check Q ( "<<Q.rows()<<" x "<<Q.cols()<<" )");
481 ATH_MSG_DEBUG("before check Q: "<<Q);
482
483 if(!checkValidity(Q)) {
484 ATH_MSG_DEBUG("Matrix Q = HCH is invalid, skipping the track");
485 return false;
486 }
487
488 return true;
489 }
490
491 //________________________________________________________________________
492 // is this method used used anywhere? maybe we should remove it
493 bool AnalyticalDerivCalcTool::getMeasErrorMatrix(const AlignTrack* alignTrack, Amg::MatrixX& V /*Symmetric Matrix*/) const
494 {
495 int index(0);
497 for (; itAtsos != alignTrack->lastAtsos(); ++itAtsos) {
498
499 std::vector<Residual>::const_iterator itRes=(**itAtsos).firstResidual();
500 for (; itRes!=(**itAtsos).lastResidual(); ++itRes,index++) {
501
502 V(index,index) = itRes->errSq();
503 }
504 }
505 return checkValidity(V);
506 }
507
508 //________________________________________________________________________
509 bool AnalyticalDerivCalcTool::checkValidity(const Amg::MatrixX& R /*symmetric matrix*/) const
510 {
511 // perform some sort of sanity check. depending on how many hits
512 // on the track we use, R can have zero determinant, but it
513 // should definitely not be negative. for now, we'll just check
514 // that all diagonal elements are positive and that all correlation
515 // coefficients are within bounds
516
517 bool Risvalid(true);
518 const double epsilon=1e-10;
519 for( int irow=0; irow<R.rows(); ++irow) {
520
521 Risvalid = Risvalid && R(irow,irow)>0;
522 if ( msgLvl(MSG::DEBUG) ) {
523 if( !(R(irow,irow)>0) )
524 msg(MSG::DEBUG) << "matrix invalid: (" << irow << "," << irow<<") = " << R(irow,irow) << endmsg;
525 }
526 else if (!Risvalid)
527 break;
528
529 for(int icol=0; icol<=irow; ++icol) {
530 // this one must be true if everything else succeeded
531 double Rcorr = R(irow,icol)/sqrt(R(irow,irow)*R(icol,icol));
532 if( Rcorr+epsilon<-1 || Rcorr-epsilon>1 )
533 {
534 Risvalid = false;
535 if (msgLvl(MSG::DEBUG))
536 ATH_MSG_DEBUG("matrix corr invalid for (" << irow << "," << icol << ") Rcorr = " << Rcorr);
537 else
538 break;
539 }
540 }
541 }
542
543 if( !Risvalid ) {
544 ATH_MSG_WARNING("Checked matrix is invalid.");
545 ATH_MSG_WARNING("R: \n"<<R);
546 }
547 return Risvalid;
548 }
549
550 //________________________________________________________________________
551 std::vector<Amg::VectorX> AnalyticalDerivCalcTool::getDerivatives(AlignTrack * alignTrack, const AlignModule * module)
552 {
553 // module-specific transforms
554 Amg::Transform3D globalFrameToAlignFrame = module->globalFrameToAlignFrame();
555 ATH_MSG_DEBUG("globalFrameToAlignFrame: ");
556 ATH_MSG_DEBUG(globalFrameToAlignFrame(0,0)<<" "<<
557 globalFrameToAlignFrame(0,1)<<" "<<
558 globalFrameToAlignFrame(0,2));
559 ATH_MSG_DEBUG(globalFrameToAlignFrame(1,0)<<" "<<
560 globalFrameToAlignFrame(1,1)<<" "<<
561 globalFrameToAlignFrame(1,2));
562 ATH_MSG_DEBUG(globalFrameToAlignFrame(2,0)<<" "<<
563 globalFrameToAlignFrame(2,1)<<" "<<
564 globalFrameToAlignFrame(2,2));
565
566 Amg::RotationMatrix3D globalToAlignFrameRotation = module->globalToAlignFrameRotation();
567 ATH_MSG_DEBUG("globalToAlignFrameRotation: ");
568 ATH_MSG_DEBUG(globalToAlignFrameRotation(0,0)<<" "<<
569 globalToAlignFrameRotation(0,1)<<" "<<
570 globalToAlignFrameRotation(0,2));
571 ATH_MSG_DEBUG(globalToAlignFrameRotation(1,0)<<" "<<
572 globalToAlignFrameRotation(1,1)<<" "<<
573 globalToAlignFrameRotation(1,2));
574 ATH_MSG_DEBUG(globalToAlignFrameRotation(2,0)<<" "<<
575 globalToAlignFrameRotation(2,1)<<" "<<
576 globalToAlignFrameRotation(2,2));
577
578 DataVector<AlignPar> * alignPars = m_alignModuleTool->getAlignPars(module);
579 const int nAlignPar = alignPars->size();
580
581 //Create derivatives storage vector and initialise them ro zero
582 std::vector<Amg::VectorX> derivatives( nAlignPar+3 , Amg::VectorX(alignTrack->nAlignTSOSMeas()));
583 for(int i(0); i<nAlignPar+3; ++i) derivatives[i].setZero();
584
585 int imeas(0);
586 AlignTSOSCollection::iterator iatsos = alignTrack->firstAtsos();
587 for (; iatsos != alignTrack->lastAtsos(); ++iatsos) {
588
589 AlignTSOS * alignTSOS = *iatsos;
590 if (!alignTSOS->isValid() || nullptr==alignTSOS->module())
591 continue;
592
593 // we only calculate the derivatives if the AlignTSOS belongs to the align module
594 int nResDim = alignTSOS->nResDim();
595 if (alignTSOS->module() != module) {
596 imeas += nResDim;
597 continue;
598 }
599
600 // derivatives to be stored on the AlignTSOS
601 std::unique_ptr<std::vector<Amg::VectorX>> atsosDerivs;
602 std::unique_ptr<std::vector<Amg::VectorX>>atsosDerVtx;
603 if (m_storeDerivatives) {
604 atsosDerivs = std::make_unique<std::vector<Amg::VectorX>>(nResDim,Amg::VectorX(nAlignPar));
605 atsosDerVtx = std::make_unique<std::vector<Amg::VectorX>>(nResDim,Amg::VectorX(3));
606 ATH_MSG_DEBUG("nResDim = "<<nResDim<<" vector size is "<<atsosDerivs->size());
607 ATH_MSG_DEBUG("nAlignPar = "<<nAlignPar<<" CLHEP::HepVector size is "<<atsosDerivs->at(0).rows());
608 }
609
610 // Get the rotation to the frame in which the residual is
611 // defined. In this frame the trkdistance is the x-coordinate.
612
613 const TrackParameters * mtp = alignTSOS->trackParameters();
614 if (!mtp || !(mtp->covariance()) ){
615 continue;
616 }
617 Amg::RotationMatrix3D localToGlobalRotation = mtp->measurementFrame();
618
619
620 ATH_MSG_DEBUG( "localToGlobalRotation:");
621 ATH_MSG_DEBUG(localToGlobalRotation(0,0) << " " <<
622 localToGlobalRotation(0,1) << " " <<
623 localToGlobalRotation(0,2));
624 ATH_MSG_DEBUG(localToGlobalRotation(1,0) << " " <<
625 localToGlobalRotation(1,1) << " " <<
626 localToGlobalRotation(1,2));
627 ATH_MSG_DEBUG(localToGlobalRotation(2,0) << " " <<
628 localToGlobalRotation(2,1) << " " <<
629 localToGlobalRotation(2,2));
630
631 if(double alphastrip=alignTSOS->alphaStrip()) {
632 ATH_MSG_DEBUG( "applying fanout rotation : " << alphastrip );
633 localToGlobalRotation = localToGlobalRotation * Amg::AngleAxis3D(alphastrip, Amg::Vector3D(0.,0.,1.));
634 ATH_MSG_DEBUG( "localToGlobalRotation * fanout_rotation:");
635 ATH_MSG_DEBUG(localToGlobalRotation(0,0) << " " <<
636 localToGlobalRotation(0,1) << " " <<
637 localToGlobalRotation(0,2));
638 ATH_MSG_DEBUG(localToGlobalRotation(1,0) << " " <<
639 localToGlobalRotation(1,1) << " " <<
640 localToGlobalRotation(1,2));
641 ATH_MSG_DEBUG(localToGlobalRotation(2,0) << " " <<
642 localToGlobalRotation(2,1) << " " <<
643 localToGlobalRotation(2,2));
644 }
645
646 // get the position of the track in the alignmentframe.
647 Amg::Vector3D refPos = globalFrameToAlignFrame * alignTSOS->trackParameters()->position();
648 ATH_MSG_DEBUG("refPos: "<<refPos);
649
650
651 const Amg::RotationMatrix3D R = globalToAlignFrameRotation * localToGlobalRotation;
652 ATH_MSG_DEBUG("R:");
653 ATH_MSG_DEBUG(R(0,0) << " " << R(0,1) << " " << R(0,2));
654 ATH_MSG_DEBUG(R(1,0) << " " << R(1,1) << " " << R(1,2));
655 ATH_MSG_DEBUG(R(2,0) << " " << R(2,1) << " " << R(2,2));
656
657 // In the SCT measurement frame:
658 // x --> perpendicular to strips in wafer plane
659 // y --> along strips in wafer plane
660 // z --> perpendicular to wafer plane
661
662 // In the TRT measurement frame:
663 // x --> perpendicular to track and straw
664 // y --> along straw wire
665 // z --> perpendicular to x and y (but not parallel to track!)
666
667 // now 'correct' for the track angle in the measurement frame.
668 const TrackParameters * trkpars = nullptr;
669 if(m_residualType == HitOnly) {
670 ATH_MSG_DEBUG("using BIASED track parameters");
671 trkpars = alignTSOS->trackParameters();
672 }
673 else {
674 ATH_MSG_DEBUG("using UNBIASED track parameters");
675 trkpars = alignTSOS->unbiasedTrackPars();
676 }
677
678
679 Amg::Vector3D trackdir = localToGlobalRotation.inverse() * trkpars->momentum();
680 ATH_MSG_DEBUG( "trackdir " << trackdir[0] << " " << trackdir[1] << " " << trackdir[2]);
681
682 // for 1-dimensional measurements and Pixel-x
683 ATH_MSG_DEBUG( "trackdir.z(): " << trackdir.z() );
684 double cotphi_x = trackdir.x() / trackdir.z();
685
686 // some 1D measurements are in Y direction (e.g. in CSC)
687 // so we need the other angle
688 if (alignTSOS->measDir() == Trk::y)
689 cotphi_x = trackdir.y() / trackdir.z();
690
691
692 double Rxx = R(0,0) - cotphi_x * R(0,2);
693 double Ryx = R(1,0) - cotphi_x * R(1,2);
694 double Rzx = R(2,0) - cotphi_x * R(2,2);
695 ATH_MSG_DEBUG("Rxx/Ryx/Rzx: " << Rxx << "/" << Ryx << "/" << Rzx);
696
697 double projR[AlignModule::NTransformPar];
698 projR[AlignModule::TransX] = Rxx;
699 projR[AlignModule::TransY] = Ryx;
700 projR[AlignModule::TransZ] = Rzx;
701 projR[AlignModule::RotX] = -Ryx * refPos.z() + Rzx * refPos.y();
702 projR[AlignModule::RotY] = -Rzx * refPos.x() + Rxx * refPos.z();
703 projR[AlignModule::RotZ] = -Rxx * refPos.y() + Ryx * refPos.x();
704 projR[AlignModule::BowX] = 0;
705 projR[AlignModule::BowY] = 0;
706 projR[AlignModule::BowZ] = 0;
707
717
726
727
729 const double localz = alignTSOS->trackParameters()->position().z(); // - globalToAlignFrameTranslation().z(); // the last term to be doublechecked!
730 // stave length in the IBL -- we will see if there is a more generic way of doing this
731 const double z0z0 = 366.5*366.5;
732
733 projR[AlignModule::BowX] = ( localz*localz - z0z0) / z0z0; // this formula should work for both L11 ans L16, sign to be checked!
734
735
736 // prepare derivatives w.r.t. the vertex position:
737 Amg::Vector3D RxLoc(Rxx, Ryx, Rzx);
738 Amg::Vector3D RxGlob=-1.0 * (globalToAlignFrameRotation.inverse() * RxLoc); // to be double checked!!!
739
740 for (int ipar=0; ipar<nAlignPar; ipar++) {
741 const AlignPar * alignPar = (*alignPars)[ipar];
742 int paramType = alignPar->paramType();
743 //double sigma = alignPar->sigma();
744 ATH_MSG_DEBUG("ipar="<<ipar<<", paramType="<<paramType);
745 derivatives[ipar][imeas] = projR[paramType];//*sigma;
747 (*atsosDerivs)[0][ipar] = projR[paramType];//*sigma;
748 }
749 // the dr/db bit:
750 for (int ipar=0; ipar<3; ipar++) {
751 derivatives[nAlignPar+ipar][imeas] = RxGlob[ipar];
752 if (m_storeDerivatives) (*atsosDerVtx)[0][ipar] = RxGlob[ipar];
753 }
754
755 for (int i=0;i<nAlignPar+3;i++)
756 ATH_MSG_DEBUG("derivatives["<<i<<"]["<<imeas<<"]="<<derivatives[i][imeas]);
757
758 imeas++;
759
760 if (nResDim>1) {
761 // for Pixel the second measurement has to be corrected
762 // for the second angle
763 double cotphi_y = trackdir.y() / trackdir.z() ;
764 double Rxy = R(0,1) - cotphi_y * R(0,2) ;
765 double Ryy = R(1,1) - cotphi_y * R(1,2) ;
766 double Rzy = R(2,1) - cotphi_y * R(2,2) ;
767 ATH_MSG_DEBUG("Rxy/Ryy/Rzy: " << Rxy << "/" << Ryy << "/" << Rzy);
768
769 projR[AlignModule::TransX] = Rxy;
770 projR[AlignModule::TransY] = Ryy;
771 projR[AlignModule::TransZ] = Rzy;
772 projR[AlignModule::RotX] = -Ryy * refPos.z() + Rzy * refPos.y();
773 projR[AlignModule::RotY] = -Rzy * refPos.x() + Rxy * refPos.z();
774 projR[AlignModule::RotZ] = -Rxy * refPos.y() + Ryy * refPos.x();
775
776 //Possibly could add the bowing correction -- very weakly coupled to y residuals
777 projR[AlignModule::BowX] = 0;
778 projR[AlignModule::BowY] = 0;
779 projR[AlignModule::BowZ] = 0;
780
781
782 // prepare derivatives w.r.t. the vertex position:
783 Amg::Vector3D RyLoc(Rxy, Ryy, Rzy);
784 Amg::Vector3D RyGlob=-1.0 * (globalToAlignFrameRotation.inverse() * RyLoc); // to be double checked!!!
785
786 for (int ipar=0; ipar<nAlignPar; ipar++) {
787 const AlignPar * alignPar = (*alignPars)[ipar];
788 int paramType = alignPar->paramType();
789 ATH_MSG_DEBUG("2nd dim, ipar="<<ipar<<", paramType="<<paramType);
790 //double sigma=alignPar->sigma();
791 derivatives[ipar][imeas] = projR[paramType];//*sigma;
793 (*atsosDerivs)[1][ipar] = projR[paramType];//*sigma;
794 }
795
796 // the dr/db bit:
797 for (int ipar=0; ipar<3; ipar++) {
798 derivatives[nAlignPar+ipar][imeas] = RyGlob[ipar];
799 if (m_storeDerivatives) (*atsosDerVtx)[1][ipar] = RyGlob[ipar];
800 }
801
802 for (int i=0;i<nAlignPar+3;i++)
803 ATH_MSG_DEBUG("2nd dim: derivatives["<<i<<"]["<<imeas<<"]="<<derivatives[i][imeas]);
804
805 imeas++;
806 }
807
808 alignTSOS->setDerivatives(atsosDerivs.release());//alignTSOS takes ownership
809 alignTSOS->setDerivativesVtx(atsosDerVtx.release());//alignTSOS DOES NOT take ownership: leak?
810 }
811 ATH_MSG_DEBUG("returning derivatives");
812 return derivatives;
813 }
814
815 //________________________________________________________________________
817 {
818 // get first AlignTSOS of the AlignTrack
819 // this assumes that for unbiased or DCA residuals the scatterers
820 // and energy deposits are not included in the AlignTSOSSollection
821 const AlignTSOS * atsos = *(alignTrack->firstAtsos());
822
823 // get residual type of the first residual
824 m_residualType = atsos->firstResidual()->residualType();
825 ATH_MSG_DEBUG("setting residualType to "<<m_residualType);
826
827 m_residualTypeSet = true;
828 }
829
830} // end namespace
#define endmsg
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
This class provides an interface to generate or decode an identifier for the upper levels of the dete...
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
const ServiceHandle< StoreGateSvc > & detStore() const
bool msgLvl(const MSG::Level lvl) const
MsgStream & msg() const
Derived DataVector<T>.
Definition DataVector.h:795
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:838
DataModel_detail::iterator< DataVector > iterator
Definition DataVector.h:842
size_type size() const noexcept
Returns the number of elements in the collection.
AlignModule::TransformParameters paramType() const
returns the type of parameter (i.e.
Definition AlignPar.h:47
double alphaStrip() const
returns strip angle for fan-out structured modules (SCT endcap)
Definition AlignTSOS.h:122
const TrackParameters * unbiasedTrackPars() const
returns pointer to unbiased track parameters if present
Definition AlignTSOS.h:134
Trk::ParamDefs measDir() const
retrieve the measurement direction
Definition AlignTSOS.h:128
int nResDim() const
returns number of measurement residual + scatterer residual dimensions
Definition AlignTSOS.h:77
void setDerivativesVtx(std::vector< Amg::VectorX > *derivs)
setter for the derivatives w.r.t.
Definition AlignTSOS.h:149
std::vector< Residual >::const_iterator firstResidual() const
returns first Residual iterator
Definition AlignTSOS.h:104
const AlignModule * module() const
accessor method for AlignModule to which tsos belongs
Definition AlignTSOS.h:69
void setDerivatives(std::vector< Amg::VectorX > *derivs)
setter for the derivatives
Definition AlignTSOS.h:146
bool isValid() const
Definition AlignTSOS.h:74
TrackState::MeasurementType measType() const
returns measurement type enum
Definition AlignTSOS.h:80
const Amg::SymMatrixX * fullCovarianceMatrix() const
set and get full covariance matrix
Definition AlignTrack.h:177
bool refitZ0() const
Definition AlignTrack.h:194
void setWeightMatrix(Amg::SymMatrixX *mat)
Definition AlignTrack.h:157
AlignTSOSCollection::const_iterator lastAtsos() const
returns iterator pointer to last element in collection
Definition AlignTrack.h:280
const Amg::SymMatrixX * localErrorMatrixInv() const
inverse local error matrix, calculated by AlignTrack by calling atsos->hitDistanceVar()
Definition AlignTrack.h:125
int nAlignTSOSMeas() const
number of alignTSOS (including scatterers if included on AlignTrack
Definition AlignTrack.h:128
const Amg::SymMatrixX * localErrorMatrix() const
local error matrix, calculated by AlignTrack by calling atsos->hitDistanceVar()
Definition AlignTrack.h:122
bool refitQovP() const
Definition AlignTrack.h:197
void setDerivatives(std::vector< AlignModuleDerivatives > *vec)
Definition AlignTrack.h:134
AlignTSOSCollection::const_iterator firstAtsos() const
retrieve iterator pointer to first element in collection
Definition AlignTrack.h:279
void setWeightMatrixFirstDeriv(Amg::SymMatrixX *mat)
Definition AlignTrack.h:162
const AlignTSOSCollection * alignTSOSCollection() const
returns collection of alignTSOS
Definition AlignTrack.h:267
const Amg::MatrixX * derivativeMatrix() const
set and get derivative matrix
Definition AlignTrack.h:173
bool refitPhi() const
Definition AlignTrack.h:195
bool refitTheta() const
Definition AlignTrack.h:196
bool refitD0() const
get refit flags
Definition AlignTrack.h:193
PublicToolHandle< IAlignModuleTool > m_alignModuleTool
bool checkValidity(const Amg::MatrixX &R) const
bool getMeasErrorMatrix(const AlignTrack *alignTrack, Amg::MatrixX &V) const
AnalyticalDerivCalcTool(const std::string &type, const std::string &name, const IInterface *parent)
bool getTrkParamCovMatrix(const AlignTrack *alignTrack, Amg::MatrixX &HCH) const
int m_residualType
residual type to be used in the calculations
bool setResidualCovMatrix(AlignTrack *alignTrack) const override
sets residual covariance matrix
bool m_residualTypeSet
do we have the residual type set?
bool setDerivatives(AlignTrack *alignTrack) override
sets analytical partial derivatives of residuals w.r.t alignment parameters for TSOS on alignTrack.
void checkResidualType(const AlignTrack *alignTrack)
std::vector< Amg::VectorX > getDerivatives(AlignTrack *alignTrack, const AlignModule *module)
Base class for all CompetingRIOsOnTack implementations, extends the common MeasurementBase.
virtual const RIO_OnTrack & rioOnTrack(unsigned int) const =0
returns the RIO_OnTrack (also known as ROT) objects depending on the integer.
std::ostream * m_logStream
logfile output stream
This class is the pure abstract base class for all fittable tracking measurements.
classifies a MeasurementBase into one of the known inherited flavours or one of the detector types fo...
const Amg::Vector3D & momentum() const
Access method for the momentum.
virtual Amg::RotationMatrix3D measurementFrame() const override=0
Return the measurement frame - this is needed for alignment, in particular for StraightLine and Perig...
const Amg::Vector3D & position() const
Access method for the position.
Class to handle RIO On Tracks ROT) for InDet and Muons, it inherits from the common MeasurementBase.
Definition RIO_OnTrack.h:70
Identifier identify() const
return the identifier -extends MeasurementBase
represents the track state (measurement, material, fit parameters and quality) at a surface.
const TrackParameters * trackParameters() const
return ptr to trackparameters const overload
@ Outlier
This TSoS contains an outlier, that is, it contains a MeasurementBase/RIO_OnTrack which was not used ...
@ Scatterer
This represents a scattering point on the track, and so will contain TrackParameters and MaterialEffe...
const Trk::TrackStates * trackStateOnSurfaces() const
return a pointer to a const DataVector of const TrackStateOnSurfaces.
struct color C
Eigen::AngleAxisd AngleAxis3D
Eigen::Matrix< double, 3, 3 > RotationMatrix3D
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic Matrix - dynamic allocation.
Eigen::Affine3d Transform3D
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.
DataVector< AlignTSOS > AlignTSOSCollection
Definition AlignTrack.h:37
@ y
Definition ParamDefs.h:56
ParametersBase< TrackParametersDim, Charged > TrackParameters
Definition index.py:1