LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
GFKalman.cxx
Go to the documentation of this file.
1 /* Copyright 2008-2010, Technische Universitaet Muenchen,
2  Authors: Christian Hoeppner & Sebastian Neubert
3 
4  This file is part of GENFIT.
5 
6  GENFIT is free software: you can redistribute it and/or modify
7  it under the terms of the GNU Lesser General Public License as published
8  by the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  GENFIT is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU Lesser General Public License for more details.
15 
16  You should have received a copy of the GNU Lesser General Public License
17  along with GENFIT. If not, see <http://www.gnu.org/licenses/>.
18 */
20 
21 #include <iostream>
22 
23 #include "TMath.h"
24 #include "TRandom.h"
25 #include "TDatabasePDG.h"
26 
27 #include "larreco/Genfit/GFTrack.h"
31 
32 #include "cetlib_except/exception.h"
37 
38 #define COVEXC "cov_is_zero"
39 
40 
41 genf::GFKalman::GFKalman():fInitialDirection(1),fNumIt(3),fBlowUpFactor(50.),fMomLow(-100.0),fMomHigh(100.0),fMaxUpdate(1.0),fErrScaleSTh(1.0),fErrScaleMTh(1.0), fGENfPRINT(false)
42 {
44 }
45 
47 
49  int direction=fInitialDirection;
50  if ((direction != 1) && (direction != -1))
51  throw GFException(std::string(__func__) + ": wrong direction", __LINE__, __FILE__).setFatal();
52  // trk->clearGFBookkeeping();
53  trk->clearRepAtHit();
54  /*
55  int nreps=trk->getNumReps();
56  for(int i=0; i<nreps; ++i){
57  trk->getBK(i)->setNhits(trk->getNumHits());
58  trk->getBK(i)->bookMatrices("fPredSt");
59  trk->getBK(i)->bookMatrices("fPredCov");
60  trk->getBK(i)->bookMatrices("bPredSt");
61  trk->getBK(i)->bookMatrices("bPredCov");
62  trk->getBK(i)->bookGFDetPlanes("f");
63  trk->getBK(i)->bookGFDetPlanes("b");
64  trk->getBK(i)->bookNumbers("fChi2");
65  trk->getBK(i)->bookNumbers("bChi2");
66  }
67  */
68 
69  /*why is there a factor of two here (in the for statement)?
70  Because we consider one full iteration to be one back and
71  one forth fitting pass */
72  for(int ipass=0; ipass<2*fNumIt; ipass++){
73  // std::cout << "GFKalman:: numreps, numhits, ipass, direction"<< trk->getNumReps()<<", "<< trk->getNumHits()<<", "<< ipass<<", " <<direction << std::endl;
74  // if(floor(ipass/2)==fNumIt && direction==1) blowUpCovsDiag(trk);
75  if(ipass>0) blowUpCovs(trk); // Back to >0, not >=0 EC, 9-11-Feb-2013
76  if(direction==1){
77  trk->setNextHitToFit(0);
78  }
79  else {
80  trk->setNextHitToFit(trk->getNumHits()-1);
81  }
82 
83 
84  try
85  {
86  fittingPass(trk,direction);
87  }
88  catch(GFException &)
89  {
90  throw cet::exception("GFKalman.cxx: ") << " Line " << __LINE__ << ", " << __FILE__ << " ...Rethrow. \n";
91  }
92 
93  //save first and last plane,state&cov after the fitting pass
94  if(direction==1){//forward at last hit
95  int nreps=trk->getNumReps();
96  for(int i=0; i<nreps; ++i){
97  trk->getTrackRep(i)->
98  setLastPlane( trk->getTrackRep(i)->getReferencePlane() );
99  trk->getTrackRep(i)->
100  setLastState( trk->getTrackRep(i)->getState() );
101  trk->getTrackRep(i)->
102  setLastCov( trk->getTrackRep(i)->getCov() );
103  }
104  }
105  else{//backward at first hit
106  int nreps=trk->getNumReps();
107  for(int i=0; i<nreps; ++i){
108  trk->getTrackRep(i)->
109  setFirstPlane( trk->getTrackRep(i)->getReferencePlane() );
110  trk->getTrackRep(i)->
111  setFirstState( trk->getTrackRep(i)->getState() );
112  trk->getTrackRep(i)->
113  setFirstCov( trk->getTrackRep(i)->getCov() );
114  }
115  }
116 
117  //switch direction of fitting and also inside all the reps
118  if(direction==1) direction=-1;
119  else direction=1;
120  switchDirection(trk);
121 
122  }
123  return;
124 }
125 
126 void
128  int nreps=trk->getNumReps();
129  for(int i=0; i<nreps; ++i){
130  trk->getTrackRep(i)->switchDirection();
131  }
132 }
133 
135  int nreps=trk->getNumReps();
136  for(int irep=0; irep<nreps; ++irep){
137  GFAbsTrackRep* arep=trk->getTrackRep(irep);
138  //dont do it for already compromsied reps, since they wont be fitted anyway
139  if(arep->getStatusFlag()==0) {
140  TMatrixT<Double_t> cov = arep->getCov();
141  for(int i=0;i<cov.GetNrows();++i){
142  for(int j=0;j<cov.GetNcols();++j){
143  if(i!=j){//off diagonal
144  cov[i][j]=0.;
145  }
146  else{//diagonal
147  cov[i][j] = cov[i][j] * fBlowUpFactor;
148  // cov[0][0] = 0.1;
149  }
150  }
151  }
152  arep->setCov(cov);
153  }
154  }
155 }
157  int nreps=trk->getNumReps();
158  for(int irep=0; irep<nreps; ++irep){
159  GFAbsTrackRep* arep=trk->getTrackRep(irep);
160  //dont do it for already compromsied reps, since they wont be fitted anyway
161  if(arep->getStatusFlag()==0) {
162  TMatrixT<Double_t> cov = arep->getCov();
163  for(int i=0;i<cov.GetNrows();++i){
164  for(int j=0;j<cov.GetNcols();++j){
165  //if(i!=j){//off diagonal
166  // cov[i][j]=0.;
167  //}
168  //else{//diagonal
169  cov[i][j] = cov[i][j] * fBlowUpFactor;
170  //}
171  }
172  }
173  arep->setCov(cov);
174  }
175  }
176 }
177 
178 void
180  //loop over hits
181 
182  unsigned int nhits=trk->getNumHits();
183  unsigned int starthit=trk->getNextHitToFit();
184 
185  int nreps=trk->getNumReps();
186  int ihit=(int)starthit;
187 
188  //clear chi2 sum and ndf sum in track reps
189  for(int i=0;i<nreps;++i){
190  GFAbsTrackRep* arep=trk->getTrackRep(i);
191  arep->setChiSqu(0.);
192  arep->setNDF(0);
193  }
194 
195  //clear failedHits and outliers
196  trk->getBK()->clearFailedHits();
197 
198  while((ihit<(int)nhits && direction==1) || (ihit>-1 && direction==-1)){
199  // GFAbsRecoHit* ahit=trk->getHit(ihit);
200  // loop over reps
201  for(int irep=0; irep<nreps; ++irep){
202  GFAbsTrackRep* arep=trk->getTrackRep(irep);
203  if(arep->getStatusFlag()==0) {
204  try {
205  processHit(trk,ihit,irep,direction);
206  }
207  catch(GFException& e) {
208  trk->addFailedHit(irep,ihit);
209  std::cerr << e.what();
210  e.info();
211  if(e.isFatal()) {
212  arep->setStatusFlag(1);
213  continue; // go to next rep immediately
214  }
215  }
216  }
217  }// end loop over reps
218  ihit+=direction;
219  }// end loop over hits
220  trk->setNextHitToFit(ihit-2*direction);
221  //trk->printGFBookkeeping();
222 }
223 
224 double genf::GFKalman::chi2Increment(const TMatrixT<Double_t>& r,const TMatrixT<Double_t>& H,
225  const TMatrixT<Double_t>& cov,const TMatrixT<Double_t>& V){
226 
227  // residuals covariances:R=(V - HCH^T)
228  TMatrixT<Double_t> R(V);
229  TMatrixT<Double_t> covsum1(cov,TMatrixT<Double_t>::kMultTranspose,H);
230  TMatrixT<Double_t> covsum(H,TMatrixT<Double_t>::kMult,covsum1);
231 
232  R-=covsum;
233 
234  // chisq= r^TR^(-1)r
235  double det=0.;
236  TMatrixT<Double_t> Rsave(R);
237  R.SetTol(1.0e-30); // to avoid inversion problem, EC, 8-Aug-2011. Was23, 9-Jan-2012.
238 
239  try
240  {
241  R.Invert(&det);
242  }
243  catch (cet::exception &)
244  {
245  GFException e("Kalman Chi2Increment: R is not even invertible. But keep plowing on ... ",__LINE__,__FILE__);
246  //e.setFatal();
247  //throw e;
248  }
249  if(TMath::IsNaN(det)) {
250  throw GFException("Kalman Chi2Increment: det of covsum is nan",__LINE__,__FILE__).setFatal();
251  }
252  TMatrixT<Double_t> residTranspose(r);
253  residTranspose.T();
254  TMatrixT<Double_t> chisq=residTranspose*(R*r);
255  assert(chisq.GetNoElements()==1);
256 
257  if(TMath::IsNaN(chisq[0][0])){
258  GFException exc("chi2 is nan",__LINE__,__FILE__);
259  exc.setFatal();
260  std::vector<double> numbers;
261  numbers.push_back(det);
262  exc.setNumbers("det",numbers);
263  std::vector< TMatrixT<Double_t> > matrices;
264  matrices.push_back(r);
265  matrices.push_back(V);
266  matrices.push_back(Rsave);
267  matrices.push_back(R);
268  matrices.push_back(cov);
269  exc.setMatrices("r, V, Rsave, R, cov",matrices);
270  throw exc;
271  }
272 
273  return chisq[0][0];
274 }
275 
276 
277 double
279 {
280  // get prototypes for matrices
281  int repDim=rep->getDim();
282  TMatrixT<Double_t> state(repDim,1);
283  TMatrixT<Double_t> cov(repDim,repDim);;
284  GFDetPlane pl=hit->getDetPlane(rep);
285  rep->extrapolate(pl,state,cov);
286 
287 
288  TMatrixT<Double_t> H = hit->getHMatrix(rep);
289 
290  // get hit covariances
291  TMatrixT<Double_t> V=hit->getHitCov(pl);
292  V[0][0] *= fErrScaleMTh;
293  TMatrixT<Double_t> r=hit->residualVector(rep,state,pl);
294  assert(r.GetNrows()>0);
295 
296  r[0][0] = fabs(r[0][0]);
297  //this is where chi2 is calculated
298  double chi2 = chi2Increment(r,H,cov,V);
299 
300  return chi2/r.GetNrows();
301 }
302 
303 
304 void
305 genf::GFKalman::processHit(GFTrack* tr, int ihit, int irep,int direction){
306  GFAbsRecoHit* hit = tr->getHit(ihit);
307  GFAbsTrackRep* rep = tr->getTrackRep(irep);
308 
309  // get prototypes for matrices
310  int repDim = rep->getDim();
311  TMatrixT<Double_t> state(repDim,1);
312  TMatrixT<Double_t> cov(repDim,repDim);
313  static TMatrixT<Double_t> covFilt(cov);
314  const double pi2(10.0);
315  GFDetPlane pl, plPrev;
316  unsigned int nhits=tr->getNumHits();
317  int phit=ihit;
318  static TMatrixT<Double_t> oldState(5,1);
319  static std::vector<TVector3> pointsPrev;
320 
321  const double eps(1.0e-6);
322  if (direction>0 && ihit>0)
323  {
324  phit = ihit - 1;
325  }
326  if (direction<0 && ihit<((int)nhits-1))
327  {
328  phit = ihit + 1;
329  }
330  GFAbsRecoHit* hitPrev = tr->getHit(phit);
331 
332  /* do an extrapolation, if the trackrep irep is not given
333  * at this ihit position. This will usually be the case, but
334  * not if the fit turns around
335  */
336  // std::cout << "GFKalman::ProcessHit(): ihit is " << ihit << std::endl;
337  // std::cout << "GFKalman::ProcessHit(): direction is " << direction << std::endl;
338  //rep->Print();
339 
340 
341  Double_t thetaPlanes(0.0);
342  if(ihit!=tr->getRepAtHit(irep)){
343  //std::cout << "not same" << std::endl;
344  // get the (virtual) detector plane. This call itself calls
345  // extrapolateToPoint(), which calls Extrap() with just 2 args and
346  // default 3rd arg, which propagates track through
347  // material to find the next plane. But it in fact seems
348  // to just return this pl and plPrev, as desired. Something in Extrap()
349  // kicks it out... even though I can see it walking through material ...
350  // A mystery.
351 
352  pl=hit->getDetPlane(rep);
353  plPrev=hitPrev->getDetPlane(rep);
354 
355  // std::cout << "GFKalman::ProcessHit(): hit is ... " << ihit << std::endl;
356  //hit->Print();
357  //std::cout << "GFKalman::ProcessHit(): plane is ... " << std::endl;
358  //pl.Print();
359 
360  //do the extrapolation. This calls Extrap(), which wraps up RKutta and
361  // GFMaterials calls. state is intialized, pl is unchanged. Latter behavior
362  // I will alter below.
363  try{
364  rep->extrapolate(pl,state,cov);
365  /*
366  if ( std::isnan(cov[0][0]) )
367  {
368  cov = covFilt;
369  }
370  else
371  {
372  covFilt = cov;
373  }
374  */
375  }
376  catch (cet::exception &)
377  {
378  throw cet::exception("GFKalman.cxx: ") << " Line " << __LINE__ << ", " << __FILE__ << " ...Rethrow. \n";
379  }
380 
381  }
382  else{
383  pl = rep->getReferencePlane();
384  plPrev = hitPrev->getDetPlane(rep);
385  state = rep->getState();
386  cov = rep->getCov();
387  }
388 
389  // Update plane. This is a code change from Genfit out of box.
390  // state has accumulated the material/magnetic field changes since last
391  // step. Here, we make the *plane* at this step know about that bend.
392  // We will not, in the end, save this plane, cuz Genfit knows to properly
393  // calculate it later.
394  // Actually, I do *not* change the plane. EC, 11-May-2012.
395  TVector3 u(pl.getU());
396  TVector3 v(pl.getV());
397  TVector3 wold(u.Cross(v));
398  //Double_t sign(1.0);
399  //if ((direction==-1) && ihit==((int)nhits-1)) sign = -1.0;
400 
401  TVector3 pTilde = direction * (wold + state[1][0] * u + state[2][0] * v);
402  TVector3 w(pTilde.Unit());
403  // Find angle/vector through which we rotate. Use it subsequently.
404  TVector3 rot(wold.Cross(w));
405  Double_t ang(TMath::ACos(w*wold));
406  ang = TMath::Min(ang,0.95*TMath::Pi()/2.0);
407  /*
408  {
409  u.Rotate(ang,rot);
410  v.Rotate(ang,rot);
411 
412  pl.setNormal(w);
413  pl.setU(u.Unit());
414  pl.setV(v.Unit());
415  }
416  */
417  if(cov[0][0]<1.E-50 || TMath::IsNaN(cov[0][0])){
418  //std::cout<<"GFKalman::processHit() 0. Calling Exception."<<std::endl;
419  GFException exc(COVEXC,__LINE__,__FILE__);
420  if (fGENfPRINT) cov.Print();
421  if (fGENfPRINT) std::cout<<"GFKalman::processHit() 1. No longer throw exception. Force cov[0][0] to 0.01."<<std::endl;
422  // std::cout<<"GFKalman::processHit() 1. About to throw GFException."<<std::endl;
423  cov = covFilt;
424  // throw exc;
425  // std::cout<<"GFKalman::processHit() 2. Back from GFException."<<std::endl;
426 
427  }
428 
429  /*
430  if(direction==1){
431  tr->getBK(irep)->setMatrix("fPredSt",ihit,state);
432  tr->getBK(irep)->setMatrix("fPredCov",ihit,cov);
433  tr->getBK(irep)->setGFDetPlane("f",ihit,pl);
434  }
435  else{
436  tr->getBK(irep)->setMatrix("bPredSt",ihit,state);
437  tr->getBK(irep)->setMatrix("bPredCov",ihit,cov);
438  tr->getBK(irep)->setGFDetPlane("b",ihit,pl);
439  }
440  */
441 
442  // TMatrixT<Double_t> origcov=rep->getCov();
443 
444  int pdg = tr->getPDG();
445  TParticlePDG * part = TDatabasePDG::Instance()->GetParticle(pdg);
446  Double_t mass = part->Mass();
447 
448  Double_t dist = (pl.getO()-plPrev.getO()).Mag();
449  Double_t mom = fabs(1.0/state[0][0]);
450  Double_t beta = mom/sqrt(mass*mass+mom*mom);
451  const Double_t lowerLim(0.01);
452  if (std::isnan(dist) || dist<=0.0) dist=lowerLim; // don't allow 0s here.
453  if (std::isnan(beta) || beta<0.01) beta=0.01;
454  TMatrixT<Double_t> H=hit->getHMatrix(rep,beta,dist);
455 
456 
457  // Can force huge error here on p and du,v/dw, and thus insensitivity to p,
458  // by setting V[0][0]->inf.
459  TMatrixT<Double_t> V=hit->getHitCov(pl,plPrev,state,mass);
460  V[0][0] *= fErrScaleMTh;
461  tr->setHitMeasuredCov(V);
462 
463  // calculate kalman gain ------------------------------
464  TMatrixT<Double_t> Gain(calcGain(cov,V,H));
465 
466  //std::cout << "GFKalman:: processHits(), state is " << std::endl;
467  //rep->getState().Print();
468 
469  TMatrixT<Double_t> res=hit->residualVector(rep,state,pl,plPrev,mass);
470  // calculate update -----------------------------------
471 
472 
473  // TVector3 pointer((pl.getO()-plPrev.getO()).Unit());
474 
475  TMatrixT<Double_t> rawcoord = hit->getRawHitCoord();
476  TVector3 point(rawcoord[0][0],rawcoord[1][0],rawcoord[2][0]);
477  TMatrixT<Double_t> prevrawcoord = hitPrev->getRawHitCoord();
478  TVector3 pointPrev(prevrawcoord[0][0],prevrawcoord[1][0],prevrawcoord[2][0]);
479  pointsPrev.push_back(pointPrev);
480  TMatrixT<Double_t> Hnew(H);
481  if ((ihit==((int)nhits-1)&&direction==-1) || (ihit==0&&direction==1))
482  pointsPrev.clear();
483 
484  TVector3 pointer((point-pointPrev).Unit());
485  static TVector3 pointerPrev(pointer);
486  if (ihit==0&&direction==1 )
487  {pointer[0] = 0.0;pointer[1] = 0.0;pointer[2] = 1.0;}
488  if (ihit==((int)nhits-1)&&direction==-1)
489  {pointer[0] = 0.0;pointer[1] = 0.0;pointer[2] = -1.0;}
490  double thetaMeas = TMath::Min(fabs(pointer.Angle(pointerPrev)),0.95*TMath::Pi()/2.0);
491  // Below line introduced because it's not true we predict the angle to be
492  // precisely ang. If we'd taken this quantity from our transport result
493  // (with measurement errors in it) we'd expect a smear like this on ang.
494  // EC, 22-Feb-2012.
495  // Error is taken on th^2
496  ang = (Hnew*state)[0][0]; // H->Hnew
497 
498  // fErrScale is extra-fun bonus factor!
499  //thetaPlanes = ang*ang; // + fErrScaleSTh*gRandom->Gaus(0.0,V[0][0]);
500  thetaPlanes = gRandom->Gaus(0.0,ang*ang);
501  thetaPlanes = TMath::Min(sqrt(fabs(thetaPlanes)),0.95*TMath::Pi()/2.0);
502 
503  Double_t dtheta = thetaMeas - thetaPlanes; // was fabs(res[0][0]). EC, 26-Jan-2012
504  if (((ihit==((int)nhits-1)||ihit==((int)nhits-2))&&direction==-1) || ((ihit==0||ihit==1)&&direction==1))
505  {
506  dtheta = 0.0; // at the bare minimum (Jan-2013). Now (Feb-2013), ....
507  // Do not let these 4 points*direction influence the state or chi2.
508  rep->setData(state,pl,&cov); // This is where fState,
509  // fRefPlane and fCov are updated.
510  pointerPrev = pointer;
511  return;
512  }
513 
514  oldState = state;
515 
516  res[0][0] = dtheta/Hnew[0][0];
517  // The particle was propagated through material until its poca
518  // to this current hit was found. At that point its plane is defined,
519  // in which du/dw=dv/dw=0 by construction. But, there's a deviation
520  // in those two quantities measured in the *previous* plane which we want.
521  TVector3 uPrev(plPrev.getU());
522  TVector3 vPrev(plPrev.getV());
523  TVector3 wPrev(u.Cross(v));
524  // We want the newest momentum vector's d{u,v}/dw defined in the prev plane.
525  // That is the predicted du,v/dw. We will subtract from the actual.
526  // But the u's and v's need to come from the State not the Planes, cuz I
527  // haven't updated pl,plPrev per latest State. plFilt, the updated plPrev,
528  // is what we want. w is from updated new plane pl, per latest State.
529  // e.g. plFilt.
530  static GFDetPlane plFilt;//(pl);
531  if (plFilt.getO().Mag()>eps)
532  {
533  uPrev = plFilt.getU();
534  vPrev = plFilt.getV();
535  wPrev = plFilt.getNormal();
536  }
537  //res[1][0] = (pointer*uPrev)/(pointer*wPrev) - (w*uPrev)/(w*wPrev);
538  //res[2][0] = (pointer*vPrev)/(pointer*wPrev) - (w*vPrev)/(w*wPrev);
539  // res[1][0] = 0.0;
540  // res[2][0] = 0.0;
541 
542  TMatrixT<Double_t> update=Gain*res;
543 
544  // Don't let crazy ass spacepoints which pull the fit all over the place
545  // be allowed to update the state. Use __ xRMS for fMaxUpdate.
546  // Use a larger limit (~0.1) when starting with too-high seed momentum.
547  // Smaller, when starting with an underestimate.
548  //
549  // Don't allow fits above 20 GeV, or so. Else, 1/p will likely
550  // migrate across zero. Similarly, don't allow tiny momentum.
551  //
552  tr->setHitUpdate(update);
553  if (fabs(update[0][0])>fMaxUpdate )
554  { // zero the gain so as to not update cov, state
555  // zero the updates
556  update[0][0] = 0.0;/* */
557  // update[0][0] = fMaxUpdate*update[0][0]/fabs(update[0][0]);
558  // either of below leads to craziness, somehow.
559  // update.Zero();
560  // Gain.Zero();
561  }
562  state+=update; // prediction overwritten!
563 
564  // Debugging purposes
565  TMatrixT<Double_t> GH(Gain*Hnew);
566  if (GH[0][0] > 1.)
567  {
568  // std::cout << "GFKalman:: Beginnings of a problem." << std::endl;
569  Hnew[0][0] = Hnew[0][0] - eps/Gain[0][0];
570  }
571  TMatrixT<Double_t> GHc(GH*cov);
572 
573  cov-=Gain*(Hnew*cov);
574 
575  // Below is protection required at end of contained track when
576  // momentum is tiny and cov[0][0] gets huge.
577 
578  // if (cov[0][0]>pi2/Hnew[0][0] || cov[0][0] <= 0.0 || TMath::IsNaN(cov[0][0]))
579  if (cov[0][0] <= 0.0 || TMath::IsNaN(cov[0][0]))
580  {
581  cov[0][0]=pi2/Hnew[0][0]; // some big value.a
582  //cov = covFilt;
583  }
584  else // store away a good cov matrix
585  {
586  covFilt = cov;
587  }
588 
589 
590  TMatrixT<double> cov7x7(calcCov7x7(cov,pl));
591  tr->setHitCov(cov);
592  tr->setHitCov7x7(cov7x7);
593  tr->setHitState(state);
594 
595  if (fabs(1.0/state[0][0])<fMomLow)
596  state[0][0] = 1.0/fMomLow*fabs(state[0][0])/state[0][0];
597  if (fabs(1.0/state[0][0])>fMomHigh)
598  state[0][0] = 1.0/fMomHigh*fabs(state[0][0])/state[0][0];
599 
600 
601  // Let's also calculate the "filtered" plane, and pointer here.
602  // Use those to calculate filtered chisq and pass to setHitPlane()
603  // for plane-by-plane correct "filtered" track pointing that gets
604  // stuffed into the Track().
605  TVector3 uf(pl.getU());
606  TVector3 vf(pl.getV());
607  TVector3 wf(uf.Cross(vf));
608  TVector3 Of(pl.getO());
609  // direction *
610  //Double_t sign2(1.0);
611  //if (direction==-1 && ihit==(int)nhits-1) sign2 = -1.0;
612 
613  TVector3 pf = direction*(wf + state[1][0] * uf + state[2][0] * vf);
614  TVector3 pposf = Of + state[3][0] * uf + state[4][0] * vf;
615  Double_t angf = TMath::Min(fabs(pf.Angle(wf)),0.95*TMath::Pi()/2.0);
616  TVector3 rotf(wf.Cross(pf.Unit()));
617 
618  uf.Rotate(angf,rotf);
619  vf.Rotate(angf,rotf);
620  wf = uf.Cross(vf);
621  plFilt.setU(uf.Unit());
622  plFilt.setV(vf.Unit());
623  plFilt.setO(pposf);
624  plFilt.setNormal(pf.Unit());
625 
626  tr->setHitPlaneXYZ(plFilt.getO());
627  tr->setHitPlaneUxUyUz(plFilt.getNormal());
628  tr->setHitPlaneU(plFilt.getU());
629  tr->setHitPlaneV(plFilt.getV());
630 
631  // calculate filtered chisq from filtered residuals
632  TMatrixT<Double_t> r=hit->residualVector(rep,state,plFilt,plPrev,mass);
633  if (direction==-1) wold.Rotate(TMath::Pi(),wold.Orthogonal());
634  dtheta = thetaMeas - TMath::Min(fabs(wold.Angle(plFilt.getNormal())),0.95*TMath::Pi()/2.);
635  r[0][0] = dtheta/Hnew[0][0];
636  //r[1][0] = (pointer*uPrev)/(pointer*wPrev) - (wf*uPrev)/(wf*wPrev);
637  //r[2][0] = (pointer*vPrev)/(pointer*wPrev) - (wf*vPrev)/(wf*wPrev);
638  //r[1][0] = 0.;
639  //r[2][0] = 0.;
640 
641  double chi2 = chi2Increment(r,Hnew,cov,V);
642  int ndf = r.GetNrows();
643  if (update[0][0]==0.0) {chi2=0.0; ndf=0;};
644  rep->addChiSqu( chi2 );
645  rep->addNDF( ndf );
646  pointerPrev = pointer;
647  tr->setHitChi2(chi2);
648  /*
649  if(direction==1){
650  tr->getBK(irep)->setNumber("fChi2",ihit,chi2/ndf);
651  }
652  else{
653  tr->getBK(irep)->setNumber("bChi2",ihit,chi2/ndf);
654  }
655  */
656 
657  // if we survive until here: update TrackRep
658  //rep->setState(state);
659  //rep->setCov(cov);
660  //rep->setReferencePlane(pl);
661 
662  // Since I've tilted the planes, d(u,v)/dw=0 by construction.
663  // But, I *haven't* tilted the planes! EC, 11-May-2012.
664  //state[1][0] = 0.0;
665  //state[2][0] = 0.0;
666  rep->setData(state,pl,&cov); // This is where fState,
667  // fRefPlane and fCov are updated.
668  tr->setRepAtHit(irep,ihit);
669 
670 }
671 
672 TMatrixT<Double_t>
673 genf::GFKalman::calcCov7x7(const TMatrixT<Double_t>& cov, const GFDetPlane& plane)
674 {
675  // This ends up, confusingly, as: 7 columns, 5 rows!
676  TMatrixT<Double_t> jac(7,5); // X,Y,Z,UX,UY,UZ,Theta in detector coords
677 
678  TVector3 u=plane.getU();
679  TVector3 v=plane.getV();
680  TVector3 w=u.Cross(v);
681 
682  // Below line has been done, with code change in GFKalman that has updated
683  // the plane orientation by now.
684  // TVector3 pTilde = 1.0 * (w + state[1][0] * u + state[2][0] * v);
685  TVector3 pTilde = w;
686  double pTildeMag = pTilde.Mag();
687 
688  jac.Zero();
689  jac[6][0] = 1.; // Should be C as in GFSpacepointHitPolicy. 16-Feb-2013.
690 
691  jac[0][3] = u[0];
692  jac[1][3] = u[1];
693  jac[2][3] = u[2];
694 
695  jac[0][4] = v[0];
696  jac[1][4] = v[1];
697  jac[2][4] = v[2];
698 
699  // cnp'd from RKTrackRep.cxx, line ~496
700  // da{x,y,z}/du'
701  jac[3][1] = 1.0/pTildeMag*(u.X()-pTilde.X()/(pTildeMag*pTildeMag)*u*pTilde);
702  jac[4][1] = 1.0/pTildeMag*(u.Y()-pTilde.Y()/(pTildeMag*pTildeMag)*u*pTilde);
703  jac[5][1] = 1.0/pTildeMag*(u.Z()-pTilde.Z()/(pTildeMag*pTildeMag)*u*pTilde);
704  // da{x,y,z}/dv'
705  jac[3][2] = 1.0/pTildeMag*(v.X()-pTilde.X()/(pTildeMag*pTildeMag)*v*pTilde);
706  jac[4][2] = 1.0/pTildeMag*(v.Y()-pTilde.Y()/(pTildeMag*pTildeMag)*v*pTilde);
707  jac[5][2] = 1.0/pTildeMag*(v.Z()-pTilde.Z()/(pTildeMag*pTildeMag)*v*pTilde);
708 
709  // y = A.x => x = A^T.A.A^T.y
710  // Thus, y's Jacobians Jac become for x (Jac^T.Jac)^(-1) Jac^T
711 
712  TMatrixT<Double_t> jac_t(TMatrixT<Double_t>::kTransposed,jac);
713  TMatrixT<Double_t> jjInv(jac_t * jac);
714  //jInv.Zero();
715 
716  double det(0.0);
717  try {
718  jjInv.Invert(&det); // this is all 1s on the diagonal, perhaps
719  // to no one's surprise.
720  }
721  catch (cet::exception &)
722  {
723  throw GFException("GFKalman: Jac.T*Jac is not invertible. But keep plowing on ... ",__LINE__,__FILE__).setFatal();
724  }
725  if(TMath::IsNaN(det)) {
726  throw GFException("GFKalman: det of Jac.T*Jac is nan",__LINE__,__FILE__).setFatal();
727  }
728 
729  TMatrixT<Double_t> j5x7 = jjInv*jac_t;
730  TMatrixT<Double_t> c7x7 = j5x7.T() * (cov * j5x7);
731  return c7x7;
732 }
733 
734 TMatrixT<Double_t>
735 genf::GFKalman::calcGain(const TMatrixT<Double_t>& cov,
736  const TMatrixT<Double_t>& HitCov,
737  const TMatrixT<Double_t>& H){
738 
739  // calculate covsum (V + HCH^T)
740 
741  // Comment next 3 out for normal running.
742  //cov.Print();
743  //H.Print();
744  //HitCov.Print();
745  TMatrixT<Double_t> covsum1(cov,TMatrixT<Double_t>::kMultTranspose,H);
746  // covsum1.Print();
747  TMatrixT<Double_t> covsum(H,TMatrixT<Double_t>::kMult,covsum1);
748 
749  //covsum.Print();
750 
751  covsum+=HitCov;
752  //covsum = (covsum,TMatrixT<Double_t>::kPlus,HitCov);
753  // covsum.Print();
754 
755  // invert
756  double det=0;
757  covsum.SetTol(1.0e-23); // to avoid inversion problem, EC, 8-Aug-2011.
758  covsum.Invert(&det);
759  // std::cout << "GFKalman:: calGain(), det is "<< det << std::endl;
760  if(TMath::IsNaN(det)) {
761  throw GFException("Kalman Gain: det of covsum is nan",__LINE__,__FILE__).setFatal();
762  }
763 
764  if(det==0){
765  GFException exc("cannot invert covsum in Kalman Gain - det=0",
766  __LINE__,__FILE__);
767  exc.setFatal();
768  std::vector< TMatrixT<Double_t> > matrices;
769  matrices.push_back(cov);
770  matrices.push_back(HitCov);
771  matrices.push_back(covsum1);
772  matrices.push_back(covsum);
773  exc.setMatrices("cov, HitCov, covsum1 and covsum",matrices);
774  throw exc;
775 
776  }
777 
778  // gain is CH^T/(V + HCH^T)
779  // calculate gain
780  TMatrixT<Double_t> gain1(H,TMatrixT<Double_t>::kTransposeMult,covsum);
781  TMatrixT<Double_t> gain(cov,TMatrixT<Double_t>::kMult,gain1);
782 
783  return gain;
784 }
785 
void clearRepAtHit()
clear the hit indices at which plane,state&cov of reps are defined
Definition: GFTrack.h:404
void setNDF(unsigned int n)
GFException & setNumbers(std::string, const std::vector< double > &)
set list of numbers with description
Definition: GFException.cxx:32
double getChi2Hit(GFAbsRecoHit *, GFAbsTrackRep *)
Calculates chi2 of a given hit with respect to a given track representation.
Definition: GFKalman.cxx:278
const GFDetPlane & getReferencePlane() const
Double_t fErrScaleMTh
Definition: GFKalman.h:164
Float_t E
Definition: plot.C:23
void setNextHitToFit(unsigned int i)
Set next hit to be used in a fit.
Definition: GFTrack.h:191
void setRepAtHit(unsigned int irep, int ihit)
set the hit index at which plane,state&cov of rep irep is defined
Definition: GFTrack.h:388
void processHit(GFTrack *, int, int, int)
One Kalman step.
Definition: GFKalman.cxx:305
virtual const char * what() const
standard error message handling for exceptions. use like "std::cerr << e.what();" ...
Definition: GFException.cxx:46
TMatrixT< Double_t > calcGain(const TMatrixT< Double_t > &cov, const TMatrixT< Double_t > &HitCov, const TMatrixT< Double_t > &H)
Calculate Kalman Gain.
Definition: GFKalman.cxx:735
GFAbsTrackRep * getTrackRep(int id) const
Accessor for track representations.
Definition: GFTrack.h:195
void fittingPass(GFTrack *, int dir)
Performs fit on a GFTrack beginning with the current hit.
Definition: GFKalman.cxx:179
virtual TMatrixT< Double_t > getHMatrix(const GFAbsTrackRep *stateVector)=0
Get transformation matrix. Transformation between hit coordinates and track representation coordinate...
virtual const GFDetPlane & getDetPlane(GFAbsTrackRep *)=0
Get detector plane for a given track representation.
TMatrixT< Double_t > getRawHitCoord() const
Get raw hit coordinates.
Definition: GFAbsRecoHit.h:182
Double_t beta
const TMatrixT< Double_t > & getState() const
void blowUpCovs(GFTrack *trk)
this is needed to blow up the covariance matrix before a fitting pass drops off-diagonal elements and...
Definition: GFKalman.cxx:156
Base Class for genfit track representations. Defines interface for track parameterizations.
Definition: GFAbsTrackRep.h:85
void setCov(const TMatrixT< Double_t > &aCov)
int fInitialDirection
Definition: GFKalman.h:156
void setChiSqu(double aChiSqu)
Double_t fMomLow
Definition: GFKalman.h:160
void setHitState(TMatrixT< Double_t > mat)
Definition: GFTrack.h:353
Double_t fMaxUpdate
Definition: GFKalman.h:162
void addNDF(unsigned int n)
TVector3 getO() const
Definition: GFDetPlane.h:76
void switchDirection(GFTrack *trk)
Used to switch between forward and backward filtering.
Definition: GFKalman.cxx:127
unsigned int getNumReps() const
Get number of track represenatations.
Definition: GFTrack.h:201
void setHitMeasuredCov(TMatrixT< Double_t > mat)
Definition: GFTrack.h:350
virtual void setData(const TMatrixT< Double_t > &st, const GFDetPlane &pl, const TMatrixT< Double_t > *cov=NULL)
double chi2Increment(const TMatrixT< Double_t > &r, const TMatrixT< Double_t > &H, const TMatrixT< Double_t > &cov, const TMatrixT< Double_t > &V)
this returns the reduced chi2 increment for a hit
Definition: GFKalman.cxx:224
void addFailedHit(unsigned int irep, unsigned int id)
Definition: GFTrack.h:293
TString part[npart]
Definition: Style.C:32
virtual TMatrixT< Double_t > getHitCov(const GFDetPlane &)=0
Get hit covariances in a specific detector plane.
bool isFatal()
get fatal flag.
Definition: GFException.h:82
Double_t R
void addChiSqu(double aChiSqu)
GFAbsRecoHit * getHit(int id) const
Definition: GFTrack.h:159
int getRepAtHit(unsigned int irep)
get the hit index at which plane,state&cov of rep irep is defined
Definition: GFTrack.h:396
void setHitPlaneV(TVector3 pl)
Definition: GFTrack.h:359
void setHitPlaneUxUyUz(TVector3 pl)
Definition: GFTrack.h:357
virtual double extrapolate(const GFDetPlane &plane, TMatrixT< Double_t > &statePred)
returns the tracklength spanned in this extrapolation
void processTrack(GFTrack *)
Performs fit on a GFTrack.
Definition: GFKalman.cxx:48
void setHitChi2(Double_t mat)
Definition: GFTrack.h:352
const TMatrixT< Double_t > & getCov() const
GFBookkeeping * getBK(int index=-1)
get GFBookKeeping object for particular track rep (default is cardinal rep)
Definition: GFTrack.h:334
GFException & setMatrices(std::string, const std::vector< TMatrixT< Double_t > > &)
set list of matrices with description
Definition: GFException.cxx:39
void setHitCov7x7(TMatrixT< Double_t > mat)
Definition: GFTrack.h:355
void blowUpCovsDiag(GFTrack *trk)
Definition: GFKalman.cxx:134
Detector simulation of raw signals on wires.
void info()
print information in the exception object
Definition: GFException.cxx:56
double fBlowUpFactor
Definition: GFKalman.h:158
unsigned int getNumHits() const
Definition: GFTrack.h:163
void setHitCov(TMatrixT< Double_t > mat)
Definition: GFTrack.h:354
bool fGENfPRINT
Definition: GFKalman.h:165
Double_t fMomHigh
Definition: GFKalman.h:161
Exception class for error handling in GENFIT (provides storage for diagnostic information) ...
Definition: GFException.h:50
TVector3 getU() const
Definition: GFDetPlane.h:77
void setStatusFlag(int _val)
void setHitUpdate(TMatrixT< Double_t > mat)
Definition: GFTrack.h:351
TMatrixT< Double_t > calcCov7x7(const TMatrixT< Double_t > &cov, const genf::GFDetPlane &plane)
Definition: GFKalman.cxx:673
GFException & setFatal(bool b=true)
set fatal flag. if this is true, the fit stops for this current track repr.
Definition: GFException.h:80
#define COVEXC
Definition: GFKalman.cxx:38
void setHitPlaneXYZ(TVector3 pl)
Definition: GFTrack.h:356
int getPDG()
Definition: GFTrack.h:372
TVector3 getV() const
Definition: GFDetPlane.h:78
unsigned int getDim() const
returns dimension of state vector
Float_t e
Definition: plot.C:34
unsigned int getNextHitToFit() const
Accessor for fNextHitToFit.
Definition: GFTrack.h:187
Float_t w
Definition: plot.C:23
virtual TMatrixT< Double_t > residualVector(const GFAbsTrackRep *stateVector, const TMatrixT< Double_t > &state, const GFDetPlane &d)
Calculate residual with respect to a track representation.
Definition: GFAbsRecoHit.h:147
virtual void switchDirection()=0
void setHitPlaneU(TVector3 pl)
Definition: GFTrack.h:358
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
Int_t fNumIt
Definition: GFKalman.h:157