// ****************************************************** // DecayTreeFitter Package // We thank the original author Wouter Hulsbergen // (BaBar, LHCb) for providing the sources. // http://arxiv.org/abs/physics/0503191v1 (2005) // Adaptation & Development for PANDA: Ralf Kliemt (2015) // ****************************************************** #include "KalmanCalculator.h" #define SLOWBUTSAFE 1 //#undef SLOWBUTSAFE #undef SKIPHIGHACCURACYCORRECTION #include "RhoCalculationTools.h" using namespace DecayTreeFitter; ClassImp(KalmanCalculator); extern int vtxverbose; namespace DecayTreeFitter { inline double fastsymmatrixaccess(double* m, int row, int col) { return *(m+(row*(row-1))/2+(col-1)); } inline double symmatrixaccess(double* m, int row, int col) { return (row>=col? fastsymmatrixaccess(m,row,col) : fastsymmatrixaccess(m,col,row)) ; } } ErrCode DecayTreeFitter::KalmanCalculator::init(const TVectorD& value, const TMatrixD& G, const FitParams* fitparams, const TMatrixDSym& V, int weight) { ErrCode status ; if(vtxverbose>=5) { std::cout << "KalmanCalculator::init()"<dim() ; // dimension of the state int valdim = value.GetNrows() ; // dimension of the constraint int statdim = fitparams->par().GetNrows() ; // dimension of the state #ifdef VTK_BOUNDSCHECKING assert( G.GetNrows() == valdim && G.GetNcols() == statdim && (V.GetNrows()==valdim) ) ; #endif m_value = &value ; m_matrixG = &G ; TMatrixDSym C(fitparams->cov()); if(vtxverbose>=5) { 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());} // calculate C*G.T() #ifdef SLOWBUTSAFE if(vtxverbose>=7) { std::cout << "KalmanCalculator::init() calc C*GT 'slow'"<=7) { std::cout << "KalmanCalculator::init() CGT:";CGt.Print();} m_matrixCGT.ResizeTo(CGt); m_matrixCGT = CGt; #else if(vtxverbose>=7) { std::cout << "KalmanCalculator::init() calc C*GT 'fast'"<=5) { std::cout << "KalmanCalculator::init() calc R = G*C*GT + V"<=5) { std::cout << "KalmanCalculator::init() V"<=7) { theV.Print();} #else m_matrixRinv = V ; if(weight!=1) m_matrixRinv *= weight ; for(int row=0; row=5) { std::cout << "KalmanCalculator::init() G*C*GT"<=7) { Rinv.Print();} if(vtxverbose>=5) { std::cout << "KalmanCalculator::init() invert R"<=7) { m_matrixRinv.Print();} if(vtxverbose>=5) { std::cout << "KalmanCalculator::init() calculate gain"<=7) { m_matrixK.Print();} m_chisq = -1 ; // // let's see if we get same results using sparce matrices // VtkSparseMatrix Gs(G) ; // VtkSparseMatrix CGT = Gs.transposeAndMultiplyRight(fitparams->cov()) ; // HepSymMatrix Rs(value.numrow()) ; // Gs.multiplyLeft(CGT,Rs) ; // if(V) Rs += (*V) ; // Rs.invert(m_ierr) ; // VtkSparseMatrix Ks = CGT*Rs ; if(vtxverbose>=5) { std::cout << "KalmanCalculator::init() done"<=5) { std::cout << "KalmanCalculator::updatePar(FitParams*):"<cov() * (G.T() * (R * value) ) ; fitparams->par() -= m_matrixK * (*m_value) ; if(vtxverbose>=7) {(m_matrixK * (*m_value)).Print();} m_chisq = m_matrixRinv.Similarity(*m_value) ; if(vtxverbose>=5) { std::cout << "KalmanCalculator::updatePar() done"<=5) { std::cout << "KalmanCalculator::updatePar(TVectorD&,FitParams*)"<par()) ; fitparams->par() = pred - m_matrixK*valueprime ; m_chisq = m_matrixRinv.Similarity( valueprime ) ; if(vtxverbose>=5) { std::cout << "KalmanCalculator::updatePar() done"<=7) { std::cout << "KalmanCalculator::updateCov(FitParams*)"<=8) { std::cout << "KalmanCalculator::updateCov: previous fitpar->cov()" ; RhoCalculationTools::PrintMatrix(fitparams->cov()); } // RK: nice try, sadly crappy //TMatrixDSym deltaCov = m_matrixRinv.SimilarityT(*m_matrixG).Similarity(fitparams->cov()) ; //fitparams->cov() -= deltaCov ; //TMatrixD dcov1(m_matrixCGT,TMatrixD::kMultTranspose,m_matrixK); //const TMatrixDSym C(fitparams->cov()); TMatrixD HC(*m_matrixG,TMatrixD::kMult,fitparams->cov()); TMatrixD dcov1(m_matrixK,TMatrixD::kMult,HC); TMatrixDSym KRKt = m_matrixR.Similarity(m_matrixK); TMatrixDSym dcov3(dcov1.GetNrows()); for(int row=0; rowcov() += KRKt ; fitparams->cov() += dcov3 ; //if(vtxverbose>=8) { std::cout << "KalmanCalculator::updateCov: -1*deltacov = V*{R^(-1)*G*R^(-1T)}*V^T" ; RhoCalculationTools::PrintMatrix(deltaCov); } if(vtxverbose>=8) { std::cout << "KalmanCalculator::updateCov: KRKt = K*R*KT"; RhoCalculationTools::PrintMatrix(KRKt);} if(vtxverbose>=8) { std::cout << "KalmanCalculator::updateCov: dcov3 = -2*C*GT*KT"; RhoCalculationTools::PrintMatrix(dcov3);} if(vtxverbose>=7) { std::cout << "KalmanCalculator::updateCov: afterwds fitpar->cov()" ; RhoCalculationTools::PrintMatrix(fitparams->cov()); } #else // There are two expessions for updating the covariance // matrix. // slow: deltaCov = - 2*C*GT*KT + K*R*KT // fast: deltaCov = - C*GT*KT // The fast expression is very sensitive to machine accuracy. The // following piece of code effectively invokes the slow // expression. I couldn't write it faster than this. double tmp ; #ifndef SKIPHIGHACCURACYCORRECTION // substitute C*GT --> 2*C*GT - K*R. of course, this invalidates // C*GT, but we do not need it after this routine. // we use the fact that _in principle_ C*GT = K*R, such that // they have the same zero elements for(int row=0; rowcov().fast(row,col) += tmp * m_matrixK(col,k) ; // deltaCov = - C*GT*KT for(int row=0; rownConstraintsVec(k)) ; if(vtxverbose>=5) { std::cout << "KalmanCalculator::updateCov() done"<