00001
00002
00003 #include "SimG4Core/GFlash/interface/GflashTrajectory.h"
00004 #include "SimG4Core/GFlash/interface/GflashTrajectoryPoint.h"
00005
00006 #include "CLHEP/Geometry/Point3D.h"
00007 #include "CLHEP/Geometry/Vector3D.h"
00008
00009 GflashTrajectory::GflashTrajectory()
00010 :
00011 _cotTheta(0.0),_curvature(0.0),_z0(0.0),_d0(0.0),_phi0(0.0),
00012 _isStale(1),
00013 _sinPhi0(2),_cosPhi0(2),_sinTheta(2),_cosTheta(2),
00014 _s(-999.999),
00015 _aa(2),_ss(2),_cc(2)
00016 {
00017
00018 }
00019
00020
00021
00022 void GflashTrajectory::initializeTrajectory(const HepVector3D & MomentumGev, const HepPoint3D & PositionCm,
00023 double q, double BFieldTesla)
00024 {
00025 double CotTheta = 0.0 ;
00026 double W = 0;
00027 double Z0 = 0;
00028 double D0 = 0;
00029 double Phi0 =0;
00030
00031 if (BFieldTesla != 0.0 && q != 0.0) {
00032 double CurvatureConstant=0.0029979;
00033 double Helicity = -1.0 * fabs(BFieldTesla) * fabs(q) / (BFieldTesla*q);
00034 double Radius = fabs(MomentumGev.perp()/(CurvatureConstant*BFieldTesla*q));
00035
00036 if(Radius==0.0) W = HUGE_VAL; else W = Helicity/Radius;
00037 double phi1 = MomentumGev.phi();
00038 double x = PositionCm.x(), y = PositionCm.y(), z = PositionCm.z();
00039 double sinPhi1 = sin(phi1), cosPhi1 = cos(phi1);
00040 double gamma = atan((x*cosPhi1 + y*sinPhi1)/(x*sinPhi1-y*cosPhi1 -1/W));
00041 Phi0 = phi1+gamma;
00042 if(Phi0 > M_PI) Phi0 = Phi0 - 2.0*M_PI;
00043 if(Phi0 < -M_PI) Phi0 = Phi0 + 2.0*M_PI;
00044 D0 = ((1/W + y*cosPhi1 - x*sinPhi1) /cos(gamma) - 1/W);
00045 CotTheta = MomentumGev.z()/MomentumGev.perp();
00046 Z0 = z + gamma*CotTheta/W;
00047 }
00048 else {
00049 Hep3Vector direction = MomentumGev.unit();
00050 Hep3Vector projectedDirection = Hep3Vector(direction.x(),direction.y(),0.0).unit();
00051 double s = projectedDirection.dot(PositionCm);
00052 double sprime = s/sin(direction.theta());
00053 Z0 = (PositionCm - sprime*direction).z();
00054 Phi0 = MomentumGev.phi();
00055 CotTheta = MomentumGev.z()/MomentumGev.perp();
00056 W = 0.0;
00057 D0 = (PositionCm.y()*cos(Phi0) - PositionCm.x()*sin(Phi0));
00058 }
00059
00060 _cotTheta=CotTheta;
00061 _curvature=W/2;
00062 _z0=Z0;
00063 _d0=D0;
00064 _phi0=Phi0;
00065
00066 _isStale=1;
00067 _s=-999.999;
00068 _aa =-999.999;
00069 _ss =-999.999;
00070 _cc =-999.999;
00071 _sinPhi0 = 1.0;
00072 _cosPhi0 = 1.0;
00073 _sinTheta = 1.0;
00074 _cosTheta = 1.0;
00075 }
00076
00077 GflashTrajectory::~GflashTrajectory()
00078 {
00079 }
00080
00081 void GflashTrajectory::setCotTheta(double cotTheta) {
00082 _cotTheta=cotTheta;
00083 _isStale=true;
00084 }
00085
00086 void GflashTrajectory::setCurvature(double curvature){
00087 _curvature=curvature;
00088 _isStale=true;
00089 }
00090
00091 void GflashTrajectory::setZ0(double z0) {
00092 _z0 = z0;
00093 _isStale=true;
00094 }
00095
00096 void GflashTrajectory::setD0(double d0){
00097 _d0=d0;
00098 _isStale=true;
00099 }
00100
00101 void GflashTrajectory::setPhi0(double phi0){
00102 _phi0=phi0;
00103 _isStale=true;
00104 }
00105
00106 double GflashTrajectory::getSinPhi0() const{
00107 _refreshCache();
00108 return _sinPhi0;
00109 }
00110 double GflashTrajectory::getCosPhi0() const{
00111 _refreshCache();
00112 return _cosPhi0;
00113 }
00114 double GflashTrajectory::getSinTheta() const{
00115 _refreshCache();
00116 return _sinTheta;
00117 }
00118 double GflashTrajectory::getCosTheta() const{
00119 _refreshCache();
00120 return _cosTheta;
00121 }
00122
00123 HepPoint3D GflashTrajectory::getPosition(double s) const
00124 {
00125 _cacheSinesAndCosines(s);
00126 if (s==0.0 || _curvature==0.0) {
00127 return HepPoint3D(-_d0*_sinPhi0+s*_cosPhi0*_sinTheta,
00128 _d0*_cosPhi0+s*_sinPhi0*_sinTheta,
00129 _z0+s*_cosTheta);
00130 } else {
00131 return HepPoint3D((_cosPhi0*_ss-_sinPhi0*(2.0*_curvature*_d0+1.0-_cc))
00132 /(2.0*_curvature),
00133 (_sinPhi0*_ss+_cosPhi0*(2.0*_curvature*_d0+1.0-_cc))
00134 /(2.0*_curvature),
00135 _s*_cosTheta + _z0);
00136 }
00137 }
00138
00139 HepVector3D GflashTrajectory::getDirection(double s) const
00140 {
00141 _cacheSinesAndCosines(s);
00142 if (s==0.0) {
00143 return HepVector3D(_cosPhi0*_sinTheta,_sinPhi0*_sinTheta,_cosTheta);
00144 }
00145 double xtan = _sinTheta*(_cosPhi0*_cc -_sinPhi0*_ss);
00146 double ytan = _sinTheta*(_cosPhi0*_ss +_sinPhi0*_cc);
00147 double ztan = _cosTheta;
00148 return HepVector3D(xtan,ytan,ztan);
00149 }
00150
00151
00152 void GflashTrajectory::getGflashTrajectoryPoint(GflashTrajectoryPoint& point, double s) const {
00153
00154 _cacheSinesAndCosines(s);
00155
00156 double cP0sT = _cosPhi0*_sinTheta, sP0sT = _sinPhi0*_sinTheta;
00157 if ( s && _curvature) {
00158 point.getPosition().set((_cosPhi0*_ss-
00159 _sinPhi0*(2.0*_curvature*_d0+1.0-_cc))
00160 /(2.0*_curvature),
00161 (_sinPhi0*_ss+
00162 _cosPhi0*(2.0*_curvature*_d0+1.0-_cc))
00163 /(2.0*_curvature),
00164 s*_cosTheta + _z0);
00165
00166 point.getMomentum().set(cP0sT*_cc-sP0sT*_ss,
00167 cP0sT*_ss+sP0sT*_cc,
00168 _cosTheta);
00169 point.setPathLength(s);
00170 }
00171 else {
00172 point.getPosition().set(-_d0*_sinPhi0+s*cP0sT,
00173 _d0*_cosPhi0+s*sP0sT,
00174 _z0+s*_cosTheta);
00175
00176 point.getMomentum().set(cP0sT,sP0sT,_cosTheta);
00177
00178 point.setPathLength(s);
00179 }
00180
00181 }
00182
00183 double GflashTrajectory::getPathLengthAtRhoEquals(double rho) const
00184 {
00185 return (getSinTheta()?(getL2DAtR(rho)/getSinTheta()):0.0);
00186 }
00187
00188 double GflashTrajectory::getPathLengthAtZ(double z) const {
00189 return (getCosTheta()?(z-getZ0())/getCosTheta():0.0);
00190 }
00191
00192 double GflashTrajectory::getZAtR(double rho) const {
00193 return _z0 + getCotTheta()*getL2DAtR(rho);
00194 }
00195
00196 double GflashTrajectory::getL2DAtR(double rho) const {
00197
00198 double L2D;
00199
00200 double c = getCurvature();
00201 double d = getD0();
00202
00203 if (c!=0.0) {
00204 double rad = (rho*rho-d*d)/(1.0+2.0*c*d);
00205 double rprime;
00206 if (rad<0.0) {
00207 rprime = 0.0;
00208 }
00209 else {
00210 rprime = sqrt( rad );
00211 }
00212 if (c*rprime > 1.0 || c*rprime < -1.0) {
00213 L2D = c*rprime > 0. ? M_PI/c : -M_PI/c;
00214 }
00215 else
00216 L2D = asin(c*rprime)/c;
00217 } else {
00218 double rad = rho*rho-d*d;
00219 double rprime;
00220 if (rad<0.0) rprime = 0.0;
00221 else rprime = sqrt( rad );
00222
00223 L2D = rprime;
00224 }
00225 return L2D;
00226 }
00227
00228
00229 void GflashTrajectory::_refreshCache() const {
00230 if (_isStale) {
00231 _isStale=false;
00232 double theta;
00233 if ( _cotTheta==0.0 ) {
00234 theta = M_PI/2.0;
00235 }
00236 else {
00237 theta=atan(1.0/_cotTheta);
00238 if (theta<0.0) theta+=M_PI;
00239 }
00240 if (theta==0.0) {
00241 _sinTheta=0.0;
00242 _cosTheta=1.0;
00243 }
00244 else {
00245 _cosTheta=cos(theta);
00246 _sinTheta=sqrt(1-_cosTheta*_cosTheta);
00247 }
00248 if (_phi0==0.0) {
00249 _sinPhi0=0.0;
00250 _cosPhi0=1.0;
00251 }
00252 else {
00253 _cosPhi0 = cos(_phi0);
00254 _sinPhi0 = sin(_phi0);
00255
00256
00257 }
00258 }
00259 }
00260
00261 void GflashTrajectory::_cacheSinesAndCosines(double s) const {
00262 _refreshCache();
00263 if (_s!=s){
00264 _s=s;
00265 _aa=2.0*_s*_curvature*_sinTheta;
00266 if (_aa==0.0) {
00267 _ss=0.0;
00268 _cc=1.0;
00269 }
00270 else {
00271 _ss=sin(_aa);
00272 _cc=cos(_aa);
00273 }
00274 }
00275 }