CMS 3D CMS Logo

/data/git/CMSSW_5_3_11_patch5/src/TrackingTools/TrajectoryState/src/PerigeeConversions.cc

Go to the documentation of this file.
00001 #include "TrackingTools/TrajectoryState/interface/PerigeeConversions.h"
00002 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateClosestToPoint.h"
00003 #include "MagneticField/Engine/interface/MagneticField.h" 
00004 #include <cmath>
00005 
00006 PerigeeTrajectoryParameters PerigeeConversions::ftsToPerigeeParameters
00007   (const FTS& originalFTS, const GlobalPoint& referencePoint, double & pt) const
00008 
00009 {
00010   GlobalVector impactDistance = originalFTS.position() - referencePoint;
00011 
00012   pt = originalFTS.momentum().perp();
00013   if (pt==0.) throw cms::Exception("PerigeeConversions", "Track with pt=0");
00014   
00015   double theta = originalFTS.momentum().theta();
00016   double phi = originalFTS.momentum().phi();
00017   double field  = originalFTS.parameters().magneticField().inInverseGeV(originalFTS.position()).z();
00018 //   if (field==0.) throw cms::Exception("PerigeeConversions", "Field is 0") << " at " << originalFTS.position() << "\n" ;
00019 
00020   double positiveMomentumPhi = ( (phi>0) ? phi : (2*M_PI+phi) );
00021   double positionPhi = impactDistance.phi();
00022   double positivePositionPhi =
00023    ( (positionPhi>0) ? positionPhi : (2*M_PI+positionPhi) );
00024   double phiDiff = positiveMomentumPhi - positivePositionPhi;
00025   if (phiDiff<0.0) phiDiff+= (2*M_PI);
00026   double signEpsilon = ( (phiDiff > M_PI) ? -1.0 : 1.0);
00027 
00028   double epsilon = signEpsilon *
00029                      sqrt ( impactDistance.x()*impactDistance.x() +
00030                             impactDistance.y()*impactDistance.y() );
00031 
00032   // The track parameters:
00033   AlgebraicVector5 theTrackParameters;
00034 
00035   double signTC = - originalFTS.charge();
00036   bool isCharged = (signTC!=0) && (fabs(field)>1.e-10);
00037   if (isCharged) {
00038     theTrackParameters[0] = field / pt*signTC;
00039   } else {
00040     theTrackParameters[0] = 1 / pt;
00041   }
00042   theTrackParameters[1] = theta;
00043   theTrackParameters[2] = phi;
00044   theTrackParameters[3] = epsilon;
00045   theTrackParameters[4] = impactDistance.z();
00046   return PerigeeTrajectoryParameters(theTrackParameters, isCharged);
00047 }
00048 
00049 // PerigeeTrajectoryParameters PerigeeConversions::helixToPerigeeParameters
00050 //   (const reco::helix::Parameters & helixPar, const GlobalPoint& referencePoint) const
00051 // {
00052 //   AlgebraicVector theTrackParameters = AlgebraicVector(5);
00053 //   double field  = TrackingTools::FakeField::Field::inTesla(helixPar.vertex()).z() * 2.99792458e-3;
00054 //   theTrackParameters[0] = - field*helixPar.omega();
00055 //   theTrackParameters[1] = atan(1/helixPar.tanDip());
00056 //   theTrackParameters[2] = helixPar.phi0() - M_PI/2;
00057 //   theTrackParameters[3] = helixPar.d0();
00058 //   theTrackParameters[4] = helixPar.dz();
00059 //   return PerigeeTrajectoryParameters(theTrackParameters, helixPar.pt(), true);
00060 // }
00061 
00062 PerigeeTrajectoryError PerigeeConversions::ftsToPerigeeError
00063   (const FTS& originalFTS) const
00064 {
00065   AlgebraicSymMatrix55 errorMatrix = originalFTS.curvilinearError().matrix();
00066   AlgebraicMatrix55 curv2perigee = jacobianCurvilinear2Perigee(originalFTS);
00067   return PerigeeTrajectoryError(ROOT::Math::Similarity(curv2perigee,errorMatrix));
00068 }
00069 
00070 // PerigeeTrajectoryError PerigeeConversions::helixToPerigeeError
00071 //   (const reco::helix::Parameters & helixPar, 
00072 //      const reco::helix::Covariance & helixCov) const
00073 // {
00074 // //FIXME: verify that the order of the parameters are correct
00075 //   AlgebraicSymMatrix55 helixCovMatrix;
00076 //   helixCovMatrix(0,0) = helixCov(reco::helix::i_d0,reco::helix::i_d0);
00077 //   helixCovMatrix(1,1) = helixCov(reco::helix::i_phi0,reco::helix::i_phi0);
00078 //   helixCovMatrix(2,2) = helixCov(reco::helix::i_omega,reco::helix::i_omega);
00079 //   helixCovMatrix(3,3) = helixCov(reco::helix::i_dz,reco::helix::i_dz);
00080 //   helixCovMatrix(4,4) = helixCov(reco::helix::i_tanDip,reco::helix::i_tanDip);
00081 // 
00082 //   helixCovMatrix(0,1) = helixCov(reco::helix::i_d0,reco::helix::i_phi0);
00083 //   helixCovMatrix(0,2) = helixCov(reco::helix::i_d0,reco::helix::i_omega);
00084 //   helixCovMatrix(0,3) = helixCov(reco::helix::i_d0,reco::helix::i_dz);
00085 //   helixCovMatrix(0,4) = helixCov(reco::helix::i_d0,reco::helix::i_tanDip);
00086 // 
00087 //   helixCovMatrix(1,2) = helixCov(reco::helix::i_phi0,reco::helix::i_omega);
00088 //   helixCovMatrix(1,3) = helixCov(reco::helix::i_phi0,reco::helix::i_dz);
00089 //   helixCovMatrix(1,4) = helixCov(reco::helix::i_phi0,reco::helix::i_tanDip);
00090 // 
00091 //   helixCovMatrix(2,3) = helixCov(reco::helix::i_omega,reco::helix::i_dz);
00092 //   helixCovMatrix(2,4) = helixCov(reco::helix::i_omega,reco::helix::i_tanDip);
00093 // 
00094 //   helixCovMatrix(3,4) = helixCov(reco::helix::i_dz,reco::helix::i_tanDip);
00095 // 
00096 //   AlgebraicMatrix helix2perigee = jacobianHelix2Perigee(helixPar, helixCov);
00097 //   return PerigeeTrajectoryError(helixCovMatrix.similarity(helix2perigee));
00098 // }
00099 
00100 
00101 CurvilinearTrajectoryError PerigeeConversions::curvilinearError
00102   (const PerigeeTrajectoryError& perigeeError, const GlobalTrajectoryParameters& gtp) const
00103 {
00104   AlgebraicMatrix55 perigee2curv = jacobianPerigee2Curvilinear(gtp);
00105   return CurvilinearTrajectoryError(ROOT::Math::Similarity(perigee2curv, perigeeError.covarianceMatrix()));
00106 }
00107 
00108 GlobalPoint PerigeeConversions::positionFromPerigee
00109   (const PerigeeTrajectoryParameters& parameters, const GlobalPoint& referencePoint) const
00110 {
00111   AlgebraicVector5 theVector = parameters.vector();
00112   return GlobalPoint(theVector[3]*sin(theVector[2])+referencePoint.x(),
00113                      -theVector[3]*cos(theVector[2])+referencePoint.y(),
00114                      theVector[4]+referencePoint.z());
00115 }
00116 
00117 
00118 GlobalVector PerigeeConversions::momentumFromPerigee
00119   (const PerigeeTrajectoryParameters& parameters, double pt, const GlobalPoint& referencePoint) const
00120 {
00121   return GlobalVector(cos(parameters.phi()) * pt,
00122                       sin(parameters.phi()) * pt,
00123                       pt / tan(parameters.theta()));
00124 }
00125 
00126 
00127 GlobalVector PerigeeConversions::momentumFromPerigee
00128   (const AlgebraicVector3& momentum, const TrackCharge& charge, 
00129    const GlobalPoint& referencePoint, const MagneticField* field) const
00130 {
00131   double pt;
00132   if (momentum[0]==0.) throw cms::Exception("PerigeeConversions", "Track with rho=0");
00133 
00134   double bz = fabs(field->inInverseGeV(referencePoint).z());
00135   if ( charge!=0 && bz>1.e-10 ) {
00136     pt = std::abs(bz/momentum[0]);
00137     if (pt<1.e-10) throw cms::Exception("PerigeeConversions", "pt is 0");
00138   } else {
00139     pt = 1 / momentum[0];
00140   }
00141 
00142   return GlobalVector(cos(momentum[2]) * pt,
00143                       sin(momentum[2]) * pt,
00144                       pt/tan(momentum[1]));
00145 }
00146 
00147 TrackCharge PerigeeConversions::chargeFromPerigee
00148   (const PerigeeTrajectoryParameters& parameters) const
00149 {
00150   return parameters.charge();
00151 }
00152 
00153 TrajectoryStateClosestToPoint PerigeeConversions::trajectoryStateClosestToPoint
00154         (const AlgebraicVector3& momentum, const GlobalPoint& referencePoint,
00155          const TrackCharge& charge, const AlgebraicSymMatrix66& theCovarianceMatrix,
00156          const MagneticField* field) const
00157 {
00158   AlgebraicMatrix66 param2cart = jacobianParameters2Cartesian
00159         (momentum, referencePoint, charge, field);
00160   CartesianTrajectoryError cartesianTrajErr(ROOT::Math::Similarity(param2cart, theCovarianceMatrix));
00161 
00162   FTS theFTS(GlobalTrajectoryParameters(referencePoint,
00163             momentumFromPerigee(momentum, charge, referencePoint, field), charge,
00164             field), cartesianTrajErr);
00165 
00166   return TrajectoryStateClosestToPoint(theFTS, referencePoint);
00167 }
00168 
00169 
00170 AlgebraicMatrix66
00171 PerigeeConversions::jacobianParameters2Cartesian(
00172         const AlgebraicVector3& momentum, const GlobalPoint& position,
00173         const TrackCharge& charge, const MagneticField* field) const
00174 {
00175   if (momentum[0]==0.) throw cms::Exception("PerigeeConversions", "Track with rho=0");
00176   double factor = 1.;
00177   double bField = field->inInverseGeV(position).z();
00178   if (charge!=0 && fabs(bField)>1.e-10) {
00179 //     if (bField==0.) throw cms::Exception("PerigeeConversions", "Field is 0");
00180     factor = -bField*charge;
00181   }
00182   AlgebraicMatrix66 frameTransJ;
00183   frameTransJ(0,0) = 1;
00184   frameTransJ(1,1) = 1;
00185   frameTransJ(2,2) = 1;
00186   frameTransJ(3,3) = - factor * cos(momentum[2]) / (momentum[0]*momentum[0]);
00187   frameTransJ(4,3) = - factor * sin(momentum[2]) / (momentum[0]*momentum[0]);
00188   frameTransJ(5,3) = - factor / tan(momentum[1]) / (momentum[0]*momentum[0]);
00189 
00190   frameTransJ(3,5) = - factor * sin(momentum[2])  / (momentum[0]);
00191   frameTransJ(4,5) = factor * cos(momentum[2]) / (momentum[0]);
00192   frameTransJ(5,4) = - factor / (momentum[0]*sin(momentum[1])*sin(momentum[1]));
00193 
00194   return frameTransJ;
00195 }
00196 
00197 
00198 AlgebraicMatrix55
00199 PerigeeConversions::jacobianCurvilinear2Perigee(const FreeTrajectoryState& fts) const {
00200 
00201   GlobalVector p = fts.momentum();
00202 
00203   GlobalVector Z = GlobalVector(0.,0.,1.);
00204   GlobalVector T = p.unit();
00205   GlobalVector U = Z.cross(T).unit();; 
00206   GlobalVector V = T.cross(U);
00207 
00208   GlobalVector I = GlobalVector(-p.x(), -p.y(), 0.); //opposite to track dir.
00209   I = I.unit();
00210   GlobalVector J(-I.y(), I.x(),0.); //counterclockwise rotation
00211   GlobalVector K(Z);
00212   GlobalPoint x = fts.position();
00213   GlobalVector B  = fts.parameters().magneticField().inInverseGeV(x);
00214   GlobalVector H = B.unit();
00215   GlobalVector HxT = H.cross(T);
00216   GlobalVector N = HxT.unit();
00217   double alpha = HxT.mag();
00218   double qbp = fts.signedInverseMomentum();
00219   double Q = -B.mag() * qbp;
00220   double alphaQ = alpha * Q;
00221 
00222   double lambda = 0.5 * M_PI - p.theta();
00223   double coslambda = cos(lambda), tanlambda = tan(lambda);
00224 
00225   double TI = T.dot(I);
00226   double NU = N.dot(U);
00227   double NV = N.dot(V);
00228   double UI = U.dot(I);
00229   double VI = V.dot(I);
00230   double UJ = U.dot(J);
00231   double VJ = V.dot(J);
00232   double UK = U.dot(K);
00233   double VK = V.dot(K);
00234 
00235   AlgebraicMatrix55 jac;
00236 
00237   if( fabs(fts.transverseCurvature())<1.e-10 ) {
00238     jac(0,0) = 1/coslambda;
00239     jac(0,1) = tanlambda/coslambda/fts.parameters().momentum().mag();
00240   }else{
00241     double Bz = B.z();
00242     jac(0,0) = -Bz/coslambda;
00243     jac(0,1) = -Bz * tanlambda/coslambda*qbp;
00244     jac(1,3) = alphaQ * NV * UI/TI;
00245     jac(1,4) = alphaQ * NV * VI/TI;
00246     jac(0,3) = -jac(0,1) * jac(1,3);
00247     jac(0,4) = -jac(0,1) * jac(1,4);
00248     jac(2,3) = -alphaQ/coslambda * NU * UI/TI;
00249     jac(2,4) = -alphaQ/coslambda * NU * VI/TI;
00250   }
00251   jac(1,1) = -1.;
00252   jac(2,2) = 1.;
00253   jac(3,3) = VK/TI;
00254   jac(3,4) = -UK/TI;
00255   jac(4,3) = -VJ/TI;
00256   jac(4,4) = UJ/TI;
00257   
00258   return jac;
00259   
00260 }
00261 
00262 
00263 
00264 AlgebraicMatrix55 
00265 PerigeeConversions::jacobianPerigee2Curvilinear(const GlobalTrajectoryParameters& gtp) const {
00266 
00267   GlobalVector p = gtp.momentum();
00268 
00269   GlobalVector Z = GlobalVector(0.f,0.f,1.f);
00270   GlobalVector T = p.unit();
00271   GlobalVector U = Z.cross(T).unit();; 
00272   GlobalVector V = T.cross(U);
00273 
00274   GlobalVector I = GlobalVector(-p.x(), -p.y(), 0.f); //opposite to track dir.
00275   I = I.unit();
00276   GlobalVector J(-I.y(), I.x(),0.f); //counterclockwise rotation
00277   GlobalVector K(Z);
00278   GlobalPoint x = gtp.position();
00279   GlobalVector B  = gtp.magneticField().inInverseGeV(x);
00280   GlobalVector H = B.unit();
00281   GlobalVector HxT = H.cross(T);
00282   GlobalVector N = HxT.unit();
00283   double alpha = HxT.mag();
00284   double qbp = gtp.signedInverseMomentum();
00285   double Q = -B.mag() * qbp;
00286   double alphaQ = alpha * Q;
00287 
00288   double lambda = 0.5 * M_PI - p.theta();
00289   double coslambda = cos(lambda), sinlambda = sin(lambda);
00290   double mqbpt = -1./coslambda * qbp;
00291 
00292   double TJ = T.dot(J);
00293   double TK = T.dot(K);
00294   double NU = N.dot(U);
00295   double NV = N.dot(V);
00296   double UJ = U.dot(J);
00297   double VJ = V.dot(J);
00298   double UK = U.dot(K);
00299   double VK = V.dot(K);
00300 
00301   AlgebraicMatrix55 jac;
00302 
00303   if( fabs(gtp.transverseCurvature())<1.e-10f ) {
00304     jac(0,0) = coslambda;
00305     jac(0,1) = sinlambda/coslambda/gtp.momentum().mag();
00306   }else{
00307     jac(0,0) = -coslambda/B.z();
00308     jac(0,1) = -sinlambda * mqbpt;
00309     jac(1,3) = -alphaQ * NV * TJ;
00310     jac(1,4) = -alphaQ * NV * TK;
00311     jac(2,3) = -alphaQ/coslambda * NU * TJ;
00312     jac(2,4) = -alphaQ/coslambda * NU * TK;
00313   }
00314   jac(1,1) = -1.;
00315   jac(2,2) = 1.;
00316   jac(3,3) = UJ;
00317   jac(3,4) = UK;
00318   jac(4,3) = VJ;
00319   jac(4,4) = VK;
00320   
00321   return jac;
00322 }
00323 
00324 // AlgebraicMatrix 
00325 // PerigeeConversions::jacobianHelix2Perigee(const reco::helix::Parameters & helixPar, 
00326 //      const reco::helix::Covariance & helixCov) const
00327 // {
00328 //   AlgebraicMatrix55 jac;
00329 // 
00330 //   jac(3,0) = 1.;
00331 //   jac(2,1) = 1.;
00332 // //   jac(0,2) = - 1. / magField.inTesla(helixPar.vertex()).z() * 2.99792458e-3;
00333 //   jac(0,2) = - 1. / (TrackingTools::FakeField::Field::inTesla(helixPar.vertex()).z() * 2.99792458e-3);
00334 //   jac(4,3) = 1.;
00335 //   jac(1,4) = -(1. + helixPar.tanDip()*helixPar.tanDip());
00336 // std::std::cout << jac;
00337 //   return jac;
00338 // }