00001
00008 #include "jbltools/kinfit/ChargedParticleTrack.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 <cstring>
00016 #include <cmath>
00017 using std::sin;
00018 using std::cos;
00019 using std::sqrt;
00020 using std::tan;
00021 using std::pow;
00022 using std::abs;
00023 using std::isfinite;
00024
00025 #include <iostream>
00026 using std::cout;
00027 using std::endl;
00028
00029 const double ChargedParticleTrack::parfact[NPARMAX] =
00030 {0.0001, 0.001, 0.01, 0.01, 1., 1., 1., 1.};
00031
00032 ChargedParticleTrack::ChargedParticleTrack (const char *name_,
00033 double kappa,
00034 double phi0,
00035 double theta,
00036 double dca,
00037 double z0,
00038 double mass,
00039 double charge_,
00040 double sstart,
00041 double sstop
00042 )
00043 : TrackFitObject (name_), charge (abs(charge_))
00044 {
00045 setParam (0, kappa/parfact[0], true);
00046 setParam (1, phi0/parfact[1], true);
00047 setParam (2, theta/parfact[2], true);
00048 setParam (3, dca/parfact[3], true);
00049 setParam (4, z0/parfact[4], true);
00050 setParam (5, mass/parfact[5], false, true);
00051 setParam (6, sstart/parfact[6], false);
00052 setParam (7, sstop/parfact[7], false);
00053 setMParam (0, kappa/parfact[0]);
00054 setMParam (1, phi0/parfact[1]);
00055 setMParam (2, theta/parfact[2]);
00056 setMParam (3, dca/parfact[3]);
00057 setMParam (4, z0/parfact[4]);
00058 TrackFitObject::initCov();
00059 }
00060 ChargedParticleTrack::ChargedParticleTrack (const char *name_,
00061 double kappa,
00062 double phi0,
00063 double theta,
00064 double dca,
00065 double z0,
00066 double mass,
00067 double charge_,
00068 double sstart
00069 )
00070 : TrackFitObject (name_), charge (abs(charge_))
00071 {
00072 setParam (0, kappa/parfact[0], true);
00073 setParam (1, phi0/parfact[1], true);
00074 setParam (2, theta/parfact[2], true);
00075 setParam (3, dca/parfact[3], true);
00076 setParam (4, z0/parfact[4], true);
00077 setParam (5, mass/parfact[5], false, true);
00078 setParam (6, sstart/parfact[6], false);
00079 setParam (7, 0, false, true);
00080 setMParam (0, kappa/parfact[0]);
00081 setMParam (1, phi0/parfact[1]);
00082 setMParam (2, theta/parfact[2]);
00083 setMParam (3, dca/parfact[3]);
00084 setMParam (4, z0/parfact[4]);
00085 TrackFitObject::initCov();
00086 }
00087 ChargedParticleTrack::ChargedParticleTrack (const char *name_,
00088 const ThreeVector& vertex,
00089 const ThreeVector& momentum,
00090 double mass,
00091 double charge_
00092 )
00093 : TrackFitObject (name_), charge (abs (charge_))
00094 {
00095 setParameters (0, vertex, FourVector (momentum, mass), charge_);
00096 assert (charge != 0);
00097 assert (bfield != 0);
00098 cBq = charge_*0.002998*bfield;
00099 kappa = -cBq/momentum.getPt();
00100 r = 1/kappa;
00101 theta = momentum.getTheta();
00102 double phi0plkappas = momentum.getPhi();
00103
00104 double si = sin(phi0plkappas);
00105 double co = cos(phi0plkappas);
00106
00107 double xc = vertex.getX()-r*si;
00108 double yc = vertex.getY()+r*co;
00109
00110
00111 double rc = sqrt(xc*xc + yc*yc);
00112 dca = r*(1 - abs(kappa)*rc);
00113
00114 if (dca-r > 0)
00115 phi0 = atan2 (xc, -yc);
00116 else
00117 phi0 = atan2 (-xc, yc);
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127 double sstart = (phi0plkappas-phi0)/kappa;
00128
00129 if (sstart < -1.57*abs(r)) sstart += 6.2831853*abs(r);
00130
00131
00132 double z0 = vertex.getZ() - sstart*(cos(theta)/sin(theta));
00133
00134
00135
00136 setParam (0, kappa/parfact[0], true);
00137 setParam (1, phi0/parfact[1], true);
00138 setParam (2, theta/parfact[2], true);
00139 setParam (3, dca/parfact[3], true);
00140 setParam (4, z0/parfact[4], true);
00141 setParam (5, mass/parfact[5], false, true);
00142 setParam (6, sstart/parfact[6], false);
00143 setParam (7, 0, false, true);
00144 setMParam (0, kappa/parfact[0]);
00145 setMParam (1, phi0/parfact[1]);
00146 setMParam (2, theta/parfact[2]);
00147 setMParam (3, dca/parfact[3]);
00148 setMParam (4, z0/parfact[4]);
00149
00150 TrackFitObject::initCov();
00151 }
00152 ChargedParticleTrack::ChargedParticleTrack (const char *name_,
00153 const float par_[5],
00154 const float cov_[15],
00155 double mass,
00156 double charge_,
00157 double sstart,
00158 double sstop
00159 )
00160 : TrackFitObject (name_), charge (abs(charge_))
00161 {
00162 setParam (0, par_[0]/parfact[0], true);
00163 setParam (1, par_[1]/parfact[1], true);
00164 setParam (2, par_[2]/parfact[2], true);
00165 setParam (3, par_[3]/parfact[3], true);
00166 setParam (4, par_[4]/parfact[4], true);
00167 setParam (5, mass /parfact[5], false, true);
00168 setParam (6, sstart /parfact[6], false);
00169 setParam (7, sstop /parfact[7], false, true);
00170 setMParam (0, par_[0]/parfact[0]);
00171 setMParam (1, par_[1]/parfact[1]);
00172 setMParam (2, par_[2]/parfact[2]);
00173 setMParam (3, par_[3]/parfact[3]);
00174 setMParam (4, par_[4]/parfact[4]);
00175 initCov(cov_);
00176 calculateCovInv();
00177 }
00178 ChargedParticleTrack::~ChargedParticleTrack ()
00179 {}
00180
00181 int ChargedParticleTrack::getNPar() const {
00182 return NPAR;
00183 }
00184
00185 const char *ChargedParticleTrack::getParamName (int ilocal) const {
00186 switch (ilocal) {
00187 case 0: return "kappa";
00188 case 1: return "phi0";
00189 case 2: return "theta";
00190 case 3: return "dca";
00191 case 4: return "z0";
00192 case 5: return "mass";
00193 case 6: return "sstart";
00194 case 7: return "sstop";
00195 }
00196 return "undefined";
00197 }
00198
00199 bool ChargedParticleTrack::setParam (int ilocal, double par_,
00200 bool measured_, bool fixed_) {
00201 assert (ilocal >= 0 && ilocal < NPARMAX);
00202 if (measured[ilocal] != measured_ || fixed[ilocal] != fixed_) invalidateCache();
00203 measured[ilocal] = measured_;
00204 fixed[ilocal] = fixed_;
00205 return setParam (ilocal, par_);
00206 };
00207
00208 bool ChargedParticleTrack::setParameters (int ivertex,
00209 const ThreeVector& vertex,
00210 const FourVector& momentum,
00211 double charge_
00212 ) {
00213 bool result = true;
00214 charge = std::abs(charge_);
00215 assert (charge > 0);
00216 assert (bfield > 0);
00217 cBq = 0.002998*bfield*charge_;
00218 if (momentum.getPt() == 0) return false;
00219 kappa = -cBq/momentum.getPt();
00220 r = 1/kappa;
00221 theta = momentum.getTheta();
00222 double phi0plkappas = momentum.getPhi();
00223
00224 mass = (isParamFixed(5)) ? par[5]*parfact[5] : momentum.getMass();
00225
00226
00227 double si = sin(phi0plkappas);
00228 double co = cos(phi0plkappas);
00229
00230 double xc = vertex.getX()-r*si;
00231 double yc = vertex.getY()+r*co;
00232
00233
00234 double rc = sqrt(xc*xc + yc*yc);
00235 dca = r*(1 - abs(kappa)*rc);
00236
00237 if (dca-r > 0)
00238 phi0 = atan2 (xc, -yc);
00239 else
00240 phi0 = atan2 (-xc, yc);
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250 double s = getNormalS((phi0plkappas-phi0)/kappa);
00251 z0 = vertex.getZ() - s*(cos(theta)/sin(theta));
00252
00253
00254
00255
00256 if (!isParamFixed (0)) result &= setParam (0, kappa/parfact[0]);
00257 if (!isParamFixed (1)) result &= setParam (1, phi0/parfact[1]);
00258 if (!isParamFixed (2)) result &= setParam (2, theta/parfact[2]);
00259 if (!isParamFixed (3)) result &= setParam (3, dca/parfact[3]);
00260 if (!isParamFixed (4)) result &= setParam (4, z0/parfact[4]);
00261 if (!isParamFixed (5)) result &= setParam (5, mass/parfact[5]);
00262 assert (ivertex >= 0 && 6+ivertex < NPAR);
00263 result &= setParam (6+ivertex, s/parfact[6+ivertex]);
00264 return result;
00265 }
00266
00267
00268 bool ChargedParticleTrack::setParam (int ilocal, double par_ ) {
00269 assert (ilocal >= 0 && ilocal < NPAR);
00270 if (!isfinite(par_)) return false;
00271
00272
00273
00274 switch (ilocal) {
00275
00276
00277 case 2: if (par_ < 0 || par_ >= M_PI/parfact[2]) par_ = acos (cos (par_*parfact[2]))/parfact[2];
00278 break;
00279 case 5: if (par_ < 0) par_ = abs (par_);
00280 break;
00281 }
00282 if (par[ilocal] == par_) return true;
00283 invalidateCache();
00284 par[ilocal] = par_;
00285 return true;
00286 };
00287
00288 void ChargedParticleTrack::getTrajectoryPointEx (double s, ThreeVector& p) const {
00289 if (!cachevalid) updateCache();
00290
00291 if (abs (kappa*s) < 1.e-6) {
00292 double ssq = s*s;
00293 double kssq = 0.5*kappa*ssq;
00294 double dcamikssq = dca - kssq;
00295 p.setValues ( sphi0*dcamikssq + cphi0*s,
00296 -cphi0*dcamikssq + sphi0*s,
00297 z0 + s*cottheta);
00298 }
00299 else {
00300 double kappas = kappa*s;
00301 double phi0plkappas = phi0 + kappas;
00302 double si = sin(phi0plkappas);
00303 double co = cos(phi0plkappas);
00304 p.setValues ( dcamir*sphi0 + r*si,
00305 -dcamir*cphi0 - r*co,
00306 z0 + s*cottheta);
00307 }
00308 }
00309
00310 void ChargedParticleTrack::getTrajectoryDerivativeEx (double s, int ilocal, ThreeVector& p) const {
00311 if (!cachevalid) updateCache();
00312 assert (ilocal >= 0 && ilocal < NPAR);
00313 switch (ilocal) {
00314 case 0:
00315 if (abs (kappa*s) < 1.e-6) {
00316 double ssq = s*s;
00317 p.setValues (-0.5*sphi0*ssq,
00318 0.5*cphi0*ssq,
00319 0);
00320 }
00321 else {
00322 double kappas = kappa*s;
00323 double phi0plkappas = phi0 + kappas;
00324 double si = sin(phi0plkappas);
00325 double co = cos(phi0plkappas);
00326 p.setValues ( co*kappas + sphi0 -si,
00327 si*kappas - cphi0 +co,
00328 0);
00329 }
00330 break;
00331 case 1:
00332 if (abs (kappa*s) < 1.e-6) {
00333 double ssq = s*s;
00334 double kssq = 0.5*kappa*ssq;
00335 double dcamikssq = dca - kssq;
00336 p.setValues ( cphi0*dcamikssq - sphi0*s,
00337 sphi0*dcamikssq + cphi0*s,
00338 0);
00339 }
00340 else {
00341 double kappas = kappa*s;
00342 double phi0plkappas = phi0 + kappas;
00343 p.setValues ( dcamir*cphi0 + r*cos(phi0plkappas),
00344 dcamir*sphi0 + r*sin(phi0plkappas),
00345 0);
00346 }
00347 break;
00348 case 2:
00349 p.setValues (0, 0, - s/sin2theta);
00350 break;
00351 case 3:
00352 p.setValues (sphi0, -cphi0, 0);
00353 break;
00354 case 4:
00355 p.setValues (0, 0, 1);
00356 break;
00357 case 5:
00358 p.setValues (0, 0, 0);
00359 break;
00360 case 6:
00361
00362 case 7:
00363 {
00364 double kappas = kappa*s;
00365 double phi0plkappas = phi0 + kappas;
00366 p.setValues (cos(phi0plkappas), sin(phi0plkappas), cottheta);
00367 }
00368 break;
00369 default:
00370 assert (0);
00371 }
00372 p *= parfact[ilocal];
00373 }
00374
00375 void ChargedParticleTrack::getVertexEx (int ivertex, ThreeVector& p) const {
00376 assert (ivertex >= 0 && 6+ivertex < NPAR);
00377 getTrajectoryPointEx (par[6+ivertex]*parfact[6+ivertex], p);
00378 }
00379
00380 void ChargedParticleTrack::setVertex (int ivertex, const TwoVector& p) {
00381 assert (ivertex >= 0 && 6+ivertex < NPAR);
00382 if (!cachevalid) updateCache();
00383 if (std::abs (kappa) < 1.e-8) {
00384
00385
00386
00387 double xc = sphi0*dca;
00388 double yc = -cphi0*dca;
00389 par[6+ivertex] = ((p.getX()-xc)*cphi0 + (p.getY()-yc)*sphi0)/parfact[6+ivertex];
00390 }
00391 else {
00392
00393 double xc = dcamir*sphi0;
00394 double yc = -dcamir*cphi0;
00395 double psi = (r > 0) ?
00396 std::atan2(p.getX()-xc, -p.getY()+yc) - phi0 :
00397 std::atan2(p.getX()-xc, p.getY()-yc) + phi0;
00398 par[6+ivertex] = getNormalS (std::abs(r)*psi)/parfact[6+ivertex];
00399 }
00400 }
00401
00402 void ChargedParticleTrack::getVertexDerivativeEx (int ivertex,
00403 int ilocal,
00404 ThreeVector& p) const {
00405 assert (ivertex >= 0 && 6+ivertex < NPAR);
00406 assert (ilocal >= 0 && ilocal < NPAR);
00407
00408
00409
00410 if (ilocal >= 6 && ilocal != 6+ivertex) {
00411 p.setValues (0, 0, 0);
00412 }
00413 else {
00414 getTrajectoryDerivativeEx (par[6+ivertex]*parfact[6+ivertex], ilocal, p);
00415 }
00416 }
00417
00418 void ChargedParticleTrack::getMomentumAtTrajectoryEx (double s, FourVector& p) const {
00419 if (!cachevalid) updateCache();
00420 double phi0plkappas = phi0 + kappa*s;
00421 p.setValues (energy,
00422 pt*cos(phi0plkappas),
00423 pt*sin(phi0plkappas),
00424 pt*cottheta);
00425 }
00426
00427 void ChargedParticleTrack::getMomentumEx (int ivertex, FourVector& p) const {
00428 assert (ivertex >= 0 && 6+ivertex < NPAR);
00429 getMomentumAtTrajectoryEx (par[6+ivertex]*parfact[6+ivertex], p);
00430 }
00431
00432 double ChargedParticleTrack::getCharge () const {
00433 return (kappa<0) ? charge : -charge;
00434 }
00435
00436 double ChargedParticleTrack::getMass () const {
00437 return par[5]*parfact[5];
00438 }
00439
00440 void ChargedParticleTrack::getMomentumDerivativeAtTrajectoryEx (double s, int ilocal, FourVector& p) const {
00441 if (!cachevalid) updateCache();
00442 assert (ilocal >= 0 && ilocal < NPAR);
00443 switch (ilocal) {
00444 case 0:
00445 {
00446 double kappas = kappa*s;
00447 double phi0plkappas = phi0 + kappas;
00448 double si = sin(phi0plkappas);
00449 double co = cos(phi0plkappas);
00450 p.setValues (-beta*momentum/(energy*kappa),
00451 momderfact*(co + kappas*si) ,
00452 momderfact*(si - kappas*co) ,
00453 momderfact*cottheta );
00454 }
00455 break;
00456 case 1:
00457 {
00458 double kappas = kappa*s;
00459 double phi0plkappas = phi0 + kappas;
00460 p.setValues (0, -pt*sin(phi0plkappas), pt*cos(phi0plkappas), 0);
00461 }
00462 break;
00463 case 2:
00464 p.setValues (-beta*momentum*cottheta, 0, 0, -pt/sin2theta);
00465 break;
00466 case 3:
00467 p.setValues (0, 0, 0, 0);
00468 break;
00469 case 4:
00470 p.setValues (0, 0, 0, 0);
00471 break;
00472 case 5:
00473 p.setValues (par[5]/energy, 0, 0, 0);
00474 break;
00475 case 6:
00476
00477 case 7:
00478 {
00479 double kappas = kappa*s;
00480 double phi0plkappas = phi0 + kappas;
00481 p.setValues ( 0,
00482 cBq*sin(phi0plkappas),
00483 -cBq*cos(phi0plkappas),
00484 0);
00485 }
00486 break;
00487 default:
00488 assert (0);
00489 }
00490 p *= parfact[ilocal];
00491 }
00492
00493 void ChargedParticleTrack::getMomentumDerivativeEx (int ivertex,
00494 int ilocal,
00495 FourVector& p) const {
00496 assert (ivertex >= 0 && 6+ivertex < NPAR);
00497 assert (ilocal >= 0 && ilocal < NPAR);
00498
00499
00500
00501 if (ilocal >= 6 && ilocal != 6+ivertex) {
00502 p.setValues (0, 0, 0, 0);
00503 }
00504 else {
00505 getMomentumDerivativeAtTrajectoryEx (par[6+ivertex]*parfact[6+ivertex], ilocal, p);
00506 }
00507 }
00508
00509 double ChargedParticleTrack::getArcLength (int ivertex) const {
00510 assert (ivertex >= 0 && 6+ivertex < NPAR);
00511 return par[6+ivertex]*parfact[6+ivertex];
00512 }
00513
00514 void ChargedParticleTrack::updateCache() const {
00515 kappa = par[0]*parfact[0];
00516 phi0 = par[1]*parfact[1];
00517 theta = par[2]*parfact[2];
00518 dca = par[3]*parfact[3];
00519 z0 = par[4]*parfact[4];
00520 mass = par[5]*parfact[5];
00521 sphi0 = sin(phi0);
00522 cphi0 = cos(phi0);
00523 r = (kappa != 0) ? 1/kappa : 0;
00524 dcamir = dca - r;
00525 sintheta = sin(theta);
00526 cottheta = cos(theta)/sintheta;
00527 sin2theta = sintheta*sintheta;
00528 assert (charge > 0);
00529 assert (bfield > 0);
00530 cBq = 0.002998*bfield*charge * ((kappa < 0) ? +1 : -1);
00531 pt = (kappa != 0) ? -cBq/kappa : 0;
00532 assert (kappa == 0 || pt > 0);
00533 momderfact = (kappa != 0) ? -pt/kappa : 0;
00534
00535 momentum = (sintheta != 0) ? pt/sintheta : 0;
00536
00537 energy = (kappa != 0) ?
00538 sqrt(momentum*momentum + mass*mass) :
00539 mass;
00540 beta = (energy != 0) ? momentum/energy : 0;
00541
00542 calculateChi2();
00543 cachevalid = true;
00544
00545 }
00546
00547 void ChargedParticleTrack::initCov(const float cov_[15]) {
00548 TrackFitObject::initCov();
00549
00550 int i = 0;
00551 for (int k = 0; k < 5; ++k) {
00552 for (int l = k; l < 5; ++l) {
00553 cov[k][l] = cov[l][k] = cov_[i++]/(parfact[k]*parfact[l]);
00554 }
00555 }
00556 assert (i==15);
00557
00558 TrackFitObject::checkCov();
00559 covinvvalid = false;
00560 }
00561
00562
00563 JBLHelix ChargedParticleTrack::getTangentialHelix (double) {
00564 return JBLHelix (par[0]*parfact[0],
00565 par[1]*parfact[1],
00566 par[2]*parfact[2],
00567 par[3]*parfact[3],
00568 par[4]*parfact[4]);
00569
00570
00571 }
00572
00573 double ChargedParticleTrack::getNormalS (double s) const {
00574 kappa = par[0]*parfact[0];
00575 double kappas = par[0]*parfact[0]*s;
00576 if (kappas >= -M_PI &&kappas < M_PI) return s;
00577 return std::atan2 (std::sin(kappas), std::cos (kappas))/kappa;
00578 }