Main Page | Class Hierarchy | Compound List | File List | Compound Members | File Members

VertexFitObject.C

Go to the documentation of this file.
00001 
00014 #include "jbltools/kinfit/VertexFitObject.h"
00015 #include "jbltools/kinfit/TwoVector.h"
00016 #include "jbltools/kinfit/ThreeVector.h"
00017 #include "jbltools/kinfit/FourVector.h"
00018 #include "jbltools/kinfit/VertexConstraint.h"
00019 #include "jbltools/kinfit/TrackMomentumConstraint.h"
00020 #include "jbltools/kinfit/TrackFitObject.h"
00021 #include "jbltools/kinfit/BaseFitter.h"
00022 #include "jbltools/kinfit/JBLHelix.h"
00023 #include "cernlib.h"
00024 
00025 #include <iostream>
00026 using std::cout;
00027 using std::endl;
00028 
00029 #include <cassert>
00030 #include <cmath>
00031 using std::isfinite;
00032 
00033 #include <cstring>
00034 
00035 static int debug = 0;
00036 
00037 VertexFitObject::VertexFitObject(const char *name_,
00038                                  double x,
00039                                  double y,
00040                                  double z
00041                                 )
00042 : covinvvalid (false), name (0),
00043   tracks (0), constraints (0)
00044 {
00045   setParam (0, x, false);
00046   setParam (1, y, false);
00047   setParam (2, z, false);
00048   setMParam (0, x);
00049   setMParam (1, y);
00050   setMParam (2, z);
00051   setName (name_);
00052   initCov();
00053 }
00054 
00055 VertexFitObject::VertexFitObject (const VertexFitObject& rhs) 
00056 : covinvvalid (false), name (0)
00057 {
00058   copy (rhs);
00059 }
00060 
00061 VertexFitObject& VertexFitObject::operator= (const VertexFitObject& rhs) {
00062   if (&rhs != this) copy (rhs);
00063   return *this;
00064 }
00065 
00066 int VertexFitObject::getNPar() const {
00067   return NPAR;
00068 }
00069 
00070 void VertexFitObject::copy (const VertexFitObject& source) 
00071 {
00072   covinvvalid =false;
00073   name = 0;
00074   for (int i = 0; i < NPAR; i++) {
00075     par[i] = source.par[i];
00076     mpar[i] = source.mpar[i];
00077     err[i] = source.err[i];
00078     measured[i] = source.measured[i];
00079     fixed[i] = source.fixed[i];
00080     globalParNum[i] = source.globalParNum[i];
00081     for (int j = 0; j < NPAR; j++) {
00082       cov[i][j] = source.cov[i][j];
00083     }
00084   } 
00085   tracks = source.tracks;
00086   setName (source.name);
00087 }
00088 
00089 VertexFitObject::~VertexFitObject()
00090 {
00091   delete[] name;
00092   name = 0;
00093   for (CIterator it = constraints.begin(); it != constraints.end(); ++it) {
00094     delete (*it);
00095     (*it) = 0;
00096   }
00097 }
00098 
00099 bool VertexFitObject::setParam (int ilocal, double par_, 
00100                                  bool measured_, bool fixed_) {
00101   assert (ilocal >= 0 && ilocal < NPAR);
00102   measured[ilocal] = measured_;
00103   fixed[ilocal] = fixed_;
00104   return setParam (ilocal, par_);
00105 };  
00106 
00107 bool VertexFitObject::setParam (int ilocal, double par_ ) {
00108   if (!isfinite(par_)) return false;
00109   assert (ilocal >= 0 && ilocal < NPAR);
00110   par[ilocal] = par_;
00111   return true;
00112 }  
00113 bool VertexFitObject::setMParam (int ilocal, double mpar_ ) {
00114   if (!isfinite(mpar_)) return false;
00115   assert (ilocal >= 0 && ilocal < NPAR);
00116   mpar[ilocal] = mpar_;
00117   return true;
00118 }  
00119 
00120 bool VertexFitObject::setError (int ilocal, double err_) {
00121   if (!isfinite(err_)) return false;
00122   assert (ilocal >= 0 && ilocal < NPAR);
00123   cov[ilocal][ilocal] = err_*err_;
00124   covinvvalid = false;
00125   return true;
00126 }
00127 
00128 bool VertexFitObject::setCov (int ilocal, int jlocal, double cov_) {
00129   if (!isfinite(cov_)) return false;
00130   assert (ilocal >= 0 && ilocal < NPAR);
00131   assert (jlocal >= 0 && jlocal < NPAR);
00132   cov[ilocal][jlocal] = cov[jlocal][ilocal] = cov_;
00133   covinvvalid = false;
00134   return true;
00135 }
00136 
00137 const char *VertexFitObject::getName() const {
00138   return name ? name : "???";
00139 }
00140 
00141 const char *VertexFitObject::getParamName (int ilocal) const {
00142   switch (ilocal) {
00143     case 0: return "x";
00144     case 1: return "y";
00145     case 2: return "z";
00146   }
00147   return "undefined";
00148 }
00149 
00150 void VertexFitObject::setName(const char *name_) {
00151   if (!name_) return;
00152   delete[] name;
00153   name = 0;
00154   
00155   size_t len = strlen(name_)+1;
00156   name = new char[len];
00157   strncpy (name, name_, len);
00158 }
00159 
00160   
00161 bool VertexFitObject::setGlobalParNum (int ilocal, int iglobal) {
00162   assert (ilocal >= 0 && ilocal < NPAR);
00163   assert (!isParamFixed(ilocal));
00164   globalParNum[ilocal] = iglobal;
00165   return true;
00166 }
00167 bool VertexFitObject::fixParam (int ilocal, bool fix) {
00168   assert (ilocal >= 0 && ilocal < NPAR);
00169   return fixed [ilocal] = fix;
00170 }
00171 int  VertexFitObject::getGlobalParNum(int ilocal) const {
00172   if (ilocal < 0 || ilocal >= getNPar()) return -1;
00173   return globalParNum[ilocal];
00174 }
00175 
00176 double VertexFitObject::getParam (int ilocal) const {
00177   assert (ilocal >= 0 && ilocal < NPAR);
00178   return par[ilocal];
00179 }
00180 double VertexFitObject::getMParam (int ilocal) const {
00181   assert (ilocal >= 0 && ilocal < NPAR);
00182   assert (isParamMeasured(ilocal));
00183   return mpar[ilocal];
00184 }
00185 
00186 double VertexFitObject::getError (int ilocal) const {
00187   assert (ilocal >= 0 && ilocal < NPAR);
00188   return std::sqrt(cov[ilocal][ilocal]);
00189 }
00190 
00191 double VertexFitObject::getCov (int ilocal, int jlocal) const {
00192   assert (ilocal >= 0 && ilocal < NPAR);
00193   assert (jlocal >= 0 && jlocal < NPAR);
00194   return cov[ilocal][jlocal];
00195 }
00196 
00197 bool VertexFitObject::isParamMeasured (int ilocal) const {
00198   assert (ilocal >= 0 && ilocal < NPAR);
00199   return measured[ilocal];
00200 }
00201 
00202 bool VertexFitObject::isParamFixed (int ilocal) const {
00203   assert (ilocal >= 0 && ilocal < NPAR);
00204   return fixed[ilocal];
00205 }
00206     
00207 std::ostream& VertexFitObject::print (std::ostream& os) const {
00208   os << getName() << ":\n";
00209   printParams(os);
00210   return os;
00211 }
00212 
00213 
00214 ThreeVector VertexFitObject::getVertex () const {
00215   ThreeVector result;
00216   getVertexEx (result);
00217   return result;
00218 }
00219 
00220 void VertexFitObject::getVertexEx (ThreeVector& p) const {
00221   p.setValues (par[0], par[1], par[2]);
00222 } 
00223                                                     
00224 ThreeVector VertexFitObject::getVertexDerivative (int ilocal) const  {
00225   ThreeVector result;
00226   getVertexDerivativeEx (ilocal, result);
00227   return result;
00228 }
00229 
00230 void VertexFitObject::getVertexDerivativeEx (int ilocal, ThreeVector& p) const {
00231   switch (ilocal) {
00232     case 0: // d / d par[0] = d / d x
00233       p.setValues (1, 0, 0);
00234       break;
00235     case 1: // d / d par[1] = d / d y
00236       p.setValues (0, 1, 0);
00237       break;
00238     case 2: // d / d par[2] = d / d z
00239       p.setValues (0, 0, 1);
00240       break;
00241     default: // should never happen!
00242       assert (0);
00243   }
00244 }
00245 
00246 void VertexFitObject::addToGlobCov(double *glcov, int idim) const {
00247   int globalnum[NPAR];
00248   bool ok [NPAR];
00249   for (int ilocal = 0; ilocal < getNPar(); ilocal++) {
00250     int iglobal = globalnum[ilocal] = getGlobalParNum(ilocal);
00251     assert (iglobal < idim);
00252     if (ok [ilocal] = (iglobal >= 0 && !isParamFixed(ilocal) && isParamMeasured (ilocal))) {
00253       for (int jlocal = 0; jlocal <= ilocal; jlocal++) {
00254         int jglobal = globalnum[jlocal];
00255         assert (jglobal < idim);
00256         if (ok [jlocal]) {
00257           double c = cov[ilocal][jlocal];
00258           glcov[jglobal+iglobal*idim] += c;
00259           if (jglobal != iglobal) glcov[iglobal+jglobal*idim] += c;
00260         }
00261       }
00262     }
00263   }
00264 } 
00265 
00266 
00267 void VertexFitObject::initCov() {
00268   int n = getNPar();
00269   for (int i = 0; i < n; ++i) {
00270     for (int j = 0; j < n; ++j) {
00271       cov[i][j] = static_cast<double> (i == j);
00272     }
00273   }
00274   covinvvalid = false;
00275 }
00276 
00277 double VertexFitObject::getChi2() const {
00278   calculateChi2();
00279   return chi2;
00280 }
00281 
00282 bool VertexFitObject::calculateCovInv() const {
00283   int n = getNPar();
00284   int idim = 0;
00285   for (int i = 0; i < n; ++i) {
00286     if (isParamMeasured (i)) {
00287       idim = i;
00288       for (int j = 0; j < n; ++j) {
00289         covinv[i][j] = isParamMeasured (j) ? cov[i][j] : 0;
00290       }
00291     }
00292     else {
00293       for (int j = 0; j < n; ++j) {
00294         covinv[i][j] = static_cast<double>(i == j);
00295       }
00296     }
00297   }
00298   int ierr = (idim == 0) ? 0 : dsinv(idim, &covinv[0][0], NPAR);
00299   if (ierr != 0) {
00300     std::cerr << "VertexFitObject::calculateCovInv: Error "
00301               << ierr << " from dsinv!" << std::endl;
00302   }
00303   return covinvvalid = (ierr == 0);
00304 }
00305 
00306 
00307 void VertexFitObject::calculateChi2() const {
00308   if (!covinvvalid) calculateCovInv();
00309   if (!covinvvalid) {
00310     chi2 = -1;
00311     return;
00312   }
00313   chi2 = 0;
00314   for (int i = 0; i < getNPar(); ++i) {
00315     resid[i] = par[i]-mpar[i];
00316     if (chi2contr[i] = isParamMeasured(i) && !isParamFixed(i)) {
00317       chi2 += resid[i]*covinv[i][i]*resid[i];
00318       for (int j = 0; j < i; ++j) {
00319         if (chi2contr[j]) chi2 += 2*(resid[i])*covinv[i][j]*(resid[j]);
00320       }
00321     }
00322   }
00323 }
00324 
00325 void VertexFitObject::addVertexConstraints (BaseFitter& fitter, int axis) {
00326   for (TIterator it = tracks.begin(); it != tracks.end(); ++it) {
00327     assert(it->track); 
00328     VertexConstraint *con = new VertexConstraint (*this, *(it->track), (it->inbound ? 1 : 0), axis);
00329     fitter.addConstraint (con);
00330     constraints.push_back (con);
00331     it->track->releaseVertexParam (it->inbound ? 1 : 0);
00332   }
00333 }
00334 
00335 void VertexFitObject::addMomentumConstraint (BaseFitter& fitter, int axis) {
00336   TrackMomentumConstraint *con = new TrackMomentumConstraint (axis);
00337   fitter.addConstraint (con);
00338   constraints.push_back (con);
00339   
00340   // Add first inbound track
00341   for (TIterator it = tracks.begin(); it != tracks.end(); ++it) {
00342     if (it->inbound) {
00343       assert(it->track); 
00344       con->addToFOList(*(it->track), 1);
00345       break;
00346     }
00347   }
00348   // Now add outgoing tracks
00349   for (TIterator it = tracks.begin(); it != tracks.end(); ++it) {
00350     assert(it->track); 
00351     if (!it->inbound) con->addToFOList(*(it->track), 0);
00352   }
00353 }
00354 
00355 void VertexFitObject::addConstraints (BaseFitter& fitter, int mask) {
00356   if (mask & VX) addVertexConstraints (fitter, 0); else fixParam (0);
00357   if (mask & VY) addVertexConstraints (fitter, 1); else fixParam (1);
00358   if (mask & VZ) addVertexConstraints (fitter, 2); else fixParam (2);
00359   if (mask & PX) addMomentumConstraint (fitter, 1);
00360   if (mask & PY) addMomentumConstraint (fitter, 2);
00361   if (mask & PZ) addMomentumConstraint (fitter, 3);
00362   if (mask & E)  addMomentumConstraint (fitter, 0);
00363 }
00364 
00365 void VertexFitObject::addTrack (TrackFitObject *track, bool inbound, bool measured) {
00366   assert (track);
00367   tracks.push_back (TrackDescriptor (track, inbound, measured));
00368 }
00369 
00370 ThreeVector VertexFitObject::estimatePosition () {
00371   if (debug) cout << "VertexFitObject::estimatePosition(): starting" << endl;
00372   ThreeVector position (0, 0, 0);
00373   int n = 0;
00374   for (TIterator it0 = tracks.begin(); it0 != tracks.end(); ++it0) {
00375     if (it0->measured) {
00376       JBLHelix h0 = it0->track->getTangentialHelix(0);
00377       TIterator it1 = it0;
00378       for (++it1; it1 != tracks.end(); ++it1) {
00379         if (it1->measured) {
00380           if (debug)
00381             cout << "Intersecting " << it0->track->getName()
00382                  << " and " << it1->track->getName() << endl;
00383           JBLHelix h1 = it1->track->getTangentialHelix(0);
00384           double s0, s1, s02nd, s12nd;
00385           h0.getClosestApproach (h1, s0, s1, s02nd, s12nd);
00386           position += h0.getTrajectoryPoint (s0);
00387           position += h1.getTrajectoryPoint (s1);
00388           if (debug)
00389             cout << "  point 0: " << h0.getTrajectoryPoint (s0)
00390                  << ", point 1: " << h1.getTrajectoryPoint (s1) << endl;
00391           n += 2;
00392         }
00393       }
00394     }
00395   }
00396   position *= (1./n);
00397   if (debug) cout << "Final position estimate: " << position << endl;
00398   return position;
00399 }
00400 
00401 void VertexFitObject::initForFit() {
00402   if (debug) 
00403     cout << "VertexFitObject::initForFit(): starting for " << getName() << endl;
00404 
00405   // Estimate and set vertex position
00406   ThreeVector position = estimatePosition ();
00407   for (int i = 0; i < 3; i++) par[i] = position.getComponent (i);
00408   if (debug) 
00409     cout << "VertexFitObject now: " << *this << endl;
00410   if (debug) {
00411     cout << "TrackFit objects before adjustment: \n";
00412     for (TIterator it = tracks.begin(); it != tracks.end(); ++it) {
00413       cout << "   " << it->track->getName() << " = " << *(it->track)
00414            << (it->measured ? "  measured " : "  not meas.")
00415            << (it->inbound ? " decays at " : " starts at ")
00416            << it->track->getVertex(it->inbound ? 1 : 0)
00417            << endl;
00418     }
00419   }  
00420     
00421   // For all measured tracks, set s to be close to vertex position,
00422   // at the same time estimate total 4-momentum and total charge
00423   FourVector ptot;
00424   double chargetot = 0;
00425   int nunm = 0;
00426   for (TIterator it = tracks.begin(); it != tracks.end(); ++it) {
00427     if (it->measured) {
00428       if (it->inbound) {
00429         it->track->setVertex (1, TwoVector (par[0], par[1]));
00430         ptot -= it->track->getMomentum (1);
00431         chargetot -= it->track->getCharge();
00432       }
00433       else {
00434         it->track->setVertex (0, TwoVector (par[0], par[1]));
00435         ptot += it->track->getMomentum (0);
00436         chargetot += it->track->getCharge();
00437       }
00438     }
00439     else {
00440       nunm++;
00441     }
00442   }
00443   assert (nunm <= 1);
00444   // Now, init remaining unmeasured track
00445   for (TIterator it = tracks.begin(); it != tracks.end(); ++it) {
00446     if (!it->measured) {
00447       if (it->inbound) {
00448         assert (ptot.getE() > 0);
00449         it->track->setParameters (1, position, ptot, chargetot);
00450       }
00451       else {
00452         assert (ptot.getE() < 0);
00453         it->track->setParameters (0, position, -ptot, -chargetot);
00454       }
00455     }
00456   }
00457   if (debug) {
00458     cout << "TrackFit objects after adjustment: \n";
00459     for (TIterator it = tracks.begin(); it != tracks.end(); ++it) {
00460       cout << "   " << it->track->getName() << " = " << *(it->track)
00461            << (it->measured ? "  measured " : "  not meas.")
00462            << (it->inbound ? " decays at " : " starts at ")
00463            << it->track->getVertex(it->inbound ? 1 : 0)
00464            << endl;
00465     }
00466   }  
00467 }

Generated on Fri Sep 14 17:38:21 2007 for Kinfit by doxygen 1.3.2