FairRoot/PandaRoot
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 */
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 
35 
36 GFKalman::GFKalman():fInitialDirection(1),fNumIt(3),fBlowUpFactor(500.){;}
37 
39 
41 
42  fSmooth = trk->getSmoothing();
43 
44  if(fSmooth) {
45  int nreps = trk->getNumReps();
46  for(int i=0; i<nreps; i++) {
47 
48  std::vector<std::string> mat_keys = trk->getBK(i)->getMatrixKeys();
49  bool already_there = false;
50  for(unsigned int j=0; j<mat_keys.size(); j++) {
51  if(mat_keys.at(j) == "fUpSt") already_there = true;
52  }
53  if(already_there) continue;
54 
55  trk->getBK(i)->setNhits(trk->getNumHits());
56  trk->getBK(i)->bookMatrices("fUpSt");
57  trk->getBK(i)->bookMatrices("fUpCov");
58  trk->getBK(i)->bookMatrices("bUpSt");
59  trk->getBK(i)->bookMatrices("bUpCov");
60  trk->getBK(i)->bookGFDetPlanes("fPl");
61  trk->getBK(i)->bookGFDetPlanes("bPl");
62  if(trk->getTrackRep(i)->hasAuxInfo()) {
63  trk->getBK(i)->bookMatrices("fAuxInfo");
64  trk->getBK(i)->bookMatrices("bAuxInfo");
65  }
66  }
67  }
68 
69  int direction=fInitialDirection;
70  assert(direction==1 || direction==-1);
71  // trk->clearGFBookkeeping();
72  trk->clearRepAtHit();
73 
74  /*why is there a factor of two here (in the for statement)?
75  Because we consider one full iteration to be one back and
76  one forth fitting pass */
77  for(int ipass=0; ipass<2*fNumIt; ipass++){
78  if(ipass>0) blowUpCovs(trk);
79  if(direction==1){
80  trk->setNextHitToFit(0);
81  }
82  else {
83  trk->setNextHitToFit(trk->getNumHits()-1);
84  }
85  fittingPass(trk,direction);
86 
87  //save first and last plane,state&cov after the fitting pass
88  if(direction==1){//forward at last hit
89  int nreps=trk->getNumReps();
90  for(int i=0; i<nreps; ++i){
91  trk->getTrackRep(i)->
92  setLastPlane( trk->getTrackRep(i)->getReferencePlane() );
93  trk->getTrackRep(i)->
94  setLastState( trk->getTrackRep(i)->getState() );
95  trk->getTrackRep(i)->
96  setLastCov( trk->getTrackRep(i)->getCov() );
97  }
98  }
99  else{//backward at first hit
100  int nreps=trk->getNumReps();
101  for(int i=0; i<nreps; ++i){
102  trk->getTrackRep(i)->
103  setFirstPlane( trk->getTrackRep(i)->getReferencePlane() );
104  trk->getTrackRep(i)->
105  setFirstState( trk->getTrackRep(i)->getState() );
106  trk->getTrackRep(i)->
107  setFirstCov( trk->getTrackRep(i)->getCov() );
108  }
109  }
110 
111  //switch direction of fitting and also inside all the reps
112  if(direction==1) direction=-1;
113  else direction=1;
114  switchDirection(trk);
115  }
116 
117  return;
118 }
119 
120 void
122  int nreps=trk->getNumReps();
123  for(int i=0; i<nreps; ++i){
124  trk->getTrackRep(i)->switchDirection();
125  }
126 }
127 
130 }
131 
132 void
134  //loop over hits
135  unsigned int nhits=trk->getNumHits();
136  unsigned int starthit=trk->getNextHitToFit();
137 
138  int nreps=trk->getNumReps();
139  int ihit=(int)starthit;
140 
141  for(int irep=0; irep<nreps; ++irep) {
142  GFAbsTrackRep* arep=trk->getTrackRep(irep);
143  if(arep->getStatusFlag()==0) {
144  //clear chi2 sum and ndf sum in track reps
145  arep->setChiSqu(0.);
146  arep->setNDF(0);
147  //clear failedHits and outliers
148  trk->getBK(irep)->clearFailedHits();
149  }
150  }
151 
152  while((ihit<(int)nhits && direction==1) || (ihit>-1 && direction==-1)){
153  // GFAbsRecoHit* ahit=trk->getHit(ihit);
154  // loop over reps
155  for(int irep=0; irep<nreps; ++irep){
156  GFAbsTrackRep* arep=trk->getTrackRep(irep);
157  if(arep->getStatusFlag()==0) {
158  try {
159  processHit(trk,ihit,irep,direction);
160  }
161  catch(GFException& e) {
162  trk->addFailedHit(irep,ihit);
163  std::cerr << e.what();
164  e.info();
165  if(e.isFatal()) {
166  arep->setStatusFlag(1);
167  continue; // go to next rep immediately
168  }
169  }
170  }
171  }// end loop over reps
172  ihit+=direction;
173  }// end loop over hits
174  trk->setNextHitToFit(ihit-2*direction);
175  //trk->printGFBookkeeping();
176 }
177 
178 double GFKalman::chi2Increment(const TMatrixT<double>& r,const TMatrixT<double>& H,
179  const TMatrixT<double>& cov,const TMatrixT<double>& V){
180 
181  // residuals covariances:R=(V - HCH^T)
182  TMatrixT<double> R(V);
183  TMatrixT<double> covsum1(cov,TMatrixT<double>::kMultTranspose,H);
184  TMatrixT<double> covsum(H,TMatrixT<double>::kMult,covsum1);
185 
186  R-=covsum;
187 
188  // chisq= r^TR^(-1)r
189  TMatrixT<double> Rinv;
190  GFTools::invertMatrix(R,Rinv);
191 
192 
193  TMatrixT<double> residTranspose(r);
194  residTranspose.T();
195  TMatrixT<double> chisq=residTranspose*(Rinv*r);
196  assert(chisq.GetNoElements()==1);
197 
198  if(TMath::IsNaN(chisq[0][0])){
199  GFException exc("chi2 is nan",__LINE__,__FILE__);
200  exc.setFatal();
201  std::vector< TMatrixT<double> > matrices;
202  matrices.push_back(r);
203  matrices.push_back(V);
204  matrices.push_back(R);
205  matrices.push_back(cov);
206  exc.setMatrices("r, V, R, cov",matrices);
207  throw exc;
208  }
209 
210  return chisq[0][0];
211 }
212 
213 
214 double
216 {
217  // get prototypes for matrices
218  int repDim=rep->getDim();
219  TMatrixT<double> state(repDim,1);
220  TMatrixT<double> cov(repDim,repDim);;
221  GFDetPlane pl=hit->getDetPlane(rep);
222  rep->extrapolate(pl,state,cov);
223 
224 
225  TMatrixT<double> H = hit->getHMatrix(rep);
226  // get hit covariances
227  TMatrixT<double> V=hit->getHitCov(pl);
228 
229  TMatrixT<double> r=hit->residualVector(rep,state,pl);
230  assert(r.GetNrows()>0);
231 
232  //this is where chi2 is calculated
233  double chi2 = chi2Increment(r,H,cov,V);
234 
235  return chi2/r.GetNrows();
236 }
237 
238 
239 void
240 GFKalman::processHit(GFTrack* tr, int ihit, int irep,int direction){
241  GFAbsRecoHit* hit = tr->getHit(ihit);
242  GFAbsTrackRep* rep = tr->getTrackRep(irep);
243 
244  // get prototypes for matrices
245  int repDim = rep->getDim();
246  TMatrixT<double> state(repDim,1);
247  TMatrixT<double> cov(repDim,repDim);;
248  GFDetPlane pl;
249  /* do an extrapolation, if the trackrep irep is not given
250  * at this ihit position. This will usually be the case, but
251  * not if the fit turnes around
252  */
253  //std::cout << "fitting " << ihit << std::endl;
254  if(ihit!=tr->getRepAtHit(irep)){
255  //std::cout << "not same" << std::endl;
256  // get the (virtual) detector plane
257  pl=hit->getDetPlane(rep);
258  //do the extrapolation
259  rep->extrapolate(pl,state,cov);
260  }
261  else{
262  //std::cout << "same" << std::endl;
263  // return;
264  pl = rep->getReferencePlane();
265  state = rep->getState();
266  cov = rep->getCov();
267  }
268 
269  if(cov[0][0]<1.E-50){
270  GFException exc(COVEXC,__LINE__,__FILE__);
271  throw exc;
272  }
273 
274  // TMatrixT<double> origcov=rep->getCov();
275  TMatrixT<double> H=hit->getHMatrix(rep);
276  // get hit covariances
277  TMatrixT<double> V=hit->getHitCov(pl);
278  // calculate kalman gain ------------------------------
279  TMatrixT<double> Gain(calcGain(cov,V,H));
280  TMatrixT<double> res=hit->residualVector(rep,state,pl);
281  // calculate update -----------------------------------
282  TMatrixT<double> update=Gain*res;
283  state+=update; // prediction overwritten!
284  cov-=Gain*(H*cov);
285 
286  if(fSmooth) {
287  if(direction == 1) {
288  tr->getBK(irep)->setMatrix("fUpSt",ihit,state);
289  tr->getBK(irep)->setMatrix("fUpCov",ihit,cov);
290  if(rep->hasAuxInfo()) tr->getBK(irep)->setMatrix("fAuxInfo",ihit,*(rep->getAuxInfo(pl)));
291  tr->getBK(irep)->setDetPlane("fPl",ihit,pl);
292  } else {
293  tr->getBK(irep)->setMatrix("bUpSt",ihit,state);
294  tr->getBK(irep)->setMatrix("bUpCov",ihit,cov);
295  if(rep->hasAuxInfo()) tr->getBK(irep)->setMatrix("bAuxInfo",ihit,*(rep->getAuxInfo(pl)));
296  tr->getBK(irep)->setDetPlane("bPl",ihit,pl);
297  }
298  }
299 
300  // calculate filtered chisq
301  // filtered residual
302  TMatrixT<double> r=hit->residualVector(rep,state,pl);
303  double chi2 = chi2Increment(r,H,cov,V);
304  int ndf = r.GetNrows();
305  rep->addChiSqu( chi2 );
306  rep->addNDF( ndf );
307 
308  /*
309  if(direction==1){
310  tr->getBK(irep)->setNumber("fChi2",ihit,chi2/ndf);
311  }
312  else{
313  tr->getBK(irep)->setNumber("bChi2",ihit,chi2/ndf);
314  }
315  */
316 
317  // if we survive until here: update TrackRep
318  //rep->setState(state);
319  //rep->setCov(cov);
320  //rep->setReferencePlane(pl);
321  rep->setData(state,pl,&cov);
322  tr->setRepAtHit(irep,ihit);
323 }
324 
325 
326 TMatrixT<double>
327 GFKalman::calcGain(const TMatrixT<double>& cov,
328  const TMatrixT<double>& HitCov,
329  const TMatrixT<double>& H){
330 
331  // calculate covsum (V + HCH^T)
332  TMatrixT<double> covsum1(cov,TMatrixT<double>::kMultTranspose,H);
333  TMatrixT<double> covsum(H,TMatrixT<double>::kMult,covsum1);
334 
335  covsum+=HitCov;
336 
337  // invert
338  TMatrixT<double> covsumInv;
339  GFTools::invertMatrix(covsum,covsumInv);
340 
341  // calculate gain
342  TMatrixT<double> gain1(H,TMatrixT<double>::kTransposeMult,covsumInv);
343  TMatrixT<double> gain(cov,TMatrixT<double>::kMult,gain1);
344 
345  return gain;
346 }
347 
348 
349 
350 
351 
352 
353 
double chi2Increment(const TMatrixT< double > &r, const TMatrixT< double > &H, const TMatrixT< double > &cov, const TMatrixT< double > &V)
this returns the reduced chi2 increment for a hit
Definition: GFKalman.cxx:178
Base Class for genfit track representations. Defines interface for track parameterizations.
Definition: GFAbsTrackRep.h:80
GFBookkeeping * getBK(int index=-1)
get GFBookKeeping object for particular track rep (default is cardinal rep)
Definition: GFTrack.h:326
const GFDetPlane & getReferencePlane() const
void addFailedHit(unsigned int irep, unsigned int id)
Definition: GFTrack.h:284
void addNDF(unsigned int n)
unsigned int getNumHits() const
Definition: GFTrack.h:148
virtual TMatrixT< double > residualVector(const GFAbsTrackRep *stateVector, const TMatrixT< double > &state, const GFDetPlane &d)
Calculate residual with respect to a track representation.
Definition: GFAbsRecoHit.h:142
TMatrixT< double > calcGain(const TMatrixT< double > &cov, const TMatrixT< double > &HitCov, const TMatrixT< double > &H)
Calculate Kalman Gain.
Definition: GFKalman.cxx:327
int fInitialDirection
Definition: GFKalman.h:145
TMatrixT< double > getState() const
double r
Definition: RiemannTest.C:14
unsigned int getNextHitToFit() const
Accessor for fNextHitToFit.
Definition: GFTrack.h:178
Int_t res
Definition: anadigi.C:166
Int_t i
Definition: run_full.C:25
Detector plane genfit geometry class.
Definition: GFDetPlane.h:59
Track object for genfit. genfit algorithms work on these objects.
Definition: GFTrack.h:60
bool getSmoothing()
Read back if smoothing is/was turned on or off for this track.
Definition: GFTrack.h:405
double fBlowUpFactor
Definition: GFKalman.h:147
static void update(void)
Definition: ranlxd.cxx:453
virtual const GFDetPlane & getDetPlane(GFAbsTrackRep *)=0
Get detector plane for a given track representation.
virtual const char * what() const
standard error message handling for exceptions. use like &quot;std::cerr &lt;&lt; e.what();&quot; ...
Definition: GFException.cxx:47
bool fSmooth
Definition: GFKalman.h:148
void fittingPass(GFTrack *, int dir)
Performs fit on a GFTrack beginning with the current hit.
Definition: GFKalman.cxx:133
void bookGFDetPlanes(std::string key)
~GFKalman()
Definition: GFKalman.cxx:38
unsigned int getNumReps() const
Get number of track represenatations.
Definition: GFTrack.h:192
unsigned int getDim() const
returns dimension of state vector
void invertMatrix(const TMatrixT< double > &mat, TMatrixT< double > &inv)
Invert a matrix, throwing GFException when inversion fails.
Definition: GFTools.cxx:334
virtual const TMatrixT< double > * getAuxInfo(const GFDetPlane &)
Get auxillary information from the track representation.
bool getStatusFlag()
virtual bool hasAuxInfo()
See if the track representation has auxillary information stored.
virtual TMatrixT< double > getHMatrix(const GFAbsTrackRep *stateVector)=0
Get transformation matrix. Transformation between hit coordinates and track representation coordinate...
void blowUpCovs(double blowUpFactor)
this is needed to blow up the covariance matrix before a fitting pass drops off-diagonal elements and...
Definition: GFTrack.cxx:257
void setRepAtHit(unsigned int irep, int ihit)
set the hit index at which plane,state&amp;cov of rep irep is defined
Definition: GFTrack.h:357
void setDetPlane(std::string key, unsigned int index, const GFDetPlane &pl)
void clearRepAtHit()
clear the hit indices at which plane,state&amp;cov of reps are defined
Definition: GFTrack.h:371
void setNhits(int n)
Definition: GFBookkeeping.h:50
bool isFatal()
get fatal flag.
Definition: GFException.h:79
std::vector< std::string > getMatrixKeys()
void addChiSqu(double aChiSqu)
virtual TMatrixT< double > getHitCov(const GFDetPlane &)=0
Get hit covariances in a specific detector plane.
int getRepAtHit(unsigned int irep)
get the hit index at which plane,state&amp;cov of rep irep is defined
Definition: GFTrack.h:364
void setMatrices(std::string, const std::vector< TMatrixT< double > > &)
set list of matrices with description
Definition: GFException.cxx:41
void processTrack(GFTrack *trk)
Performs fit on a GFTrack.
Definition: GFKalman.cxx:40
GFKalman()
Definition: GFKalman.cxx:36
virtual double extrapolate(const GFDetPlane &plane, TMatrixT< double > &statePred)
returns the tracklength spanned in this extrapolation
void info()
print information in the exception object
Definition: GFException.cxx:52
Base Class for representing a Hit in GENFIT.
Definition: GFAbsRecoHit.h:73
GFAbsTrackRep * getTrackRep(int id) const
Accessor for track representations.
Definition: GFTrack.h:186
GFTrack * trk
Definition: checkgenfit.C:13
void setNDF(unsigned int n)
void setMatrix(std::string key, unsigned int index, const TMatrixT< double > &mat)
void bookMatrices(std::string key)
void setChiSqu(double aChiSqu)
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:128
Exception class for error handling in GENFIT (provides storage for diagnostic information) ...
Definition: GFException.h:45
GFAbsRecoHit * getHit(int id) const
Definition: GFTrack.h:144
void processHit(GFTrack *, int, int, int)
One Kalman step.
Definition: GFKalman.cxx:240
void setStatusFlag(int _val)
double getChi2Hit(GFAbsRecoHit *, GFAbsTrackRep *)
Calculates chi2 of a given hit with respect to a given track representation.
Definition: GFKalman.cxx:215
void setFatal(bool b=true)
set fatal flag. if this is true, the fit stops for this current track repr.
Definition: GFException.h:77
PndSdsMCPoint * hit
Definition: anasim.C:70
void switchDirection(GFTrack *trk)
Used to switch between forward and backward filtering.
Definition: GFKalman.cxx:121
#define COVEXC
Definition: GFKalman.cxx:33
virtual void setData(const TMatrixT< double > &st, const GFDetPlane &pl, const TMatrixT< double > *cov=NULL, const TMatrixT< double > *aux=NULL)
Puts the track representation in a given state.
void clearFailedHits()
virtual void switchDirection()=0
Int_t fNumIt
Definition: GFKalman.h:146
Double_t R
Definition: checkhelixhit.C:61
void setNextHitToFit(unsigned int i)
Set next hit to be used in a fit.
Definition: GFTrack.h:182
TMatrixT< double > getCov() const