CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_3/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 (isOldPropagationType && 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 (isOldPropagationType && 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     if(isOldPropagationType){
00237       HelixArbitraryPlaneCrossing planeCrossing(helixPos,helixDir,rho,propagationDirection());
00238       return propagateWithHelixCrossing(planeCrossing,plane,fts.momentum().mag(),x,p,s);
00239     }else{
00240       //--- Alternative implementation to be used for the propagation of the parameters  of looping
00241       //    particles that cross twice the (infinite) surface of the plane. It is not trivial to determine
00242       //    which of the two intersections has to be returned.
00243 
00244       //---- FIXME: WHAT FOLLOWS HAS TO BE REWRITTEN IN A CLEANER (AND CPU-OPTIMIZED) WAY ---------
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       //move forward a bit to avoid that the propagator doesn't propagate because the state is already on surface.
00277       //we want to go to the other point of intersection between the helix and the plane
00278       xGen = planeCrossing1.position(s1+tolerance);
00279       pGen = planeCrossing1.direction(s1+tolerance);
00280       
00281       /*
00282       if(!check1 || s1>170 ){
00283         //PropagationDirection newDir = (propagationDirection() == alongMomentum) ? oppositeToMomentum : alongMomentum;
00284         PropagationDirection newDir = anyDirection;
00285         HelixArbitraryPlaneCrossing  planeCrossing1B(helixPos1,helixDir1,rho1,newDir);
00286         check1 = propagateWithHelixCrossing(planeCrossing1B,plane,fts.momentum().mag(),gp1,gm1,s1);
00287         LogDebug("AnalyticalPropagator") << "after second attempt, check1, s1,gp1: "
00288                                          << check1 << " , "
00289                                          << s1 << " , " << gp1 << "\n";
00290 
00291         xGen = planeCrossing1B.position(s1+tolerance);
00292         pGen = planeCrossing1B.direction(s1+tolerance);
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       //If there are two solutions, the one which is the closest to the module's center is chosen
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       //-------- END of ugly piece of code  ---------------
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   // Instantiate auxiliary object for finding intersection.
00377   // Frame-independant point and vector are created explicitely to 
00378   // avoid confusing gcc (refuses to compile with temporary objects
00379   // in the constructor).
00380   //
00381   StraightLinePlaneCrossing::PositionType pos(x0);
00382   StraightLinePlaneCrossing::DirectionType dir(p0);
00383   StraightLinePlaneCrossing planeCrossing(pos,dir,propagationDirection());
00384   //
00385   // get solution
00386   //
00387   std::pair<bool,double> propResult = planeCrossing.pathLength(plane);
00388   if ( !propResult.first )  return false;
00389   s = propResult.second;
00390   // point (reconverted to GlobalPoint)
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   // Instantiate auxiliary object for finding intersection.
00403   // Frame-independant point and vector are created explicitely to 
00404   // avoid confusing gcc (refuses to compile with temporary objects
00405   // in the constructor).
00406   //
00407   StraightLineBarrelCylinderCrossing cylCrossing(x0,p0,propagationDirection());
00408   //
00409   // get solution
00410   //
00411   std::pair<bool,double> propResult = cylCrossing.pathLength(cylinder);
00412   if ( !propResult.first )  return false;
00413   s = propResult.second;
00414   // point (reconverted to GlobalPoint)
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   // get solution
00428   std::pair<bool,double> propResult = planeCrossing.pathLength(plane);
00429   if ( !propResult.first )  return false;
00430   s = propResult.second;
00431   // point (reconverted to GlobalPoint)
00432   HelixPlaneCrossing::PositionType xGen = planeCrossing.position(s);
00433   x = GlobalPoint(xGen);
00434   // direction (reconverted to GlobalVector, renormalised)
00435   HelixPlaneCrossing::DirectionType pGen = planeCrossing.direction(s);
00436   pGen *= pmag/pGen.mag();
00437   p = GlobalVector(pGen);
00438   //
00439   return true;
00440 }