Public Member Functions | Static Public Member Functions | Static Private Member Functions | List of all members
util::TrackPropagator Class Reference

#include <TrackPropagator.h>

Public Member Functions

 TrackPropagator ()=delete
 
 TrackPropagator (const TrackPropagator &)=delete
 
 ~TrackPropagator ()=delete
 

Static Public Member Functions

static int PropagateToCylinder (const float *trackpar, const float *Xpoint, const float rCyl, const float yCyl, const float zCyl, float *retXYZ1, float *retXYZ2, const float Xmax=0.0, const float epsilon=2.0e-5)
 
static int PropagateToX (const float *trackpar, const float *Xpoint, const float x, float *retXYZ, const float Rmax=0.0)
 
static int DistXYZ (const float *trackpar, const float *Xpoint, const float *xyz, float &retDist)
 
static int DirectionX (const float *trackpar, const float *Xpoint, float &xEval, float *retXYZ)
 
static int DirectionPhi (const float *trackpar, const float *Xpoint, float &phiEval, float *retXYZ)
 

Static Private Member Functions

static float d2 (float xt, float yt, float zt, float x0, float yc, float zc, float r, float s, float phi, float phi0)
 

Detailed Description

Definition at line 25 of file TrackPropagator.h.

Constructor & Destructor Documentation

util::TrackPropagator::TrackPropagator ( )
delete
util::TrackPropagator::TrackPropagator ( const TrackPropagator )
delete
util::TrackPropagator::~TrackPropagator ( )
delete

Member Function Documentation

float util::TrackPropagator::d2 ( float  xt,
float  yt,
float  zt,
float  x0,
float  yc,
float  zc,
float  r,
float  s,
float  phi,
float  phi0 
)
staticprivate

Definition at line 339 of file TrackPropagator.cxx.

341  {
342  float dx = (xt -x0) - (r/s)*(phi -phi0);
343  float dy = (yt -yc) + r*TMath::Cos(phi);
344  float dz = (zt -zc) - r*TMath::Sin(phi);
345  return dx*dx + dy*dy + dz*dz;
346  }
static QCString * s
Definition: config.cpp:1042
int util::TrackPropagator::DirectionPhi ( const float *  trackpar,
const float *  Xpoint,
float &  phiEval,
float *  retXYZ 
)
static

Definition at line 324 of file TrackPropagator.cxx.

325  {
326 
327  retXYZ[0] = std::tan(trackpar[4]);
328  retXYZ[1] = std::sin(phiEval);
329  retXYZ[2] = std::cos(phiEval);
330  float norm = std::hypot(retXYZ[0],retXYZ[1],retXYZ[2]);
331  for (int i=0; i<3; ++i) retXYZ[i] /= norm;
332 
333  return 0;
334  }
std::enable_if_t< std::is_arithmetic_v< T >, T > hypot(T x, T y)
Definition: hypot.h:60
auto norm(Vector const &v)
Return norm of the specified vector.
int util::TrackPropagator::DirectionX ( const float *  trackpar,
const float *  Xpoint,
float &  xEval,
float *  retXYZ 
)
static

Two methods for direction of track at an arbitrary x or phi. Differs from Track::FindDirectionFromTrackParameters in that that method only finds directions at the two ends of the track and has a different sign convention. One evaluates at a value of x and the other evaluates at a specific value of phi. You may call them like so:

util::TrackPropagator::DirectionX (Track::TrackParBeg(),Track::Vertex(), float&,float[3]) util::TrackPropagator::DirectionPar(Track::TrackParBeg(),Track::Vertex(), float&,float[3])

where Track::Vertex() would specify the Xo where the track parameters of the first argument are valid. The float& is either the x or phi value at which the direction is wanted and the float[3] will be the returned unit direction vector.

The return value is 0 for good return; DirectionX can return 1 for zero curvature.

Definition at line 309 of file TrackPropagator.cxx.

310  {
311 
312  if (trackpar[2]==0) return 1;
313  float r = 1.0/trackpar[2];
314  float s = std::tan(trackpar[4]);
315  float x0 = Xpoint[0];
316 
317  float phi = (xEval -x0)/(r*s);
318  DirectionPhi(trackpar,Xpoint, phi, retXYZ);
319  return 0;
320  }
static int DirectionPhi(const float *trackpar, const float *Xpoint, float &phiEval, float *retXYZ)
static QCString * s
Definition: config.cpp:1042
int util::TrackPropagator::DistXYZ ( const float *  trackpar,
const float *  Xpoint,
const float *  xyz,
float &  retDist 
)
static

