00001
00008 #include "jbltools/kinfit/NeutralParticleTrack.h"
00009 #include "jbltools/kinfit/TwoVector.h"
00010 #include "jbltools/kinfit/ThreeVector.h"
00011 #include "jbltools/kinfit/FourVector.h"
00012 #include "jbltools/kinfit/JBLHelix.h"
00013
00014 #include <cassert>
00015 #include <cmath>
00016 using std::sin;
00017 using std::cos;
00018 using std::sqrt;
00019 using std::tan;
00020 using std::pow;
00021 using std::abs;
00022 using std::isfinite;
00023 #include <iostream>
00024 using std::cout;
00025 using std::endl;
00026
00027
00028 const double NeutralParticleTrack::parfact[NPARMAX] =
00029 {1., 1., 1., 1., 1., 1., 1., 1.};
00030
00031 NeutralParticleTrack::NeutralParticleTrack (const char *name_,
00032 double pt,
00033 double phi0,
00034 double theta,
00035 double dca,
00036 double z0,
00037 double mass,
00038 double sstart,
00039 double sstop
00040 )
00041 : TrackFitObject (name_)
00042 {
00043 setParam (0, pt, false);
00044 setParam (1, phi0, false);
00045 setParam (2, theta, false);
00046 setParam (3, dca, false);
00047 setParam (4, z0, false);
00048 setParam (5, mass, false, true);
00049 setParam (6, sstart, false);
00050 setParam (7, sstop, false);
00051
00052 setMParam (0, pt);
00053 setMParam (1, phi0);
00054 setMParam (2, theta);
00055 setMParam (3, dca);
00056 setMParam (4, z0);
00057 TrackFitObject::initCov();
00058 }
00059 NeutralParticleTrack::NeutralParticleTrack (const char *name_,
00060 double pt,
00061 double phi0,
00062 double theta,
00063 double dca,
00064 double z0,
00065 double mass,
00066 double sstart
00067 )
00068 : TrackFitObject (name_)
00069 {
00070 setParam (0, pt, false);
00071 setParam (1, phi0, false);
00072 setParam (2, theta, false);
00073 setParam (3, dca, false);
00074 setParam (4, z0, false);
00075 setParam (5, mass, false, true);
00076 setParam (6, sstart, false);
00077 setParam (7, 0, false, true);
00078
00079 setMParam (0, pt);
00080 setMParam (1, phi0);
00081 setMParam (2, theta);
00082 setMParam (3, dca);
00083 setMParam (4, z0);
00084 TrackFitObject::initCov();
00085 }
00086 NeutralParticleTrack::NeutralParticleTrack (const char *name_,
00087 const ThreeVector& vertex,
00088 const ThreeVector& momentum,
00089 double mass
00090 )
00091 : TrackFitObject (name_)
00092 {
00093 pt = momentum.getPt();
00094 theta = momentum.getTheta();
00095 phi0 = momentum.getPhi();
00096
00097
00098
00099
00100
00101 sphi0 = sin(phi0);
00102 cphi0 = cos(phi0);
00103 double sstop = vertex.getX()*cphi0 + vertex.getY()*sphi0;
00104 dca = vertex.getX()*sphi0 - vertex.getY()*cphi0;
00105 z0 = vertex.getZ() - sstop*cos(theta)/sin(theta);
00106
00107
00108
00109
00110
00111
00112 setParam (0, pt, false);
00113 setParam (1, phi0, false);
00114 setParam (2, theta, false);
00115 setParam (3, dca, false);
00116 setParam (4, z0, false);
00117 setParam (5, mass, false, true);
00118 setParam (6, 0, false, true);
00119 setParam (7, sstop, false);
00120
00121
00122
00123
00124 setMParam (0, pt);
00125 setMParam (1, phi0);
00126 setMParam (2, theta);
00127 setMParam (3, dca);
00128 setMParam (4, z0);
00129 TrackFitObject::initCov();
00130 }
00131
00132 NeutralParticleTrack::~NeutralParticleTrack ()
00133 {}
00134
00135 int NeutralParticleTrack::getNPar() const {
00136 return NPAR;
00137 }
00138
00139 const char *NeutralParticleTrack::getParamName (int ilocal) const {
00140 switch (ilocal) {
00141 case 0: return "pt";
00142 case 1: return "phi0";
00143 case 2: return "theta";
00144 case 3: return "dca";
00145 case 4: return "z0";
00146 case 5: return "mass";
00147 case 6: return "sstart";
00148 case 7: return "sstop";
00149 }
00150 return "undefined";
00151 }
00152
00153 bool NeutralParticleTrack::setParam (int ilocal, double par_,
00154 bool measured_, bool fixed_) {
00155 assert (ilocal >= 0 && ilocal < NPAR);
00156 if (measured[ilocal] != measured_ || fixed[ilocal] != fixed_) invalidateCache();
00157 measured[ilocal] = measured_;
00158 fixed[ilocal] = fixed_;
00159 return setParam (ilocal, par_);
00160 };
00161
00162 bool NeutralParticleTrack::setParam (int ilocal, double par_ ) {
00163 assert (ilocal >= 0 && ilocal < NPAR);
00164 if (!isfinite(par_)) return false;
00165
00166
00167
00168 switch (ilocal) {
00169 case 0: if (par_ <= 0) return false;
00170 break;
00171
00172
00173 case 2: if (par_ < 0 || par_*parfact[2] >= M_PI) par_ = acos (cos (par_*parfact[2]))/parfact[2];
00174 break;
00175 case 5: if (par_ < 0) par_ = abs (par_);
00176 break;
00177 }
00178 if (par[ilocal] == par_) return true;
00179 invalidateCache();
00180 par[ilocal] = par_;
00181 return true;
00182 };
00183
00184 bool NeutralParticleTrack::setParameters (int ivertex,
00185 const ThreeVector& vertex,
00186 const FourVector& momentum,
00187 double charge_
00188 ) {
00189 bool result = true;
00190 pt = momentum.getPt();
00191 theta = momentum.getTheta();
00192 phi0 = momentum.getPhi();
00193
00194
00195
00196
00197
00198 sphi0 = sin(phi0);
00199 cphi0 = cos(phi0);
00200 double s = vertex.getX()*cphi0 + vertex.getY()*sphi0;
00201 dca = vertex.getX()*sphi0 - vertex.getY()*cphi0;
00202 z0 = vertex.getZ() - s*cos(theta)/sin(theta);
00203
00204
00205
00206
00207
00208
00209 if (!isParamFixed (0)) result &= setParam (0, pt/parfact[0]);
00210 if (!isParamFixed (1)) result &= setParam (1, phi0/parfact[1]);
00211 if (!isParamFixed (2)) result &= setParam (2, theta/parfact[2]);
00212 if (!isParamFixed (3)) result &= setParam (3, dca/parfact[3]);
00213 if (!isParamFixed (4)) result &= setParam (4, z0/parfact[4]);
00214 if (!isParamFixed (5)) result &= setParam (5, mass/parfact[5]);
00215 assert (ivertex >= 0 && 6+ivertex < NPAR);
00216 result &= setParam (6+ivertex, s/parfact[6+ivertex]);
00217 return result;
00218 }
00219
00220
00221 void NeutralParticleTrack::getTrajectoryPointEx (double s, ThreeVector& p) const {
00222 if (!cachevalid) updateCache();
00223 p.setValues (x0 + cphi0*s,
00224 y0 + sphi0*s,
00225 z0 + s*cottheta);
00226 }
00227
00228 void NeutralParticleTrack::getTrajectoryDerivativeEx (double s, int ilocal, ThreeVector& p) const {
00229 if (!cachevalid) updateCache();
00230 assert (ilocal >= 0 && ilocal < NPAR);
00231 switch (ilocal) {
00232 case 0:
00233 p.setValues (0, 0, 0);
00234 break;
00235 case 1:
00236 p.setValues (-y0 - sphi0*s, x0 + cphi0*s, 0);
00237 break;
00238 case 2:
00239 p.setValues (0, 0, - s/sin2theta);
00240 break;
00241 case 3:
00242 p.setValues (sphi0, -cphi0, 0);
00243 break;
00244 case 4:
00245 p.setValues (0, 0, 1);
00246 break;
00247 case 5:
00248 p.setValues (0, 0, 0);
00249 break;
00250 case 6:
00251
00252 case 7:
00253 p.setValues (cphi0, sphi0, cottheta);
00254 break;
00255 default:
00256 assert (0);
00257 }
00258 p *= parfact[ilocal];
00259 }
00260
00261 void NeutralParticleTrack::getVertexEx (int ivertex, ThreeVector& p) const {
00262 assert (ivertex >= 0 && 6+ivertex < NPAR);
00263 getTrajectoryPointEx (par[6+ivertex]*parfact[6+ivertex], p);
00264 }
00265
00266 void NeutralParticleTrack::setVertex (int ivertex, const TwoVector& p) {
00267 assert (ivertex >= 0 && 6+ivertex < NPAR);
00268 if (!cachevalid) updateCache();
00269
00270 double xc = sphi0*dca;
00271 double yc = -cphi0*dca;
00272 par[6+ivertex] = ((p.getX()-xc)*cphi0 + (p.getY()-yc)*sphi0)/parfact[6+ivertex];
00273 }
00274
00275 void NeutralParticleTrack::getVertexDerivativeEx (int ivertex,
00276 int ilocal,
00277 ThreeVector& p) const {
00278 assert (ivertex >= 0 && 6+ivertex < NPAR);
00279 assert (ilocal >= 0 && ilocal < NPAR);
00280
00281
00282
00283 if (ilocal >= 6 && ilocal != 6+ivertex) {
00284 p.setValues (0, 0, 0);
00285 }
00286 else {
00287 getTrajectoryDerivativeEx (par[6+ivertex]*parfact[6+ivertex], ilocal, p);
00288 }
00289 }
00290
00291 void NeutralParticleTrack::getMomentumAtTrajectoryEx (double s, FourVector& p) const {
00292 if (!cachevalid) updateCache();
00293 p.setValues (energy,
00294 px,
00295 py,
00296 pt*cottheta);
00297 }
00298
00299 void NeutralParticleTrack::getMomentumEx (int ivertex, FourVector& p) const {
00300 assert (ivertex >= 0 && 6+ivertex < NPAR);
00301 getMomentumAtTrajectoryEx (par[6+ivertex]*parfact[6+ivertex], p);
00302 }
00303
00304
00305 double NeutralParticleTrack::getCharge () const {
00306 return 0;
00307 }
00308
00309 double NeutralParticleTrack::getMass () const {
00310 return par[5]*parfact[5];
00311 }
00312
00313 void NeutralParticleTrack::getMomentumDerivativeAtTrajectoryEx (double s, int ilocal, FourVector& p) const {
00314 if (!cachevalid) updateCache();
00315 assert (ilocal >= 0 && ilocal < getNPar() && ilocal < NPAR);
00316 switch (ilocal) {
00317 case 0:
00318 {
00319 p.setValues (beta/sintheta, cphi0, sphi0, cottheta);
00320 }
00321 break;
00322 case 1:
00323 p.setValues (0, -py, px, 0);
00324 break;
00325 case 2:
00326 p.setValues (beta*momentum*cottheta,0, 0, -pt/sin2theta);
00327 break;
00328 case 3:
00329 p.setValues (0, 0, 0, 0);
00330 break;
00331 case 4:
00332 p.setValues (0, 0, 0, 0);
00333 break;
00334 case 5:
00335 p.setValues (par[5]/energy, 0, 0, 0);
00336 break;
00337 case 6:
00338
00339 case 7:
00340 p.setValues (0, 0, 0, 0);
00341 break;
00342 default:
00343 assert (0);
00344 }
00345 p *= parfact[ilocal];
00346 }
00347
00348 void NeutralParticleTrack::getMomentumDerivativeEx (int ivertex,
00349 int ilocal,
00350 FourVector& p) const {
00351 assert (ivertex >= 0 && 6+ivertex < NPAR);
00352 assert (ilocal >= 0 && ilocal < NPAR);
00353
00354
00355 if (ilocal >= 6) {
00356 p.setValues (0, 0, 0, 0);
00357 }
00358 else {
00359 getMomentumDerivativeAtTrajectoryEx (par[6+ivertex]*parfact[6+ivertex], ilocal, p);
00360 }
00361 }
00362
00363
00364 double NeutralParticleTrack::getArcLength (int ivertex) const {
00365 assert (ivertex >= 0 && 6+ivertex < NPAR);
00366 return par[6+ivertex]*parfact[6+ivertex];
00367 }
00368
00369 void NeutralParticleTrack::addToGlobCov(double *glcov, int idim) const {
00370 int globalnum[NPARMAX];
00371 bool ok [NPARMAX];
00372 for (int ilocal = 0; ilocal < getNPar(); ilocal++) {
00373 int iglobal = globalnum[ilocal] = getGlobalParNum(ilocal);
00374 if (ok [iglobal] = (iglobal >= 0 && !isParamFixed(ilocal) && isParamMeasured (ilocal))) {
00375 for (int jlocal = 0; jlocal <= ilocal; jlocal++) {
00376 int jglobal = globalnum[jlocal];
00377 if (ok [jlocal]) {
00378 double c = cov[ilocal][jlocal];
00379 glcov[jglobal+iglobal*idim] += c;
00380 if (jlocal != ilocal) glcov[iglobal+jglobal*idim] += c;
00381 }
00382 }
00383 }
00384 }
00385 }
00386
00387
00388
00389 void NeutralParticleTrack::updateCache() const {
00390 pt = par[0]*parfact[0];
00391 phi0 = par[1]*parfact[1];
00392 theta = par[2]*parfact[2];
00393 dca = par[3]*parfact[3];
00394 z0 = par[4]*parfact[4];
00395 mass = par[5]*parfact[5];
00396
00397 sphi0 = sin(phi0);
00398 cphi0 = cos(phi0);
00399 px = pt*cphi0;
00400 py = pt*sphi0;
00401 x0 = dca*sphi0;
00402 y0 = -dca*cphi0;
00403
00404 sintheta = sin(theta);
00405 cottheta = cos(theta)/sintheta;
00406 sin2theta = sintheta*sintheta;
00407
00408 momentum = pt/sintheta;
00409
00410 energy = sqrt(momentum*momentum + mass*mass);
00411 beta = (energy != 0) ? momentum/energy : 0;
00412
00413 calculateChi2();
00414 cachevalid = true;
00415
00416 }
00417
00418 void NeutralParticleTrack::initCov(const float cov_[15]) {
00419 TrackFitObject::initCov();
00420
00421 int i = 0;
00422 for (int k = 0; k < 5; ++k) {
00423 for (int l = k; l < 5; ++l) {
00424 cov[k][l] = cov[l][k] = cov_[i++]/(parfact[k]*parfact[l]);
00425 }
00426 }
00427 assert (i==15);
00428 TrackFitObject::checkCov();
00429
00430 covinvvalid = false;
00431 }
00432
00433 JBLHelix NeutralParticleTrack::getTangentialHelix (double) {
00434 return JBLHelix (0,
00435 par[1]*parfact[1],
00436 par[2]*parfact[2],
00437 par[3]*parfact[3],
00438 par[4]*parfact[4]);
00439 }