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
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
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
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
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
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
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
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.);
00209 I = I.unit();
00210 GlobalVector J(-I.y(), I.x(),0.);
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);
00275 I = I.unit();
00276 GlobalVector J(-I.y(), I.x(),0.f);
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
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338