CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
AnalyticalPropagator.cc
Go to the documentation of this file.
2 
6 
8 
20 
22 
23 #include <cmath>
24 
25 using namespace SurfaceSideDefinition;
26 
27 std::pair<TrajectoryStateOnSurface,double>
28 AnalyticalPropagator::propagateWithPath(const FreeTrajectoryState& fts,
29  const Plane& plane) const
30 {
31  // check curvature
32  float rho = fts.transverseCurvature();
33 
34  // propagate parameters
35  GlobalPoint x;
37  double s;
38 
39  // check if already on plane
40  if likely (plane.localZclamped(fts.position()) !=0) {
41  // propagate
42  bool parametersOK = this->propagateParametersOnPlane(fts, plane, x, p, s);
43  // check status and deltaPhi limit
44  float dphi2 = float(s)*rho;
45  dphi2 = dphi2*dphi2*fts.momentum().perp2();
46  if unlikely( !parametersOK || dphi2>theMaxDPhi2*fts.momentum().mag2() ) return TsosWP(TrajectoryStateOnSurface(),0.);
47  }
48  else {
49  LogDebug("AnalyticalPropagator")<<"not going anywhere. Already on surface.\n"
50  <<"plane.localZ(fts.position()): "<<plane.localZ(fts.position())<<"\n"
51  <<"plane.position().mag(): "<<plane.position().mag() <<"\n"
52  <<"plane.posPrec: "<<plane.posPrec();
53  x = fts.position();
54  p = fts.momentum();
55  s = 0;
56  }
57  //
58  // Compute propagated state and check change in curvature
59  //
60  GlobalTrajectoryParameters gtp(x,p,fts.charge(),theField);
61  if unlikely(std::abs(gtp.transverseCurvature()-rho)>theMaxDBzRatio*std::abs(rho) )
62  return TsosWP(TrajectoryStateOnSurface(),0.);
63  //
64  // construct TrajectoryStateOnSurface
65  //
66  return propagatedStateWithPath(fts,plane,gtp,s);
67 }
68 
69 
70 std::pair<TrajectoryStateOnSurface,double>
71 AnalyticalPropagator::propagateWithPath(const FreeTrajectoryState& fts,
72  const Cylinder& cylinder) const
73 {
74  // check curvature
75  double rho = fts.transverseCurvature();
76 
77  // propagate parameters
78  GlobalPoint x;
80  double s = 0;
81 
82  bool parametersOK = this->propagateParametersOnCylinder(fts, cylinder, x, p, s);
83  // check status and deltaPhi limit
84  float dphi2 = s*rho;
85  dphi2 = dphi2*dphi2*fts.momentum().perp2();
86  if unlikely( !parametersOK || dphi2>theMaxDPhi2*fts.momentum().mag2() ) return TsosWP(TrajectoryStateOnSurface(),0.);
87  //
88  // Compute propagated state and check change in curvature
89  //
90  GlobalTrajectoryParameters gtp(x,p,fts.charge(),theField);
91  if unlikely( std::abs(gtp.transverseCurvature()-rho)>theMaxDBzRatio*std::abs(rho) )
92  return TsosWP(TrajectoryStateOnSurface(),0.);
93  //
94  // create result TSOS on TangentPlane (local parameters & errors are better defined)
95  //
96 
97  //try {
98  ReferenceCountingPointer<TangentPlane> plane(cylinder.tangentPlane(x)); // need to be here until tsos is created!
99  return propagatedStateWithPath(fts,*plane,gtp,s);
100  /*
101  } catch(...) {
102  std::cout << "wrong tangent to cylinder " << x
103  << " pos, rad " << cylinder.position() << " " << cylinder.radius()
104  << std::endl;
105  return TsosWP(TrajectoryStateOnSurface(),0.);
106  }
107  */
108 }
109 
110 std::pair<TrajectoryStateOnSurface,double>
111 AnalyticalPropagator::propagatedStateWithPath (const FreeTrajectoryState& fts,
112  const Surface& surface,
113  const GlobalTrajectoryParameters& gtp,
114  const double& s) const
115 {
116  //
117  // for forward propagation: state is before surface,
118  // for backward propagation: state is after surface
119  //
120  SurfaceSide side = PropagationDirectionFromPath()(s,propagationDirection())==alongMomentum
122  //
123  //
124  // error propagation (if needed) and conversion to a TrajectoryStateOnSurface
125  //
126  if (fts.hasError()) {
127  //
128  // compute jacobian
129  //
130  AnalyticalCurvilinearJacobian analyticalJacobian(fts.parameters(), gtp.position(), gtp.momentum(), s);
131  const AlgebraicMatrix55 &jacobian = analyticalJacobian.jacobian();
132  CurvilinearTrajectoryError cte(ROOT::Math::Similarity(jacobian, fts.curvilinearError().matrix()));
133  return TsosWP(TrajectoryStateOnSurface(gtp,cte,surface,side),s);
134  }
135  else {
136  //
137  // return state without errors
138  //
139  return TsosWP(TrajectoryStateOnSurface(gtp,surface,side),s);
140  }
141 }
142 
143 bool AnalyticalPropagator::propagateParametersOnCylinder(
144  const FreeTrajectoryState& fts, const Cylinder& cylinder,
145  GlobalPoint& x, GlobalVector& p, double& s) const
146 {
147 
148  GlobalPoint const & sp = cylinder.position();
149  if (sp.x()!=0. || sp.y()!=0.) {
150  throw PropagationException("Cannot propagate to an arbitrary cylinder");
151  }
152  // preset output
153  x = fts.position();
154  p = fts.momentum();
155  s = 0;
156  // (transverse) curvature
157  double rho = fts.transverseCurvature();
158  //
159  // Straight line approximation? |rho|<1.e-10 equivalent to ~ 1um
160  // difference in transversal position at 10m.
161  //
162  if( fabs(rho)<1.e-10 )
163  return propagateWithLineCrossing(fts.position(),p,cylinder,x,s);
164  //
165  // Helix case
166  //
167  // check for possible intersection
168  const double tolerance = 1.e-4; // 1 micron distance
169  double rdiff = x.perp() - cylinder.radius();
170  if ( fabs(rdiff) < tolerance ) return true;
171  //
172  // Instantiate HelixBarrelCylinderCrossing and get solutions
173  //
174  HelixBarrelCylinderCrossing cylinderCrossing(fts.position(),fts.momentum(),rho,
175  propagationDirection(),cylinder);
176  if ( !cylinderCrossing.hasSolution() ) return false;
177  // path length
178  s = cylinderCrossing.pathLength();
179  // point
180  x = cylinderCrossing.position();
181  // direction (renormalised)
182  p = cylinderCrossing.direction().unit()*fts.momentum().mag();
183  return true;
184 }
185 
186 bool
187 AnalyticalPropagator::propagateParametersOnPlane(const FreeTrajectoryState& fts,
188  const Plane& plane,
189  GlobalPoint& x,
190  GlobalVector& p,
191  double& s) const
192 {
193  // initialisation of position, momentum and path length
194  x = fts.position();
195  p = fts.momentum();
196  s = 0;
197  // (transverse) curvature
198  double rho = fts.transverseCurvature();
199  //
200  // Straight line approximation? |rho|<1.e-10 equivalent to ~ 1um
201  // difference in transversal position at 10m.
202  //
203  if( fabs(rho)<1.e-10 )
204  return propagateWithLineCrossing(fts.position(),p,plane,x,s);
205  //
206  // Helix case
207  //
208  GlobalVector u = plane.normalVector();
209  const double small = 1.e-6; // for orientation of planes
210  //
211  // Frame-independant point and vector are created explicitely to
212  // avoid confusing gcc (refuses to compile with temporary objects
213  // in the constructor).
214  //
217  if (isOldPropagationType && fabs(u.z()) < small) {
218  // barrel plane:
219  // instantiate HelixBarrelPlaneCrossing, get vector of solutions and check for existance
220  HelixBarrelPlaneCrossingByCircle planeCrossing(helixPos,helixDir,rho,propagationDirection());
221  return propagateWithHelixCrossing(planeCrossing,plane,fts.momentum().mag(),x,p,s);
222  }
223  if (isOldPropagationType && fabs(u.x()) < small && fabs(u.y()) < small) {
224  // forward plane:
225  // instantiate HelixForwardPlaneCrossing, get vector of solutions and check for existance
226  HelixForwardPlaneCrossing planeCrossing(helixPos,helixDir,rho,propagationDirection());
227  return propagateWithHelixCrossing(planeCrossing,plane,fts.momentum().mag(),x,p,s);
228  }
229  else {
230  // arbitrary plane:
231  // instantiate HelixArbitraryPlaneCrossing, get vector of solutions and check for existance
232  if(isOldPropagationType){
233  HelixArbitraryPlaneCrossing planeCrossing(helixPos,helixDir,rho,propagationDirection());
234  return propagateWithHelixCrossing(planeCrossing,plane,fts.momentum().mag(),x,p,s);
235  }else{
236  //--- Alternative implementation to be used for the propagation of the parameters of looping
237  // particles that cross twice the (infinite) surface of the plane. It is not trivial to determine
238  // which of the two intersections has to be returned.
239 
240  //---- FIXME: WHAT FOLLOWS HAS TO BE REWRITTEN IN A CLEANER (AND CPU-OPTIMIZED) WAY ---------
241  LogDebug("AnalyticalPropagator") << "In AnaliticalProp, calling HAPC " << "\n"
242  << "plane is centered in xyz: "
243  << plane.position().x() << " , "
244  << plane.position().y() << " , "
245  << plane.position().z() << "\n";
246 
247 
248  GlobalPoint gp1 = fts.position();
249  GlobalVector gm1 = fts.momentum();
250  double s1 = 0;
251  double rho1 = fts.transverseCurvature();
252  HelixPlaneCrossing::PositionType helixPos1(gp1);
253  HelixPlaneCrossing::DirectionType helixDir1(gm1);
254  LogDebug("AnalyticalPropagator") << "gp1 before calling planeCrossing1: " << gp1 << "\n";
255  HelixArbitraryPlaneCrossing planeCrossing1(helixPos1,helixDir1,rho1,propagationDirection());
256 
259 
260  double tolerance(0.0050);
261  if(propagationDirection()==oppositeToMomentum)
262  tolerance *=-1;
263 
264  bool check1 = propagateWithHelixCrossing(planeCrossing1,plane,fts.momentum().mag(),gp1,gm1,s1);
265  double dphi1 = fabs(fts.momentum().phi()-gm1.phi());
266  LogDebug("AnalyticalPropagator") << "check1, s1, dphi, gp1: "
267  << check1 << " , "
268  << s1 << " , "
269  << dphi1 << " , "
270  << gp1 << "\n";
271 
272  //move forward a bit to avoid that the propagator doesn't propagate because the state is already on surface.
273  //we want to go to the other point of intersection between the helix and the plane
274  xGen = planeCrossing1.position(s1+tolerance);
275  pGen = planeCrossing1.direction(s1+tolerance);
276 
277  /*
278  if(!check1 || s1>170 ){
279  //PropagationDirection newDir = (propagationDirection() == alongMomentum) ? oppositeToMomentum : alongMomentum;
280  PropagationDirection newDir = anyDirection;
281  HelixArbitraryPlaneCrossing planeCrossing1B(helixPos1,helixDir1,rho1,newDir);
282  check1 = propagateWithHelixCrossing(planeCrossing1B,plane,fts.momentum().mag(),gp1,gm1,s1);
283  LogDebug("AnalyticalPropagator") << "after second attempt, check1, s1,gp1: "
284  << check1 << " , "
285  << s1 << " , " << gp1 << "\n";
286 
287  xGen = planeCrossing1B.position(s1+tolerance);
288  pGen = planeCrossing1B.direction(s1+tolerance);
289  }
290  */
291 
292  if(!check1){
293  LogDebug("AnalyticalPropagator") << "failed also second attempt. No idea what to do, then bailout" << "\n";
294  }
295 
296 
297  pGen *= gm1.mag()/pGen.mag();
298  GlobalPoint gp2(xGen);
299  GlobalVector gm2(pGen);
300  double s2 = 0;
301  double rho2 = rho1;
302  HelixPlaneCrossing::PositionType helixPos2(gp2);
303  HelixPlaneCrossing::DirectionType helixDir2(gm2);
304  HelixArbitraryPlaneCrossing planeCrossing2(helixPos2,helixDir2,rho2,propagationDirection());
305 
306  bool check2 = propagateWithHelixCrossing(planeCrossing2,plane,gm2.mag(),gp2,gm2,s2);
307 
308  if(!check2){
309  x = gp1;
310  p = gm1;
311  s = s1;
312  return check1;
313  }
314 
315  if(!check1){
316  edm::LogError("AnalyticalPropagator") << "LOGIC ERROR: I should not have entered here!" << "\n";
317  return false;
318  }
319 
320 
321  LogDebug("AnalyticalPropagator") << "check2, s2, gp2: "
322  << check2 << " , "
323  << s2 << " , " << gp2 << "\n";
324 
325 
326  double dist1 = (plane.position()-gp1).perp();
327  double dist2 = (plane.position()-gp2).perp();
328 
329 
330  LogDebug("AnalyticalPropagator") << "propDir, dist1, dist2: "
331  << propagationDirection() << " , "
332  << dist1 << " , "
333  << dist2 << "\n";
334 
335  //If there are two solutions, the one which is the closest to the module's center is chosen
336  if(dist1<2*dist2){
337  x = gp1;
338  p = gm1;
339  s = s1;
340  return check1;
341  }else if(dist2<2*dist1){
342  x = gp2;
343  p = gm2;
344  s = s1+s2+tolerance;
345  return check2;
346  }else{
347  if(fabs(s1)<fabs(s2)){
348  x = gp1;
349  p = gm1;
350  s = s1;
351  return check1;
352  }else{
353  x = gp2;
354  p = gm2;
355  s = s1+s2+tolerance;
356  return check2;
357  }
358  }
359 
360  //-------- END of ugly piece of code ---------------
361  }
362 
363  }
364 }
365 
366 bool
367 AnalyticalPropagator::propagateWithLineCrossing (const GlobalPoint& x0,
368  const GlobalVector& p0,
369  const Plane& plane,
370  GlobalPoint& x, double& s) const {
371  //
372  // Instantiate auxiliary object for finding intersection.
373  // Frame-independant point and vector are created explicitely to
374  // avoid confusing gcc (refuses to compile with temporary objects
375  // in the constructor).
376  //
379  StraightLinePlaneCrossing planeCrossing(pos,dir,propagationDirection());
380  //
381  // get solution
382  //
383  std::pair<bool,double> propResult = planeCrossing.pathLength(plane);
384  if ( !propResult.first ) return false;
385  s = propResult.second;
386  // point (reconverted to GlobalPoint)
387  x = GlobalPoint(planeCrossing.position(s));
388  //
389  return true;
390 }
391 
392 bool
393 AnalyticalPropagator::propagateWithLineCrossing (const GlobalPoint& x0,
394  const GlobalVector& p0,
395  const Cylinder& cylinder,
396  GlobalPoint& x, double& s) const {
397  //
398  // Instantiate auxiliary object for finding intersection.
399  // Frame-independant point and vector are created explicitely to
400  // avoid confusing gcc (refuses to compile with temporary objects
401  // in the constructor).
402  //
403  StraightLineBarrelCylinderCrossing cylCrossing(x0,p0,propagationDirection());
404  //
405  // get solution
406  //
407  std::pair<bool,double> propResult = cylCrossing.pathLength(cylinder);
408  if ( !propResult.first ) return false;
409  s = propResult.second;
410  // point (reconverted to GlobalPoint)
411  x = cylCrossing.position(s);
412  //
413  return true;
414 }
415 
416 bool
417 AnalyticalPropagator::propagateWithHelixCrossing (HelixPlaneCrossing& planeCrossing,
418  const Plane& plane,
419  const float pmag,
420  GlobalPoint& x,
421  GlobalVector& p,
422  double& s) const {
423  // get solution
424  std::pair<bool,double> propResult = planeCrossing.pathLength(plane);
425  if ( !propResult.first ) return false;
426  s = propResult.second;
427  // point (reconverted to GlobalPoint)
428  HelixPlaneCrossing::PositionType xGen = planeCrossing.position(s);
429  x = GlobalPoint(xGen);
430  // direction (reconverted to GlobalVector, renormalised)
431  HelixPlaneCrossing::DirectionType pGen = planeCrossing.direction(s);
432  pGen *= pmag/pGen.mag();
433  p = GlobalVector(pGen);
434  //
435  return true;
436 }
#define LogDebug(id)
T mag2() const
Definition: PV3DBase.h:66
T mag() const
The vector magnitude. Equivalent to sqrt(vec.mag2())
const GlobalTrajectoryParameters & parameters() const
const AlgebraicMatrix55 & jacobian() const
virtual DirectionType direction(double s) const =0
Definition: DDAxes.h:10
Geom::Phi< T > phi() const
Definition: PV3DBase.h:69
Global3DPoint GlobalPoint
Definition: GlobalPoint.h:10
T y() const
Definition: PV3DBase.h:63
float localZ(const GlobalPoint &gp) const
Definition: Plane.h:49
float posPrec() const
Definition: Plane.h:66
T perp2() const
Definition: PV3DBase.h:71
TrackCharge charge() const
const CurvilinearTrajectoryError & curvilinearError() const
Definition: Plane.h:17
tuple s2
Definition: indexGen.py:106
#define unlikely(x)
Definition: Likely.h:21
T mag() const
Definition: PV3DBase.h:67
T phi() const
Definition: Phi.h:41
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
GlobalVector momentum() const
Vector3DBase unit() const
Definition: Vector3DBase.h:57
GlobalPoint position() const
float localZclamped(const GlobalPoint &gp) const
Definition: Plane.h:54
virtual std::pair< bool, double > pathLength(const Plane &)=0
double transverseCurvature() const
virtual PositionType position(double s) const =0
T perp() const
Magnitude of transverse component.
#define likely(x)
Definition: Likely.h:20
const AlgebraicSymMatrix55 & matrix() const
dbl *** dir
Definition: mlp_gen.cc:35
Definition: DDAxes.h:10
T x() const
Definition: PV3DBase.h:62
const PositionType & position() const
ROOT::Math::SMatrix< double, 5, 5, ROOT::Math::MatRepStd< double, 5, 5 > > AlgebraicMatrix55
Global3DVector GlobalVector
Definition: GlobalVector.h:10