Finds the distance from the point xyz to this track. You may call it so:

util::TrackPropagator::DistXYZ( Track::TrackParBeg(), Track::Vertex(), float[3], &float)

where the float[3] is the input (x,y,z) point and last float will be the computed distance. Or, you may call it like this:

util::TrackPropagator::DistXYZ( Track::TrackParEnd(), Track::End(), float[3], &float)

but don't mix the ends! The 2nd argument is an initial guess for the iteration to the point of closest approach.

Return values are 0 for good finish, 1 for straight track, or 2 for track parallel to the x axis; but the computed distance is OK for all return values.

Definition at line 208 of file TrackPropagator.cxx.

209  {
210 
211  retDist = 0;
212 
213  // just to make formulas more readable. (xt,yt,zt) = test point.
214  float xt = xyz[0];
215  float yt = xyz[1];
216  float zt = xyz[2];
217 
218  float x0 = Xpoint[0];
219  float y0 = trackpar[0];
220  float z0 = trackpar[1];
221  float curv = trackpar[2];
222  float r = 1.0/curv;
223  float phi0 = trackpar[3];
224 
225  float s = std::tan(trackpar[4]);
226  if (s != 0) {
227  s = 1.0/s;
228  } else {
229  s = 1E9;
230  }
231 
232  float sinphi0 = std::sin(phi0);
233  float cosphi0 = std::cos(phi0);
234  float zc = trackpar[1] - r * sinphi0;
235  float yc = trackpar[0] + r * cosphi0;
236 
237  if (curv == 0) {
238  // distance from a point to a line -- use the norm of the cross product of the
239  // unit vector along the line and the displacement between the test point and
240  // a point on the line
241 
242  float h = std::sqrt(1.0 + s*s);
243  float xhc = s*(yt-y0)*(cosphi0/h) - s*(sinphi0/h)*(zt-z0);
244  float yhc = (zt-z0)/h - s*(xt-x0)*(cosphi0/h);
245  float zhc = s*(xt-x0)*(sinphi0/h) - (yt-y0)/h;
246 
247  retDist = std::sqrt( xhc*xhc + yhc*yhc + zhc*zhc );
248  return 1;
249  }
250 
251  if (s == 0) {
252  // zero slope. The track is another line, this time along the x axis
253  retDist = std::sqrt( TMath::Sq(yt-y0) + TMath::Sq(zt-z0) );
254  return 2;
255  }
256 
257  // general case -- need to compute distance from a point to a helix
258  float span = M_PI;
259  float gold = 1.61803398875;
260 
261  // First guess is phi for this xt; but try also +/- a half turn as
262  // that could easily be closer
263  float phicent = (s*curv)*(xt-x0) +phi0;
264  float d2cent = d2(xt,yt,zt, x0,yc,zc, r,s, phicent, phi0);
265  float philow = phicent -span;
266  float d2low = d2(xt,yt,zt, x0,yc,zc, r,s, philow, phi0);
267  float phihi = phicent +span;
268  float d2hi = d2(xt,yt,zt, x0,yc,zc, r,s, phihi, phi0);
269  if ( d2low<d2cent ) {
270  // In fact, d2low==d2high at this point. Pick one solution,
271  // somewhat arbitrarily; go for the one closest to phi0.
272  if ( std::fabs(philow -phi0) < std::fabs(phihi -phi0) ) {
273  phicent = philow;
274  } else {
275  phicent = phihi;
276  }
277  philow = phicent -span;
278  phihi = phicent +span;
279  }
280 
281 
282  // solve for phi of the closest point using quadratic fit; 18 iters gives
283  // phi to 1mrad accuracy
284  for (size_t iter=0; iter<18; ++iter) {
285  // 2 coefficients of the quadratic; requires (phihi -phicent) == (phicent -philow)
286  float B = (d2hi -d2low) / (2*span);
287  float A = (d2hi +d2low -2*d2cent) / ( 2*span*span );
288  if ( A == 0 ) break; // d2hi, d2low & d2cent all pretty close- just quit
289  phicent += -B / (2*A);
290  span /= gold;
291  philow = phicent -span;
292  phihi = phicent +span;
293  d2cent = d2(xt,yt,zt, x0,yc,zc, r,s, phicent, phi0);
294  d2low = d2(xt,yt,zt, x0,yc,zc, r,s, philow, phi0);
295  d2hi = d2(xt,yt,zt, x0,yc,zc, r,s, phihi, phi0);
296  }
297 
298  float xp = x0 + r*(phicent -phi0)/s;
299  float yp = yc - r*TMath::Cos(phicent);
300  float zp = zc + r*TMath::Sin(phicent);
301  retDist = std::sqrt(TMath::Sq(xt-xp) +TMath::Sq(yt-yp) +TMath::Sq(zt-zp));
302 
303  return 0;
304  }
span(IterB &&b, IterE &&e, Adaptor &&adaptor) -> span< decltype(adaptor(std::forward< IterB >(b))), decltype(adaptor(std::forward< IterE >(e))) >
#define M_PI
Definition: includeROOT.h:54
#define A
Definition: memgrp.cpp:38
static float d2(float xt, float yt, float zt, float x0, float yc, float zc, float r, float s, float phi, float phi0)
static QCString * s
Definition: config.cpp:1042
int util::TrackPropagator::PropagateToCylinder ( const float *  trackpar,
const float *  Xpoint,
const float  rCyl,
const float  yCyl,
const float  zCyl,
float *  retXYZ1,
float *  retXYZ2,
const float  Xmax = 0.0,
const float  epsilon = 2.0e-5 
)
static

