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:
00233 p.setValues (1, 0, 0);
00234 break;
00235 case 1:
00236 p.setValues (0, 1, 0);
00237 break;
00238 case 2:
00239 p.setValues (0, 0, 1);
00240 break;
00241 default:
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
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
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
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
00422
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
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 }