CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_1/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 #include <vdt/vdtMath.h>
00006 
00007 PerigeeTrajectoryParameters PerigeeConversions::ftsToPerigeeParameters
00008   (const FTS& originalFTS, const GlobalPoint& referencePoint, double & pt)
00009 
00010 {
00011   GlobalVector impactDistance = originalFTS.position() - referencePoint;
00012 
00013   pt = originalFTS.momentum().perp();
00014   if (pt==0.) throw cms::Exception("PerigeeConversions", "Track with pt=0");
00015   
00016   double theta = originalFTS.momentum().theta();
00017   double phi = originalFTS.momentum().phi();
00018   double field  = originalFTS.parameters().magneticField().inInverseGeV(originalFTS.position()).z();
00019 //   if (field==0.) throw cms::Exception("PerigeeConversions", "Field is 0") << " at " << originalFTS.position() << "\n" ;
00020 
00021   double positiveMomentumPhi = ( (phi>0) ? phi : (2*M_PI+phi) );
00022   double positionPhi = impactDistance.phi();
00023   double positivePositionPhi =
00024    ( (positionPhi>0) ? positionPhi : (2*M_PI+positionPhi) );
00025   double phiDiff = positiveMomentumPhi - positivePositionPhi;
00026   if (phiDiff<0.0) phiDiff+= (2*M_PI);
00027   double signEpsilon = ( (phiDiff > M_PI) ? -1.0 : 1.0);
00028 
00029   double epsilon = signEpsilon *
00030                      sqrt ( impactDistance.x()*impactDistance.x() +
00031                             impactDistance.y()*impactDistance.y() );
00032 
00033   // The track parameters:
00034   AlgebraicVector5 theTrackParameters;
00035 
00036   double signTC = - originalFTS.charge();
00037   bool isCharged = (signTC!=0) && (std::abs(field)>1.e-10);
00038   if (isCharged) {
00039     theTrackParameters[0] = field / pt*signTC;
00040   } else {
00041     theTrackParameters[0] = 1 / pt;
00042   }
00043   theTrackParameters[1] = theta;
00044   theTrackParameters[2] = phi;
00045   theTrackParameters[3] = epsilon;
00046   theTrackParameters[4] = impactDistance.z();
00047   return PerigeeTrajectoryParameters(theTrackParameters, isCharged);
00048 }
00049 
00050 
00051 PerigeeTrajectoryError PerigeeConversions::ftsToPerigeeError
00052   (const FTS& originalFTS)
00053 {
00054   AlgebraicSymMatrix55 errorMatrix = originalFTS.curvilinearError().matrix();
00055   AlgebraicMatrix55 curv2perigee = jacobianCurvilinear2Perigee(originalFTS);
00056   return PerigeeTrajectoryError(ROOT::Math::Similarity(curv2perigee,errorMatrix));
00057 }
00058 
00059 
00060 CurvilinearTrajectoryError PerigeeConversions::curvilinearError
00061   (const PerigeeTrajectoryError& perigeeError, const GlobalTrajectoryParameters& gtp)
00062 {
00063   AlgebraicMatrix55 perigee2curv = jacobianPerigee2Curvilinear(gtp);
00064   return CurvilinearTrajectoryError(ROOT::Math::Similarity(perigee2curv, perigeeError.covarianceMatrix()));
00065 }
00066 
00067 GlobalPoint PerigeeConversions::positionFromPerigee
00068   (const PerigeeTrajectoryParameters& parameters, const GlobalPoint& referencePoint)
00069 {
00070   AlgebraicVector5 theVector = parameters.vector();
00071   return GlobalPoint(theVector[3]*vdt::fast_sin(theVector[2])+referencePoint.x(),
00072                      -theVector[3]*vdt::fast_cos(theVector[2])+referencePoint.y(),
00073                      theVector[4]+referencePoint.z());
00074 }
00075 
00076 
00077 GlobalVector PerigeeConversions::momentumFromPerigee
00078   (const PerigeeTrajectoryParameters& parameters, double pt, const GlobalPoint& referencePoint)
00079 {
00080   return GlobalVector(vdt::fast_cos(parameters.phi()) * pt,
00081                       vdt::fast_sin(parameters.phi()) * pt,
00082                       pt /vdt::fast_tan(parameters.theta()));
00083 }
00084 
00085 
00086 GlobalVector PerigeeConversions::momentumFromPerigee
00087   (const AlgebraicVector3& momentum, const TrackCharge& charge, 
00088    const GlobalPoint& referencePoint, const MagneticField* field)
00089 {
00090   double pt;
00091 
00092   double bz = fabs(field->inInverseGeV(referencePoint).z());
00093   if ( charge!=0 && std::abs(bz)>1.e-10 ) {
00094     pt = std::abs(bz/momentum[0]);
00095     // if (pt<1.e-10) throw cms::Exception("PerigeeConversions", "pt is 0");
00096   } else {
00097     pt = 1 / momentum[0];
00098   }
00099 
00100   return GlobalVector(vdt::fast_cos(momentum[2]) * pt,
00101                       vdt::fast_sin(momentum[2]) * pt,
00102                       pt/vdt::fast_tan(momentum[1]));
00103 }
00104 
00105 
00106 TrajectoryStateClosestToPoint PerigeeConversions::trajectoryStateClosestToPoint
00107         (const AlgebraicVector3& momentum, const GlobalPoint& referencePoint,
00108          const TrackCharge& charge, const AlgebraicSymMatrix66& theCovarianceMatrix,
00109          const MagneticField* field)
00110 {
00111   AlgebraicMatrix66 param2cart = jacobianParameters2Cartesian
00112         (momentum, referencePoint, charge, field);
00113   CartesianTrajectoryError cartesianTrajErr(ROOT::Math::Similarity(param2cart, theCovarianceMatrix));
00114 
00115   FTS theFTS(GlobalTrajectoryParameters(referencePoint,
00116             momentumFromPerigee(momentum, charge, referencePoint, field), charge,
00117             field), cartesianTrajErr);
00118 
00119   return TrajectoryStateClosestToPoint(theFTS, referencePoint);
00120 }
00121 
00122 
00123 AlgebraicMatrix66
00124 PerigeeConversions::jacobianParameters2Cartesian(
00125         const AlgebraicVector3& momentum, const GlobalPoint& position,
00126         const TrackCharge& charge, const MagneticField* field)
00127 {
00128   float factor = -1.;
00129   float bField = field->inInverseGeV(position).z();
00130   if (charge!=0 && std::abs(bField)>1.e-10f)
00131     factor = bField*charge;
00132  
00133 
00134   float s1,c1; vdt::fast_sincosf(momentum[1],s1,c1);
00135   float s2,c2; vdt::fast_sincosf(momentum[2],s2,c2);
00136   float f1 = factor/(momentum[0]*momentum[0]);
00137   float f2 = factor/momentum[0];
00138 
00139   AlgebraicMatrix66 frameTransJ;
00140   frameTransJ(0,0) = 1;
00141   frameTransJ(1,1) = 1;
00142   frameTransJ(2,2) = 1;
00143   frameTransJ(3,3) =  (f1 * c2); 
00144   frameTransJ(4,3) =  (f1 * s2);
00145   frameTransJ(5,3) =  (f1*c1/s1);  
00146 
00147   frameTransJ(3,5) = (f2 * s2);
00148   frameTransJ(4,5) = -(f2 * c2);
00149   frameTransJ(5,4) = (f2/(s1*s1));
00150 
00151   return frameTransJ;
00152 }
00153 
00154 
00155 AlgebraicMatrix55
00156 PerigeeConversions::jacobianCurvilinear2Perigee(const FreeTrajectoryState& fts){
00157 
00158   GlobalVector p = fts.momentum();
00159 
00160   GlobalVector Z = GlobalVector(0.,0.,1.);
00161   GlobalVector T = p.unit();
00162   GlobalVector U = Z.cross(T).unit();; 
00163   GlobalVector V = T.cross(U);
00164 
00165   GlobalVector I = GlobalVector(-p.x(), -p.y(), 0.); //opposite to track dir.
00166   I = I.unit();
00167   GlobalVector J(-I.y(), I.x(),0.); //counterclockwise rotation
00168   GlobalVector K(Z);
00169   GlobalPoint x = fts.position();
00170   GlobalVector B  = fts.parameters().magneticField().inInverseGeV(x);
00171   GlobalVector H = B.unit();
00172   GlobalVector HxT = H.cross(T);
00173   GlobalVector N = HxT.unit();
00174   double alpha = HxT.mag();
00175   double qbp = fts.signedInverseMomentum();
00176   double Q = -B.mag() * qbp;
00177   double alphaQ = alpha * Q;
00178 
00179   double lambda = 0.5 * M_PI - p.theta();
00180   double sinlambda, coslambda;  vdt::fast_sincos(lambda, sinlambda, coslambda);
00181   double seclambda = 1./coslambda;
00182 
00183   double ITI = 1./T.dot(I);
00184   double NU = N.dot(U);
00185   double NV = N.dot(V);
00186   double UI = U.dot(I);
00187   double VI = V.dot(I);
00188   double UJ = U.dot(J);
00189   double VJ = V.dot(J);
00190   double UK = U.dot(K);
00191   double VK = V.dot(K);
00192 
00193   AlgebraicMatrix55 jac;
00194 
00195   if( fabs(fts.transverseCurvature())<1.e-10 ) {
00196     jac(0,0) = seclambda;
00197     jac(0,1) = sinlambda*seclambda*seclambda*std::abs(qbp);
00198   }else{
00199     double Bz = B.z();
00200     jac(0,0) = -Bz * seclambda;
00201     jac(0,1) = -Bz * sinlambda*seclambda*seclambda*qbp;
00202     jac(1,3) = alphaQ * NV * UI*ITI;
00203     jac(1,4) = alphaQ * NV * VI*ITI;
00204     jac(0,3) = -jac(0,1) * jac(1,3);
00205     jac(0,4) = -jac(0,1) * jac(1,4);
00206     jac(2,3) = -alphaQ*seclambda * NU * UI*ITI;
00207     jac(2,4) = -alphaQ*seclambda * NU * VI*ITI;
00208   }
00209   jac(1,1) = -1.;
00210   jac(2,2) = 1.;
00211   jac(3,3) = VK*ITI;
00212   jac(3,4) = -UK*ITI;
00213   jac(4,3) = -VJ*ITI;
00214   jac(4,4) = UJ*ITI;
00215   
00216   return jac;
00217   
00218 }
00219 
00220 
00221 
00222 AlgebraicMatrix55 
00223 PerigeeConversions::jacobianPerigee2Curvilinear(const GlobalTrajectoryParameters& gtp) {
00224 
00225   GlobalVector p = gtp.momentum();
00226 
00227   GlobalVector Z = GlobalVector(0.f,0.f,1.f);
00228   GlobalVector T = p.unit();
00229   GlobalVector U = Z.cross(T).unit();; 
00230   GlobalVector V = T.cross(U);
00231 
00232   GlobalVector I = GlobalVector(-p.x(), -p.y(), 0.f); //opposite to track dir.
00233   I = I.unit();
00234   GlobalVector J(-I.y(), I.x(),0.f); //counterclockwise rotation
00235   GlobalVector K(Z);
00236   GlobalPoint x = gtp.position();
00237   GlobalVector B  = gtp.magneticField().inInverseGeV(x);
00238   GlobalVector H = B.unit();
00239   GlobalVector HxT = H.cross(T);
00240   GlobalVector N = HxT.unit();
00241   double alpha = HxT.mag();
00242   double qbp = gtp.signedInverseMomentum();
00243   double Q = -B.mag() * qbp;
00244   double alphaQ = alpha * Q;
00245 
00246 
00247   double lambda = 0.5 * M_PI - p.theta();
00248   double sinlambda, coslambda;  vdt::fast_sincos(lambda, sinlambda, coslambda);
00249   double seclambda = 1./coslambda;
00250 
00251   double mqbpt = -1./coslambda * qbp;
00252 
00253   double TJ = T.dot(J);
00254   double TK = T.dot(K);
00255   double NU = N.dot(U);
00256   double NV = N.dot(V);
00257   double UJ = U.dot(J);
00258   double VJ = V.dot(J);
00259   double UK = U.dot(K);
00260   double VK = V.dot(K);
00261 
00262   AlgebraicMatrix55 jac;
00263 
00264   if( fabs(gtp.transverseCurvature())<1.e-10f ) {
00265     jac(0,0) = coslambda;
00266     jac(0,1) = sinlambda/coslambda/gtp.momentum().mag();
00267   }else{
00268     jac(0,0) = -coslambda/B.z();
00269     jac(0,1) = -sinlambda * mqbpt;
00270     jac(1,3) = -alphaQ * NV * TJ;
00271     jac(1,4) = -alphaQ * NV * TK;
00272     jac(2,3) = -alphaQ*seclambda * NU * TJ;
00273     jac(2,4) = -alphaQ*seclambda * NU * TK;
00274   }
00275   jac(1,1) = -1.;
00276   jac(2,2) = 1.;
00277   jac(3,3) = UJ;
00278   jac(3,4) = UK;
00279   jac(4,3) = VJ;
00280   jac(4,4) = VK;
00281   
00282   return jac;
00283 }
00284