IMPORTANT: Make sure that you have a consistent set of coordinate systems in the arguments passed to all these methods. As a rule, track parameters are expressed in the coordinate system implicitly defined by the geometry gdml file specified in the —.fcl file. But in writing algorithms that check if some track extrapolates out to some point or whatever, you might be thinking in another coordinate system, e.g. one where the center of the MPD is at (0, 0, 0). That would be an error. Consider trying instead something like

int result = util::TrackPropagator::PropagateToCylinder(trk->TrackParEnd(), trk->End(), fGeo->GetECALInnerBarrelRadius(),fGeo->TPCYCent(),fGeo->TPCZCent(), xyz_intersection, fGeo->GetECALEndcapStartX() );

where fGeo is an

const gar::geo::GeometryCore* fGeo = gar::providerFrom<geo::GeometryGAr>(); Finds two intersections of a helix with an infinite cylinder of radius rCyl, centered at yCyl, zCyl and parallel to the x axis, storing the "closest" intersection in retXYZ1, meaning that the value of phi at the intersection is closest to what it is at Xpoint. The other intersection is returned in retXYZ2. Status codes: 0 is success; 1,2, 3 and 4 are rno-intersection conditions. If the helix cylinder and given cylinder are disjoint, returns 1; if one is entirely inside the other, status is 2; if the cylinders have a common axes, status is 3. Status code 4 results when the track has zero curvature and the line does not intersect the cylinder. If the intersections are found, and Xmax > 0, this function checks if the selected intersection is outside the range [-Xmax,+Xmax] and returns status code 5 if either of them are. In this case the return value retXYZ is still valid. retXYZ must be float[3] in the calling code; trackpar and Xpoint are as in PropagateToX and DistXYZ.

Definition at line 9 of file TrackPropagator.cxx.

