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

ChargedParticleTrack.C

Go to the documentation of this file.
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;    // charge_ is signed, charge is not!
00099   kappa = -cBq/momentum.getPt();
00100   r = 1/kappa;
00101   theta = momentum.getTheta();
00102   double phi0plkappas = momentum.getPhi();
00103 //  double phi0plkappas = atan2 (momentum.getPy(), momentum.getPx());
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   // rc is the distance of the circle's center to the origin
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 //   cout << "ChargedParticleTrack::ChargedParticleTrack"
00120 //        << "\nvertex = " << vertex << ", momentum = " << momentum
00121 //        << "\ncBq=" << cBq << ", kappa=" << kappa << ", r=" << r << ", theta=" << theta 
00122 //        << "\nphi0plkappas=" << phi0plkappas << ", si=" << si << ", co=" << co << ", phi0=" << phi0 
00123 //        << "\nxc=" << xc << ", yc=" << yc 
00124 //        << endl;
00125        
00126   // if (phi0plkappas - phi0 < -1.57) phi0plkappas += 6.2831853;
00127   double sstart = (phi0plkappas-phi0)/kappa;
00128 //   cout << "sstart = " << sstart;
00129   if (sstart < -1.57*abs(r)) sstart += 6.2831853*abs(r);
00130 //   cout << " => sstart = " << sstart << endl;
00131     
00132   double z0 = vertex.getZ()  - sstart*(cos(theta)/sin(theta));
00133 
00134 //   cout << "rc = " << rc << ", dca = " << dca << ", z0 = " << z0 << endl << endl;
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 //  double phi0plkappas = atan2 (momentum.getPy(), momentum.getPx());
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   // rc is the distance of the circle's center to the origin
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 //   cout << "ChargedParticleTrack::setParameters"
00243 //        << "\nvertex = " << vertex << ", momentum = " << momentum
00244 //        << "\ncBq=" << cBq << ", kappa=" << kappa << ", r=" << r << ", theta=" << theta 
00245 //        << "\nphi0plkappas=" << phi0plkappas << ", si=" << si << ", co=" << co << ", phi0=" << phi0 
00246 //        << "\nxc=" << xc << ", yc=" << yc 
00247 //        << endl;
00248        
00249   // if (phi0plkappas - phi0 < -1.57) phi0plkappas += 6.2831853;
00250   double s = getNormalS((phi0plkappas-phi0)/kappa);
00251   z0 = vertex.getZ()  - s*(cos(theta)/sin(theta));
00252 
00253 //   cout << "rc = " << rc << ", dca = " << dca << ", z0 = " << z0 << endl << endl;
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   // enforce parameter range restrictions
00272   // dont restrict phi0 to -pi ... pi, because otherwise residual calculation
00273   // becomes too complicated!
00274   switch (ilocal) {
00275    // case 1:  if (abs(par_) > M_PI) par_ = atan2 (sin (par_), cos (par_)); // -pi <= phi0 <= pi
00276    //   break;
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, // bug fixed! BL 4.1.05
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: // d / d par[0] = d / d kappa * kappafact
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: // d / d phi0
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: // d / d theta
00349       p.setValues (0, 0, - s/sin2theta);          
00350       break;
00351     case 3: // d / d dca
00352       p.setValues (sphi0, -cphi0, 0);          
00353       break;
00354     case 4: // d / d z0
00355       p.setValues (0, 0, 1);  
00356       break;
00357     case 5: // d / d mass
00358       p.setValues (0, 0, 0);  
00359       break;
00360     case 6: // d / d s 
00361             // fall through 
00362     case 7: // d / d s
00363       {
00364         double kappas = kappa*s;
00365         double phi0plkappas = phi0 + kappas;
00366         p.setValues (cos(phi0plkappas), sin(phi0plkappas), cottheta);   
00367       }
00368       break;
00369     default: // should never happen!
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     // If helix is almost a straight line,
00385     // treat it as straight line here.
00386     // Get point of closest approach to origin
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     // Get center of circle
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   // Check: Parameters 6 and 7 are sstart and sstop.
00408   // Start vertex does not depend on par[6], 
00409   // stop vertex does not depend on par[5]
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: // d / d par[0] = d / d kappa * kappafact
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: // d / d phi0
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: // d / d theta
00464       p.setValues (-beta*momentum*cottheta, 0, 0, -pt/sin2theta);          
00465       break;
00466     case 3: // d / d dca
00467       p.setValues (0, 0, 0, 0);          
00468       break;
00469     case 4: // d / d z0
00470       p.setValues (0, 0, 0, 0);  
00471       break;
00472     case 5: // d / d mass
00473       p.setValues (par[5]/energy, 0, 0, 0);  
00474       break;
00475     case 6: // d / d s 
00476             // fall through 
00477     case 7: // d / d s
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: // should never happen!
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   // Check: Parameters 6 and 7 are sstart ans sstop.
00499   // Start vertex does not depend on par[6], 
00500   // stop vertex does not depend on par[5]
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   // assert (momentum > 0);
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 }

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