FairRoot/PandaRoot
KalmanCalculator.cxx
Go to the documentation of this file.
1 // ******************************************************
2 // DecayTreeFitter Package
3 // We thank the original author Wouter Hulsbergen
4 // (BaBar, LHCb) for providing the sources.
5 // http://arxiv.org/abs/physics/0503191v1 (2005)
6 // Adaptation & Development for PANDA: Ralf Kliemt (2015)
7 // ******************************************************
8 
9 #include "KalmanCalculator.h"
10 
11 #define SLOWBUTSAFE 1
12 //#undef SLOWBUTSAFE
13 #undef SKIPHIGHACCURACYCORRECTION
14 #include "RhoCalculationTools.h"
15 using namespace DecayTreeFitter;
17 extern int vtxverbose;
18 namespace DecayTreeFitter
19 {
20  inline double fastsymmatrixaccess(double* m, int row, int col)
21  {
22  return *(m+(row*(row-1))/2+(col-1));
23  }
24 
25  inline double symmatrixaccess(double* m, int row, int col)
26  {
27  return (row>=col? fastsymmatrixaccess(m,row,col) : fastsymmatrixaccess(m,col,row)) ;
28  }
29 }
30 ErrCode
31 DecayTreeFitter::KalmanCalculator::init(const TVectorD& value, const TMatrixD& G,
32  const FitParams* fitparams, const TMatrixDSym& V,
33  int weight)
34 {
35  ErrCode status ;
36  if(vtxverbose>=6) { std::cout << "KalmanCalculator::init()"<<std::endl;}
37  m_nconstraints = value.GetNrows() ; // dimension of the constraint
38  m_nparameters = fitparams->dim() ; // dimension of the state
39 
40  int valdim = value.GetNrows() ; // dimension of the constraint
41  int statdim = fitparams->par().GetNrows() ; // dimension of the state
42 
43 #ifdef VTK_BOUNDSCHECKING
44  assert( G.GetNrows() == valdim && G.GetNcols() == statdim &&
45  (V.GetNrows()==valdim) ) ;
46 #endif
47  m_value = &value ;
48  m_matrixG = &G ;
49  TMatrixDSym C(fitparams->cov());
50  if(vtxverbose>=6) { printf("KalmanCalculator::init() G.GetNrows()/G.GetNcols() = %i/%i \t valdim/statdim = %i/%i \t V.GetNrows()/C.GetNrows() = %i/%i V.GetNcols()/C.GetNcols() = %i/%i \n",G.GetNrows(),G.GetNcols(),valdim,statdim,V.GetNrows(),C.GetNrows(),V.GetNcols(),C.GetNcols());}
51 
52  // calculate C*G.T()
53 #ifdef SLOWBUTSAFE
54  if(vtxverbose>=7) { std::cout << "KalmanCalculator::init() calc C*GT 'slow'"<<std::endl;}
55  //m_matrixCGT = C * G.T() ;
56  TMatrixD CGt(C,TMatrixD::kMultTranspose,G);
57  if(vtxverbose>=7) { std::cout << "KalmanCalculator::init() CGT:";CGt.Print();}
58  m_matrixCGT.ResizeTo(CGt);
59  m_matrixCGT = CGt;
60 #else
61  if(vtxverbose>=7) { std::cout << "KalmanCalculator::init() calc C*GT 'fast'"<<std::endl;}
62  double tmp ;
63  m_matrixCGT = TMatrixD(statdim,valdim) ;
64  for(int col=0; col<m_nconstraints; col++)
65  for(int k=0; k<m_nparameters; k++)
66  if( (tmp=G(col,k)) !=0 ) {
67  for(int row=0; row<k; row++)
68  m_matrixCGT(row,col) += C(k,row) * tmp ;
69  for(int row=k; row<=statdim; row++)
70  m_matrixCGT(row,col) += C(row,k) * tmp ;
71  }
72 #endif
73  if(vtxverbose>=6) { std::cout << "KalmanCalculator::init() calc R = G*C*GT + V"<<std::endl;}
74 
75  // calculate the error in the predicted residual R = G*C*GT + V
76  // slow:
77 #ifdef SLOWBUTSAFE
78  TMatrixDSym Rinv=C.Similarity(G);
79  m_matrixRinv.ResizeTo(Rinv);
80  m_matrixRinv = Rinv;
81  TMatrixDSym theV(V);
82  theV *= weight;
83  m_matrixRinv += theV;
84  if(vtxverbose>=6) { std::cout << "KalmanCalculator::init() V"<<std::endl;}
85  if(vtxverbose>=7) { theV.Print();}
86 #else
87  m_matrixRinv = V ;
88  if(weight!=1) m_matrixRinv *= weight ;
89 
90  for(int row=0; row<m_nconstraints; row++)
91  {
92  for(int k=0; k<m_nparameters; k++)
93  if( (tmp=G(row,k)) != 0 )
94  for(int col=0; col<=row; col++)
95  m_matrixRinv(row,col) += tmp*m_matrixCGT(k,col) ;
96  for(int col=0; col<=row; col++) // fill the other side, too as TMatrixD is not symmetric
97  m_matrixRinv(col,row) = m_matrixRinv(row,col)
98  }
99 #endif
100  if(vtxverbose>=6) { std::cout << "KalmanCalculator::init() G*C*GT"<<std::endl;}
101  if(vtxverbose>=7) { Rinv.Print();}
102 
103  if(vtxverbose>=6) { std::cout << "KalmanCalculator::init() invert R"<<std::endl;}
104  m_matrixR.ResizeTo(m_matrixRinv);
105  m_matrixR = m_matrixRinv ;
106  double det=0;
107  m_matrixRinv.InvertFast(&det); //If determinant is zero the inversion failed.
108  if(!det) {
109  status |= ErrCode::inversionerror;
110  std::cout << "Error inverting matrix. Vertex fit fails." << std::endl ;
111  }
112  if(vtxverbose>=7) { m_matrixRinv.Print();}
113 
114  if(vtxverbose>=6) { std::cout << "KalmanCalculator::init() calculate gain"<<std::endl;}
115  // calculate the gain matrix
116  TMatrixD K(m_matrixCGT,TMatrixD::kMult,m_matrixRinv);
117  m_matrixK.ResizeTo(K) ;
118  m_matrixK = K ;
119  if(vtxverbose>=7) { m_matrixK.Print();}
120  m_chisq = -1 ;
121  // // let's see if we get same results using sparce matrices
122  // VtkSparseMatrix Gs(G) ;
123  // VtkSparseMatrix CGT = Gs.transposeAndMultiplyRight(fitparams->cov()) ;
124  // HepSymMatrix Rs(value.numrow()) ;
125  // Gs.multiplyLeft(CGT,Rs) ;
126  // if(V) Rs += (*V) ;
127  // Rs.invert(m_ierr) ;
128  // VtkSparseMatrix Ks = CGT*Rs ;
129  if(vtxverbose>=6) { std::cout << "KalmanCalculator::init() done"<<std::endl;}
130  return status ;
131 }
132 
133 void
135 {
136  if(vtxverbose>=5) { std::cout << "KalmanCalculator::updatePar(FitParams*):"<<std::endl;}
137  //fitparams.par() -= fitparams->cov() * (G.T() * (R * value) ) ;
138  fitparams->par() -= m_matrixK * (*m_value) ;
139  if(vtxverbose>=7) {(m_matrixK * (*m_value)).Print();}
140  m_chisq = m_matrixRinv.Similarity(*m_value) ;
141  if(vtxverbose>=5) { std::cout << "KalmanCalculator::updatePar() done"<<std::endl;}
142 }
143 
144 void
146 {
147  if(vtxverbose>=5) { std::cout << "KalmanCalculator::updatePar(TVectorD&,FitParams*)"<<std::endl;}
148  // this is still very, very slow !
149  TVectorD valueprime = (*m_value) + (*m_matrixG) * (pred-fitparams->par()) ;
150  fitparams->par() = pred - m_matrixK*valueprime ;
151  m_chisq = m_matrixRinv.Similarity( valueprime ) ;
152  if(vtxverbose>=5) { std::cout << "KalmanCalculator::updatePar() done"<<std::endl;}
153 }
154 
155 void
157 {
158  if(vtxverbose>=7) { std::cout << "KalmanCalculator::updateCov(FitParams*)"<<std::endl;}
159 
160 #ifdef SLOWBUTSAFE
161  if(vtxverbose>=8) { std::cout << "KalmanCalculator::updateCov: previous fitpar->cov()" ; RhoCalculationTools::PrintMatrix(fitparams->cov()); }
162 
163  // RK: nice try, sadly crappy
164  //TMatrixDSym deltaCov = m_matrixRinv.SimilarityT(*m_matrixG).Similarity(fitparams->cov()) ;
165  //fitparams->cov() -= deltaCov ;
166 
167  //TMatrixD dcov1(m_matrixCGT,TMatrixD::kMultTranspose,m_matrixK);
168  //const TMatrixDSym C(fitparams->cov());
169  TMatrixD HC(*m_matrixG,TMatrixD::kMult,fitparams->cov());
170  TMatrixD dcov1(m_matrixK,TMatrixD::kMult,HC);
171  TMatrixDSym KRKt = m_matrixR.Similarity(m_matrixK);
172  TMatrixDSym dcov3(dcov1.GetNrows());
173  for(int row=0; row<dcov1.GetNrows(); row++){
174  for(int col=0; col<=row; col++){
175  dcov3(row,col) = -2*dcov1(row,col);
176  dcov3(col,row) = -2*dcov1(row,col);
177  }
178  }
179  fitparams->cov() += KRKt ;
180  fitparams->cov() += dcov3 ;
181  //if(vtxverbose>=8) { std::cout << "KalmanCalculator::updateCov: -1*deltacov = V*{R^(-1)*G*R^(-1T)}*V^T" ; RhoCalculationTools::PrintMatrix(deltaCov); }
182  if(vtxverbose>=8) { std::cout << "KalmanCalculator::updateCov: KRKt = K*R*KT"; RhoCalculationTools::PrintMatrix(KRKt);}
183  if(vtxverbose>=8) { std::cout << "KalmanCalculator::updateCov: dcov3 = -2*C*GT*KT"; RhoCalculationTools::PrintMatrix(dcov3);}
184  if(vtxverbose>=7) { std::cout << "KalmanCalculator::updateCov: afterwds fitpar->cov()" ; RhoCalculationTools::PrintMatrix(fitparams->cov()); }
185 #else
186 
187  // There are two expessions for updating the covariance
188  // matrix.
189  // slow: deltaCov = - 2*C*GT*KT + K*R*KT
190  // fast: deltaCov = - C*GT*KT
191  // The fast expression is very sensitive to machine accuracy. The
192  // following piece of code effectively invokes the slow
193  // expression. I couldn't write it faster than this.
194 
195  double tmp ;
196 #ifndef SKIPHIGHACCURACYCORRECTION
197  // substitute C*GT --> 2*C*GT - K*R. of course, this invalidates
198  // C*GT, but we do not need it after this routine.
199 
200  // we use the fact that _in principle_ C*GT = K*R, such that
201  // they have the same zero elements
202  for(int row=0; row<m_nparameters; row++)
203  for(int col=0; col<m_nconstraints; col++)
204  if( (tmp =2*m_matrixCGT(row,col))!=0 ) {
205  for(int k=0; k<m_nconstraints; k++)
206  tmp -= m_matrixK(row,k) * m_matrixR(k,col) ;
207  m_matrixCGT(row,col) = tmp ;
208  }
209 #endif
210 
211  // HepMatrix KR = m_matrixK*m_matrixR ;
212  // double tmp ;
213  // for(int row=1; row<=m_nparameters; ++row)
214  // for(int k=1; k<=m_nconstraints; ++k)
215  // if( (tmp= (KR(row,k) - 2*m_matrixCGT(row,k))) != 0 )
216  // for(int col=1; col<=row; ++col)
217  // fitparams->cov().fast(row,col) += tmp * m_matrixK(col,k) ;
218 
219  // deltaCov = - C*GT*KT
220  for(int row=0; row<m_nparameters; row++)
221  for(int k=0; k<m_nconstraints; k++)
222  if( (tmp = -(m_matrixCGT(row,k))) != 0 ) // they have same size, and same 'emptiness'
223  for(int col=0; col<=row; col++)
224  fitparams.cov()(row,col) += tmp * m_matrixK(col,k) ;
225 
226 #endif
227  for(int col=0; col<m_nconstraints; col++)
228  for(int k=0; k<m_nparameters; k++)
229  if( (*m_matrixG)(col,k) !=0 ) ++(fitparams->nConstraintsVec(k)) ;
230  if(vtxverbose>=5) { std::cout << "KalmanCalculator::updateCov() done"<<std::endl;}
231 }
int row
Definition: anaLmdDigi.C:67
MechFsc Print()
ClassImp(KalmanCalculator)
printf("RealTime=%f seconds, CpuTime=%f seconds\n", rtime, ctime)
int vtxverbose
__m128 m
Definition: P4_F32vec4.h:28
int col
Definition: anaLmdDigi.C:67
double fastsymmatrixaccess(double *m, int row, int col)
double symmatrixaccess(double *m, int row, int col)
int Pic_FED Eff_lEE C()
static void PrintMatrix(TMatrixT< double > m)
void updatePar(FitParams *fitparams)
int & nConstraintsVec(int row)
Definition: FitParams.h:47
void updateCov(FitParams *fitparams)
TMatrixT< double > TMatrixD
Definition: PndLmdDim.h:52
TMatrixDSym & cov()
Definition: FitParams.h:34
int status[10]
Definition: f_Init.h:28
ErrCode init(const TVectorD &value, const TMatrixD &G, const FitParams *fitparams, const TMatrixDSym &V, int weight=1)