CMS 3D CMS Logo

CMSSW_4_4_3_patch1/src/TrackingTools/GeomPropagators/src/AnalyticalPropagator.cc

Go to the documentation of this file.
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   // check curvature
00032   double rho = fts.transverseCurvature();
00033   
00034   // propagate parameters
00035   GlobalPoint x;
00036   GlobalVector p;
00037   double s;
00038   
00039   // check if already on plane
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     // propagate
00045     bool parametersOK = this->propagateParametersOnPlane(fts, plane, x, p, s);
00046     // check status and deltaPhi limit
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   // Compute propagated state and check change in curvature
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   // construct TrajectoryStateOnSurface
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   // check curvature
00079   double rho = fts.transverseCurvature();
00080 
00081   // propagate parameters
00082   GlobalPoint x;
00083   GlobalVector p;
00084   double s = 0;
00085 
00086   bool parametersOK = this->propagateParametersOnCylinder(fts, cylinder, x, p, s);
00087   // check status and deltaPhi limit
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   // Compute propagated state and check change in curvature
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   // create result TSOS on TangentPlane (local parameters & errors are better defined)
00099   //
00100 
00101   //try {
00102     ReferenceCountingPointer<TangentPlane> plane(cylinder.tangentPlane(x));  // need to be here until tsos is created!
00103     return propagatedStateWithPath(fts,*plane,gtp,s);
00104   /*
00105   } catch(...) {
00106     std::cout << "wrong tangent to cylinder " << x 
00107               << " pos, rad " << cylinder.position() << " " << cylinder.radius()
00108               << std::endl;
00109     return TsosWP(TrajectoryStateOnSurface(),0.);
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   // for forward propagation: state is before surface,
00122   // for backward propagation: state is after surface
00123   //
00124   SurfaceSide side = PropagationDirectionFromPath()(s,propagationDirection())==alongMomentum 
00125     ? beforeSurface : afterSurface;
00126   // 
00127   //
00128   // error propagation (if needed) and conversion to a TrajectoryStateOnSurface
00129   //
00130   if (fts.hasError()) {
00131     //
00132     // compute jacobian
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     // return state without errors
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   // preset output
00157   x = fts.position();
00158   p = fts.momentum();
00159   s = 0;
00160   // (transverse) curvature
00161   double rho = fts.transverseCurvature();
00162   //
00163   // Straight line approximation? |rho|<1.e-10 equivalent to ~ 1um 
00164   // difference in transversal position at 10m.
00165   //
00166   if( fabs(rho)<1.e-10 )
00167     return propagateWithLineCrossing(fts.position(),p,cylinder,x,s);
00168   //
00169   // Helix case
00170   //
00171   // check for possible intersection
00172   const double tolerance = 1.e-4; // 1 micron distance
00173   double rdiff = x.perp() - cylinder.radius();
00174   if ( fabs(rdiff) < tolerance )  return true;
00175   //
00176   // Instantiate HelixBarrelCylinderCrossing and get solutions
00177   //
00178   HelixBarrelCylinderCrossing cylinderCrossing(fts.position(),fts.momentum(),rho,
00179                                                propagationDirection(),cylinder);
00180   if ( !cylinderCrossing.hasSolution() )  return false;
00181   // path length
00182   s = cylinderCrossing.pathLength();
00183   // point
00184   x = cylinderCrossing.position();
00185   // direction (renormalised)
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   // initialisation of position, momentum and path length
00198   x = fts.position();
00199   p = fts.momentum();
00200   s = 0;
00201   // (transverse) curvature
00202   double rho = fts.transverseCurvature();
00203   //
00204   // Straight line approximation? |rho|<1.e-10 equivalent to ~ 1um 
00205   // difference in transversal position at 10m.
00206   //
00207   if( fabs(rho)<1.e-10 )
00208     return propagateWithLineCrossing(fts.position(),p,plane,x,s);
00209   //
00210   // Helix case 
00211   //
00212   GlobalVector u = plane.normalVector();
00213   const double small = 1.e-6; // for orientation of planes
00214   //
00215   // Frame-independant point and vector are created explicitely to 
00216   // avoid confusing gcc (refuses to compile with temporary objects
00217   // in the constructor).
00218   //
00219   HelixPlaneCrossing::PositionType helixPos(x);
00220   HelixPlaneCrossing::DirectionType helixDir(p);
00221   if (fabs(u.z()) < small) {
00222     // barrel plane:
00223     // instantiate HelixBarrelPlaneCrossing, get vector of solutions and check for existance
00224     HelixBarrelPlaneCrossingByCircle planeCrossing(helixPos,helixDir,rho,propagationDirection());
00225     return propagateWithHelixCrossing(planeCrossing,plane,fts.momentum().mag(),x,p,s);
00226   }
00227   if (fabs(u.x()) < small && fabs(u.y()) < small) {
00228     // forward plane:
00229     // instantiate HelixForwardPlaneCrossing, get vector of solutions and check for existance
00230     HelixForwardPlaneCrossing planeCrossing(helixPos,helixDir,rho,propagationDirection());
00231     return propagateWithHelixCrossing(planeCrossing,plane,fts.momentum().mag(),x,p,s);
00232   }
00233   else {
00234     // arbitrary plane:
00235     // instantiate HelixArbitraryPlaneCrossing, get vector of solutions and check for existance
00236     HelixArbitraryPlaneCrossing planeCrossing(helixPos,helixDir,rho,propagationDirection());
00237     return propagateWithHelixCrossing(planeCrossing,plane,fts.momentum().mag(),x,p,s);
00238   }
00239 }
00240 
00241 bool
00242 AnalyticalPropagator::propagateWithLineCrossing (const GlobalPoint& x0, 
00243                                                  const GlobalVector& p0,
00244                                                  const Plane& plane,
00245                                                  GlobalPoint& x, double& s) const {
00246   //
00247   // Instantiate auxiliary object for finding intersection.
00248   // Frame-independant point and vector are created explicitely to 
00249   // avoid confusing gcc (refuses to compile with temporary objects
00250   // in the constructor).
00251   //
00252   StraightLinePlaneCrossing::PositionType pos(x0);
00253   StraightLinePlaneCrossing::DirectionType dir(p0);
00254   StraightLinePlaneCrossing planeCrossing(pos,dir,propagationDirection());
00255   //
00256   // get solution
00257   //
00258   std::pair<bool,double> propResult = planeCrossing.pathLength(plane);
00259   if ( !propResult.first )  return false;
00260   s = propResult.second;
00261   // point (reconverted to GlobalPoint)
00262   x = GlobalPoint(planeCrossing.position(s));
00263   //
00264   return true;
00265 }
00266 
00267 bool
00268 AnalyticalPropagator::propagateWithLineCrossing (const GlobalPoint& x0, 
00269                                                  const GlobalVector& p0,
00270                                                  const Cylinder& cylinder,
00271                                                  GlobalPoint& x, double& s) const {
00272   //
00273   // Instantiate auxiliary object for finding intersection.
00274   // Frame-independant point and vector are created explicitely to 
00275   // avoid confusing gcc (refuses to compile with temporary objects
00276   // in the constructor).
00277   //
00278   StraightLineBarrelCylinderCrossing cylCrossing(x0,p0,propagationDirection());
00279   //
00280   // get solution
00281   //
00282   std::pair<bool,double> propResult = cylCrossing.pathLength(cylinder);
00283   if ( !propResult.first )  return false;
00284   s = propResult.second;
00285   // point (reconverted to GlobalPoint)
00286   x = cylCrossing.position(s);
00287   //
00288   return true;
00289 }
00290 
00291 bool
00292 AnalyticalPropagator::propagateWithHelixCrossing (HelixPlaneCrossing& planeCrossing,
00293                                                   const Plane& plane,
00294                                                   const float pmag,
00295                                                   GlobalPoint& x,
00296                                                   GlobalVector& p,
00297                                                   double& s) const {
00298   // get solution
00299   std::pair<bool,double> propResult = planeCrossing.pathLength(plane);
00300   if ( !propResult.first )  return false;
00301   s = propResult.second;
00302   // point (reconverted to GlobalPoint)
00303   HelixPlaneCrossing::PositionType xGen = planeCrossing.position(s);
00304   x = GlobalPoint(xGen);
00305   // direction (reconverted to GlobalVector, renormalised)
00306   HelixPlaneCrossing::DirectionType pGen = planeCrossing.direction(s);
00307   pGen *= pmag/pGen.mag();
00308   p = GlobalVector(pGen);
00309   //
00310   return true;
00311 }