MarlinTrk  02.08
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
LCIOTrackPropagators.cc
Go to the documentation of this file.
1 
3 
4 #include <cmath>
5 #include <iostream>
6 
7 #include "IMPL/TrackStateImpl.h"
8 
9 #include "CLHEP/Matrix/Matrix.h"
10 #include "CLHEP/Matrix/SymMatrix.h"
11 #include "CLHEP/Vector/TwoVector.h"
12 
13 #include "streamlog/streamlog.h"
14 
15 
16 namespace LCIOTrackPropagators{
17 
18  int PropagateLCIOToNewRef( IMPL::TrackStateImpl& ts, double xref, double yref, double zref ) {
19 
20  // std::cout << "PropagateLCIOToNewRef: x:y:z = " << xref << " : " << yref << " : " << zref << std::endl ;
21 
22  // Convert Parameters
23 
24  const double d0 = ts.getD0() ;
25  const double phi0 = ts.getPhi() ;
26  const double omega = ts.getOmega() ;
27  const double z0 = ts.getZ0() ;
28  const double tanL = ts.getTanLambda() ;
29 
30  // const double charge = omega/fabs(omega) ;
31  const float* ref = ts.getReferencePoint() ;
32 
33  const double radius = 1.0/omega ;
34 
35  const double sinPhi0 = sin(phi0) ;
36  const double cosPhi0 = cos(phi0) ;
37 
38  const double deltaX = xref - ref[0] ;
39  const double deltaY = yref - ref[1] ;
40 
41  double phi0Prime = atan2( sinPhi0 - (deltaX/(radius-d0)) , cosPhi0 + (deltaY/(radius-d0)) ) ;
42 
43  while ( phi0Prime < 0 ) phi0Prime += 2.0*M_PI ;
44  while ( phi0Prime >= 2.0*M_PI ) phi0Prime -= 2.0*M_PI ;
45 
46  const double d0Prime = d0 + deltaX*sinPhi0 - deltaY*cosPhi0 + ( ( deltaX*cosPhi0 + deltaY*sinPhi0 ) * tan( (phi0Prime-phi0) / 2.0) ) ;
47 
48  // In order to have terms which behave well as Omega->0 we make use of deltaX and deltaY to replace sin( phi0Prime - phi0 ) and cos( phi0Prime - phi0 )
49 
50  const double sinDeltaPhi = ( -omega / ( 1.0 - ( omega * d0Prime ) ) ) * ( deltaX * cosPhi0 + deltaY * sinPhi0 ) ;
51 
52  const double cosDeltaPhi = 1.0 + ( omega*omega / ( 2.0 * ( 1.0 - omega * d0Prime ) ) ) * ( d0Prime*d0Prime - ( deltaX + d0 * sinPhi0 )*( deltaX + d0 * sinPhi0 ) - ( deltaY - d0 * cosPhi0 )*( deltaY - d0 * cosPhi0 ) ) ;
53 
54  const double s = atan2(-sinDeltaPhi,cosDeltaPhi) / omega ;
55 
56  const double z0Prime = ref[2] - zref + z0 + tanL * s ;
57 
58 
59  // Convert Covariance Matrix
60  CLHEP::HepSymMatrix cov0(5) ;
61 
62  int icov = 0 ;
63 
64  for(int irow=0; irow<5; ++irow ){
65  for(int jcol=0; jcol<irow+1; ++jcol){
66  // std::cout << "row = " << irow << " col = " << jcol << std::endl ;
67  // std::cout << "cov["<< icov << "] = " << _cov[icov] << std::endl ;
68  cov0[irow][jcol] = ts.getCovMatrix()[icov] ;
69  ++icov ;
70  }
71  }
72 
73  CLHEP::HepMatrix propagatorMatrix(5, 5, 0) ;
74 
75  // LC_0 = { d0, phi0, omega, z0, tanLambda }
76 
77  // d d0' / d LC_0
78  propagatorMatrix(1,1) = cosDeltaPhi ;
79  propagatorMatrix(1,2) = -( radius - d0 ) * sinDeltaPhi ;
80  propagatorMatrix(1,3) = radius*radius * ( cosDeltaPhi -1 ) ;
81 
82  // d phi0' / d LC_0
83  propagatorMatrix(2,1) = sinDeltaPhi / ( radius - d0Prime ) ;
84  propagatorMatrix(2,2) = ( ( radius - d0 ) * cosDeltaPhi ) / ( radius - d0Prime ) ;
85  propagatorMatrix(2,3) = radius*radius * sinDeltaPhi / ( radius - d0Prime ) ;
86 
87  // d omega' / d LC_0
88  propagatorMatrix(3,3) = 1.0 ;
89 
90  // d z0' / d LC_0
91  propagatorMatrix(4,1) = radius * tanL * sinDeltaPhi / ( d0Prime + radius ) ;
92  propagatorMatrix(4,2) = radius * tanL * ( 1.0 - ( ( d0 + radius ) * cosDeltaPhi / ( d0Prime + radius ) ) ) ;
93  propagatorMatrix(4,3) = radius*radius * tanL * ( (phi0Prime - phi0) - radius * sinDeltaPhi / ( d0Prime + radius ) ) ;
94  propagatorMatrix(4,4) = 1.0 ;
95  propagatorMatrix(4,5) = s ;
96 
97  // d tanLambda' / d LC_0
98  propagatorMatrix(5,5) = 1.0 ;
99 
100 
101  CLHEP::HepSymMatrix covPrime = cov0.similarity(propagatorMatrix);
102 
103  EVENT::FloatVec cov( 15 ) ;
104 
105  icov = 0 ;
106 
107  for(int irow=0; irow<5; ++irow ){
108  for(int jcol=0; jcol<irow+1; ++jcol){
109  // std::cout << "row = " << irow << " col = " << jcol << std::endl ;
110  cov[icov] = covPrime[irow][jcol] ;
111  // std::cout << "lcCov["<< icov << "] = " << lcCov[icov] << std::endl ;
112  ++icov ;
113  }
114  }
115 
116  while ( phi0Prime < -M_PI ) phi0Prime += 2.0*M_PI ;
117  while ( phi0Prime >= M_PI ) phi0Prime -= 2.0*M_PI ;
118 
119  ts.setD0( d0Prime ) ;
120  ts.setPhi( phi0Prime ) ;
121  ts.setOmega( omega ) ;
122  ts.setZ0( z0Prime ) ;
123  ts.setTanLambda( tanL ) ;
124 
125 
126  float refPointPrime[3] ;
127  refPointPrime[0] = xref ;
128  refPointPrime[1] = yref ;
129  refPointPrime[2] = zref ;
130 
131  ts.setReferencePoint(refPointPrime) ;
132 
133  ts.setCovMatrix( cov ) ;
134 
135  return 0 ;
136 
137 
138  }
139 
140  // Propagate track to a new reference point taken as its crossing point with a cylinder of infinite length centered at x0,y0, parallel to the z axis.
141  // For direction== 0 the closest crossing point will be taken
142  // For direction== 1 the first crossing traversing in positive s will be taken
143  // For direction==-1 the first crossing traversing in negative s will be taken
144 
145  int PropagateLCIOToCylinder( IMPL::TrackStateImpl& ts, float r0, float x0, float y0, int direction, double epsilon){
146 
147  // taken from http://paulbourke.net/geometry/2circle/tvoght.c
148 
149  // std::cout << "PropagateLCIOToCylinder: r = " << r0 << " x0:y0 = " << x0 << " : " << y0 << " direction = " << direction << std::endl ;
150 
151 
152  const double x_ref = ts.getReferencePoint()[0] ;
153  const double y_ref = ts.getReferencePoint()[1] ;
154  const double z_ref = ts.getReferencePoint()[2] ;
155 
156  const double d0 = ts.getD0() ;
157  const double z0 = ts.getZ0() ;
158  const double phi0 = ts.getPhi() ;
159  const double tanl = ts.getTanLambda() ;
160  const double omega = ts.getOmega() ;
161 
162  const double rho = 1.0 / omega ;
163  const double x_pca = x_ref - d0 * sin(phi0) ;
164  const double y_pca = y_ref + d0 * cos(phi0) ;
165  const double z_pca = z_ref + z0 ;
166 
167  const double sin_phi0 = sin(phi0);
168  const double cos_phi0 = cos(phi0);
169 
170  const double x_c = x_ref + ( rho - d0) * sin_phi0 ;
171  const double y_c = y_ref - ( rho - d0) * cos_phi0 ;
172 
173  const double r1 = fabs(rho) ;
174 
175  /* dx and dy are the vertical and horizontal distances between
176  * the circle centers.
177  */
178  const double dx = x_c - x0;
179  const double dy = y_c - y0;
180 
181  /* Determine the straight-line distance between the centers. */
182  const double d = hypot(dx,dy);
183 
184  /* Check for solvability. */
185  if (d > (r0 + r1))
186  {
187  /* no solution. circles do not intersect. */
188  return 1;
189  }
190  if (d < fabs(r0 - r1))
191  {
192  /* no solution. one circle is contained in the other */
193  return 2;
194  }
195  if (d < epsilon)
196  {
197  /* no solution. circles have common centre */
198  return 3;
199  }
200 
201  /* 'point 2' is the point where the line through the circle
202  * intersection points crosses the line between the circle
203  * centers.
204  */
205 
206  /* Determine the distance from point 0 to point 2. */
207  const double a = ((r0*r0) - (r1*r1) + (d*d)) / (2.0 * d) ;
208 
209  /* Determine the coordinates of point 2. */
210  const double x2 = x0 + (dx * a/d);
211  const double y2 = y0 + (dy * a/d);
212 
213  /* Determine the distance from point 2 to either of the
214  * intersection points.
215  */
216  const double h = sqrt((r0*r0) - (a*a));
217 
218  /* Now determine the offsets of the intersection points from
219  * point 2.
220  */
221  const double rx = -dy * (h/d);
222  const double ry = dx * (h/d);
223 
224  /* Determine the absolute intersection points. */
225  const double x_ins1 = x2 + rx;
226  const double y_ins1 = y2 + ry;
227 
228  const double x_ins2 = x2 - rx;
229  const double y_ins2 = y2 - ry;
230 
231  // std::cout << "PropagateLCIOToCylinder: 1st solution x:y = " << x_ins1 << " : " << y_ins1 << std::endl ;
232  // std::cout << "PropagateLCIOToCylinder: 2nd solution x:y = " << x_ins2 << " : " << y_ins2 << std::endl ;
233 
234  // now calculate the path lengths
235  double s_1 = 0.0 ;
236  double s_2 = 0.0 ;
237 
238  const double delta_x1 = x_ins1 - x_pca ;
239  const double delta_y1 = y_ins1 - y_pca ;
240 
241  const double sin_delta_phi1 = - omega*delta_x1*cos_phi0 - omega*delta_y1*sin_phi0 ;
242  const double cos_delta_phi1 = 1.0 - omega*delta_x1*sin_phi0 + omega*delta_y1*cos_phi0 ;
243 
244  s_1 = atan2(-sin_delta_phi1,cos_delta_phi1) / omega ;
245 
246 
247  const double delta_x2 = x_ins2 - x_pca ;
248  const double delta_y2 = y_ins2 - y_pca ;
249 
250  const double sin_delta_phi2 = - omega*delta_x2*cos_phi0 - omega*delta_y2*sin_phi0 ;
251  const double cos_delta_phi2 = 1.0 - omega*delta_x2*sin_phi0 + omega*delta_y2*cos_phi0 ;
252 
253  s_2 = atan2(-sin_delta_phi2,cos_delta_phi2) / omega ;
254 
255  double x=0, y=0, z=0 ;
256 
257  if( direction == 0 ) { // take closest intersection
258  if( fabs(s_1) < fabs(s_2) ) {
259  // std::cout << "PropagateLCIOToCylinder: use 1st solution" << std::endl ;
260  x = x_ins1 ;
261  y = y_ins1 ;
262  z = z_pca + s_1 * tanl ;
263  }
264  else {
265  // std::cout << "PropagateLCIOToCylinder: use 2nd solution" << std::endl ;
266  x = x_ins2 ;
267  y = y_ins2 ;
268  z = z_pca + s_2 * tanl ;
269  }
270  }
271 
272  else {
273 
274  if ( s_1 < 0.0 ) s_1 += 2.0*M_PI * r1 ;
275  if ( s_2 < 0.0 ) s_2 += 2.0*M_PI * r1 ;
276 
277  if( direction == 1 ){ // take the intersection with smallest s
278  if( s_1 < s_2 ) {
279  x = x_ins1 ;
280  y = y_ins1 ;
281  z = z_pca + s_1 * tanl ;
282  }
283  else {
284  x = x_ins2 ;
285  y = y_ins2 ;
286  z = z_pca + s_2 * tanl ;
287  }
288  }
289  else if(direction == -1) { // else take the intersection with largest s
290  if( s_1 > s_2 ){
291  x = x_ins1 ;
292  y = y_ins1 ;
293  z = z_pca + s_1 * tanl ;
294  }
295  else{
296  x = x_ins2 ;
297  y = y_ins2 ;
298  z = z_pca + s_2 * tanl ;
299  }
300  }
301  }
302 
303 
304  return PropagateLCIOToNewRef(ts,x,y,z);
305 
306  }
307 
309 
310 
311  const double x_ref = ts.getReferencePoint()[0] ;
312  const double y_ref = ts.getReferencePoint()[1] ;
313  const double z_ref = ts.getReferencePoint()[2] ;
314 
315  const double d0 = ts.getD0() ;
316  const double z0 = ts.getZ0() ;
317  const double phi0 = ts.getPhi() ;
318  const double tanl = ts.getTanLambda() ;
319  const double omega = ts.getOmega() ;
320 
321  const double x_pca = x_ref - d0 * sin(phi0) ;
322  const double y_pca = y_ref + d0 * cos(phi0) ;
323  const double z_pca = z_ref + z0 ;
324 
325  // get path length to crossing point
326  const double s = ( z - z_pca ) / tanl;
327 
328  const double delta_phi_half = (omega*s)/2.0 ;
329 
330  const double x = x_pca + s * ( sin(delta_phi_half) / delta_phi_half ) * cos( phi0 - delta_phi_half ) ;
331  const double y = y_pca + s * ( sin(delta_phi_half) / delta_phi_half ) * sin( phi0 - delta_phi_half ) ;
332 
333  return PropagateLCIOToNewRef(ts,x,y,z);
334 
335  }
336 
337 
338 
339  // Propagate track to a new reference point taken as its crossing point with a plane parallel to the z axis, containing points x1,x2 and y1,y2. Tolerance for intersection determined by epsilon.
340  // For direction == 0 the closest crossing point will be taken
341  // For direction == 1 the first crossing traversing in positive s will be taken
342  // For direction == -1 the first crossing traversing in negative s will be taken
343  int PropagateLCIOToPlaneParralelToZ( IMPL::TrackStateImpl& ts, float x1, float y1, float x2, float y2, int direction, double epsilon) {
344 
345  // check that direction has one of the correct values
346  if( !( direction == 0 || direction == 1 || direction == -1) ) return -1 ;
347 
348  // taken from http://paulbourke.net/geometry/sphereline/raysphere.c
349 
350  const double x_ref = ts.getReferencePoint()[0] ;
351  const double y_ref = ts.getReferencePoint()[1] ;
352  const double z_ref = ts.getReferencePoint()[2] ;
353 
354  const double d0 = ts.getD0() ;
355  const double z0 = ts.getZ0() ;
356  const double phi0 = ts.getPhi() ;
357  const double tanl = ts.getTanLambda() ;
358  const double omega = ts.getOmega() ;
359 
360  const double rho = 1.0 / omega ;
361  const double x_pca = x_ref - d0 * sin(phi0) ;
362  const double y_pca = y_ref + d0 * cos(phi0) ;
363  const double z_pca = z_ref + z0 ;
364 
365  const double sin_phi0 = sin(phi0);
366  const double cos_phi0 = cos(phi0);
367 
368  const double x_c = x_ref + ( rho - d0) * sin_phi0 ;
369  const double y_c = y_ref - ( rho - d0) * cos_phi0 ;
370 
371  const double dx = x2 - x1 ;
372  const double dy = y2 - y1 ;
373 
374  const double a = dx * dx + dy * dy ;
375 
376  const double b = 2.0 * ( dx * (x1 - x_c) + dy * (y1 - y_c) ) ;
377 
378  double c = x_c * x_c + y_c * y_c;
379  c += x1 * x1 + y1 * y1 ;
380 
381  c -= 2.0 * ( x_c * x1 + y_c * y1 );
382  c -= rho * rho;
383 
384  const double bb4ac = b * b - 4.0 * a * c;
385 
386  double u1 ; // first solution
387  double u2 ; // second solution
388 
389  /* Check for solvability. */
390  if (bb4ac + epsilon < 0.0 ) { // no intersection
391  return(1);
392  }
393  else if(bb4ac - epsilon < 0.0) { // circle intersects at one point, tangential
394  return(2);
395  }
396  else{
397  u1 = (-b + sqrt(bb4ac)) / (2.0 * a);
398  u2 = (-b - sqrt(bb4ac)) / (2.0 * a);
399  }
400 
401  const double x_ins1 = x1 + u1 * (dx) ;
402  const double y_ins1 = y1 + u1 * (dy) ;
403 
404  const double x_ins2 = x1 + u2 * (dx) ;
405  const double y_ins2 = y1 + u2 * (dy) ;
406 
407  // std::cout << "PropagateLCIOToPlaneParralelToZ: 1st solution u = " << u1 << " : " << u1 * dx << " " << u1 * dy << std::endl ;
408  // std::cout << "PropagateLCIOToPlaneParralelToZ: 2nd solution u = " << u2 << " : " << u2 * dx << " " << u2 * dy << std::endl ;
409  // std::cout << "PropagateLCIOToPlaneParralelToZ: 1st solution x:y = " << x_ins1 << " : " << y_ins1 << std::endl ;
410  // std::cout << "PropagateLCIOToPlaneParralelToZ: 2nd solution x:y = " << x_ins2 << " : " << y_ins2 << std::endl ;
411 
412  // now calculate the path lengths
413  double s_1 = 0.0 ;
414  double s_2 = 0.0 ;
415 
416  const double delta_x1 = x_ins1 - x_pca ;
417  const double delta_y1 = y_ins1 - y_pca ;
418 
419  const double sin_delta_phi1 = - omega*delta_x1*cos_phi0 - omega*delta_y1*sin_phi0 ;
420  const double cos_delta_phi1 = 1.0 - omega*delta_x1*sin_phi0 + omega*delta_y1*cos_phi0 ;
421 
422  s_1 = atan2(-sin_delta_phi1,cos_delta_phi1) / omega ;
423 
424  const double delta_x2 = x_ins2 - x_pca ;
425  const double delta_y2 = y_ins2 - y_pca ;
426 
427  const double sin_delta_phi2 = - omega*delta_x2*cos_phi0 - omega*delta_y2*sin_phi0 ;
428  const double cos_delta_phi2 = 1.0 - omega*delta_x2*sin_phi0 + omega*delta_y2*cos_phi0 ;
429 
430  s_2 = atan2(-sin_delta_phi2,cos_delta_phi2) / omega ;
431 
432  double x(0.0), y(0.0), z(0.0) ;
433 
434  if( direction == 0 ) { // take closest intersection
435  if( fabs(s_1) < fabs(s_2) ) {
436  // std::cout << "PropagateLCIOToPlaneParralelToZ: take 1st solution " << std::endl;
437  x = x_ins1 ;
438  y = y_ins1 ;
439  z = z_pca + s_1 * tanl ;
440  }
441  else {
442  // std::cout << "PropagateLCIOToPlaneParralelToZ: take 2nd solution " << std::endl;
443  x = x_ins2 ;
444  y = y_ins2 ;
445  z = z_pca + s_2 * tanl ;
446  }
447  }
448 
449  else{
450 
451  if ( s_1 < 0.0 ) s_1 += 2.0*M_PI * fabs(rho) ;
452  if ( s_2 < 0.0 ) s_2 += 2.0*M_PI * fabs(rho) ;
453 
454  if( direction == 1 ){ // take the intersection with smallest s
455  if( s_1 < s_2 ) {
456  // std::cout << "PropagateLCIOToPlaneParralelToZ: take 1st solution " << std::endl;
457  x = x_ins1 ;
458  y = y_ins1 ;
459  z = z_pca + s_1 * tanl ;
460  }
461  else {
462  // std::cout << "PropagateLCIOToPlaneParralelToZ: take 2nd solution " << std::endl;
463  x = x_ins2 ;
464  y = y_ins2 ;
465  z = z_pca + s_2 * tanl ;
466  }
467  }
468  else if( direction == -1 ) { // else take the intersection with largest s
469  if( s_1 > s_2 ){
470  // std::cout << "PropagateLCIOToPlaneParralelToZ: take 1st solution " << std::endl;
471  x = x_ins1 ;
472  y = y_ins1 ;
473  z = z_pca + s_1 * tanl ;
474  }
475  else{
476  // std::cout << "PropagateLCIOToPlaneParralelToZ: take 2nd solution " << std::endl;
477  x = x_ins2 ;
478  y = y_ins2 ;
479  z = z_pca + s_2 * tanl ;
480  }
481  }
482  }
483 
484  return PropagateLCIOToNewRef(ts,x,y,z);
485 
486  }
487 
488 
489 } // end of TrackPropagators
virtual float getZ0() const
virtual void setD0(float d0)
virtual float getOmega() const
virtual void setTanLambda(float tanLambda)
#define M_PI
virtual void setReferencePoint(const float *rPnt)
virtual void setCovMatrix(const float *cov)
int PropagateLCIOToPlaneParralelToZ(IMPL::TrackStateImpl &ts, float x1, float y1, float x2, float y2, int direction=0, double epsilon=1.0e-8)
Propagate trackstate to a new reference point taken as its crossing point with a plane parallel to th...
virtual float getTanLambda() const
virtual float getD0() const
virtual void setZ0(float z0)
virtual const float * getReferencePoint() const
int PropagateLCIOToCylinder(IMPL::TrackStateImpl &ts, float r, float x0, float y0, int direction=0, double epsilon=1.0e-8)
Propagate trackstate to a new reference point taken as its crossing point with a cylinder of infinite...
virtual void setPhi(float phi)
virtual const EVENT::FloatVec & getCovMatrix() const
int PropagateLCIOToNewRef(IMPL::TrackStateImpl &ts, double xref, double yref, double zref)
Propagate trackstate to a new reference point.
int PropagateLCIOToZPlane(IMPL::TrackStateImpl &ts, float z)
Propagate trackstate to a new reference point taken as its crossing point with an infinite plane loca...
virtual void setOmega(float omega)
virtual float getPhi() const