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 double positiveMomentumPhi = ( (phi>0) ? phi : (2*M_PI+phi) );
00020 double positionPhi = impactDistance.phi();
00021 double positivePositionPhi =
00022 ( (positionPhi>0) ? positionPhi : (2*M_PI+positionPhi) );
00023 double phiDiff = positiveMomentumPhi - positivePositionPhi;
00024 if (phiDiff<0.0) phiDiff+= (2*M_PI);
00025 double signEpsilon = ( (phiDiff > M_PI) ? -1.0 : 1.0);
00026
00027 double epsilon = signEpsilon *
00028 sqrt ( impactDistance.x()*impactDistance.x() +
00029 impactDistance.y()*impactDistance.y() );
00030
00031
00032 AlgebraicVector5 theTrackParameters;
00033
00034 double signTC = - originalFTS.charge();
00035 bool isCharged = (signTC!=0);
00036 if (isCharged) {
00037 theTrackParameters[0] = field / pt*signTC;
00038 } else {
00039 theTrackParameters[0] = 1 / pt;
00040 }
00041 theTrackParameters[1] = theta;
00042 theTrackParameters[2] = phi;
00043 theTrackParameters[3] = epsilon;
00044 theTrackParameters[4] = impactDistance.z();
00045 return PerigeeTrajectoryParameters(theTrackParameters, isCharged);
00046 }
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 PerigeeTrajectoryError PerigeeConversions::ftsToPerigeeError
00062 (const FTS& originalFTS) const
00063 {
00064 AlgebraicSymMatrix55 errorMatrix = originalFTS.curvilinearError().matrix();
00065 AlgebraicMatrix55 curv2perigee = jacobianCurvilinear2Perigee(originalFTS);
00066 return PerigeeTrajectoryError(ROOT::Math::Similarity(curv2perigee,errorMatrix));
00067 }
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 CurvilinearTrajectoryError PerigeeConversions::curvilinearError
00101 (const PerigeeTrajectoryError& perigeeError, const GlobalTrajectoryParameters& gtp) const
00102 {
00103 AlgebraicMatrix55 perigee2curv = jacobianPerigee2Curvilinear(gtp);
00104 return CurvilinearTrajectoryError(ROOT::Math::Similarity(perigee2curv, perigeeError.covarianceMatrix()));
00105 }
00106
00107 GlobalPoint PerigeeConversions::positionFromPerigee
00108 (const PerigeeTrajectoryParameters& parameters, const GlobalPoint& referencePoint) const
00109 {
00110 AlgebraicVector5 theVector = parameters.vector();
00111 return GlobalPoint(theVector[3]*sin(theVector[2])+referencePoint.x(),
00112 -theVector[3]*cos(theVector[2])+referencePoint.y(),
00113 theVector[4]+referencePoint.z());
00114 }
00115
00116
00117 GlobalVector PerigeeConversions::momentumFromPerigee
00118 (const PerigeeTrajectoryParameters& parameters, double pt, const GlobalPoint& referencePoint) const
00119 {
00120 return GlobalVector(cos(parameters.phi()) * pt,
00121 sin(parameters.phi()) * pt,
00122 pt / tan(parameters.theta()));
00123 }
00124
00125 GlobalVector PerigeeConversions::momentumFromPerigee
00126 (const AlgebraicVector& momentum, const TrackCharge& charge,
00127 const GlobalPoint& referencePoint, const MagneticField* field) const {
00128 return momentumFromPerigee(asSVector<3>(momentum), charge, referencePoint, field);
00129 }
00130
00131 GlobalVector PerigeeConversions::momentumFromPerigee
00132 (const AlgebraicVector3& momentum, const TrackCharge& charge,
00133 const GlobalPoint& referencePoint, const MagneticField* field) const
00134 {
00135 double pt;
00136 if (momentum[0]==0.) throw cms::Exception("PerigeeConversions", "Track with rho=0");
00137
00138 if (charge!=0) {
00139 pt = std::abs(field->inInverseGeV(referencePoint).z() / momentum[0]);
00140 } else {
00141 pt = 1 / momentum[0];
00142 }
00143 return GlobalVector(cos(momentum[2]) * pt,
00144 sin(momentum[2]) * pt,
00145 pt/tan(momentum[1]));
00146 }
00147
00148 TrackCharge PerigeeConversions::chargeFromPerigee
00149 (const PerigeeTrajectoryParameters& parameters) const
00150 {
00151 return parameters.charge();
00152 }
00153
00154 TrajectoryStateClosestToPoint PerigeeConversions::trajectoryStateClosestToPoint
00155 (const AlgebraicVector& momentum, const GlobalPoint& referencePoint,
00156 const TrackCharge& charge, const AlgebraicMatrix& theCovarianceMatrix,
00157 const MagneticField* field) const {
00158 AlgebraicSymMatrix sym; sym.assign(theCovarianceMatrix);
00159 return trajectoryStateClosestToPoint(asSVector<3>(momentum), referencePoint,
00160 charge, asSMatrix<6>(sym), field);
00161
00162 }
00163
00164
00165 TrajectoryStateClosestToPoint PerigeeConversions::trajectoryStateClosestToPoint
00166 (const AlgebraicVector3& momentum, const GlobalPoint& referencePoint,
00167 const TrackCharge& charge, const AlgebraicSymMatrix66& theCovarianceMatrix,
00168 const MagneticField* field) const
00169 {
00170 AlgebraicMatrix66 param2cart = jacobianParameters2Cartesian
00171 (momentum, referencePoint, charge, field);
00172 CartesianTrajectoryError cartesianTrajErr(ROOT::Math::Similarity(param2cart, theCovarianceMatrix));
00173
00174 FTS theFTS(GlobalTrajectoryParameters(referencePoint,
00175 momentumFromPerigee(momentum, charge, referencePoint, field), charge,
00176 field), cartesianTrajErr);
00177
00178 return TrajectoryStateClosestToPoint(theFTS, referencePoint);
00179 }
00180
00181 AlgebraicMatrix
00182 PerigeeConversions::jacobianParameters2Cartesian_old(
00183 const AlgebraicVector& momentum, const GlobalPoint& position,
00184 const TrackCharge& charge, const MagneticField* field) const {
00185 return asHepMatrix(jacobianParameters2Cartesian(asSVector<3>(momentum), position, charge, field));
00186 }
00187
00188 AlgebraicMatrix66
00189 PerigeeConversions::jacobianParameters2Cartesian(
00190 const AlgebraicVector3& momentum, const GlobalPoint& position,
00191 const TrackCharge& charge, const MagneticField* field) const
00192 {
00193 if (momentum[0]==0.) throw cms::Exception("PerigeeConversions", "Track with rho=0");
00194 double factor = 1.;
00195 if (charge!=0) {
00196 double bField = field->inInverseGeV(position).z();
00197 factor = -bField*charge;
00198 }
00199 AlgebraicMatrix66 frameTransJ;
00200 frameTransJ(0,0) = 1;
00201 frameTransJ(1,1) = 1;
00202 frameTransJ(2,2) = 1;
00203 frameTransJ(3,3) = - factor * cos(momentum[2]) / (momentum[0]*momentum[0]);
00204 frameTransJ(4,3) = - factor * sin(momentum[2]) / (momentum[0]*momentum[0]);
00205 frameTransJ(5,3) = - factor / tan(momentum[1]) / (momentum[0]*momentum[0]);
00206
00207 frameTransJ(3,5) = - factor * sin(momentum[2]) / (momentum[0]);
00208 frameTransJ(4,5) = factor * cos(momentum[2]) / (momentum[0]);
00209 frameTransJ(5,4) = - factor / (momentum[0]*sin(momentum[1])*sin(momentum[1]));
00210
00211 return frameTransJ;
00212 }
00213
00214 AlgebraicMatrix
00215 PerigeeConversions::jacobianCurvilinear2Perigee_old(const FreeTrajectoryState& fts) const {
00216 return asHepMatrix(jacobianCurvilinear2Perigee(fts));
00217 }
00218
00219
00220 AlgebraicMatrix55
00221 PerigeeConversions::jacobianCurvilinear2Perigee(const FreeTrajectoryState& fts) const {
00222
00223 GlobalVector p = fts.momentum();
00224
00225 GlobalVector Z = GlobalVector(0.,0.,1.);
00226 GlobalVector T = p.unit();
00227 GlobalVector U = Z.cross(T).unit();;
00228 GlobalVector V = T.cross(U);
00229
00230 GlobalVector I = GlobalVector(-p.x(), -p.y(), 0.);
00231 I = I.unit();
00232 GlobalVector J(-I.y(), I.x(),0.);
00233 GlobalVector K(Z);
00234 GlobalPoint x = fts.position();
00235 GlobalVector B = fts.parameters().magneticField().inInverseGeV(x);
00236 GlobalVector H = B.unit();
00237 GlobalVector HxT = H.cross(T);
00238 GlobalVector N = HxT.unit();
00239 double alpha = HxT.mag();
00240 double qbp = fts.signedInverseMomentum();
00241 double Q = -B.mag() * qbp;
00242 double alphaQ = alpha * Q;
00243
00244 double lambda = 0.5 * M_PI - p.theta();
00245 double coslambda = cos(lambda), tanlambda = tan(lambda);
00246
00247 double TI = T.dot(I);
00248 double NU = N.dot(U);
00249 double NV = N.dot(V);
00250 double UI = U.dot(I);
00251 double VI = V.dot(I);
00252 double UJ = U.dot(J);
00253 double VJ = V.dot(J);
00254 double UK = U.dot(K);
00255 double VK = V.dot(K);
00256
00257 AlgebraicMatrix55 jac;
00258
00259 if( fabs(fts.transverseCurvature())<1.e-10 ) {
00260 jac(0,0) = 1/coslambda;
00261 jac(0,1) = tanlambda/coslambda/fts.parameters().momentum().mag();
00262 }else{
00263 double Bz = B.z();
00264 jac(0,0) = -Bz/coslambda;
00265 jac(0,1) = -Bz * tanlambda/coslambda*qbp;
00266 jac(1,3) = alphaQ * NV * UI/TI;
00267 jac(1,4) = alphaQ * NV * VI/TI;
00268 jac(0,3) = -jac(0,1) * jac(1,3);
00269 jac(0,4) = -jac(0,1) * jac(1,4);
00270 jac(2,3) = -alphaQ/coslambda * NU * UI/TI;
00271 jac(2,4) = -alphaQ/coslambda * NU * VI/TI;
00272 }
00273 jac(1,1) = -1.;
00274 jac(2,2) = 1.;
00275 jac(3,3) = VK/TI;
00276 jac(3,4) = -UK/TI;
00277 jac(4,3) = -VJ/TI;
00278 jac(4,4) = UJ/TI;
00279
00280 return jac;
00281
00282 }
00283
00284
00285 AlgebraicMatrix
00286 PerigeeConversions::jacobianPerigee2Curvilinear_old(const GlobalTrajectoryParameters& gtp) const {
00287 return asHepMatrix(jacobianPerigee2Curvilinear(gtp));
00288 }
00289
00290 AlgebraicMatrix55
00291 PerigeeConversions::jacobianPerigee2Curvilinear(const GlobalTrajectoryParameters& gtp) const {
00292
00293 GlobalVector p = gtp.momentum();
00294
00295 GlobalVector Z = GlobalVector(0.,0.,1.);
00296 GlobalVector T = p.unit();
00297 GlobalVector U = Z.cross(T).unit();;
00298 GlobalVector V = T.cross(U);
00299
00300 GlobalVector I = GlobalVector(-p.x(), -p.y(), 0.);
00301 I = I.unit();
00302 GlobalVector J(-I.y(), I.x(),0.);
00303 GlobalVector K(Z);
00304 GlobalPoint x = gtp.position();
00305 GlobalVector B = gtp.magneticField().inInverseGeV(x);
00306 GlobalVector H = B.unit();
00307 GlobalVector HxT = H.cross(T);
00308 GlobalVector N = HxT.unit();
00309 double alpha = HxT.mag();
00310 double qbp = gtp.signedInverseMomentum();
00311 double Q = -B.mag() * qbp;
00312 double alphaQ = alpha * Q;
00313
00314 double lambda = 0.5 * M_PI - p.theta();
00315 double coslambda = cos(lambda), sinlambda = sin(lambda);
00316 double mqbpt = -1./coslambda * qbp;
00317
00318 double TJ = T.dot(J);
00319 double TK = T.dot(K);
00320 double NU = N.dot(U);
00321 double NV = N.dot(V);
00322 double UJ = U.dot(J);
00323 double VJ = V.dot(J);
00324 double UK = U.dot(K);
00325 double VK = V.dot(K);
00326
00327 AlgebraicMatrix55 jac;
00328
00329 if( fabs(gtp.transverseCurvature())<1.e-10 ) {
00330 jac(0,0) = coslambda;
00331 jac(0,1) = sinlambda/coslambda/gtp.momentum().mag();
00332 }else{
00333 jac(0,0) = -coslambda/B.z();
00334 jac(0,1) = -sinlambda * mqbpt;
00335 jac(1,3) = -alphaQ * NV * TJ;
00336 jac(1,4) = -alphaQ * NV * TK;
00337 jac(2,3) = -alphaQ/coslambda * NU * TJ;
00338 jac(2,4) = -alphaQ/coslambda * NU * TK;
00339 }
00340 jac(1,1) = -1.;
00341 jac(2,2) = 1.;
00342 jac(3,3) = UJ;
00343 jac(3,4) = UK;
00344 jac(4,3) = VJ;
00345 jac(4,4) = VK;
00346
00347 return jac;
00348 }
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364