CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_13_patch3/src/PhysicsTools/KinFitter/src/TKinFitter.cc

Go to the documentation of this file.
00001 // Classname: TKinFitter
00002 // Author: Jan E. Sundermann, Verena Klose (TU Dresden)      
00003 
00004 
00005 //________________________________________________________________
00006 // 
00007 // TKinFitter::
00008 // --------------------
00009 //
00010 // Class to perform kinematic fit with non-linear constraints
00011 //
00012 
00013 #include <iostream>
00014 #include <iomanip>
00015 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00016 #include "PhysicsTools/KinFitter/interface/TKinFitter.h"
00017 #include "PhysicsTools/KinFitter/interface/TAbsFitParticle.h"
00018 #include "PhysicsTools/KinFitter/interface/TAbsFitConstraint.h"
00019 
00020 
00021 TKinFitter::TKinFitter():
00022   TNamed("UnNamed", "UnTitled"),
00023   _A(1, 1),
00024   _AT(1, 1),
00025   _B(1, 1),
00026   _BT(1, 1),
00027   _V(1, 1),
00028   _Vinv(1, 1),
00029   _VB(1, 1),
00030   _VBinv(1, 1),
00031   _VA(1, 1),
00032   _VAinv(1, 1),
00033   _c(1, 1),
00034   _C11(1, 1),
00035   _C11T(1, 1),
00036   _C21(1, 1),
00037   _C21T(1, 1),
00038   _C22(1, 1),
00039   _C22T(1, 1),
00040   _C31(1, 1),
00041   _C31T(1, 1),
00042   _C32(1, 1),
00043   _C32T(1, 1),
00044   _C33(1, 1),
00045   _C33T(1, 1),
00046   _deltaA(1, 1),
00047   _deltaY(1, 1),
00048   _deltaAstar(1, 1),
00049   _deltaYstar(1, 1),
00050   _lambda(1, 1),
00051   _lambdaT(1, 1),
00052   _lambdaVFit(1, 1),
00053   _yaVFit(1, 1),
00054   _constraints(0),
00055   _measParticles(0),
00056   _unmeasParticles(0)
00057 {
00058 
00059   reset();
00060 
00061 }
00062 
00063 TKinFitter::TKinFitter(const TString &name, const TString &title):
00064   TNamed(name, title),
00065   _A(1, 1),
00066   _AT(1, 1),
00067   _B(1, 1),
00068   _BT(1, 1),
00069   _V(1, 1),
00070   _Vinv(1, 1),
00071   _VB(1, 1),
00072   _VBinv(1, 1),
00073   _VA(1, 1),
00074   _VAinv(1, 1),
00075   _c(1, 1),
00076   _C11(1, 1),
00077   _C11T(1, 1),
00078   _C21(1, 1),
00079   _C21T(1, 1),
00080   _C22(1, 1),
00081   _C22T(1, 1),
00082   _C31(1, 1),
00083   _C31T(1, 1),
00084   _C32(1, 1),
00085   _C32T(1, 1),
00086   _C33(1, 1),
00087   _C33T(1, 1),
00088   _deltaA(1, 1),
00089   _deltaY(1, 1),
00090   _deltaAstar(1, 1),
00091   _deltaYstar(1, 1),
00092   _lambda(1, 1),
00093   _lambdaT(1, 1),
00094   _lambdaVFit(1, 1),
00095   _yaVFit(1, 1),
00096   _constraints(0),
00097   _measParticles(0),
00098   _unmeasParticles(0)
00099 {
00100 
00101   reset();
00102 
00103 }
00104 
00105 void TKinFitter::reset() {
00106   // reset all internal parameters of the fitter
00107 
00108   _status = -1;
00109   _nbIter = 0;
00110   _nParA = 0;
00111   _nParB = 0;
00112   _verbosity = 1;
00113   _A.ResizeTo(1, 1);
00114   _AT.ResizeTo(1, 1);
00115   _B.ResizeTo(1, 1);
00116   _BT.ResizeTo(1, 1);
00117   _V.ResizeTo(1, 1);
00118   _Vinv.ResizeTo(1, 1);
00119   _VB.ResizeTo(1, 1);
00120   _VBinv.ResizeTo(1, 1);
00121   _VA.ResizeTo(1, 1);
00122   _VAinv.ResizeTo(1, 1);
00123   _c.ResizeTo(1, 1);
00124   _C11.ResizeTo(1, 1);
00125   _C11T.ResizeTo(1, 1);
00126   _C21.ResizeTo(1, 1);
00127   _C21T.ResizeTo(1, 1);
00128   _C22.ResizeTo(1, 1);
00129   _C22T.ResizeTo(1, 1);
00130   _C31.ResizeTo(1, 1);
00131   _C31T.ResizeTo(1, 1);
00132   _C32.ResizeTo(1, 1);
00133   _C32T.ResizeTo(1, 1);
00134   _C33.ResizeTo(1, 1);
00135   _C33T.ResizeTo(1, 1);
00136   _deltaA.ResizeTo(1, 1);
00137   _deltaY.ResizeTo(1, 1);
00138   _deltaAstar.ResizeTo(1, 1);
00139   _deltaYstar.ResizeTo(1, 1);
00140   _lambda.ResizeTo(1, 1);
00141   _lambdaT.ResizeTo(1, 1);
00142   _lambdaVFit.ResizeTo(1, 1);
00143   _yaVFit.ResizeTo(1, 1);
00144 
00145   _constraints.clear();
00146   _measParticles.clear();
00147   _unmeasParticles.clear();
00148 
00149   // Set to default values
00150   _maxNbIter = 50;
00151   _maxDeltaS = 5e-3;
00152   _maxF =  1e-4;
00153 
00154 }
00155 
00156 void TKinFitter::resetStatus() {
00157   // reset status of the fit
00158 
00159   _status = -1;
00160   _nbIter = 0;
00161 
00162 }
00163 
00164 void TKinFitter::resetParams() {
00165   // reset all particles to their initial parameters
00166 
00167   for (unsigned int iP = 0; iP < _measParticles.size(); iP++) {
00168     TAbsFitParticle* particle = _measParticles[iP];
00169     particle->reset();
00170   }
00171   for (unsigned int iP = 0; iP < _unmeasParticles.size(); iP++) {
00172     TAbsFitParticle* particle = _unmeasParticles[iP];
00173     particle->reset();
00174   }
00175   for (unsigned int iC = 0; iC < _constraints.size(); iC++) {
00176     TAbsFitConstraint* constraint = _constraints[iC];
00177     constraint->reset();
00178   }
00179 
00180 }
00181 
00182 TKinFitter::~TKinFitter() {
00183 
00184 }
00185 
00186 void TKinFitter::countMeasParams() {
00187   // count number of measured parameters
00188 
00189   _nParB = 0;
00190   for (unsigned int indexParticle = 0; indexParticle < _measParticles.size(); indexParticle++) {
00191     _nParB += _measParticles[indexParticle]->getNPar();
00192   }
00193   for (unsigned int indexConstraint = 0; indexConstraint < _constraints.size(); indexConstraint++) {
00194     _nParB += _constraints[indexConstraint]->getNPar();
00195   }
00196 
00197 }
00198 
00199 void TKinFitter::countUnmeasParams() {
00200   // count number of unmeasured parameters
00201 
00202   _nParA = 0;
00203   for (unsigned int indexParticle = 0; indexParticle < _unmeasParticles.size(); indexParticle++) {
00204     _nParA += _unmeasParticles[indexParticle]->getNPar();
00205   }
00206 
00207 }
00208 
00209 void TKinFitter::addMeasParticle( TAbsFitParticle* particle ) {
00210   // add one measured particle
00211 
00212   resetStatus();
00213 
00214   if ( particle != 0 ) {
00215     _measParticles.push_back( particle );
00216   } else {
00217     edm::LogError ("NullPointer") << "Measured particle points to NULL. It will not be added to the KinFitter.";
00218   }
00219 
00220   countMeasParams();
00221 
00222 }
00223 
00224 void TKinFitter::addMeasParticles( TAbsFitParticle* p1, TAbsFitParticle* p2, TAbsFitParticle* p3, 
00225                               TAbsFitParticle* p4, TAbsFitParticle* p5, TAbsFitParticle* p6,
00226                               TAbsFitParticle* p7, TAbsFitParticle* p8, TAbsFitParticle* p9) {
00227   // add many measured particles
00228 
00229   resetStatus();
00230 
00231   if ( p1 != 0 ) _measParticles.push_back( p1 );
00232   if ( p2 != 0 ) _measParticles.push_back( p2 );
00233   if ( p3 != 0 ) _measParticles.push_back( p3 );
00234   if ( p4 != 0 ) _measParticles.push_back( p4 );
00235   if ( p5 != 0 ) _measParticles.push_back( p5 );
00236   if ( p6 != 0 ) _measParticles.push_back( p6 );
00237   if ( p7 != 0 ) _measParticles.push_back( p7 );
00238   if ( p8 != 0 ) _measParticles.push_back( p8 );
00239   if ( p9 != 0 ) _measParticles.push_back( p9 );
00240 
00241   countMeasParams();
00242 
00243 }
00244 
00245 void TKinFitter::addUnmeasParticle( TAbsFitParticle* particle ) {
00246   // add one unmeasured particle
00247 
00248   resetStatus();
00249 
00250   if ( particle != 0 ) {
00251     _unmeasParticles.push_back( particle );
00252   } else {
00253     edm::LogError ("NullPointer") << "Unmeasured particle points to NULL. It will not be added to the KinFitter.";
00254   }
00255 
00256   countUnmeasParams();
00257 
00258 }
00259 
00260 void TKinFitter::addUnmeasParticles( TAbsFitParticle* p1, TAbsFitParticle* p2, TAbsFitParticle* p3, 
00261                                      TAbsFitParticle* p4, TAbsFitParticle* p5, TAbsFitParticle* p6,
00262                                      TAbsFitParticle* p7, TAbsFitParticle* p8, TAbsFitParticle* p9) {
00263   // add many unmeasured particles
00264 
00265   resetStatus();
00266 
00267   if ( p1 != 0 ) _unmeasParticles.push_back( p1 );
00268   if ( p2 != 0 ) _unmeasParticles.push_back( p2 );
00269   if ( p3 != 0 ) _unmeasParticles.push_back( p3 );
00270   if ( p4 != 0 ) _unmeasParticles.push_back( p4 );
00271   if ( p5 != 0 ) _unmeasParticles.push_back( p5 );
00272   if ( p6 != 0 ) _unmeasParticles.push_back( p6 );
00273   if ( p7 != 0 ) _unmeasParticles.push_back( p7 );
00274   if ( p8 != 0 ) _unmeasParticles.push_back( p8 );
00275   if ( p9 != 0 ) _unmeasParticles.push_back( p9 );
00276 
00277   countUnmeasParams();
00278 
00279 }
00280 
00281 void TKinFitter::addConstraint( TAbsFitConstraint* constraint ) {
00282   // add a constraint
00283 
00284   resetStatus();
00285 
00286   if ( constraint != 0 ) {
00287     _constraints.push_back( constraint );
00288   }
00289 
00290   countMeasParams();
00291 
00292 }
00293 
00294 void TKinFitter::setVerbosity( Int_t verbosity ) { 
00295   // Set verbosity of the fitter:
00296   // 0: quiet
00297   // 1: print information before and after the fit
00298   // 2: print output for every iteration of the fit
00299   // 3: print debug information
00300 
00301 
00302   if ( verbosity < 0 ) verbosity = 0;
00303   if ( verbosity > 3 ) verbosity = 3;
00304   _verbosity = verbosity;
00305 
00306 }
00307 
00308 
00309 Int_t TKinFitter::fit() {
00310   // Perform the fit
00311   // Returns:
00312   // 0: converged
00313   // 1: not converged
00314 
00315   resetParams();
00316   resetStatus();
00317 
00318   _nbIter = 0;
00319   Bool_t isConverged = false;
00320   Double_t prevF;
00321   Double_t currF = getF();
00322   Double_t prevS;
00323   Double_t currS = 0.;
00324 
00325   // Calculate covariance matrix V
00326   calcV();
00327 
00328   // print status
00329   if ( _verbosity >= 1 ) {
00330     print();
00331   }
00332 
00333   do {
00334 
00335     // Reset status to "RUNNING"
00336     // (if it was not aborted already due to singular covariance matrix)
00337     if ( _status != -10 ) {
00338       _status = 10;
00339     }
00340 
00341     // Calculate matrices
00342     calcB();
00343     calcVB();
00344     if ( _nParA > 0 ) {
00345       calcA();
00346       calcVA();
00347       calcC32();
00348     }
00349     calcC31();
00350     calcC33();
00351     calcC();
00352 
00353     // Calculate corretion for a, y, and lambda
00354     if ( _nParA > 0 ){
00355       calcDeltaA();
00356     }
00357     calcDeltaY();
00358     calcLambda();
00359    
00360     if( _verbosity >= 3 ) {
00361       printMatrix( _A      , "A"      );
00362       printMatrix( _B      , "B"      );
00363       printMatrix( _VBinv  , "VBinv"  );
00364       printMatrix( _VB     , "VB"     );
00365       printMatrix( _V      , "V"      );
00366       printMatrix( _deltaY , "deltaY" );
00367       printMatrix( _deltaA , "deltaA" );
00368       printMatrix( _C32T   , "C32T"   );
00369       printMatrix( _c      , "C"      );
00370     }
00371 
00372     if( _verbosity >= 2 ) {
00373       print();   
00374     }
00375 
00376     // Apply calculated corrections to measured and unmeasured particles
00377     if ( _nParA > 0 ) {
00378       applyDeltaA();
00379     }
00380     applyDeltaY();
00381 
00382     _nbIter++;
00383     
00384     //calculate F and S
00385     prevF = currF;
00386     currF = getF();
00387     prevS = currS;
00388     currS = getS();
00389 
00390     if( TMath::IsNaN(currF) ) {
00391       edm::LogInfo ("KinFitter") << "The current value of F is NaN. Fit will be aborted.";
00392       _status = -10;
00393     }
00394     if( TMath::IsNaN(currS) ) {
00395       edm::LogInfo ("KinFitter") << "The current value of S is NaN. Fit will be aborted.";
00396       _status = -10;
00397     }
00398 
00399     // Reduce step width if F is not getting smaller
00400     Int_t nstep = 0;
00401     while (currF >= prevF) {
00402       nstep++;
00403       if (nstep == 10) break;
00404       if (_nParA > 0) _deltaA -= (0.5) * (_deltaA - _deltaAstar);
00405       _deltaY -= (0.5) * (_deltaY - _deltaYstar);
00406       _lambda *= 0.5;
00407       _lambdaT *= 0.5;
00408       if (_nParA > 0) applyDeltaA();
00409       applyDeltaY();
00410       currF = getF();
00411       currS = getS();
00412     }
00413     
00414     // Test convergence
00415     isConverged = converged(currF, prevS, currS);
00416 
00417  
00418   } while ( (! isConverged) && (_nbIter < _maxNbIter) && (_status != -10) );
00419 
00420   // Calculate covariance matrices
00421   calcB();
00422   calcVB();
00423   
00424   if ( _nParA > 0 ) {
00425     calcA();
00426     calcVA();
00427     calcC21();
00428     calcC22();
00429     calcC32();
00430   }
00431   calcC11();
00432   calcC31();
00433   calcC33();
00434   calcVFit();
00435   applyVFit();
00436   
00437   // Set status information
00438   if (isConverged) {
00439     _status = 0;
00440   }
00441   else if (_status != -10) {
00442     _status = 1;
00443   }
00444   
00445   // print status
00446   if ( _verbosity >= 1 ) {
00447     print();
00448   }
00449 
00450   return _status;
00451 
00452 }
00453 
00454 void TKinFitter::setCovMatrix( TMatrixD &V ) {
00455   // Set the covariance matrix of the measured particles
00456 
00457   if ( (V.GetNrows() != _nParB) || (V.GetNcols() != _nParB) ) {
00458     edm::LogError ("WrongMatrixSize")
00459       << "Covariance matrix of measured particles needs to be a " << _nParB << "x" << _nParB << " matrix.";
00460   } else {
00461     _V.ResizeTo( V );
00462     _V = V;
00463   }
00464 
00465 }
00466 
00467 Bool_t TKinFitter::calcV() {
00468   // Combines the covariance matrices of all measured particles
00469 
00470   _V.ResizeTo( _nParB, _nParB );
00471   _V.Zero();
00472 
00473   Int_t offsetP = 0;
00474   for (unsigned int iP = 0; iP < _measParticles.size(); iP++) {
00475     TAbsFitParticle* particle = _measParticles[iP];
00476     Int_t nParP = particle->getNPar();
00477     const TMatrixD* covMatrix =  particle->getCovMatrix();
00478 
00479     for (int iX = offsetP; iX < offsetP + nParP; iX++) {
00480       for (int iY = offsetP; iY < offsetP + nParP; iY++) {
00481 
00482         _V(iX, iY) = (*covMatrix)(iX-offsetP, iY-offsetP);
00483 
00484       }
00485     }
00486 
00487     offsetP += nParP;
00488   }
00489 
00490   for (unsigned int iC = 0; iC < _constraints.size(); iC++) {
00491     TAbsFitConstraint* constraint = _constraints[iC];
00492     Int_t nParP = constraint->getNPar();
00493     const TMatrixD* covMatrix =  constraint->getCovMatrix();
00494 
00495     for (int iX = offsetP; iX < offsetP + nParP; iX++) {
00496       for (int iY = offsetP; iY < offsetP + nParP; iY++) {
00497 
00498         _V(iX, iY) = (*covMatrix)(iX-offsetP, iY-offsetP);
00499 
00500       }
00501     }
00502 
00503     offsetP += nParP;
00504   }
00505 
00506   _Vinv.ResizeTo( _V );
00507   _Vinv = _V;
00508   try {
00509     _Vinv.Invert();
00510   } catch (cms::Exception& e) {
00511     edm::LogInfo ("KinFitter") << "Failed to invert covariance matrix V. Fit will be aborted.";
00512     _status = -10;
00513   }
00514 
00515   return true;
00516 
00517 }
00518 
00519 Bool_t TKinFitter::calcA() {
00520   // Calculate the Jacobi matrix of unmeasured parameters df_i/da_i
00521   // Row i contains the derivatives of constraint f_i. Column q contains
00522   // the derivative wrt. a_q.
00523 
00524   _A.ResizeTo( _constraints.size(), _nParA );
00525 
00526   for (unsigned int indexConstr = 0; indexConstr < _constraints.size(); indexConstr++) {
00527 
00528     int offsetParam = 0;
00529     for (unsigned int indexParticle = 0; indexParticle < _unmeasParticles.size(); indexParticle++) {
00530 
00531       // Calculate matrix product  df/dP * dP/dy = (df/dr, df/dtheta, df/dphi, ...)
00532 
00533       TAbsFitParticle* particle = _unmeasParticles[indexParticle];
00534       TMatrixD* derivParticle = particle->getDerivative();
00535       TMatrixD* derivConstr = _constraints[indexConstr]->getDerivative( particle );
00536       TMatrixD deriv( *derivConstr, TMatrixD::kMult, *derivParticle );
00537 
00538       for (int indexParam = 0; indexParam < deriv.GetNcols(); indexParam++) {
00539         _A(indexConstr,indexParam+offsetParam) = deriv(0, indexParam);
00540       }
00541       offsetParam += deriv.GetNcols();
00542 
00543       delete derivParticle;
00544       delete derivConstr;
00545 
00546     }
00547   }
00548 
00549   // Calculate transposed matrix
00550   TMatrixD AT(TMatrixD::kTransposed, _A);
00551   _AT.ResizeTo( AT );
00552   _AT = AT;
00553 
00554   return true;
00555 
00556 }
00557 
00558 Bool_t TKinFitter::calcB() {
00559   // Calculate the Jacobi matrix of measured parameters df_i/da_i
00560   // Row i contains the derivatives of constraint f_i. Column q contains
00561   // the derivative wrt. a_q.
00562 
00563   _B.ResizeTo( _constraints.size(), _nParB );
00564 
00565   int offsetParam = 0;
00566   for (unsigned int indexConstr = 0; indexConstr < _constraints.size(); indexConstr++) {
00567 
00568     offsetParam = 0;
00569     for (unsigned int indexParticle = 0; indexParticle < _measParticles.size(); indexParticle++) {
00570 
00571       // Calculate matrix product  df/dP * dP/dy = (df/dr, df/dtheta, df/dphi, ...)
00572       TAbsFitParticle* particle = _measParticles[indexParticle];
00573       TMatrixD* derivParticle = particle->getDerivative();
00574       TMatrixD* derivConstr = _constraints[indexConstr]->getDerivative( particle );
00575       TMatrixD deriv( *derivConstr,  TMatrixD::kMult, *derivParticle );
00576       if (_verbosity >= 3) {
00577         TString matrixName = "B deriv: Particle -> ";
00578         matrixName += particle->GetName();
00579         printMatrix( *derivParticle, matrixName );
00580         matrixName = "B deriv: Constraint -> ";
00581         matrixName += _constraints[indexConstr]->GetName();
00582         matrixName += " , Particle -> ";
00583         matrixName += particle->GetName();
00584         printMatrix( *derivConstr, matrixName );
00585       } 
00586       for (int indexParam = 0; indexParam < deriv.GetNcols(); indexParam++) {
00587         _B(indexConstr,indexParam+offsetParam) = deriv(0, indexParam);
00588       }
00589       offsetParam += deriv.GetNcols();
00590 
00591       delete derivParticle;
00592       delete derivConstr;
00593 
00594     }
00595   }
00596 
00597   for (unsigned int iC = 0; iC < _constraints.size(); iC++) {
00598 
00599     TAbsFitConstraint* constraint = _constraints[iC];
00600     TMatrixD* deriv = constraint->getDerivativeAlpha();
00601 
00602     if (deriv != 0) {
00603 
00604       if (_verbosity >= 3) {
00605         TString matrixName = "B deriv alpha: Constraint -> ";
00606         matrixName += constraint->GetName();
00607         printMatrix( *deriv, matrixName );
00608       } 
00609       for (int indexParam = 0; indexParam < deriv->GetNcols(); indexParam++) {
00610         _B( iC, indexParam+offsetParam ) = (*deriv)(0, indexParam);
00611       }
00612       offsetParam += deriv->GetNcols();
00613       
00614       delete deriv;
00615     }
00616   }
00617 
00618   TMatrixD BT( TMatrixD::kTransposed,  _B );
00619   _BT.ResizeTo( BT );
00620   _BT = BT;
00621 
00622   return true;
00623 
00624 }
00625 
00626 Bool_t TKinFitter::calcVB() {
00627   // Calculate the matrix V_B = (B*V*B^T)^-1
00628 
00629   TMatrixD BV( _B, TMatrixD::kMult, _V );
00630   TMatrixD VBinv( BV, TMatrixD::kMult, _BT );
00631   _VBinv.ResizeTo( VBinv );
00632   _VBinv = VBinv;
00633 
00634   _VB.ResizeTo( _VBinv );
00635   _VB = _VBinv;
00636   try {
00637     _VB.Invert();
00638   } catch (cms::Exception& e) {
00639     edm::LogInfo ("KinFitter") << "Failed to invert matrix VB. Fit will be aborted.";
00640     _status = -10;
00641   }
00642 
00643   return true;
00644 
00645 }
00646 
00647 Bool_t TKinFitter::calcVA() {
00648   // Calculate the matrix VA = (A^T*VB*A)
00649 
00650   TMatrixD ATVB( _AT, TMatrixD::kMult, _VB );
00651   TMatrixD VA(ATVB, TMatrixD::kMult, _A);
00652   _VA.ResizeTo( VA );
00653   _VA = VA;
00654 
00655   _VAinv.ResizeTo( _VA );
00656   _VAinv = _VA;
00657   try {
00658     _VAinv.Invert();
00659   } catch (cms::Exception& e) {
00660     edm::LogInfo ("KinFitter") << "Failed to invert matrix VA. Fit will be aborted.";
00661     _status = -10;
00662   }
00663 
00664   return true;
00665 
00666 }
00667 
00668 Bool_t TKinFitter::calcC11() {
00669   // Calculate the matrix C11 = V^(-1) - V^(-1)*BT*VB*B*V^(-1) + V^(-1)*BT*VB*A*VA^(-1)*AT*VB*B*V^(-1)
00670 
00671   TMatrixD VBT( _V, TMatrixD::kMult, _BT );
00672   TMatrixD VBB( _VB, TMatrixD::kMult, _B );
00673   TMatrixD VBTVBB( VBT, TMatrixD::kMult, VBB );
00674   TMatrixD m2( VBTVBB,  TMatrixD::kMult, _V );
00675 
00676   _C11.ResizeTo( _V );
00677   _C11 = _V;
00678   _C11 -= m2;
00679 
00680   if ( _nParA > 0 ) {
00681     TMatrixD VBA( _VB, TMatrixD::kMult, _A );
00682     TMatrixD VBTVBA( VBT, TMatrixD::kMult, VBA );
00683     TMatrixD VAinvAT( _VAinv, TMatrixD::kMult, _AT );
00684     TMatrixD VBTVBAVAinvAT( VBTVBA, TMatrixD::kMult, VAinvAT );
00685     TMatrixD VBTVBAVAinvATVBB( VBTVBAVAinvAT, TMatrixD::kMult, VBB );
00686     TMatrixD m3( VBTVBAVAinvATVBB, TMatrixD::kMult, _V );
00687     _C11 += m3;
00688   }
00689 
00690   TMatrixD C11T( TMatrixD::kTransposed,  _C11 );
00691   _C11T.ResizeTo( C11T );
00692   _C11T = C11T;
00693 
00694   return true;
00695 
00696 }
00697 
00698 Bool_t TKinFitter::calcC21() {
00699   // Calculate the matrix  C21 = -VA^(-1)*AT*VB*B*V^(-1)
00700 
00701   TMatrixD VAinvAT( _VAinv, TMatrixD::kMult, _AT );
00702   TMatrixD VBB( _VB, TMatrixD::kMult, _B );
00703   TMatrixD VAinvATVBB( VAinvAT, TMatrixD::kMult, VBB );
00704   TMatrixD C21( VAinvATVBB, TMatrixD::kMult, _V );
00705   C21 *= -1.;
00706   _C21.ResizeTo( C21 );
00707   _C21 = C21;
00708   
00709   TMatrixD C21T( TMatrixD::kTransposed,  _C21 );
00710   _C21T.ResizeTo( C21T );
00711   _C21T = C21T;
00712 
00713   return true;
00714 
00715 }
00716 
00717 Bool_t TKinFitter::calcC22() {
00718   //  Calculate the matrix C22 = VA^(-1)
00719 
00720   _C22.ResizeTo( _VAinv );
00721   _C22 = _VAinv;
00722 
00723   TMatrixD C22T( TMatrixD::kTransposed,  _C22 );
00724   _C22T.ResizeTo( C22T );
00725   _C22T = C22T;
00726 
00727   return true;
00728 
00729 }
00730 
00731 Bool_t TKinFitter::calcC31() {
00732   // Calculate the matrix  C31 = VB*B*V^(-1) - VB*A*VA^(-1)*AT*VB*B*V^(-1)
00733 
00734   TMatrixD VbB(_VB, TMatrixD::kMult, _B);
00735   TMatrixD m1( VbB, TMatrixD::kMult, _V );
00736 
00737   _C31.ResizeTo( m1 );
00738   _C31 = m1;
00739 
00740   if ( _nParA > 0 ) {
00741     TMatrixD VbA(_VB, TMatrixD::kMult, _A);
00742     TMatrixD VAinvAT( _VAinv, TMatrixD::kMult, _AT );
00743     TMatrixD VbBV( VbB,  TMatrixD::kMult, _V );
00744     TMatrixD VbAVAinvAT(VbA, TMatrixD::kMult, VAinvAT); 
00745     TMatrixD m2(VbAVAinvAT, TMatrixD::kMult, VbBV);
00746 
00747     _C31 -= m2;
00748   }
00749 
00750   TMatrixD C31T( TMatrixD::kTransposed,  _C31 );
00751   _C31T.ResizeTo( C31T );
00752   _C31T = C31T;
00753 
00754   return true;
00755 
00756 }
00757 
00758 Bool_t TKinFitter::calcC32() {
00759   // Calculate the matrix  C32 = VB*A*VA^(-1)
00760 
00761   TMatrixD VbA( _VB, TMatrixD::kMult, _A );
00762   TMatrixD C32( VbA, TMatrixD::kMult, _VAinv );
00763   _C32.ResizeTo( C32 );
00764   _C32 = C32;
00765 
00766   TMatrixD C32T( TMatrixD::kTransposed,  _C32 );
00767   _C32T.ResizeTo( C32T );
00768   _C32T = C32T;
00769 
00770   return true;
00771 
00772 }
00773 
00774 Bool_t TKinFitter::calcC33() {
00775   // Calculate the matrix C33 = -VB + VB*A*VA^(-1)*AT*VB
00776 
00777   _C33.ResizeTo( _VB );
00778   _C33 = _VB;
00779   _C33 *= -1.;
00780 
00781   if ( _nParA > 0 ) {
00782     TMatrixD VbA(_VB, TMatrixD::kMult, _A );
00783     TMatrixD VAinvAT( _VAinv, TMatrixD::kMult, _AT );
00784     TMatrixD VbAVAinvAT( VbA, TMatrixD::kMult, VAinvAT );
00785     TMatrixD C33( VbAVAinvAT,  TMatrixD::kMult, _VB );
00786     _C33 += C33;
00787   }
00788 
00789   TMatrixD C33T( TMatrixD::kTransposed,  _C33 );
00790   _C33T.ResizeTo( C33T );
00791   _C33T = C33T;
00792 
00793   return true;
00794 }
00795 
00796 Bool_t TKinFitter::calcC() {
00797   // Calculate the matrix c = A*deltaAStar + B*deltaYStar - fStar
00798 
00799   int offsetParam = 0;
00800 
00801   // calculate delta(a*), = 0 in the first iteration
00802   TMatrixD deltaastar( 1, 1 );
00803   if ( _nParA > 0 ) {
00804 
00805     deltaastar.ResizeTo( _nParA, 1 );
00806     for (unsigned int indexParticle = 0; indexParticle < _unmeasParticles.size(); indexParticle++) {
00807     
00808       TAbsFitParticle* particle = _unmeasParticles[indexParticle];
00809       const TMatrixD* astar = particle->getParCurr();
00810       const TMatrixD* a = particle->getParIni();
00811       TMatrixD deltaastarpart(*astar);
00812       deltaastarpart -= *a;
00813       
00814       for (int indexParam = 0; indexParam < deltaastarpart.GetNrows(); indexParam++) {
00815         deltaastar(indexParam+offsetParam, 0) = deltaastarpart(indexParam, 0);
00816       }
00817       offsetParam += deltaastarpart.GetNrows();
00818       
00819     }
00820 
00821     if ( _verbosity >= 3 ) {
00822       printMatrix( deltaastar, "deltaastar" );
00823     }
00824 
00825   }
00826 
00827   // calculate delta(y*), = 0 in the first iteration
00828   TMatrixD deltaystar( _nParB, 1 );
00829   offsetParam = 0;
00830   for (unsigned int indexParticle = 0; indexParticle < _measParticles.size(); indexParticle++) {
00831 
00832     TAbsFitParticle* particle = _measParticles[indexParticle];
00833     const TMatrixD* ystar = particle->getParCurr();
00834     const TMatrixD* y = particle->getParIni();
00835     TMatrixD deltaystarpart(*ystar);
00836     deltaystarpart -= *y;
00837 
00838     for (int indexParam = 0; indexParam < deltaystarpart.GetNrows(); indexParam++) {
00839       deltaystar(indexParam+offsetParam, 0) = deltaystarpart(indexParam, 0);
00840     }
00841     offsetParam += deltaystarpart.GetNrows();
00842 
00843   } 
00844 
00845   for (unsigned int iC = 0; iC < _constraints.size(); iC++) {
00846 
00847     TAbsFitConstraint* constraint = _constraints[iC];
00848     
00849     if ( constraint->getNPar() > 0 ) {
00850 
00851       const TMatrixD* alphastar = constraint->getParCurr();
00852       const TMatrixD* alpha = constraint->getParIni();
00853 
00854       TMatrixD deltaalphastarpart(*alphastar);
00855       deltaalphastarpart -= *alpha;
00856 
00857       for (int indexParam = 0; indexParam < deltaalphastarpart.GetNrows(); indexParam++) {
00858         deltaystar(indexParam+offsetParam, 0) = deltaalphastarpart(indexParam, 0);
00859       }
00860       offsetParam += deltaalphastarpart.GetNrows();
00861 
00862     }
00863   }
00864 
00865   if ( _verbosity >= 3 ) {
00866     printMatrix( deltaystar, "deltaystar" );
00867   }
00868 
00869   // calculate f*
00870   TMatrixD fstar( _constraints.size(), 1 );
00871   for (unsigned int indexConstr = 0; indexConstr < _constraints.size(); indexConstr++) {
00872     fstar( indexConstr, 0 ) = _constraints[indexConstr]->getCurrentValue();
00873   }
00874 
00875   // calculate c
00876   _c.ResizeTo( fstar );
00877   _c = fstar;
00878   _c *= (-1.);
00879   TMatrixD Bdeltaystar( _B, TMatrixD::kMult, deltaystar );
00880   _c += Bdeltaystar;
00881   if ( _nParA ) {
00882     TMatrixD Adeltaastar( _A, TMatrixD::kMult, deltaastar );
00883     _c += Adeltaastar;
00884   }
00885 
00886   return true;
00887 
00888 }
00889 
00890 Bool_t TKinFitter::calcDeltaA() {
00891   // Calculate the matrix deltaA = C32T * c
00892   // (corrections to unmeasured parameters)
00893 
00894   TMatrixD deltaA( _C32T, TMatrixD::kMult, _c );
00895   _deltaA.ResizeTo( deltaA );
00896 
00897   if (_nbIter == 0) {
00898     _deltaAstar.ResizeTo(deltaA);
00899     _deltaAstar.Zero();
00900   } else
00901     _deltaAstar = _deltaA;
00902 
00903   _deltaA = deltaA;
00904 
00905   return true;
00906 
00907 }
00908 
00909 Bool_t TKinFitter::calcDeltaY() {
00910   // Calculate the matrix deltaY = C31T * c 
00911   // (corrections to measured parameters)
00912 
00913   TMatrixD deltaY( _C31T, TMatrixD::kMult, _c );
00914   _deltaY.ResizeTo( deltaY );
00915 
00916   if (_nbIter == 0) {
00917     _deltaYstar.ResizeTo(deltaY);
00918     _deltaYstar.Zero();
00919   } else
00920     _deltaYstar = _deltaY;
00921 
00922   _deltaY = deltaY;
00923 
00924   return true;
00925 
00926 }
00927 
00928 Bool_t TKinFitter::calcLambda() {
00929   // Calculate the matrix Lambda = C33 * c 
00930   // (Lagrange Multipliers)
00931 
00932   TMatrixD lambda( _C33,  TMatrixD::kMult, _c );
00933   _lambda.ResizeTo( lambda );
00934   _lambda = lambda;
00935 
00936   TMatrixD lambdaT( TMatrixD::kTransposed,  _lambda );
00937   _lambdaT.ResizeTo( lambdaT );
00938   _lambdaT = lambdaT;
00939 
00940   return true;
00941 
00942 }
00943 
00944 Bool_t TKinFitter::calcVFit() {
00945   // Calculate the covariance matrix of fitted parameters
00946   //
00947   // Vfit(y) = ( C11  C21T )
00948   //     (a)   ( C21  C22  )
00949   //
00950   // Vfit(lambda) = (-C33)
00951   
00952   // Calculate covariance matrix of lambda
00953   _lambdaVFit.ResizeTo( _C33 );
00954   _lambdaVFit = _C33;
00955   _lambdaVFit *= -1.;
00956 
00957 
00958   // Calculate combined covariance matrix of y and a
00959   Int_t nbRows = _C11.GetNrows();
00960   Int_t nbCols = _C11.GetNcols();
00961   if ( _nParA > 0 ) {
00962     nbRows += _C21.GetNrows();
00963     nbCols += _C21T.GetNcols();
00964   }
00965   _yaVFit.ResizeTo( nbRows, nbCols );
00966 
00967   for (int iRow = 0; iRow < nbRows; iRow++) {
00968     for (int iCol = 0; iCol < nbCols; iCol++) {
00969 
00970       if (iRow >= _C11.GetNrows()) {
00971         if (iCol >= _C11.GetNcols()) {
00972           _yaVFit(iRow, iCol) = _C22(iRow-_C11.GetNrows(), iCol-_C11.GetNcols());
00973         } else {
00974           _yaVFit(iRow, iCol) = _C21(iRow-_C11.GetNrows(), iCol);
00975         }
00976       } else {
00977         if (iCol >= _C11.GetNcols()) {
00978           _yaVFit(iRow, iCol) = _C21T(iRow, iCol-_C11.GetNcols());
00979         } else {
00980           _yaVFit(iRow, iCol) = _C11(iRow, iCol);
00981         }
00982       }
00983 
00984     }
00985   }
00986 
00987   return true;
00988 
00989 }
00990 
00991 void TKinFitter::applyVFit() {
00992   // apply fit covariance matrix to measured and unmeasured  particles
00993 
00994   int offsetParam = 0;
00995   for (unsigned int indexParticle = 0; indexParticle < _measParticles.size(); indexParticle++) {
00996     TAbsFitParticle* particle = _measParticles[indexParticle];
00997     Int_t nbParams = particle->getNPar();
00998     TMatrixD vfit( nbParams, nbParams );
00999     for (Int_t c = 0; c < nbParams; c++) {
01000       for (Int_t r = 0; r < nbParams; r++) {
01001         vfit(r, c) = _yaVFit(r + offsetParam, c + offsetParam);
01002       }
01003     }
01004     particle->setCovMatrixFit( &vfit );
01005     offsetParam += nbParams;
01006   }
01007 
01008   for (unsigned int indexConstraint = 0; indexConstraint < _constraints.size(); indexConstraint++) {
01009     TAbsFitConstraint* constraint = _constraints[indexConstraint];
01010     Int_t nbParams = constraint->getNPar();
01011     if (nbParams > 0) {
01012       TMatrixD vfit( nbParams, nbParams );
01013       for (Int_t c = 0; c < nbParams; c++) {
01014         for (Int_t r = 0; r < nbParams; r++) {
01015           vfit(r, c) = _yaVFit(r + offsetParam, c + offsetParam);
01016         }
01017       }
01018       constraint->setCovMatrixFit( &vfit );
01019       offsetParam += nbParams;
01020     }
01021   }
01022 
01023   for (unsigned int indexParticle = 0; indexParticle < _unmeasParticles.size(); indexParticle++) {
01024     TAbsFitParticle* particle = _unmeasParticles[indexParticle];
01025     Int_t nbParams = particle->getNPar();
01026     TMatrixD vfit( nbParams, nbParams );
01027     for (Int_t c = 0; c < nbParams; c++) {
01028       for (Int_t r = 0; r < nbParams; r++) {
01029         vfit(r, c) = _yaVFit(r + offsetParam, c + offsetParam);
01030       }
01031     }
01032     particle->setCovMatrixFit( &vfit );
01033     offsetParam += nbParams;
01034   }
01035 
01036 }
01037 
01038 Bool_t TKinFitter::applyDeltaA() {
01039   //apply corrections to unmeasured particles
01040 
01041   int offsetParam = 0;
01042   for (unsigned int indexParticle = 0; indexParticle < _unmeasParticles.size(); indexParticle++) {
01043 
01044     TAbsFitParticle* particle = _unmeasParticles[indexParticle];
01045     Int_t nbParams = particle->getNPar();
01046     TMatrixD params( nbParams, 1 );
01047     for (Int_t index = 0; index < nbParams; index++) {
01048       params(index, 0) = _deltaA(index+offsetParam, 0);
01049     }
01050     particle->applycorr( &params );
01051     offsetParam+=nbParams;
01052 
01053   }
01054 
01055   return true;
01056 
01057 }
01058 
01059 Bool_t TKinFitter::applyDeltaY() {
01060   //apply corrections to measured particles
01061 
01062   int offsetParam = 0;
01063   for (unsigned int indexParticle = 0; indexParticle < _measParticles.size(); indexParticle++) {
01064 
01065     TAbsFitParticle* particle = _measParticles[indexParticle];
01066     Int_t nbParams = particle->getNPar();
01067     TMatrixD params( nbParams, 1 );
01068     for (Int_t index = 0; index < nbParams; index++) {
01069       params(index, 0) = _deltaY(index+offsetParam, 0);
01070     }
01071     particle->applycorr( &params );
01072     offsetParam+=nbParams;
01073 
01074   }
01075 
01076   for (unsigned int indexConstraint = 0; indexConstraint < _constraints.size(); indexConstraint++) {
01077 
01078     TAbsFitConstraint* constraint = _constraints[indexConstraint];
01079     Int_t nbParams = constraint->getNPar();
01080     if ( nbParams > 0 ) {
01081       TMatrixD params( nbParams, 1 );
01082       for (Int_t index = 0; index < nbParams; index++) {
01083         params(index, 0) = _deltaY(index+offsetParam, 0);
01084       }
01085       constraint->applyDeltaAlpha( &params );
01086       offsetParam+=nbParams;
01087     }
01088 
01089   }
01090 
01091   return true;
01092 
01093 }
01094   
01095 Double_t TKinFitter::getF() {
01096   // calculate current absolut value of constraints
01097   // F = Sum[ Abs(f_k( aStar, yStar)) ] 
01098 
01099   Double_t F = 0.;
01100   for (unsigned int indexConstr = 0; indexConstr < _constraints.size(); indexConstr++) {
01101     F += TMath::Abs( _constraints[indexConstr]->getCurrentValue() );
01102   }
01103   
01104   return F;
01105 
01106 }
01107 
01108 Double_t TKinFitter::getS() {
01109   // calculate current value of Chi2
01110   // S = deltaYT * V^-1 * deltaY
01111 
01112   Double_t S = 0.;
01113 
01114   if ( _nbIter > 0 ) {
01115     
01116     TMatrixD deltaYTVinv(_deltaY, TMatrixD::kTransposeMult, _Vinv);
01117     TMatrixD S2(deltaYTVinv, TMatrixD::kMult, _deltaY);
01118     S = S2(0,0);
01119          
01120   }
01121 
01122   return S;
01123 
01124 }
01125 
01126 Bool_t TKinFitter::converged( Double_t F, Double_t prevS, Double_t currS ) {
01127   // check whether convergence criteria are fulfilled
01128 
01129   Bool_t isConverged = false;
01130   
01131   // calculate F, delta(a) and delta(y) already applied
01132   isConverged = (F < _maxF);
01133 
01134   // Calculate current Chi^2 and delta(S)
01135   Double_t deltaS = currS - prevS;
01136   isConverged = isConverged && (TMath::Abs(deltaS) < _maxDeltaS);
01137 
01138   return isConverged;
01139 
01140 }
01141 
01142 TString TKinFitter::getStatusString() {
01143 
01144   TString statusstring = "";
01145 
01146   switch ( _status ) {
01147       
01148     case -1: {
01149       statusstring = "NO FIT PERFORMED";
01150       break;
01151     }
01152     case 10: {
01153       statusstring = "RUNNING";
01154       break;
01155     }
01156     case -10: {
01157       statusstring = "ABORTED";
01158       break;
01159     }
01160     case 0: {
01161       statusstring = "CONVERGED";
01162       break;
01163     }
01164     case 1: {
01165       statusstring = "NOT CONVERGED";
01166       break;
01167     }
01168   }
01169     
01170   return statusstring;
01171 
01172 }
01173 
01174 void TKinFitter::print() {
01175 
01176   edm::LogVerbatim log("KinFitter");
01177   log << "\n"
01178       << "\n";
01179   // Print status of fit
01180   log << "Status: " << getStatusString()
01181       << "   F=" << getF() << "   S=" << getS() << "   N=" << _nbIter << "   NDF=" << getNDF() << "\n";
01182   // Print measured particles
01183   log << "measured particles: \n";
01184   Int_t parIndex = 0;
01185   for (unsigned int iP = 0; iP < _measParticles.size(); iP++) {
01186     TAbsFitParticle* particle = _measParticles[iP];
01187     Int_t nParP = particle->getNPar();
01188     const TMatrixD* par = particle->getParCurr();
01189     const TMatrixD* covP = particle->getCovMatrix();
01190     log << std::setw(3) << setiosflags(std::ios::right) << iP;
01191     log << std::setw(15) << setiosflags(std::ios::right) << particle->GetName();
01192     log << std::setw(3) << " ";
01193     for (int iPar = 0; iPar < nParP; iPar++) {
01194       if (iPar > 0) {
01195         log << setiosflags(std::ios::right) << std::setw(21) << " ";
01196       }
01197       TString colstr = "";
01198       colstr += parIndex;
01199       colstr += ":";
01200       log << std::setw(4) << colstr;
01201       log << std::setw(2) << " ";   
01202       log << setiosflags(std::ios::left) << setiosflags(std::ios::scientific) << std::setprecision(3);
01203       log << std::setw(15) << (*par)(iPar, 0);
01204       if(_nbIter > 0 && _status < 10) {
01205         log << std::setw(15) << TMath::Sqrt( _yaVFit(iPar, iPar) );
01206       } else {
01207         log << std::setw(15) << " ";
01208       }
01209       log << std::setw(15) << TMath::Sqrt( (*covP)(iPar, iPar) );
01210       log << "\n";
01211       parIndex++;
01212     }
01213     log << particle->getInfoString();
01214   }
01215   // Print unmeasured particles
01216   log << "unmeasured particles: \n";
01217   parIndex = 0;
01218   for (unsigned int iP = 0; iP < _unmeasParticles.size(); iP++) {
01219     TAbsFitParticle* particle = _unmeasParticles[iP];
01220     Int_t nParP = particle->getNPar();
01221     const TMatrixD* par = particle->getParCurr();
01222     log << std::setw(3) << setiosflags(std::ios::right) << iP;
01223     log << std::setw(15) << particle->GetName();
01224     log << std::setw(3) << " ";
01225     for (int iPar = 0; iPar < nParP; iPar++) {
01226       if (iPar > 0) {
01227         log << setiosflags(std::ios::right) << std::setw(21) << " ";
01228       }
01229       TString colstr = "";
01230       colstr += parIndex;
01231       colstr += ":";
01232       log << std::setw(4) << colstr;
01233       log << std::setw(2) << " ";
01234       log << setiosflags(std::ios::left) << setiosflags(std::ios::scientific) << std::setprecision(3);
01235       log << std::setw(15) << (*par)(iPar, 0);
01236       if(_nbIter > 0 && _status < 10) {
01237         log << std::setw(15) << TMath::Sqrt( _yaVFit(iPar+_nParB, iPar+_nParB) );
01238       } else {
01239         log << std::setw(15) << " ";
01240       }
01241       log << "\n";
01242       parIndex++;
01243     }
01244     log << particle->getInfoString();
01245   }
01246   log << "\n";
01247   // Print constraints
01248   log << "constraints: \n";
01249   for (unsigned int indexConstr = 0; indexConstr < _constraints.size(); indexConstr++) {
01250     log << _constraints[indexConstr]->getInfoString();
01251   }
01252   log << "\n";
01253 
01254 }
01255 
01256 void TKinFitter::printMatrix(const TMatrixD &matrix, const TString name) {
01257   // produce a tabular printout for matrices
01258   // this function is a modified version of Root's TMatrixTBase<Element>::Print method
01259   // which could not be used together with the MessageLogger
01260 
01261   if (!matrix.IsValid()) {
01262     edm::LogWarning ("InvalidMatrix") << "Matrix " << name << " is invalid.";
01263     return;
01264   }
01265 
01266   edm::LogVerbatim log("KinFitter");
01267 
01268   const Int_t nCols  = matrix.GetNcols();
01269   const Int_t nRows  = matrix.GetNrows();
01270   const Int_t colsPerSheet = 5;
01271   char topbar[100];
01272   Int_t nk = 6+13*TMath::Min(colsPerSheet, nCols);
01273   for(Int_t i = 0; i < nk; i++) topbar[i] = '-';
01274   topbar[nk] = 0;
01275 
01276   Int_t sw = (70-name.Length())/2;
01277  
01278   log << std::setfill('=') << std::setw(sw) << "=  " << name << std::setw(sw) << std::left << "  ="  << "\n"
01279       << std::setfill(' ') << std::right << "\n";
01280 
01281   log << nRows << "x" << nCols << " matrix is as follows \n";
01282 
01283   for (Int_t iSheet = 0; iSheet < nCols; iSheet += colsPerSheet) {
01284     log << "\n"
01285         << "     |";
01286     for (Int_t iCol = iSheet; iCol < iSheet+colsPerSheet && iCol < nCols; iCol++)
01287       log << std::setw(8) << iCol << "    |";
01288     log << "\n"
01289         << topbar << " \n";
01290     for(Int_t iRow = 0; iRow < nRows; iRow++) {
01291       log << std::setw(4) << iRow << " |";
01292       for (Int_t iCol = iSheet; iCol < iSheet+colsPerSheet && iCol < nCols; iCol++)
01293         log << std::setw(12) << matrix(iRow, iCol) << " ";
01294       log << "\n";
01295     }
01296   }
01297 
01298 }