12  {
13  //track fitted parameters (y, z, curvature, phi, lambda)
14  // Don't forget r can be negative! But rCyl can't :)
15  const float y0 = trackpar[0];
16  const float z0 = trackpar[1];
17  const float curv = trackpar[2];
18  const float phi0 = trackpar[3];
19  const float tanl = std::tan(trackpar[4]);
20 
21 
22 
23  // Radius of curvature of track
24  float radius;
25  if (curv != 0) {
26  radius = 1.0 / curv;
27  } else {
28  // Straight-line algorithm not tested. Probably not needed, really.
29  // From Wolfram MathWorld
30  float zL[2]; float yL[2];
31  zL[0] = zCyl -rCyl -1.0; zL[1] = zCyl +rCyl +1.0;
32  for (int i=0; i<2; ++i) yL[i] = y0 +(zL[i] -z0)*std::tan(phi0);
33 
34  float Dx = zL[1] -zL[0]; float Dy = yL[1] -yL[0];
35  float Dr = std::hypot(Dx,Dy); float D = zL[0]*yL[1] -zL[1]*yL[0];
36  float det = (rCyl*Dr)*(rCyl*Dr) - D*D;
37  if (det<0) return 4;
38 
39  float zz1 = (D*Dy +Dx*det) / (Dr*Dr);
40  float zz2 = (D*Dy -Dx*det) / (Dr*Dr);
41  float yy1 = y0 +(zz1 -z0)*std::tan(phi0);
42  float yy2 = y0 +(zz2 -z0)*std::tan(phi0);
43  if ( std::hypot(zz1-z0,yy1-y0) < std::hypot(zz2-z0,yy2-y0) ) {
44  retXYZ1[1] = yy1;
45  retXYZ1[2] = zz1;
46  retXYZ2[1] = yy2;
47  retXYZ2[2] = zz2;
48  } else {
49  retXYZ1[1] = yy2;
50  retXYZ1[2] = zz2;
51  retXYZ2[1] = yy1;
52  retXYZ2[2] = zz1;
53  }
54  retXYZ1[0] = ( retXYZ1[2]-z0 ) / std::cos(phi0);
55  retXYZ2[0] = ( retXYZ2[2]-z0 ) / std::cos(phi0);
56  return 0;
57  }
58 
59 
60  //Coordinate of the center of the circle of radius r
61  float zcc = z0 - radius * std::sin(phi0);
62  float ycc = y0 + radius * std::cos(phi0);
63 
64  // dz and dy are the 'horizontal' and 'vertical' distances between
65  // the circle centers.
66  float dz = zcc - zCyl;
67  float dy = ycc - yCyl;
68 
69  /* Determine the straight-line distance between the centers. */
70  const float d = std::hypot(dy, dz);
71 
72  /* Check for solvability. */
73  if ( d > (rCyl + abs(radius)) ) {
74  /* no solution. circles do not intersect. */
75  return 1;
76  }
77  if (d < std::fabs(rCyl - abs(radius))) {
78  /* no solution. one circle is contained in the other */
79  return 2;
80  }
81  if (d < epsilon) {
82  /* no solution. circles have common centre */
83  return 3;
84  }
85 
86  // Calculate the intersection point between the cylinder and the track
87  float phiStar = (d*d + rCyl*rCyl - radius*radius);
88  phiStar /= 2 * std::max(1.e-20f, rCyl * d);
89  if (phiStar > +1.f) phiStar = +0.9999999f;
90  if (phiStar < -1.f) phiStar = -0.9999999f;
91  phiStar = std::acos(phiStar);
92 
93  float phiCentre(std::atan2(dy, dz));
94 
95  // There are two solutions which can not differ in phi from
96  // phi0 by more than 2pi.
97  float zz1 = zCyl + rCyl * std::cos(phiCentre + phiStar);
98  float yy1 = yCyl + rCyl * std::sin(phiCentre + phiStar);
99  // Add pi/2 or 3pi/2 because of definition of where phi = 0
100  float phi1 = atan2( yy1-ycc, zz1-zcc );
101  phi1 += (curv>=0) ? M_PI/2.0 : 3.0*M_PI/2.0;
102  float zz2 = zCyl + rCyl * std::cos(phiCentre - phiStar);
103  float yy2 = yCyl + rCyl * std::sin(phiCentre - phiStar);
104  float phi2 = atan2( yy2-ycc, zz2-zcc );
105  phi2 += (curv>=0) ? M_PI/2.0 : 3.0*M_PI/2.0;
106 
107  float dphi1 = phi1 -phi0;
108  float dphi2 = phi2 -phi0;
109  int nturns = dphi1/(2.0*M_PI);
110  // bring dphi1 in the range 0-2pi, then into range -pi to +pi
111  if (dphi1 > +(2.0*M_PI)) dphi1 -= (2.0*M_PI)*nturns;
112  if (dphi1 < -(2.0*M_PI)) dphi1 += (2.0*M_PI)*nturns;
113  if (dphi1 > +M_PI) dphi1 -= 2.0*M_PI;
114  if (dphi1 < -M_PI) dphi1 += 2.0*M_PI;
115  // likewise dphi2
116  nturns = dphi2/(2.0*M_PI);
117  if (dphi2 > +(2.0*M_PI)) dphi2 -= (2.0*M_PI)*nturns;
118  if (dphi2 < -(2.0*M_PI)) dphi2 += (2.0*M_PI)*nturns;
119  if (dphi2 > +M_PI) dphi2 -= 2.0*M_PI;
120  if (dphi2 < -M_PI) dphi2 += 2.0*M_PI;
121  if ( fabs(dphi1) < fabs(dphi2) ) {
122  retXYZ1[1] = yy1;
123  retXYZ1[2] = zz1;
124  retXYZ1[0] = Xpoint[0] + radius * tanl * dphi1;
125  retXYZ2[1] = yy2;
126  retXYZ2[2] = zz2;
127  retXYZ2[0] = Xpoint[0] + radius * tanl * dphi2;
128 
129  } else {
130  retXYZ1[1] = yy2;
131  retXYZ1[2] = zz2;
132  retXYZ1[0] = Xpoint[0] + radius * tanl * dphi2;
133  retXYZ2[1] = yy1;
134  retXYZ2[2] = zz1;
135  retXYZ2[0] = Xpoint[0] + radius * tanl * dphi1;
136  }
137 
138  // If Xmax > 0, check if found intersection has x beyond it - i.e.
139  // it might be in the endcap
140  if ( std::fabs(Xmax) > 0 ) {
141  if ( std::fabs(retXYZ1[0]) > std::fabs(Xmax) ) {
142  // std::cout << "5 - x > Xmax, might be in the endcap" << std::endl;
143  return 5;
144  }
145  if ( std::fabs(retXYZ2[0]) > std::fabs(Xmax) ) {
146  return 5;
147  }
148 
149  }
150 
151  return 0;
152  }
constexpr auto abs(T v)
Returns the absolute value of the argument.
#define D
Debug message.
Definition: tclscanner.cpp:775
std::enable_if_t< std::is_arithmetic_v< T >, T > hypot(T x, T y)
Definition: hypot.h:60
const double e
static int max(int a, int b)
#define M_PI
Definition: includeROOT.h:54
int util::TrackPropagator::PropagateToX ( const float *  trackpar,
const float *  Xpoint,
const float  x,
float *  retXYZ,
const float  Rmax = 0.0 
)
static

