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