00001 #include "TrackingTools/GeomPropagators/interface/AnalyticalPropagator.h"
00002
00003 #include "DataFormats/GeometrySurface/interface/Cylinder.h"
00004 #include "DataFormats/GeometrySurface/interface/TangentPlane.h"
00005 #include "DataFormats/GeometrySurface/interface/Plane.h"
00006
00007 #include "MagneticField/Engine/interface/MagneticField.h"
00008
00009 #include "TrackingTools/GeomPropagators/interface/PropagationExceptions.h"
00010 #include "TrackingTools/GeomPropagators/interface/StraightLinePlaneCrossing.h"
00011 #include "TrackingTools/GeomPropagators/interface/StraightLineBarrelCylinderCrossing.h"
00012 #include "TrackingTools/GeomPropagators/interface/HelixBarrelPlaneCrossingByCircle.h"
00013 #include "TrackingTools/GeomPropagators/interface/HelixForwardPlaneCrossing.h"
00014 #include "TrackingTools/GeomPropagators/interface/HelixArbitraryPlaneCrossing.h"
00015 #include "TrackingTools/GeomPropagators/interface/HelixBarrelCylinderCrossing.h"
00016 #include "TrackingTools/AnalyticalJacobians/interface/AnalyticalCurvilinearJacobian.h"
00017 #include "TrackingTools/GeomPropagators/interface/PropagationDirectionFromPath.h"
00018 #include "TrackingTools/TrajectoryState/interface/SurfaceSideDefinition.h"
00019 #include "TrackingTools/GeomPropagators/interface/PropagationExceptions.h"
00020
00021 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00022
00023 #include <cmath>
00024
00025 using namespace SurfaceSideDefinition;
00026
00027 std::pair<TrajectoryStateOnSurface,double>
00028 AnalyticalPropagator::propagateWithPath(const FreeTrajectoryState& fts,
00029 const Plane& plane) const
00030 {
00031
00032 double rho = fts.transverseCurvature();
00033
00034
00035 GlobalPoint x;
00036 GlobalVector p;
00037 double s;
00038
00039
00040 const float maxDistToPlane(0.1e-4);
00041 const float numericalPrecision(5.e-7);
00042 float maxDz = numericalPrecision*plane.position().mag();
00043 if ( fabs(plane.localZ(fts.position()))>(maxDistToPlane>maxDz?maxDistToPlane:maxDz) ) {
00044
00045 bool parametersOK = this->propagateParametersOnPlane(fts, plane, x, p, s);
00046
00047 float dphi2 = s*rho;
00048 dphi2 = dphi2*dphi2*fts.momentum().perp2()/fts.momentum().mag2();
00049 if ( !parametersOK || dphi2>theMaxDPhi2 ) return TsosWP(TrajectoryStateOnSurface(),0.);
00050 }
00051 else {
00052 LogDebug("AnalyticalPropagator")<<"not going anywhere. Already on surface.\n"
00053 <<"plane.localZ(fts.position()): "<<plane.localZ(fts.position())<<"\n"
00054 <<"maxDistToPlane: "<<maxDistToPlane<<"\n"
00055 <<"maxDz: "<<maxDz<<"\n"
00056 <<"plane.position().mag(): "<<plane.position().mag();
00057 x = fts.position();
00058 p = fts.momentum();
00059 s = 0.;
00060 }
00061
00062
00063
00064 GlobalTrajectoryParameters gtp(x,p,fts.charge(),theField);
00065 if ( fabs(rho)>1.e-10 && fabs((gtp.transverseCurvature()-rho)/rho)>theMaxDBzRatio )
00066 return TsosWP(TrajectoryStateOnSurface(),0.);
00067
00068
00069
00070 return propagatedStateWithPath(fts,plane,gtp,s);
00071 }
00072
00073
00074 std::pair<TrajectoryStateOnSurface,double>
00075 AnalyticalPropagator::propagateWithPath(const FreeTrajectoryState& fts,
00076 const Cylinder& cylinder) const
00077 {
00078
00079 double rho = fts.transverseCurvature();
00080
00081
00082 GlobalPoint x;
00083 GlobalVector p;
00084 double s = 0;
00085
00086 bool parametersOK = this->propagateParametersOnCylinder(fts, cylinder, x, p, s);
00087
00088 float dphi2 = s*rho;
00089 dphi2 = dphi2*dphi2*fts.momentum().perp2()/fts.momentum().mag2();
00090 if ( !parametersOK || dphi2>theMaxDPhi2 ) return TsosWP(TrajectoryStateOnSurface(),0.);
00091
00092
00093
00094 GlobalTrajectoryParameters gtp(x,p,fts.charge(),theField);
00095 if ( fabs(rho)>1.e-10 && fabs((gtp.transverseCurvature()-rho)/rho)>theMaxDBzRatio )
00096 return TsosWP(TrajectoryStateOnSurface(),0.);
00097
00098
00099
00100
00101
00102 ReferenceCountingPointer<TangentPlane> plane(cylinder.tangentPlane(x));
00103 return propagatedStateWithPath(fts,*plane,gtp,s);
00104
00105
00106
00107
00108
00109
00110
00111
00112 }
00113
00114 std::pair<TrajectoryStateOnSurface,double>
00115 AnalyticalPropagator::propagatedStateWithPath (const FreeTrajectoryState& fts,
00116 const Surface& surface,
00117 const GlobalTrajectoryParameters& gtp,
00118 const double& s) const
00119 {
00120
00121
00122
00123
00124 SurfaceSide side = PropagationDirectionFromPath()(s,propagationDirection())==alongMomentum
00125 ? beforeSurface : afterSurface;
00126
00127
00128
00129
00130 if (fts.hasError()) {
00131
00132
00133
00134 AnalyticalCurvilinearJacobian analyticalJacobian(fts.parameters(), gtp.position(), gtp.momentum(), s);
00135 const AlgebraicMatrix55 &jacobian = analyticalJacobian.jacobian();
00136 CurvilinearTrajectoryError cte(ROOT::Math::Similarity(jacobian, fts.curvilinearError().matrix()));
00137 return TsosWP(TrajectoryStateOnSurface(gtp,cte,surface,side),s);
00138 }
00139 else {
00140
00141
00142
00143 return TsosWP(TrajectoryStateOnSurface(gtp,surface,side),s);
00144 }
00145 }
00146
00147 bool AnalyticalPropagator::propagateParametersOnCylinder(
00148 const FreeTrajectoryState& fts, const Cylinder& cylinder,
00149 GlobalPoint& x, GlobalVector& p, double& s) const
00150 {
00151
00152 GlobalPoint const & sp = cylinder.position();
00153 if (sp.x()!=0. || sp.y()!=0.) {
00154 throw PropagationException("Cannot propagate to an arbitrary cylinder");
00155 }
00156
00157 x = fts.position();
00158 p = fts.momentum();
00159 s = 0;
00160
00161 double rho = fts.transverseCurvature();
00162
00163
00164
00165
00166 if( fabs(rho)<1.e-10 )
00167 return propagateWithLineCrossing(fts.position(),p,cylinder,x,s);
00168
00169
00170
00171
00172 const double tolerance = 1.e-4;
00173 double rdiff = x.perp() - cylinder.radius();
00174 if ( fabs(rdiff) < tolerance ) return true;
00175
00176
00177
00178 HelixBarrelCylinderCrossing cylinderCrossing(fts.position(),fts.momentum(),rho,
00179 propagationDirection(),cylinder);
00180 if ( !cylinderCrossing.hasSolution() ) return false;
00181
00182 s = cylinderCrossing.pathLength();
00183
00184 x = cylinderCrossing.position();
00185
00186 p = cylinderCrossing.direction().unit()*fts.momentum().mag();
00187 return true;
00188 }
00189
00190 bool
00191 AnalyticalPropagator::propagateParametersOnPlane(const FreeTrajectoryState& fts,
00192 const Plane& plane,
00193 GlobalPoint& x,
00194 GlobalVector& p,
00195 double& s) const
00196 {
00197
00198 x = fts.position();
00199 p = fts.momentum();
00200 s = 0;
00201
00202 double rho = fts.transverseCurvature();
00203
00204
00205
00206
00207 if( fabs(rho)<1.e-10 )
00208 return propagateWithLineCrossing(fts.position(),p,plane,x,s);
00209
00210
00211
00212 GlobalVector u = plane.normalVector();
00213 const double small = 1.e-6;
00214
00215
00216
00217
00218
00219 HelixPlaneCrossing::PositionType helixPos(x);
00220 HelixPlaneCrossing::DirectionType helixDir(p);
00221 if (isOldPropagationType && fabs(u.z()) < small) {
00222
00223
00224 HelixBarrelPlaneCrossingByCircle planeCrossing(helixPos,helixDir,rho,propagationDirection());
00225 return propagateWithHelixCrossing(planeCrossing,plane,fts.momentum().mag(),x,p,s);
00226 }
00227 if (isOldPropagationType && fabs(u.x()) < small && fabs(u.y()) < small) {
00228
00229
00230 HelixForwardPlaneCrossing planeCrossing(helixPos,helixDir,rho,propagationDirection());
00231 return propagateWithHelixCrossing(planeCrossing,plane,fts.momentum().mag(),x,p,s);
00232 }
00233 else {
00234
00235
00236 if(isOldPropagationType){
00237 HelixArbitraryPlaneCrossing planeCrossing(helixPos,helixDir,rho,propagationDirection());
00238 return propagateWithHelixCrossing(planeCrossing,plane,fts.momentum().mag(),x,p,s);
00239 }else{
00240
00241
00242
00243
00244
00245 LogDebug("AnalyticalPropagator") << "In AnaliticalProp, calling HAPC " << "\n"
00246 << "plane is centered in xyz: "
00247 << plane.position().x() << " , "
00248 << plane.position().y() << " , "
00249 << plane.position().z() << "\n";
00250
00251
00252 GlobalPoint gp1 = fts.position();
00253 GlobalVector gm1 = fts.momentum();
00254 double s1 = 0;
00255 double rho1 = fts.transverseCurvature();
00256 HelixPlaneCrossing::PositionType helixPos1(gp1);
00257 HelixPlaneCrossing::DirectionType helixDir1(gm1);
00258 LogDebug("AnalyticalPropagator") << "gp1 before calling planeCrossing1: " << gp1 << "\n";
00259 HelixArbitraryPlaneCrossing planeCrossing1(helixPos1,helixDir1,rho1,propagationDirection());
00260
00261 HelixPlaneCrossing::PositionType xGen;
00262 HelixPlaneCrossing::DirectionType pGen;
00263
00264 double tolerance(0.0050);
00265 if(propagationDirection()==oppositeToMomentum)
00266 tolerance *=-1;
00267
00268 bool check1 = propagateWithHelixCrossing(planeCrossing1,plane,fts.momentum().mag(),gp1,gm1,s1);
00269 double dphi1 = fabs(fts.momentum().phi()-gm1.phi());
00270 LogDebug("AnalyticalPropagator") << "check1, s1, dphi, gp1: "
00271 << check1 << " , "
00272 << s1 << " , "
00273 << dphi1 << " , "
00274 << gp1 << "\n";
00275
00276
00277
00278 xGen = planeCrossing1.position(s1+tolerance);
00279 pGen = planeCrossing1.direction(s1+tolerance);
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296 if(!check1){
00297 LogDebug("AnalyticalPropagator") << "failed also second attempt. No idea what to do, then bailout" << "\n";
00298 }
00299
00300
00301 pGen *= gm1.mag()/pGen.mag();
00302 GlobalPoint gp2(xGen);
00303 GlobalVector gm2(pGen);
00304 double s2 = 0;
00305 double rho2 = rho1;
00306 HelixPlaneCrossing::PositionType helixPos2(gp2);
00307 HelixPlaneCrossing::DirectionType helixDir2(gm2);
00308 HelixArbitraryPlaneCrossing planeCrossing2(helixPos2,helixDir2,rho2,propagationDirection());
00309
00310 bool check2 = propagateWithHelixCrossing(planeCrossing2,plane,gm2.mag(),gp2,gm2,s2);
00311
00312 if(!check2){
00313 x = gp1;
00314 p = gm1;
00315 s = s1;
00316 return check1;
00317 }
00318
00319 if(!check1){
00320 edm::LogError("AnalyticalPropagator") << "LOGIC ERROR: I should not have entered here!" << "\n";
00321 return false;
00322 }
00323
00324
00325 LogDebug("AnalyticalPropagator") << "check2, s2, gp2: "
00326 << check2 << " , "
00327 << s2 << " , " << gp2 << "\n";
00328
00329
00330 double dist1 = (plane.position()-gp1).perp();
00331 double dist2 = (plane.position()-gp2).perp();
00332
00333
00334 LogDebug("AnalyticalPropagator") << "propDir, dist1, dist2: "
00335 << propagationDirection() << " , "
00336 << dist1 << " , "
00337 << dist2 << "\n";
00338
00339
00340 if(dist1<2*dist2){
00341 x = gp1;
00342 p = gm1;
00343 s = s1;
00344 return check1;
00345 }else if(dist2<2*dist1){
00346 x = gp2;
00347 p = gm2;
00348 s = s1+s2+tolerance;
00349 return check2;
00350 }else{
00351 if(fabs(s1)<fabs(s2)){
00352 x = gp1;
00353 p = gm1;
00354 s = s1;
00355 return check1;
00356 }else{
00357 x = gp2;
00358 p = gm2;
00359 s = s1+s2+tolerance;
00360 return check2;
00361 }
00362 }
00363
00364
00365 }
00366
00367 }
00368 }
00369
00370 bool
00371 AnalyticalPropagator::propagateWithLineCrossing (const GlobalPoint& x0,
00372 const GlobalVector& p0,
00373 const Plane& plane,
00374 GlobalPoint& x, double& s) const {
00375
00376
00377
00378
00379
00380
00381 StraightLinePlaneCrossing::PositionType pos(x0);
00382 StraightLinePlaneCrossing::DirectionType dir(p0);
00383 StraightLinePlaneCrossing planeCrossing(pos,dir,propagationDirection());
00384
00385
00386
00387 std::pair<bool,double> propResult = planeCrossing.pathLength(plane);
00388 if ( !propResult.first ) return false;
00389 s = propResult.second;
00390
00391 x = GlobalPoint(planeCrossing.position(s));
00392
00393 return true;
00394 }
00395
00396 bool
00397 AnalyticalPropagator::propagateWithLineCrossing (const GlobalPoint& x0,
00398 const GlobalVector& p0,
00399 const Cylinder& cylinder,
00400 GlobalPoint& x, double& s) const {
00401
00402
00403
00404
00405
00406
00407 StraightLineBarrelCylinderCrossing cylCrossing(x0,p0,propagationDirection());
00408
00409
00410
00411 std::pair<bool,double> propResult = cylCrossing.pathLength(cylinder);
00412 if ( !propResult.first ) return false;
00413 s = propResult.second;
00414
00415 x = cylCrossing.position(s);
00416
00417 return true;
00418 }
00419
00420 bool
00421 AnalyticalPropagator::propagateWithHelixCrossing (HelixPlaneCrossing& planeCrossing,
00422 const Plane& plane,
00423 const float pmag,
00424 GlobalPoint& x,
00425 GlobalVector& p,
00426 double& s) const {
00427
00428 std::pair<bool,double> propResult = planeCrossing.pathLength(plane);
00429 if ( !propResult.first ) return false;
00430 s = propResult.second;
00431
00432 HelixPlaneCrossing::PositionType xGen = planeCrossing.position(s);
00433 x = GlobalPoint(xGen);
00434
00435 HelixPlaneCrossing::DirectionType pGen = planeCrossing.direction(s);
00436 pGen *= pmag/pGen.mag();
00437 p = GlobalVector(pGen);
00438
00439 return true;
00440 }