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 GlobalVector PerigeeConversions::momentumFromPerigee
00127 (const AlgebraicVector& momentum, const TrackCharge& charge,
00128 const GlobalPoint& referencePoint, const MagneticField* field) const {
00129 return momentumFromPerigee(asSVector<3>(momentum), charge, referencePoint, field);
00130 }
00131
00132 GlobalVector PerigeeConversions::momentumFromPerigee
00133 (const AlgebraicVector3& momentum, const TrackCharge& charge,
00134 const GlobalPoint& referencePoint, const MagneticField* field) const
00135 {
00136 double pt;
00137 if (momentum[0]==0.) throw cms::Exception("PerigeeConversions", "Track with rho=0");
00138
00139 double bz = fabs(field->inInverseGeV(referencePoint).z());
00140 if ( charge!=0 && bz>1.e-10 ) {
00141 pt = std::abs(bz/momentum[0]);
00142 if (pt<1.e-10) throw cms::Exception("PerigeeConversions", "pt is 0");
00143 } else {
00144 pt = 1 / momentum[0];
00145 }
00146
00147 return GlobalVector(cos(momentum[2]) * pt,
00148 sin(momentum[2]) * pt,
00149 pt/tan(momentum[1]));
00150 }
00151
00152 TrackCharge PerigeeConversions::chargeFromPerigee
00153 (const PerigeeTrajectoryParameters& parameters) const
00154 {
00155 return parameters.charge();
00156 }
00157
00158 TrajectoryStateClosestToPoint PerigeeConversions::trajectoryStateClosestToPoint
00159 (const AlgebraicVector& momentum, const GlobalPoint& referencePoint,
00160 const TrackCharge& charge, const AlgebraicMatrix& theCovarianceMatrix,
00161 const MagneticField* field) const {
00162 AlgebraicSymMatrix sym; sym.assign(theCovarianceMatrix);
00163 return trajectoryStateClosestToPoint(asSVector<3>(momentum), referencePoint,
00164 charge, asSMatrix<6>(sym), field);
00165
00166 }
00167
00168
00169 TrajectoryStateClosestToPoint PerigeeConversions::trajectoryStateClosestToPoint
00170 (const AlgebraicVector3& momentum, const GlobalPoint& referencePoint,
00171 const TrackCharge& charge, const AlgebraicSymMatrix66& theCovarianceMatrix,
00172 const MagneticField* field) const
00173 {
00174 AlgebraicMatrix66 param2cart = jacobianParameters2Cartesian
00175 (momentum, referencePoint, charge, field);
00176 CartesianTrajectoryError cartesianTrajErr(ROOT::Math::Similarity(param2cart, theCovarianceMatrix));
00177
00178 FTS theFTS(GlobalTrajectoryParameters(referencePoint,
00179 momentumFromPerigee(momentum, charge, referencePoint, field), charge,
00180 field), cartesianTrajErr);
00181
00182 return TrajectoryStateClosestToPoint(theFTS, referencePoint);
00183 }
00184
00185 AlgebraicMatrix
00186 PerigeeConversions::jacobianParameters2Cartesian_old(
00187 const AlgebraicVector& momentum, const GlobalPoint& position,
00188 const TrackCharge& charge, const MagneticField* field) const {
00189 return asHepMatrix(jacobianParameters2Cartesian(asSVector<3>(momentum), position, charge, field));
00190 }
00191
00192 AlgebraicMatrix66
00193 PerigeeConversions::jacobianParameters2Cartesian(
00194 const AlgebraicVector3& momentum, const GlobalPoint& position,
00195 const TrackCharge& charge, const MagneticField* field) const
00196 {
00197 if (momentum[0]==0.) throw cms::Exception("PerigeeConversions", "Track with rho=0");
00198 double factor = 1.;
00199 double bField = field->inInverseGeV(position).z();
00200 if (charge!=0 && fabs(bField)>1.e-10) {
00201
00202 factor = -bField*charge;
00203 }
00204 AlgebraicMatrix66 frameTransJ;
00205 frameTransJ(0,0) = 1;
00206 frameTransJ(1,1) = 1;
00207 frameTransJ(2,2) = 1;
00208 frameTransJ(3,3) = - factor * cos(momentum[2]) / (momentum[0]*momentum[0]);
00209 frameTransJ(4,3) = - factor * sin(momentum[2]) / (momentum[0]*momentum[0]);
00210 frameTransJ(5,3) = - factor / tan(momentum[1]) / (momentum[0]*momentum[0]);
00211
00212 frameTransJ(3,5) = - factor * sin(momentum[2]) / (momentum[0]);
00213 frameTransJ(4,5) = factor * cos(momentum[2]) / (momentum[0]);
00214 frameTransJ(5,4) = - factor / (momentum[0]*sin(momentum[1])*sin(momentum[1]));
00215
00216 return frameTransJ;
00217 }
00218
00219 AlgebraicMatrix
00220 PerigeeConversions::jacobianCurvilinear2Perigee_old(const FreeTrajectoryState& fts) const {
00221 return asHepMatrix(jacobianCurvilinear2Perigee(fts));
00222 }
00223
00224
00225 AlgebraicMatrix55
00226 PerigeeConversions::jacobianCurvilinear2Perigee(const FreeTrajectoryState& fts) const {
00227
00228 GlobalVector p = fts.momentum();
00229
00230 GlobalVector Z = GlobalVector(0.,0.,1.);
00231 GlobalVector T = p.unit();
00232 GlobalVector U = Z.cross(T).unit();;
00233 GlobalVector V = T.cross(U);
00234
00235 GlobalVector I = GlobalVector(-p.x(), -p.y(), 0.);
00236 I = I.unit();
00237 GlobalVector J(-I.y(), I.x(),0.);
00238 GlobalVector K(Z);
00239 GlobalPoint x = fts.position();
00240 GlobalVector B = fts.parameters().magneticField().inInverseGeV(x);
00241 GlobalVector H = B.unit();
00242 GlobalVector HxT = H.cross(T);
00243 GlobalVector N = HxT.unit();
00244 double alpha = HxT.mag();
00245 double qbp = fts.signedInverseMomentum();
00246 double Q = -B.mag() * qbp;
00247 double alphaQ = alpha * Q;
00248
00249 double lambda = 0.5 * M_PI - p.theta();
00250 double coslambda = cos(lambda), tanlambda = tan(lambda);
00251
00252 double TI = T.dot(I);
00253 double NU = N.dot(U);
00254 double NV = N.dot(V);
00255 double UI = U.dot(I);
00256 double VI = V.dot(I);
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(fts.transverseCurvature())<1.e-10 ) {
00265 jac(0,0) = 1/coslambda;
00266 jac(0,1) = tanlambda/coslambda/fts.parameters().momentum().mag();
00267 }else{
00268 double Bz = B.z();
00269 jac(0,0) = -Bz/coslambda;
00270 jac(0,1) = -Bz * tanlambda/coslambda*qbp;
00271 jac(1,3) = alphaQ * NV * UI/TI;
00272 jac(1,4) = alphaQ * NV * VI/TI;
00273 jac(0,3) = -jac(0,1) * jac(1,3);
00274 jac(0,4) = -jac(0,1) * jac(1,4);
00275 jac(2,3) = -alphaQ/coslambda * NU * UI/TI;
00276 jac(2,4) = -alphaQ/coslambda * NU * VI/TI;
00277 }
00278 jac(1,1) = -1.;
00279 jac(2,2) = 1.;
00280 jac(3,3) = VK/TI;
00281 jac(3,4) = -UK/TI;
00282 jac(4,3) = -VJ/TI;
00283 jac(4,4) = UJ/TI;
00284
00285 return jac;
00286
00287 }
00288
00289
00290 AlgebraicMatrix
00291 PerigeeConversions::jacobianPerigee2Curvilinear_old(const GlobalTrajectoryParameters& gtp) const {
00292 return asHepMatrix(jacobianPerigee2Curvilinear(gtp));
00293 }
00294
00295 AlgebraicMatrix55
00296 PerigeeConversions::jacobianPerigee2Curvilinear(const GlobalTrajectoryParameters& gtp) const {
00297
00298 GlobalVector p = gtp.momentum();
00299
00300 GlobalVector Z = GlobalVector(0.,0.,1.);
00301 GlobalVector T = p.unit();
00302 GlobalVector U = Z.cross(T).unit();;
00303 GlobalVector V = T.cross(U);
00304
00305 GlobalVector I = GlobalVector(-p.x(), -p.y(), 0.);
00306 I = I.unit();
00307 GlobalVector J(-I.y(), I.x(),0.);
00308 GlobalVector K(Z);
00309 GlobalPoint x = gtp.position();
00310 GlobalVector B = gtp.magneticField().inInverseGeV(x);
00311 GlobalVector H = B.unit();
00312 GlobalVector HxT = H.cross(T);
00313 GlobalVector N = HxT.unit();
00314 double alpha = HxT.mag();
00315 double qbp = gtp.signedInverseMomentum();
00316 double Q = -B.mag() * qbp;
00317 double alphaQ = alpha * Q;
00318
00319 double lambda = 0.5 * M_PI - p.theta();
00320 double coslambda = cos(lambda), sinlambda = sin(lambda);
00321 double mqbpt = -1./coslambda * qbp;
00322
00323 double TJ = T.dot(J);
00324 double TK = T.dot(K);
00325 double NU = N.dot(U);
00326 double NV = N.dot(V);
00327 double UJ = U.dot(J);
00328 double VJ = V.dot(J);
00329 double UK = U.dot(K);
00330 double VK = V.dot(K);
00331
00332 AlgebraicMatrix55 jac;
00333
00334 if( fabs(gtp.transverseCurvature())<1.e-10 ) {
00335 jac(0,0) = coslambda;
00336 jac(0,1) = sinlambda/coslambda/gtp.momentum().mag();
00337 }else{
00338 jac(0,0) = -coslambda/B.z();
00339 jac(0,1) = -sinlambda * mqbpt;
00340 jac(1,3) = -alphaQ * NV * TJ;
00341 jac(1,4) = -alphaQ * NV * TK;
00342 jac(2,3) = -alphaQ/coslambda * NU * TJ;
00343 jac(2,4) = -alphaQ/coslambda * NU * TK;
00344 }
00345 jac(1,1) = -1.;
00346 jac(2,2) = 1.;
00347 jac(3,3) = UJ;
00348 jac(3,4) = UK;
00349 jac(4,3) = VJ;
00350 jac(4,4) = VK;
00351
00352 return jac;
00353 }
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369