EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GFKalman.cxx
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file GFKalman.cxx
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 */
19 #include "GFKalman.h"
20 
21 #include "assert.h"
22 #include <iostream>
23 #include <sstream>
24 
25 #include "TMath.h"
26 
27 #include "GFTrack.h"
28 #include "GFAbsRecoHit.h"
29 #include "GFAbsTrackRep.h"
30 #include "GFException.h"
31 #include "GFTools.h"
32 
33 #define COVEXC "cov_is_zero"
34 //#define DEBUG
35 
36 GFKalman::GFKalman():fInitialDirection(1),fNumIt(3),fBlowUpFactor(500.){;}
37 
39 
41 #ifdef DEBUG
42  std::cout<<"GFKalman::processTrack "<<std::endl;
43 #endif
44 
45  fSmooth = trk->getSmoothing();
47 
48  int nreps = trk->getNumReps();
49  for(int i=0; i<nreps; i++) {
50  trk->getBK(i)->setNhits(trk->getNumHits());
51  if(fSmooth) {
52  std::vector<std::string> mat_keys = trk->getBK(i)->getMatrixKeys();
53  bool already_there = false;
54  for(unsigned int j=0; j<mat_keys.size(); j++) {
55  if(mat_keys.at(j) == "fUpSt") already_there = true;
56  }
57  if(already_there) continue;
58  trk->getBK(i)->bookNumbers("fExtLen"); // extrapolated length from last hit in forward direction
59  trk->getBK(i)->bookMatrices("fUpSt");
60  trk->getBK(i)->bookMatrices("fUpCov");
61  trk->getBK(i)->bookNumbers("bExtLen"); // extrapolated length from last hit in backward direction
62  trk->getBK(i)->bookMatrices("bUpSt");
63  trk->getBK(i)->bookMatrices("bUpCov");
64  if(fSmoothFast) {
65  trk->getBK(i)->bookMatrices("fSt");
66  trk->getBK(i)->bookMatrices("fCov");
67  trk->getBK(i)->bookMatrices("bSt");
68  trk->getBK(i)->bookMatrices("bCov");
69  }
70  trk->getBK(i)->bookGFDetPlanes("fPl");
71  trk->getBK(i)->bookGFDetPlanes("bPl");
72  if(trk->getTrackRep(i)->hasAuxInfo()) {
73  trk->getBK(i)->bookMatrices("fAuxInfo");
74  trk->getBK(i)->bookMatrices("bAuxInfo");
75  }
76  }
77  }
78 
79  int direction=fInitialDirection;
80  assert(direction==1 || direction==-1);
81  // trk->clearGFBookkeeping();
82  trk->clearRepAtHit();
83 
84  /*why is there a factor of two here (in the for statement)?
85  Because we consider one full iteration to be one back and
86  one forth fitting pass */
87  for(int ipass=0; ipass<2*fNumIt; ipass++){
88  if(ipass>0) blowUpCovs(trk);
89 
90  // reset X/X0 before last fitting pass
91  if(ipass==(2*fNumIt)-1) {
92  for(int i=0; i<nreps; ++i) {
93  trk->getTrackRep(i)->resetXX0();
94  }
95  }
96 
97  if(direction==1){
98  trk->setNextHitToFit(0);
99  }
100  else {
101  trk->setNextHitToFit(trk->getNumHits()-1);
102  }
103  fittingPass(trk,direction);
104 
105  //save first and last plane,state&cov after the fitting pass
106  if(direction==1){//forward at last hit
107  for(int i=0; i<nreps; ++i){
108  trk->getTrackRep(i)->
109  setLastPlane( trk->getTrackRep(i)->getReferencePlane() );
110  trk->getTrackRep(i)->
111  setLastState( trk->getTrackRep(i)->getState() );
112  trk->getTrackRep(i)->
113  setLastCov( trk->getTrackRep(i)->getCov() );
114  }
115  }
116  else{//backward at first hit
117  for(int i=0; i<nreps; ++i){
118  trk->getTrackRep(i)->
119  setFirstPlane( trk->getTrackRep(i)->getReferencePlane() );
120  trk->getTrackRep(i)->
121  setFirstState( trk->getTrackRep(i)->getState() );
122  trk->getTrackRep(i)->
123  setFirstCov( trk->getTrackRep(i)->getCov() );
124  }
125  }
126 
127  //switch direction of fitting and also inside all the reps
128  if(direction==1) direction=-1;
129  else direction=1;
130  switchDirection(trk);
131  }
132 
133  return;
134 }
135 
136 void
138  int nreps=trk->getNumReps();
139  for(int i=0; i<nreps; ++i){
140  trk->getTrackRep(i)->switchDirection();
141  }
142 }
143 
146 }
147 
148 void
149 GFKalman::fittingPass(GFTrack* trk, int direction){
150  //loop over hits
151  unsigned int nhits=trk->getNumHits();
152  unsigned int starthit=trk->getNextHitToFit();
153 
154  int nreps=trk->getNumReps();
155  int ihit=(int)starthit;
156 
157  for(int irep=0; irep<nreps; ++irep) {
158  GFAbsTrackRep* arep=trk->getTrackRep(irep);
159  if(arep->getStatusFlag()==0) {
160  //clear chi2 sum and ndf sum in track reps
161  if (direction == -1){
162  arep->setChiSqu(0.);
163  }
164  if (direction == 1){
165  arep->setForwardChiSqu(0.);
166  }
167  arep->setNDF(0);
168  //clear failedHits and outliers
169  trk->getBK(irep)->clearFailedHits();
170  }
171  }
172 
173  while((ihit<(int)nhits && direction==1) || (ihit>-1 && direction==-1)){
174  // GFAbsRecoHit* ahit=trk->getHit(ihit);
175  // loop over reps
176  for(int irep=0; irep<nreps; ++irep){
177  GFAbsTrackRep* arep=trk->getTrackRep(irep);
178  if(arep->getStatusFlag()==0) {
179  try {
180 #ifdef DEBUG
181  std::cout<<"++++++++++++++++++++++++++++++++++++++++\n";
182  std::cout<<"GFKalman::fittingPass - process rep nr. "<<irep<<" and hit nr. "<<ihit<<std::endl;
183 #endif
184  processHit(trk,ihit,irep,direction);
185  }
186  catch(GFException& e) {
187  trk->addFailedHit(irep,ihit);
188  std::cerr << e.what();
189  e.info();
190  if(e.isFatal()) {
191  arep->setStatusFlag(1);
192  continue; // go to next rep immediately
193  }
194  }
195  }
196  }// end loop over reps
197  ihit+=direction;
198  }// end loop over hits
199  trk->setNextHitToFit(ihit-2*direction);
200  //trk->printGFBookkeeping();
201 }
202 
203 double GFKalman::chi2Increment(const TMatrixT<double>& r,const TMatrixT<double>& H,
204  const TMatrixT<double>& cov,const TMatrixT<double>& V){
205 
206  // residuals covariances:R=(V - HCH^T)
207  TMatrixT<double> R(V);
208  TMatrixT<double> covsum1(cov,TMatrixT<double>::kMultTranspose,H);
209  TMatrixT<double> covsum(H,TMatrixT<double>::kMult,covsum1);
210 
211  R-=covsum;
212 
213  // chisq= r^TR^(-1)r
214  TMatrixT<double> Rinv;
215  GFTools::invertMatrix(R,Rinv);
216 
217 
218  TMatrixT<double> residTranspose(r);
219  residTranspose.T();
220  TMatrixT<double> chisq=residTranspose*(Rinv*r);
221  assert(chisq.GetNoElements()==1);
222 
223  if(TMath::IsNaN(chisq[0][0])){
224  GFException exc("chi2 is nan",__LINE__,__FILE__);
225  exc.setFatal();
226  std::vector< TMatrixT<double> > matrices;
227  matrices.push_back(r);
228  matrices.push_back(V);
229  matrices.push_back(R);
230  matrices.push_back(cov);
231  exc.setMatrices("r, V, R, cov",matrices);
232  throw exc;
233  }
234 
235  return chisq[0][0];
236 }
237 
238 
239 double
241 {
242  // get prototypes for matrices
243  int repDim=rep->getDim();
244  TMatrixT<double> state(repDim,1);
245  TMatrixT<double> cov(repDim,repDim);;
246  GFDetPlane pl=hit->getDetPlane(rep);
247  rep->extrapolate(pl,state,cov);
248 
249 
250  TMatrixT<double> H = hit->getHMatrix(rep);
251  TMatrixT<double> m,V;
252  hit->getMeasurement(rep,pl,state,cov,m,V);
253 
254  TMatrixT<double> res = m-(H*state);
255  assert(res.GetNrows()>0);
256 
257  //this is where chi2 is calculated
258  double chi2 = chi2Increment(res,H,cov,V);
259 
260  return chi2/res.GetNrows();
261 }
262 
263 
264 void
265 GFKalman::processHit(GFTrack* tr, int ihit, int irep,int direction){
266  GFAbsRecoHit* hit = tr->getHit(ihit);
267  GFAbsTrackRep* rep = tr->getTrackRep(irep);
268 
269  // get prototypes for matrices
270  int repDim = rep->getDim();
271  TMatrixT<double> state(repDim,1);
272  TMatrixT<double> cov(repDim,repDim);;
273  GFDetPlane pl;
274 
275  double extLen(0.);
276 
277  /* do an extrapolation, if the trackrep irep is not given
278  * at this ihit position. This will usually be the case, but
279  * not if the fit turnes around
280  */
281  if(ihit!=tr->getRepAtHit(irep)){
282  // get the (virtual) detector plane
283  pl=hit->getDetPlane(rep);
284  //do the extrapolation
285  extLen = rep->extrapolate(pl,state,cov);
286  }
287  else{
288  pl = rep->getReferencePlane();
289  state = rep->getState();
290  cov = rep->getCov();
291  extLen = 0.;
292  }
293 
294  if(cov[0][0]<1.E-50){ // diagonal elements must be >=0
295  GFException exc(COVEXC,__LINE__,__FILE__);
296  throw exc;
297  }
298 
299  if(fSmooth && fSmoothFast) {
300  if(direction == 1) {
301  tr->getBK(irep)->setMatrix("fSt",ihit,state);
302  tr->getBK(irep)->setMatrix("fCov",ihit,cov);
303  if(rep->hasAuxInfo()) tr->getBK(irep)->setMatrix("fAuxInfo",ihit,*(rep->getAuxInfo(pl)));
304  tr->getBK(irep)->setDetPlane("fPl",ihit,pl);
305  } else {
306  tr->getBK(irep)->setMatrix("bSt",ihit,state);
307  tr->getBK(irep)->setMatrix("bCov",ihit,cov);
308  if(rep->hasAuxInfo()) tr->getBK(irep)->setMatrix("bAuxInfo",ihit,*(rep->getAuxInfo(pl)));
309  tr->getBK(irep)->setDetPlane("bPl",ihit,pl);
310  }
311  }
312 
313  //state.Print();
314 #ifdef DEBUG
315  std::cerr<<"GFKalman::processHit - state and cov prediction "<<std::endl;
316  state.Print();
317  cov.Print();
318 #endif
319 
320  TMatrixT<double> H(hit->getHMatrix(rep));
321  TMatrixT<double> m, V;
322  hit->getMeasurement(rep,pl,state,cov,m,V);
323  TMatrixT<double> res = m-(H*state);
324 
325  // calculate kalman gain ------------------------------
326  TMatrixT<double> Gain(calcGain(cov,V,H));
327 
328  // calculate update -----------------------------------
329  TMatrixT<double> update=Gain*res;
330 
331 #ifdef DEBUG
332  std::cout<<"Gain"; Gain.Print();
333  std::cout<<"residual vector"; res.Print();
334  std::cout<<"update = Gain*res"; update.Print();
335 #endif
336 
337  state+=update; // prediction overwritten!
338  cov-=Gain*(H*cov);
339 
340  if(fSmooth) {
341  if(direction == 1) {
342  tr->getBK(irep)->setNumber("fExtLen",ihit,extLen);
343  tr->getBK(irep)->setMatrix("fUpSt",ihit,state);
344  tr->getBK(irep)->setMatrix("fUpCov",ihit,cov);
345  if(rep->hasAuxInfo()) tr->getBK(irep)->setMatrix("fAuxInfo",ihit,*(rep->getAuxInfo(pl)));
346  tr->getBK(irep)->setDetPlane("fPl",ihit,pl);
347  } else {
348  tr->getBK(irep)->setNumber("bExtLen",ihit,extLen);
349  tr->getBK(irep)->setMatrix("bUpSt",ihit,state);
350  tr->getBK(irep)->setMatrix("bUpCov",ihit,cov);
351  if(rep->hasAuxInfo()) tr->getBK(irep)->setMatrix("bAuxInfo",ihit,*(rep->getAuxInfo(pl)));
352  tr->getBK(irep)->setDetPlane("bPl",ihit,pl);
353  }
354  }
355 
356  // calculate filtered chisq
357  // filtered residual
358  res = m-(H*state);
359  double chi2 = chi2Increment(res,H,cov,V);
360  int ndf = res.GetNrows();
361  if (direction == -1) {
362  rep->addChiSqu( chi2 );
363  }
364  if (direction == 1) {
365  rep->addForwardChiSqu( chi2 );
366  }
367  rep->addNDF( ndf );
368 
369  /*
370  if(direction==1){
371  tr->getBK(irep)->setNumber("fChi2",ihit,chi2/ndf);
372  }
373  else{
374  tr->getBK(irep)->setNumber("bChi2",ihit,chi2/ndf);
375  }
376  */
377 
378  // if we survive until here: update TrackRep
379  //rep->setState(state);
380  //rep->setCov(cov);
381  //rep->setReferencePlane(pl);
382 
383  {
384  //printf("--> %d\n", repDim);
385  // printf("@@@ %7.2f %7.2f %7.2f -> %10.5f %10.5f %10.5f %10.5f %10.5f\n",
386  // pl.getO().X(), pl.getO().Y(), pl.getO().Z(),
387  // state[0][0], state[1][0], state[2][0], state[3][0], state[4][0]);
388  }
389 
390  rep->setData(state,pl,&cov);
391  tr->setRepAtHit(irep,ihit);
392 
393 #ifdef DEBUG
394  std::cout<<"GFKalman::processHit - updated state and cov "<<std::endl;
395  rep->getState().Print();
396  rep->getCov().Print();
397 #endif
398 }
399 
400 
401 TMatrixT<double>
402 GFKalman::calcGain(const TMatrixT<double>& cov,
403  const TMatrixT<double>& HitCov,
404  const TMatrixT<double>& H){
405 
406  // calculate covsum (V + HCH^T)
407  TMatrixT<double> covsum1(cov,TMatrixT<double>::kMultTranspose,H);
408  TMatrixT<double> covsum(H,TMatrixT<double>::kMult,covsum1);
409 
410  covsum+=HitCov;
411 
412  // invert
413  TMatrixT<double> covsumInv;
414  GFTools::invertMatrix(covsum,covsumInv);
415 
416  // calculate gain
417  TMatrixT<double> gain1(H,TMatrixT<double>::kTransposeMult,covsumInv);
418  TMatrixT<double> gain(cov,TMatrixT<double>::kMult,gain1);
419 
420  return gain;
421 }
422 
423 
424 
425 
426 
427 
428