00001 #include "TrackingTools/GeomPropagators/interface/HelixArbitraryPlaneCrossing.h"
00002 #include "DataFormats/GeometrySurface/interface/Plane.h"
00003 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00004
00005 #include <cmath>
00006 #include <iostream>
00007 #include "FWCore/Utilities/interface/Likely.h"
00008
00009 HelixArbitraryPlaneCrossing::HelixArbitraryPlaneCrossing(const PositionType& point,
00010 const DirectionType& direction,
00011 const float curvature,
00012 const PropagationDirection propDir) :
00013 theQuadraticCrossingFromStart(point,direction,curvature,propDir),
00014 theX0(point.x()),
00015 theY0(point.y()),
00016 theZ0(point.z()),
00017 theRho(curvature),
00018 thePropDir(propDir),
00019 theCachedS(0),
00020 theCachedDPhi(0.),
00021 theCachedSDPhi(0.),
00022 theCachedCDPhi(1.)
00023 {
00024
00025
00026
00027 double px = direction.x();
00028 double py = direction.y();
00029 double pz = direction.z();
00030 double pt2 = px*px+py*py;
00031 double p2 = pt2+pz*pz;
00032 double pI = 1./sqrt(p2);
00033 double ptI = 1./sqrt(pt2);
00034 theCosPhi0 = px*ptI;
00035 theSinPhi0 = py*ptI;
00036 theCosTheta = pz*pI;
00037 theSinTheta = pt2*ptI*pI;
00038 }
00039
00040
00041
00042 std::pair<bool,double>
00043 HelixArbitraryPlaneCrossing::pathLength(const Plane& plane) {
00044
00045
00046
00047 const int maxIterations(100);
00048
00049
00050
00051 float maxNumDz = theNumericalPrecision*plane.position().mag();
00052 float safeMaxDist = (theMaxDistToPlane>maxNumDz?theMaxDistToPlane:maxNumDz);
00053
00054
00055
00056 PropagationDirection propDir = thePropDir;
00057 PositionTypeDouble xnew(theX0,theY0,theZ0);
00058 DirectionTypeDouble pnew(theCosPhi0,theSinPhi0,theCosTheta/theSinTheta);
00059
00060
00061
00062 int iteration(maxIterations);
00063 double dSTotal(0.);
00064
00065 bool first = true;
00066 while ( notAtSurface(plane,xnew,safeMaxDist) ) {
00067
00068
00069
00070 if unlikely( --iteration<0 ) {
00071 edm::LogInfo("HelixArbitraryPlaneCrossing") << "pathLength : no convergence";
00072 return std::pair<bool,double>(false,0);
00073 }
00074
00075
00076
00077
00078
00079 std::pair<bool,double> deltaS2;
00080 if unlikely( first ) {
00081 first = false;
00082 deltaS2 = theQuadraticCrossingFromStart.pathLength(plane);
00083 }
00084 else {
00085 HelixArbitraryPlaneCrossing2Order quadraticCrossing(xnew.x(),xnew.y(),xnew.z(),
00086 pnew.x(),pnew.y(),
00087 theCosTheta,theSinTheta,
00088 theRho,
00089 anyDirection);
00090
00091 deltaS2 = quadraticCrossing.pathLength(plane);
00092 }
00093
00094 if unlikely( !deltaS2.first ) return deltaS2;
00095
00096
00097
00098 dSTotal += deltaS2.second;
00099 PropagationDirection newDir = dSTotal>=0 ? alongMomentum : oppositeToMomentum;
00100 if ( propDir == anyDirection ) {
00101 propDir = newDir;
00102 }
00103 else {
00104 if unlikely( newDir!=propDir ) return std::pair<bool,double>(false,0);
00105 }
00106
00107
00108
00109 xnew = positionInDouble(dSTotal);
00110 pnew = directionInDouble(dSTotal);
00111 }
00112
00113
00114
00115 return std::pair<bool,double>(true,dSTotal);
00116 }
00117
00118
00119
00120 HelixPlaneCrossing::PositionType
00121 HelixArbitraryPlaneCrossing::position (double s) const {
00122
00123 PositionTypeDouble pos = positionInDouble(s);
00124 return PositionType(pos.x(),pos.y(),pos.z());
00125 }
00126
00127
00128
00129 HelixArbitraryPlaneCrossing::PositionTypeDouble
00130 HelixArbitraryPlaneCrossing::positionInDouble (double s) const {
00131
00132
00133
00134 if unlikely( s!=theCachedS ) {
00135 theCachedS = s;
00136 theCachedDPhi = theCachedS*theRho*theSinTheta;
00137 theCachedSDPhi = sin(theCachedDPhi);
00138 theCachedCDPhi = cos(theCachedDPhi);
00139 }
00140
00141
00142
00143
00144
00145 if ( std::abs(theCachedDPhi)>1.e-4 ) {
00146
00147 double o = 1./theRho;
00148 return PositionTypeDouble(theX0+(-theSinPhi0*(1.-theCachedCDPhi)+theCosPhi0*theCachedSDPhi)*o,
00149 theY0+( theCosPhi0*(1.-theCachedCDPhi)+theSinPhi0*theCachedSDPhi)*o,
00150 theZ0+theCachedS*theCosTheta);
00151 }
00152
00153
00154
00155
00156
00157
00158
00159
00160 else {
00161
00162 return theQuadraticCrossingFromStart.positionInDouble(theCachedS);
00163 }
00164 }
00165
00166
00167
00168 HelixPlaneCrossing::DirectionType
00169 HelixArbitraryPlaneCrossing::direction (double s) const {
00170
00171 DirectionTypeDouble dir = directionInDouble(s);
00172 return DirectionType(dir.x(),dir.y(),dir.z());
00173 }
00174
00175
00176
00177 HelixArbitraryPlaneCrossing::DirectionTypeDouble
00178 HelixArbitraryPlaneCrossing::directionInDouble (double s) const {
00179
00180
00181
00182 if unlikely( s!=theCachedS ) {
00183 theCachedS = s;
00184 theCachedDPhi = theCachedS*theRho*theSinTheta;
00185 theCachedSDPhi = sin(theCachedDPhi);
00186 theCachedCDPhi = cos(theCachedDPhi);
00187 }
00188
00189 if ( std::abs(theCachedDPhi)>1.e-4 ) {
00190
00191 return DirectionTypeDouble(theCosPhi0*theCachedCDPhi-theSinPhi0*theCachedSDPhi,
00192 theSinPhi0*theCachedCDPhi+theCosPhi0*theCachedSDPhi,
00193 theCosTheta/theSinTheta);
00194 }
00195 else {
00196
00197 return theQuadraticCrossingFromStart.directionInDouble(theCachedS);
00198 }
00199 }
00200
00201
00202 bool HelixArbitraryPlaneCrossing::notAtSurface (const Plane& plane,
00203 const PositionTypeDouble& point,
00204 const float maxDist) const {
00205 float dz = plane.localZ(Surface::GlobalPoint(point.x(),point.y(),point.z()));
00206 return std::abs(dz)>maxDist;
00207 }
00208
00209 const float HelixArbitraryPlaneCrossing::theNumericalPrecision = 5.e-7f;
00210 const float HelixArbitraryPlaneCrossing::theMaxDistToPlane = 1.e-4f;