Finds the point on the track in 3d, given the x value. You might call it like this:

TrackPropagator::PropagateToX(Track::TrackParBeg(),Track::Vertex(),float,float[3])

where the first float is the x input and the float[3] will be the computed (x,y,z) point. Or, you may call it like this:

TrackPropagator::PropagateToX(Track::TrackParEnd(),Track::End(),float,float[3],250.0)

but don't mix the ends! Track::Vertex() is used to give the Xo for the parameters of Track::TrackParBeg() and Track::End() specifies the Xo where the track parameters of Track::TrackParEnd() are valid.

Return values are 0 for good finish, 1 for straight track; if Rmax > 0 , returns 2 if y^2 + z^2 > Rmax^2 – means you might want to use PropagateToCylinder

Definition at line 157 of file TrackPropagator.cxx.

159  {
160  int retval = 0;
161  float y, z;
162 
163  const float y0 = trackpar[0];
164  const float z0 = trackpar[1];
165  const float phi0 = trackpar[3];
166  const float curv = trackpar[2];
167  float radius = 0;
168  if (curv != 0) radius = 1.0 / curv;
169 
170  float ZCent = trackpar[1] - radius*std::sin(phi0);
171  float YCent = trackpar[0] + radius*std::cos(phi0);
172  float tanl = std::tan(trackpar[4]);
173 
174 
175 
176  if (radius == 0) {
177  // Straight-line case not tested yet
178  float dT = (x -Xpoint[0]) / tanl;
179  y = y0 +dT*std::sin(phi0);
180  z = z0 +dT*std::cos(phi0);
181  retval = 1;
182  } else {
183  float s;
184  if (tanl != 0) {
185  s = 1.0/tanl;
186  } else {
187  s = 1E9;
188  retval = 1;
189  }
190 
191  float phi = (x - Xpoint[0]) * s / radius + phi0;
192  y = YCent - radius * std::cos(phi);
193  z = ZCent + radius * std::sin(phi);
194  }
195 
196  if ( Rmax > 0 ) {
197  if ( std::hypot(z,y) > Rmax ) retval = 2;
198  }
199 
200  retXYZ[0] = x; retXYZ[1] = y; retXYZ[2] = z;
201 
202  return retval;
203  }
std::enable_if_t< std::is_arithmetic_v< T >, T > hypot(T x, T y)
Definition: hypot.h:60
list x
Definition: train.py:276
static QCString * s
Definition: config.cpp:1042

The documentation for this class was generated from the following files: