StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
FtfBaseTrack.cxx
1 //:>-----------------------------------------------------------------
2 //: FILE: FtfBaseTrack.cxx
3 //: HISTORY:
4 //: 28oct1996 version 1.00
5 //: 11aug1999 ppy primary flag in FtfPara replace with vertexConstrainedFit
6 //: 11aug1999 ppy primary flag in track filled now
7 //: 3sep1999 ppy fitLine, dpsi cannot be greater than 1. Check introduced
8 //: 5oct1999 ppy fitLine, bug corrected
9 //: 6oct1999 ppy Root switch added
10 //: 9mar2000 ppy extrapolation methods added
11 //: 9mar2000 ppy lots of changes to use void pointers
12 //: 28mar2000 ppy closestApproach split in two methods
13 //: 19jul2000 ppy fitHelix, for secondary tracks r0,phi0,z0
14 //: is given at a point on the helix close to
15 //: the inner most point. Previously it was given
16 //: exactly at the inner most point. Residuals
17 //: are slightly better with this change
18 //: 10Aug2001 ppy Adding bFieldPolarity
19 //: 8Sep2001 ppy when localPsi>=1 in fitLine angle was wrong, corrected
20 //:<------------------------------------------------------------------
21 //:>------------------------------------------------------------------
22 //: CLASS: FtfBaseTrack
23 //: DESCRIPTION: Basic Description of a track P
24 //: AUTHOR: ppy - Pablo Yepes, yepes@rice.edu
25 //:>------------------------------------------------------------------
26 #include "FtfBaseTrack.h"
27 
28 #include "FtfGeneral.h"
29 #include <rtsLog.h>
30 #include <limits.h>
31 
32 
33 void ftfMatrixDiagonal ( double *h, double &h11, double &h22, double &h33 ) ;
34 
35 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
36 // Track Initialization
37 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
38 FtfBaseTrack::FtfBaseTrack ( ){
39  firstHit = 0 ;
40  lastHit = 0 ;
41 }
42 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
43 // Fit a circle
44 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
45 int FtfBaseTrack::fitHelix ( )
46 {
47  if ( fitCircle ( ) ){
48  //LOG(ERR, " Problem in Fit_Circle " ) ;
49  return 1 ;
50  }
51  //
52  // Fit line in s-z plane now
53  //
54  if ( fitLine ( )) {
55  //LOG(ERR, " Problem fitting a line " ) ;
56  return 1 ;
57  }
58  return 0 ;
59 }
60 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
61 // End of Fit Helix
62 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
63 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
64 //
65 // Fits circle parameters using algorithm
66 // described by ChErnov and Oskov in Computer Physics
67 // Communications.
68 //
69 // Written in FORTRAN by Jawluen Tang, Physics department , UT-Austin
70 // Moved to C by Pablo Yepes
71 //---------------------------------------------------------------
72 int FtfBaseTrack::fitCircle ( )
73 {
74  double wsum = 0.0 ;
75  double xav = 0.0 ;
76  double yav = 0.0 ;
77 //
78 // Loop over hits calculating average
79 //
80  for ( startLoop() ; done() ; nextHit() ) {
81 
82  FtfBaseHit* cHit = (FtfBaseHit *)currentHit ;
83  cHit->wxy = 1.0F/ (double)(cHit->dx*cHit->dx + cHit->dy*cHit->dy) ;
84  wsum += cHit->wxy ;
85  xav += cHit->wxy * cHit->x ;
86  yav += cHit->wxy * cHit->y ;
87  }
88  if ( getPara()->vertexConstrainedFit ) {
89  wsum += getPara()->xyWeightVertex ;
90  xav += getPara()->xVertex ;
91  yav += getPara()->yVertex ;
92  }
93  xav = xav / wsum ;
94  yav = yav / wsum ;
95 //
96 // CALCULATE <X**2>, <XY>, AND <Y**2> WITH <X> = 0, & <Y> = 0
97 //
98  double xxav = 0.0 ;
99  double xyav = 0.0 ;
100  double yyav = 0.0 ;
101  double xi, yi ;
102 
103  for ( startLoop() ; done() ; nextHit() ) {
104  FtfBaseHit* cHit = (FtfBaseHit *)currentHit ;
105  xi = cHit->x - xav ;
106  yi = cHit->y - yav ;
107  xxav += xi * xi * cHit->wxy ;
108  xyav += xi * yi * cHit->wxy ;
109  yyav += yi * yi * cHit->wxy ;
110  }
111  if ( getPara()->vertexConstrainedFit ) {
112  xi = getPara()->xVertex - xav ;
113  yi = getPara()->yVertex - yav ;
114  xxav += xi * xi * getPara()->xyWeightVertex ;
115  xyav += xi * yi * getPara()->xyWeightVertex ;
116  yyav += yi * yi * getPara()->xyWeightVertex ;
117  }
118  xxav = xxav / wsum ;
119  xyav = xyav / wsum ;
120  yyav = yyav / wsum ;
121 //
122 //--> ROTATE COORDINATES SO THAT <XY> = 0
123 //
124 //--> SIGN(C**2 - S**2) = SIGN(XXAV - YYAV) >
125 //--> & > ==> NEW : (XXAV-YYAV) > 0
126 //--> SIGN(S) = SIGN(XYAV) >
127 
128  double a = fabs( xxav - yyav ) ;
129  double b = 4.0 * xyav * xyav ;
130 
131  double asqpb = a * a + b ;
132  double rasqpb = sqrt ( asqpb) ;
133 
134  double splus = 1.0 + a / rasqpb ;
135  double sminus = b / (asqpb * splus) ;
136 
137  splus = sqrt (0.5 * splus ) ;
138  sminus = sqrt (0.5 * sminus) ;
139 //
140 //-> FIRST REQUIRE : SIGN(C**2 - S**2) = SIGN(XXAV - YYAV)
141 //
142  double sinrot, cosrot ;
143  if ( xxav <= yyav ) {
144  cosrot = sminus ;
145  sinrot = splus ;
146  }
147  else {
148  cosrot = splus ;
149  sinrot = sminus ;
150  }
151 //
152 //-> REQUIRE : SIGN(S) = SIGN(XYAV) * SIGN(C) (ASSUMING SIGN(C) > 0)
153 //
154  if ( xyav < 0.0 ) sinrot = - sinrot ;
155 //
156 //--> WE NOW HAVE THE SMALLEST ANGLE THAT GUARANTEES <X**2> > <Y**2>
157 //--> TO GET THE SIGN OF THE CHARGE RIGHT, THE NEW X-AXIS MUST POINT
158 //--> OUTWARD FROM THE ORGIN. WE ARE FREE TO CHANGE SIGNS OF BOTH
159 //--> COSROT AND SINROT SIMULTANEOUSLY TO ACCOMPLISH THIS.
160 //
161 //--> CHOOSE SIGN OF C WISELY TO BE ABLE TO GET THE SIGN OF THE CHARGE
162 //
163  if ( cosrot*xav+sinrot*yav < 0.0 ) {
164  cosrot = -cosrot ;
165  sinrot = -sinrot ;
166  }
167 //
168 //-> NOW GET <R**2> AND RSCALE= SQRT(<R**2>)
169 //
170  double rrav = xxav + yyav ;
171  double rscale = sqrt(rrav) ;
172 
173  xxav = 0.0 ;
174  yyav = 0.0 ;
175  xyav = 0.0 ;
176  double xrrav = 0.0 ;
177  double yrrav = 0.0 ;
178  double rrrrav = 0.0 ;
179 
180  double xixi, yiyi, riri, wiriri, xold, yold ;
181  for ( startLoop() ; done() ; nextHit() ) {
182  FtfBaseHit* cHit = (FtfBaseHit *)currentHit ;
183  xold = cHit->x - xav ;
184  yold = cHit->y - yav ;
185 //
186 //--> ROTATE SO THAT <XY> = 0 & DIVIDE BY RSCALE SO THAT <R**2> = 1
187 //
188  xi = ( cosrot * xold + sinrot * yold ) / rscale ;
189  yi = ( -sinrot * xold + cosrot * yold ) / rscale ;
190 
191  xixi = xi * xi ;
192  yiyi = yi * yi ;
193  riri = xixi + yiyi ;
194  wiriri = cHit->wxy * riri ;
195 
196  xyav += cHit->wxy * xi * yi ;
197  xxav += cHit->wxy * xixi ;
198  yyav += cHit->wxy * yiyi ;
199 
200  xrrav += wiriri * xi ;
201  yrrav += wiriri * yi ;
202  rrrrav += wiriri * riri ;
203  }
204 //
205 // Include vertex if required
206 //
207  if ( getPara()->vertexConstrainedFit ) {
208  xold = getPara()->xVertex - xav ;
209  yold = getPara()->yVertex - yav ;
210 //
211 //--> ROTATE SO THAT <XY> = 0 & DIVIDE BY RSCALE SO THAT <R**2> = 1
212 //
213  xi = ( cosrot * xold + sinrot * yold ) / rscale ;
214  yi = ( -sinrot * xold + cosrot * yold ) / rscale ;
215 
216  xixi = xi * xi ;
217  yiyi = yi * yi ;
218  riri = xixi + yiyi ;
219  wiriri = getPara()->xyWeightVertex * riri ;
220 
221  xyav += getPara()->xyWeightVertex * xi * yi ;
222  xxav += getPara()->xyWeightVertex * xixi ;
223  yyav += getPara()->xyWeightVertex * yiyi ;
224 
225  xrrav += wiriri * xi ;
226  yrrav += wiriri * yi ;
227  rrrrav += wiriri * riri ;
228  }
229 //
230 //
231 //
232 //--> DIVIDE BY WSUM TO MAKE AVERAGES
233 //
234  xxav = xxav / wsum ;
235  yyav = yyav / wsum ;
236  xrrav = xrrav / wsum ;
237  yrrav = yrrav / wsum ;
238  rrrrav = rrrrav / wsum ;
239  xyav = xyav / wsum ;
240 
241  int const ntry = 5 ;
242 //
243 //--> USE THESE TO GET THE COEFFICIENTS OF THE 4-TH ORDER POLYNIMIAL
244 //--> DON'T PANIC - THE THIRD ORDER TERM IS ZERO !
245 //
246  double xrrxrr = xrrav * xrrav ;
247  double yrryrr = yrrav * yrrav ;
248  double rrrrm1 = rrrrav - 1.0 ;
249  double xxyy = xxav * yyav ;
250 
251  double c0 = rrrrm1*xxyy - xrrxrr*yyav - yrryrr*xxav ;
252  double c1 = - rrrrm1 + xrrxrr + yrryrr - 4.0*xxyy ;
253  double c2 = 4.0 + rrrrm1 - 4.0*xxyy ;
254  double c4 = - 4.0 ;
255 //
256 //--> COEFFICIENTS OF THE DERIVATIVE - USED IN NEWTON-RAPHSON ITERATIONS
257 //
258  double c2d = 2.0 * c2 ;
259  double c4d = 4.0 * c4 ;
260 //
261 //--> 0'TH VALUE OF LAMDA - LINEAR INTERPOLATION BETWEEN P(0) & P(YYAV)
262 //
263 // LAMDA = YYAV * C0 / (C0 + YRRSQ * (XXAV-YYAV))
264  double lamda = 0.0 ;
265  double dlamda = 0.0 ;
266 //
267  double chiscl = wsum * rscale * rscale ;
268  double dlamax = 0.001 / chiscl ;
269 
270  double p, pd ;
271  for ( int itry = 1 ; itry <= ntry ; itry++ ) {
272  p = c0 + lamda * (c1 + lamda * (c2 + lamda * lamda * c4 )) ;
273  pd = (c1 + lamda * (c2d + lamda * lamda * c4d)) ;
274  dlamda = -p / pd ;
275  lamda = lamda + dlamda ;
276  if (fabs(dlamda)< dlamax) break ;
277  }
278 
279  chi2[0] = (double)(chiscl * lamda) ;
280  // double dchisq = chiscl * dlamda ;
281 //
282 //--> NOW CALCULATE THE MATRIX ELEMENTS FOR ALPH, BETA & KAPPA
283 //
284  double h11 = xxav - lamda ;
285  double h14 = xrrav ;
286  double h22 = yyav - lamda ;
287  double h24 = yrrav ;
288  double h34 = 1.0 + 2.0*lamda ;
289  if ( h11 == 0.0 || h22 == 0.0 ){
290  //LOG(ERR, " Problems fitting a circle " ) ;
291  return 1 ;
292  }
293  double rootsq = (h14*h14)/(h11*h11) + 4.0*h34 ;
294 
295  double ratio, kappa, beta ;
296  if ( fabs(h22) > fabs(h24) ) {
297  ratio = h24 / h22 ;
298  rootsq = ratio * ratio + rootsq ;
299  kappa = 1.0 / sqrt(rootsq) ;
300  beta = - ratio * kappa ;
301  }
302  else {
303  ratio = h22 / h24 ;
304  rootsq = 1.0 + ratio * ratio * rootsq ;
305  beta = 1.0 / sqrt(rootsq) ;
306  if ( h24 > 0 ) beta = - beta ;
307  kappa = -ratio * beta ;
308  }
309  double alph = - (h14/h11) * kappa ;
310 //
311 //--> transform these into the lab coordinate system
312 //--> first get kappa and back to real dimensions
313 //
314  double kappa1 = kappa / rscale ;
315  double dbro = 0.5 / kappa1 ;
316 //
317 //--> next rotate alph and beta and scale
318 //
319  double alphr = (cosrot * alph - sinrot * beta)* dbro ;
320  double betar = (sinrot * alph + cosrot * beta)* dbro ;
321 //
322 //--> then translate by (xav,yav)
323 //
324  double acent = (double)(xav - alphr) ;
325  double bcent = (double)(yav - betar ) ;
326  double radius = (double)dbro ;
327 //
328 // Get charge
329 //
330 
331  q = ( ( yrrav < 0 ) ? 1 : -1 ) * getPara()->bFieldPolarity ;
332  pt = (double)fabs(2.9979e-3 * getPara()->bField * radius ) ;
333 //
334 // Get other track parameters
335 //
336  double x0, y0 ;
337  if ( getPara()->vertexConstrainedFit ) {
338  flag = 1 ; // primary track flag
339  x0 = getPara()->xVertex ;
340  y0 = getPara()->yVertex ;
341  phi0 = getPara()->phiVertex ;
342  r0 = getPara()->rVertex ;
343  psi = (double)atan2(bcent-y0,acent-x0) ;
344  psi = psi + getPara()->bFieldPolarity*q * 0.5F * pi ;
345  if ( psi < 0 ) psi = psi + twoPi ;
346  }
347  else {
348  FtfBaseHit* lHit = (FtfBaseHit *)lastHit ;
349  flag = 0 ; // primary track flag
350  psi = (double)atan2(bcent-(lHit->y),acent-(lHit->x)) ;
351  x0 = acent - radius * cos(psi);
352  y0 = bcent - radius * sin(psi);
353  psi = psi + getPara()->bFieldPolarity*q * 0.5F * pi ;
354  phi0 = atan2(y0,x0);
355  if ( phi0 < 0 ) phi0 += twoPi ;
356  r0 = sqrt ( x0 * x0 + y0 * y0 ) ;
357  }
358  //
359 //
360 // Get errors from fast fit
361 //
362  if ( getPara()->getErrors ) getErrorsCircleFit ( acent, bcent, radius ) ;
363 //
364  return 0 ;
365 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
366 // End Fit Circle
367 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
368 }
369 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
370 // Fit Line in s-z plane
371 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
372 int FtfBaseTrack::fitLine ( )
373 {
374 //
375 // initialization
376 //
377  double sum = 0.F ;
378  double ss = 0.F ;
379  double sz = 0.F ;
380  double sss = 0.F ;
381  double ssz = 0.F ;
382 //
383 // find sum , sums ,sumz, sumss
384 //
385  double dx, dy ;
386  double radius = (double)fabs(pt / ( 2.9979e-3 * getPara()->bField ) ) ;
387  if ( getPara()->vertexConstrainedFit ) {
388  dx = ((FtfBaseHit *)firstHit)->x - getPara()->xVertex ;
389  dy = ((FtfBaseHit *)firstHit)->y - getPara()->yVertex ;
390  }
391  else {
392  dx = ((FtfBaseHit *)firstHit)->x - ((FtfBaseHit *)lastHit)->x ;
393  dy = ((FtfBaseHit *)firstHit)->y - ((FtfBaseHit *)lastHit)->y ;
394  }
395  double localPsi = 0.5F * sqrt ( dx*dx + dy*dy ) / radius ;
396  if ( localPsi > 1. ) localPsi = 1. ;
397  //double total_s ;
398  //total_s = 2.0F * radius * asin ( localPsi ) ;
399  length = 2.0F * radius * asin ( localPsi ) ;
400 //
401  FtfBaseHit *previousHit = 0 ;
402 
403  for ( startLoop() ; done() ; nextHit() ) {
404  FtfBaseHit* cHit = (FtfBaseHit *)currentHit ;
405  if ( currentHit != firstHit ) {
406  dx = cHit->x - previousHit->x ;
407  dy = cHit->y - previousHit->y ;
408  dpsi = 0.5F * (double)sqrt ( dx*dx + dy*dy ) / radius ;
409  if ( dpsi > 1.) {
410 // LOG(ERR,"FtfBaseHit::fitLine(): dpsi=%f\n", dpsi);
411  dpsi = 1.;
412  }
413  cHit->s = previousHit->s - 2.0F * radius * (double)asin ( dpsi ) ;
414  }
415  else
416  cHit->s = length;
417 
418  sum += cHit->wz ;
419  ss += cHit->wz * cHit->s ;
420  sz += cHit->wz * cHit->z ;
421  sss += cHit->wz * cHit->s * cHit->s ;
422  ssz += cHit->wz * cHit->s * cHit->z ;
423  previousHit = cHit ;
424  }
425 
426  double det = sum * sss - ss * ss;
427  if ( fabs(det) < 1e-20){
428  chi2[1] = 99999.F ;
429  return 0 ;
430  }
431 //
432 // compute the best fitted parameters A,B
433 //
434  tanl = (double)((sum * ssz - ss * sz ) / det );
435  z0 = (double)((sz * sss - ssz * ss ) / det );
436 //
437 // calculate chi-square
438 //
439  chi2[1] = 0.F ;
440  double r1 ;
441  for ( startLoop() ; done() ; nextHit() ) {
442  FtfBaseHit* cHit = (FtfBaseHit *)currentHit ;
443  r1 = cHit->z - tanl * cHit->s - z0 ;
444  chi2[1] += (double) ( (double)cHit->wz * (r1 * r1) );
445  }
446 //
447 // calculate estimated variance
448 // varsq=chi/(double(n)-2.)
449 // calculate covariance matrix
450 // siga=sqrt(varsq*sxx/det)
451 // sigb=sqrt(varsq*sum/det)
452 //
453  dtanl = (double) ( sum / det );
454  dz0 = (double) ( sss / det );
455 
456  return 0 ;
457 }
458 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
459 // End Fit Line
460 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
461 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
462 // CIRCOV - a covariance matrix calculation program for circle fitting
463 // DESCRIPTION:
464 // Compute the covariance matrix of an effective circle fitting algorithm
465 // The circle equation is (X(I)-A)**2 + (Y(I)-B)**2 = R**2.
466 // The functional minimum is W(I)*[(X(I)-A)**2+(Y(I)-B)**2-R*R]**2/(R*R)
467 // For details about the algorithm, see
468 // N.I. CHERNOV, G.A. OSOSKOV, COMPUT. PHYS. COMMUN. 33(1984) 329-333
469 // INPUT ARGUMENTS: */
470 // A - Best fitted circle center in X axis, REAL
471 // B - Best fitted circle center in Y axis, REAL
472 // R - Best fitted radius REAL
473 //
474 // From a routine written in Fortran by AUTHOR:
475 // Jawluen Tang, Physics department , UT-Austin
476 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
477 int FtfBaseTrack::getErrorsCircleFit ( double a, double b, double r ) {
478 
479  double h[9] = { 0. };
480  double dx, dy ;
481  double h11, h22, h33 ;
482  static int j ;
483  static double ratio, c1, s1;
484  static double hyp;
485 
486 
487  for (j = 0; j < 9; j++ ) {
488  h[j] = 0.;
489  }
490 //
491 // If circle fit was not used the
492 // errors in the real space need to
493 // be calculated
494 //
495  if ( pt < getPara()->ptMinHelixFit ) {
496  for ( startLoop() ; done() ; nextHit() ) {
497 
498  FtfBaseHit* cHit = (FtfBaseHit *)currentHit ;
499  cHit->wxy = 1.0F/ (double)(cHit->dx*cHit->dx + cHit->dy*cHit->dy) ;
500  }
501  }
502 //
503 // Loop over points in fit
504 //
505  for ( startLoop() ; done() ; nextHit() ) {
506  FtfBaseHit* cHit = (FtfBaseHit *)currentHit ;
507  dx = cHit->x - a;
508  dy = cHit->y - b;
509  hyp = (double)sqrt( dx * dx + dy * dy );
510  s1 = dx / hyp;
511  c1 = dy / hyp;
512  ratio = r / hyp;
513  h[0] += cHit->wxy * (ratio * (s1 * s1 - 1) + 1);
514  h[1] += cHit->wxy * ratio * s1 * c1;
515  h[2] += cHit->wxy * s1;
516  h[4] += cHit->wxy * (ratio * (c1 * c1 - 1) + 1);
517  h[5] += cHit->wxy * c1;
518  h[8] += cHit->wxy ;
519  }
520  h[3] = h[1];
521  h[6] = h[2];
522  h[7] = h[5];
523 
524  ftfMatrixDiagonal ( h, h11, h22, h33 ) ;
525 //
526 // Calculate pt error now
527 //
528  dpt = (double)fabs(2.9979e-3 * getPara()->bField * h33 );
529 //
530 // Get error in psi now
531 //
532  if ( getPara()->vertexConstrainedFit ) {
533  dx = a ;
534  dy = b ;
535  }
536  else {
537  dx = ((FtfBaseHit *)lastHit)->x + a - ((FtfBaseHit *)firstHit)->x ;
538  dy = ((FtfBaseHit *)lastHit)->y + b + ((FtfBaseHit *)firstHit)->y ;
539  }
540  double w = dy / dx ;
541  dpsi = (double)(( 1. / ( 1. + w*w ) ) * ( h22 / dx - dy * h11 / ( dx*dx ) )) ;
542 
543  return 0 ;
544 }
545 
546 //*************************************************************************
547 // Prints one track information
548 //*************************************************************************
549 void FtfBaseTrack::Print ( int level )
550 {
551  double pmom, pz;
552 /*
553 -----> Print info
554 */
555  if ( level > 9 ) {
556  pz = pt * tanl ;
557  pmom = (double)sqrt ( pz * pz + pt * pt ) ;
558  LOG(NOTE, " =======> Track %d <========\n", id ) ;
559  LOG(NOTE, "p, pt, q %7.2f %7.2f %2d \n", pmom, pt, q ) ;
560  }
561  if ( level > 19 ) {
562  LOG(NOTE, "r0, z0, nHits %7.2f %7.2f %d \n", r0, z0, nHits ) ;
563  LOG(NOTE, "phi0, psi, tanl %7.2f %7.2f %7.2f \n", phi0, psi, tanl ) ;
564  }
565 
566  if ( level > 29 ) {
567  LOG(NOTE, "chi2 (s,z) %6.2e %6.2e \n", chi2[0], chi2[1] ) ;
568  }
569 
570 
571  if ( fmod((double)level,10.) > 0 ) {
572  LOG(NOTE, "*** Clusters in this track *** " ) ;
573  ((FtfBaseHit *)firstHit)->print ( 10 ) ;
574  for ( startLoop() ; done() ; nextHit() ) {
575  ((FtfBaseHit *)currentHit)->print ( 1 ) ;
576  }
577  }
578 }
579 /*:>--------------------------------------------------------------------
580 **: METHOD: Finds point of closest approach
581 **:
582 **: AUTHOR: ppy - P.P. Yepes, yepes@rice.edu
583 **: ARGUMENTS:
584 **: IN: xBeam, yBeam: beam position
585 **:
586 **: RETURNS:
587 **: tHit - Point closest approach to center
588 *:>------------------------------------------------------------------*/
589 Ftf3DHit FtfBaseTrack::closestApproach ( double xBeam, double yBeam ) {
590  double rc, xc, yc ;
591  return getClosest ( xBeam, yBeam, rc, xc, yc ) ;
592 }
593 /*:>--------------------------------------------------------------------
594 **: METHOD: Finds point of closest approach
595 **:
596 **: AUTHOR: ppy - P.P. Yepes, yepes@rice.edu
597 **: ARGUMENTS:
598 **: IN: xBeam, yBeam: beam position
599 **: OUT:
600 **: rc, xc, yc track circle radius and center
601 **:
602 **: RETURNS:
603 **: tHit - Point closest approach to center
604 *:>------------------------------------------------------------------*/
605 Ftf3DHit FtfBaseTrack::getClosest ( double xBeam, double yBeam,
606  double &rc, double &xc, double &yc ) {
607  double xp, yp, zp ;
608  xp = yp = 0. ;
609 //--------------------------------------------------------
610 // Get track parameters
611 //--------------------------------------------------------
612 //
613  // printf("in getClosest a %4.2f %4.2f %4.2f %4.2f %4.2f\n",xBeam,yBeam,rc,xc, yc);
614 
615  double tPhi0 = psi + double(q)*getPara()->bFieldPolarity * 0.5 * M_PI / fabs((double)q) ;
616 
617  double x0 = r0 * cos(phi0) ;
618  double y0 = r0 * sin(phi0) ;
619  rc = pt / fabs( bFactor * getPara()->bField ) ;
620  xc = x0 - rc * cos(tPhi0) ;
621  yc = y0 - rc * sin(tPhi0) ;
622 
623  // printf("r/phi b %4.2f %4.2f %f\n",r0,phi0,getPara()->bField);
624 
625  // printf("in getClosest b %4.2f %4.2f %4.2f %4.2f %4.2f\n",xBeam,yBeam,rc,xc, yc);
626 
627  getClosest ( xBeam, yBeam, rc, xc, yc, xp, yp ) ;
628 
629 //-----------------------------------------------------------------
630 // Get the z coordinate
631 //-----------------------------------------------------------------
632  double angle = atan2 ( (yp-yc), (xp-xc) ) ;
633  if ( angle < 0. ) angle = angle + 2.0 * M_PI ;
634 
635  double dangle = angle - tPhi0 ;
636 
637  if ( fabs(dangle) < 1.e-4 ) dangle = 0 ; // Problems with -0.000 values
638  dangle = fmod ( dangle, 2.0 * M_PI ) ;
639  if ( (float(q)*getPara()->bFieldPolarity * dangle) < 0 )
640  dangle = dangle + getPara()->bFieldPolarity*float(q) * 2. * M_PI ;
641 
642  double stot = fabs(dangle) * rc ;
643  zp = z0 - stot * tanl ;
644 
645  Ftf3DHit tHit(xp,yp,zp) ;
646  return tHit ;
647 }
648 /*:>--------------------------------------------------------------------
649 **: METHOD: Finds point of closest approach
650 **:
651 **: AUTHOR: ppy - P.P. Yepes, yepes@rice.edu
652 **: ARGUMENTS:
653 **: IN: xBeam, yBeam: beam position
654 **: rc, xc, yc : track circle radius and center
655 **: OUT:
656 **: double xClosest, yClosest
657 **:
658 **: RETURNS: 0 if Ok
659 *:>------------------------------------------------------------------*/
660 int FtfBaseTrack::getClosest ( double xBeam, double yBeam,
661  double rc, double xc, double yc,
662  double& xClosest, double& yClosest ) {
663 //----------------------------------------------------------
664 // Shift center to respect beam axis
665 //----------------------------------------------------------
666  double dx = xc - xBeam ;
667  double dy = yc - yBeam ;
668 //----------------------------------------------------------
669 // Solve the equations
670 //----------------------------------------------------------
671  double fact = rc / sqrt ( dx * dx + dy * dy ) ;
672  double f1 = 1. + fact ;
673  double f2 = 1. - fact ;
674 
675  double dx1 = dx * f1 ;
676  double dy1 = dy * f1 ;
677  double d1 = sqrt ( dx1 * dx1 + dy1 * dy1 ) ;
678 
679  double dx2 = dx * f2 ;
680  double dy2 = dy * f2 ;
681  double d2 = sqrt ( dx2 * dx2 + dy2 * dy2 ) ;
682 //---------------------------------------------------------------
683 // Choose the closest
684 //---------------------------------------------------------------
685  if ( d1 < d2 ) {
686  xClosest = dx1 + xBeam ;
687  yClosest = dy1 + yBeam ;
688  }
689  else {
690  xClosest = dx2 + xBeam ;
691  yClosest = dy2 + yBeam ;
692  }
693  return 0 ;
694 }
695 /*:>--------------------------------------------------------------------
696 **: METHOD: Extrapolates track to cylinder with radius r
697 **:
698 **:
699 **: AUTHOR: ppy - P.P. Yepes, yepes@rice.edu
700 **: ARGUMENTS:
701 **: IN:
702 **: track - Global track pointer
703 **: r - Cylinder radius
704 **: OUT:
705 **: x,y,z - Extrapolated point
706 **: xc,yc,rr - Center and radius track circle in x-y plane
707 **:
708 **: RETURNS: 0=ok, <>0 error
709 **:>------------------------------------------------------------------*/
710 Ftf3DHit FtfBaseTrack::extraRadius ( double r ) {
711  double phi ;
712 //
713 // Default values
714 //
715  double x, y, z, rc, xc, yc ;
716  x = y = z = 0.F ;
717 //
718 // If error return with error
719 //
720  Ftf3DHit tHit(0,0,0) ;
721  if ( extraRCyl ( r, phi, z, rc, xc, yc ) ) return tHit ;
722 //
723 // Otherwise get point in cartesian coordinates
724 //
725  x = r * cos(phi) ;
726  y = r * sin(phi) ;
727  tHit.x = x ;
728  tHit.y = y ;
729  tHit.z = z ;
730 
731  return tHit ;
732 }
733 /*:>--------------------------------------------------------------------
734 **: METHOD: Extrapolates track to cylinder with radius r
735 **:
736 **:
737 **: AUTHOR: ppy - P.P. Yepes, yepes@rice.edu
738 **: ARGUMENTS:
739 **: IN:
740 **: r - Cylinder radius
741 **: OUT:
742 **: phi,z - Extrapolated point
743 **: xc,yc,rc - Center and radius track circle in x-y plane
744 **:
745 **: RETURNS: 0=ok, <>0 error
746 **:>------------------------------------------------------------------*/
747 int FtfBaseTrack::extraRCyl ( double &r, double &phi, double &z,
748  double &rc, double &xc, double &yc ) {
749 
750  double td ;
751  double fac1,sfac, fac2 ;
752 //--------------------------------------------------------
753 // Get track parameters
754 //--------------------------------------------------------
755 
756 
757  double tPhi0 = psi + getPara()->bFieldPolarity*double(q) * 0.5 * M_PI / fabs((double)q) ;
758  double x0 = r0 * cos(phi0) ;
759  double y0 = r0 * sin(phi0) ;
760  rc = fabs(pt / ( bFactor * getPara()->bField )) ;
761  xc = x0 - rc * cos(tPhi0) ;
762  yc = y0 - rc * sin(tPhi0) ;
763 //
764 // Check helix and cylinder intersect
765 //
766  fac1 = xc*xc + yc*yc ;
767  sfac = sqrt( fac1 ) ;
768 //
769 // If they don't intersect return
770 // Trick to solve equation of intersection of two circles
771 // rotate coordinates to have both circles with centers on x axis
772 // pretty simple system of equations, then rotate back
773 //
774  if ( fabs(sfac-rc) > r || fabs(sfac+rc) < r ) {
775 // l3Log ( "particle does not intersect \n" ) ;
776  return 1 ;
777  }
778 //
779 // Find intersection
780 //
781  fac2 = ( r*r + fac1 - rc*rc) / (2.00 * r * sfac ) ;
782  phi = atan2(yc,xc) + getPara()->bFieldPolarity*float(q)*acos(fac2) ;
783  td = atan2(r*sin(phi) - yc,r*cos(phi) - xc) ;
784 // Intersection in z
785 
786  if ( td < 0 ) td = td + 2. * M_PI ;
787  double dangle = tPhi0 - td ;
788  dangle = fmod ( dangle, 2.0 * M_PI ) ;
789  if ( r < r0 ) dangle *= -1 ;
790 // l3Log ( "dangle %f q %d \n", dangle, q ) ;
791  if ( (getPara()->bFieldPolarity*float(q) * dangle) < 0 )
792  dangle = dangle + getPara()->bFieldPolarity*float(q) * 2. * M_PI ;
793 
794  double stot = fabs(dangle) * rc ;
795 // l3Log ( "dangle %f z0 %f stot %f \n", dangle, z0, stot ) ;
796  if ( r > r0 ) z = z0 + stot * tanl ;
797  else z = z0 - stot * tanl ;
798 //
799 // That's it
800 //
801  return 0 ;
802 }
803 /*:>--------------------------------------------------------------------
804 **: METHOD: Calculates intersection of track with plane define by line
805 **: y = a x + b and the z
806 **:
807 **: AUTHOR: ppy - P.P. Yepes, yepes@rice.edu
808 **: ARGUMENTS:
809 **: IN:
810 **: a, b - Line parameters
811 **: OUT:
812 **: crossPoint - intersection point
813 **:
814 **: RETURNS: 0=ok, <>0 track does not cross the plane
815 **:>------------------------------------------------------------------*/
816 
817 //--------------------------------------------------------------------
818 // tom: split into two methods:
819 // one gets both intersections within one turn of the helix,
820 // the other selects the intersection closest to the origin.
821 // (Provided for compatibility with older programs.)
822 //--------------------------------------------------------------------
823 
824 int FtfBaseTrack::intersectorZLine ( double a, double b, Ftf3DHit& cross ) {
825  Ftf3DHit cross1, cross2;
826 
827  if (0 != intersectorZLine(a, b, cross1, cross2))
828  return 1;
829 
830  double r1sq = cross1.x*cross1.x + cross1.y*cross1.y;
831  double r2sq = cross2.x*cross2.x + cross2.y*cross2.y;
832 
833  if (r1sq < r2sq) { // cross 1 is closer to the beamline
834  cross = cross1;
835  } else {
836  cross = cross2;
837  }
838 
839  return 0;
840 }
841 
842 int FtfBaseTrack::intersectorZLine ( double a, double b,
843  Ftf3DHit& cross1, Ftf3DHit& cross2 ) {
844  //
845  // Calculate circle center and radius
846  //
847  double x0 = r0 * cos(phi0) ; // x first point on track
848  double y0 = r0 * sin(phi0) ; // y first point on track
849 
850  double trackPhi0 = psi + getPara()->bFieldPolarity*q * 0.5 * M_PI / fabs((double)q) ;//
851  double rc = pt / fabs( bFactor * getPara()->bField ) ;
852  double xc = x0 - rc * cos(trackPhi0) ;
853  double yc = y0 - rc * sin(trackPhi0) ;
854 
855  double ycPrime = yc - b ;
856  double aa = ( 1. + a * a ) ;
857  double bb = -2. * ( xc + a * ycPrime ) ;
858  double cc = ( xc * xc + ycPrime * ycPrime - rc * rc ) ;
859 
860  double racine = bb * bb - 4. * aa * cc ;
861  if ( racine < 0 ) {
862  cross1.set(0,0,0);
863  cross2.set(0,0,0);
864  return 1 ;
865  }
866  double rootRacine = sqrt(racine) ;
867 
868  double oneOverA = 1./aa;
869  //
870  // First solution
871  //
872  double x1 = 0.5 * oneOverA * ( -1. * bb + rootRacine ) ;
873  double y1 = a * x1 + b ;
874  //
875  // Second solution
876  //
877  double x2 = 0.5 * oneOverA * ( -1. * bb - rootRacine ) ;
878  double y2 = a * x2 + b ;
879 
880 
881  //-------------------------------------------------------------------
882  // Get the first z coordinate
883  //-------------------------------------------------------------------
884  double angle, dangle, stot;
885 
886  angle = atan2 ( (y1-yc), (x1-xc) ) ;
887  if ( angle < 0. ) angle = angle + 2.0 * M_PI ;
888 
889  dangle = angle - trackPhi0 ;
890  dangle = fmod ( dangle, 2.0 * M_PI ) ;
891 
892  if ( (getPara()->bFieldPolarity*q * dangle) > 0 )
893  dangle = dangle - getPara()->bFieldPolarity*q * 2. * M_PI ;
894 
895  stot = fabs(dangle) * rc ;
896  double z1 = z0 + stot * tanl ;
897 
898  cross1.set ( x1, y1, z1 ) ;
899 
900 
901  //-------------------------------------------------------------------
902  // Get the second z coordinate
903  //-------------------------------------------------------------------
904  angle = atan2 ( (y2-yc), (x2-xc) ) ;
905  if ( angle < 0. ) angle = angle + 2.0 * M_PI ;
906 
907  dangle = angle - trackPhi0 ;
908  dangle = fmod ( dangle, 2.0 * M_PI ) ;
909 
910  if ( (getPara()->bFieldPolarity*q * dangle) > 0 )
911  dangle = dangle - getPara()->bFieldPolarity*q * 2. * M_PI ;
912 
913  stot = fabs(dangle) * rc ;
914  double z2 = z0 + stot * tanl ;
915 
916  cross2.set ( x2, y2, z2 ) ;
917 
918  return 0 ;
919 }
920 
921 
922 
923 /*:>--------------------------------------------------------------------
924 **: METHOD: Calculates intersection of track with plane define by line
925 **: x = a and the z
926 **:
927 **: AUTHOR: ppy - P.P. Yepes, yepes@rice.edu
928 **: ARGUMENTS:
929 **: IN:
930 **: a - Line parameter
931 **: OUT:
932 **: crossPoint - intersection point
933 **:
934 **: RETURNS: 0=ok, <>0 track does not cross the plane
935 **:>------------------------------------------------------------------*/
936 int FtfBaseTrack::intersectorYCteLine ( double a, Ftf3DHit& cross ) {
937 //
938 //calculate circle center and radius
939 //
940  double x0 = r0*cos(phi0);
941  double y0 = r0*sin(phi0);
942 
943  double trackPhi0= psi + getPara()->bFieldPolarity*q*0.5*M_PI/fabs((float)q);
944  double rcoc = pt / fabs( bFactor * getPara()->bField ) ;
945  double xcoc = x0 - (rcoc*cos(trackPhi0));
946  double ycoc = y0 - (rcoc*sin(trackPhi0));
947 //
948 // Calculate circle center and radius
949 //
950  double xHit = a ;
951 
952  double f1 = (xHit-xcoc)*(xHit-xcoc);
953  double r2 = rcoc*rcoc;
954  if ( f1 > r2 ) {
955  return 1 ;
956  }
957 
958  double sf2 = sqrt(r2-f1);
959  double y1 = ycoc + sf2;
960  double y2 = ycoc - sf2;
961  double yHit = y1;
962  if ( fabs(y2) < fabs(y1) ) yHit=y2;
963 
964 //Get z coordinate:
965  double angle = atan2 ( (yHit-ycoc), (xHit-xcoc) ) ;
966  if ( angle < 0. ) angle = angle + 2.0 * M_PI ;
967 
968  double dangle = angle - trackPhi0 ;
969  dangle = fmod ( dangle, 2.0 * M_PI ) ;
970  if ( (getPara()->bFieldPolarity*q * dangle) > 0 )
971  dangle = dangle - getPara()->bFieldPolarity*q * 2. * M_PI ;
972 
973  double stot = fabs(dangle) * rcoc ;
974  double zHit = z0 + stot * tanl;
975 
976  cross.set(xHit,yHit,zHit);
977 //
978  return 0 ;
979 }
980 //
981 /*:>--------------------------------------------------------------------
982 **: METHOD: Calculates trajectory length between two points on a track
983 **:
984 **: AUTHOR: ppy - P.P. Yepes, yepes@rice.edu
985 **: ARGUMENTS:
986 **: IN:
987 **: track - Track pointer
988 **: x1, y1 - Point 1
989 **: x2, y2 - Point 2
990 **: OUT:
991 **:
992 **: RETURNS: 0=ok, <>0 error
993 **:>------------------------------------------------------------------*/
994 double FtfBaseTrack::arcLength ( double x1, double y1, double x2, double y2 )
995 {
996  double x0, y0, xc, yc, rc ;
997  double angle_1, angle_2, d_angle, sleng_xy, sleng ;
998 /*----------------------------------------------------------
999  Get track parameters
1000 ----------------------------------------------------------*/
1001 
1002  x0 = r0 * cos(phi0) ;
1003  y0 = r0 * sin(phi0) ;
1004  rc = pt / fabs( bFactor * getPara()->bField ) ;
1005 
1006  double tPhi0 = psi + getPara()->bFieldPolarity*double(q) * 0.5 * M_PI / fabs((double)q) ;
1007  xc = x0 - rc * cos(tPhi0) ;
1008  yc = y0 - rc * sin(tPhi0) ;
1009 /*
1010  Get angle difference
1011 */
1012  angle_1 = atan2 ( (y1-yc), (x1-xc) ) ;
1013  if ( angle_1 < 0 ) angle_1 = angle_1 + 2. * M_PI ;
1014  angle_2 = atan2 ( (y2-yc), (x2-xc) ) ;
1015  if ( angle_2 < 0 ) angle_2 = angle_2 + 2. * M_PI ;
1016  d_angle = getPara()->bFieldPolarity*double(q) * ( angle_1 - angle_2 ) ;
1017  d_angle = fmod ( d_angle, 2. * M_PI ) ;
1018  if ( d_angle < 0 ) d_angle = d_angle + 2. * M_PI ;
1019 /*----------------------------------------------------------
1020  Get total angle and total trajectory
1021 ----------------------------------------------------------*/
1022  sleng_xy = fabs ( rc ) * d_angle ;
1023  sleng = sleng_xy * sqrt ( 1.0 + tanl * tanl ) ;
1024  return sleng ;
1025 
1026 }
1027 /*:>--------------------------------------------------------------------
1028 **: METHOD: Phi rotates the track
1029 **:
1030 **: AUTHOR: ppy - P.P. Yepes, yepes@rice.edu
1031 **: ARGUMENTS:
1032 **: IN:
1033 **: deltaPhi - Angle to rotate in phi
1034 **:
1035 **: RETURNS: 0=ok, <>0 error
1036 **:>------------------------------------------------------------------*/
1037 int FtfBaseTrack::phiRotate ( double deltaPhi ) {
1038  phi0 += deltaPhi ;
1039  if ( phi0 > 2. * M_PI ) phi0 -= 2. * M_PI ;
1040  if ( phi0 < 0 ) phi0 += 2. * M_PI ;
1041  psi += deltaPhi ;
1042  if ( psi > 2. * M_PI ) psi -= 2. * M_PI ;
1043  if ( psi < 0 ) psi += 2. * M_PI ;
1044 
1045  return 0 ;
1046 }
1047 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1048 // Fit a circle
1049 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1050 int FtfBaseTrack::refitHelix ( int mod, int modEqual, int rowMin, int rowMax ) {
1051  typedef FtfBaseHit* hitPointer;
1052 
1053  if ( nHits < 1 || nHits > 500 ) {
1054  LOG(ERR, "FtfBaseTrack:refitHelix: nHits %d out of range \n", nHits ) ;
1055  return 1 ;
1056  }
1057 //
1058  hitPointer* hitP = new hitPointer[nHits];
1059  int nHitsOrig = nHits ;
1060 
1061  int counter = 0 ;
1062  for ( startLoop() ; done() ; nextHit() ) {
1063  hitP[counter] = (FtfBaseHit *)currentHit ;
1064 // hitP[counter]->print(1);
1065  counter++ ;
1066  }
1067 
1068  int row ;
1069  firstHit = 0 ;
1070  counter = 0 ;
1071  for ( int i = 0 ; i < nHitsOrig ; i++ ) {
1072  row = hitP[i]->row ;
1073  hitP[i]->nextTrackHit = 0 ;
1074  if ( row%mod != modEqual ) continue ;
1075  if ( row < rowMin || row > rowMax ) continue ;
1076 
1077  if ( firstHit == 0 ) firstHit = hitP[i] ;
1078  else
1079  ((FtfBaseHit *)lastHit)->nextTrackHit = (void *)hitP[i] ;
1080  lastHit = (void *)hitP[i] ;
1081  counter++ ;
1082  }
1083  nHits = counter ;
1084 
1085  int problem = 0 ;
1086  if ( nHits > 5 ) fitHelix ( ) ;
1087  else problem = 1 ;
1088  //
1089  // Put hits back
1090  //
1091  firstHit = 0 ;
1092  for ( int i = 0 ; i < nHitsOrig ; i++ ) {
1093  row = hitP[i]->row ;
1094  if ( firstHit == 0 ) firstHit = hitP[i] ;
1095  else
1096  ((FtfBaseHit *)lastHit)->nextTrackHit = (void *)hitP[i] ;
1097  lastHit = (void *)hitP[i] ;
1098  }
1099  nHits = nHitsOrig ;
1100 
1101  delete []hitP ;
1102 
1103  return problem ;
1104 }
1105 /*:>--------------------------------------------------------------------
1106 **: METHOD: Updates track parameters to point of intersection with
1107 **: cylinder of radius r
1108 **:
1109 **:
1110 **: AUTHOR: ppy - P.P. Yepes, yepes@rice.edu
1111 **: ARGUMENTS:
1112 **: IN:
1113 **: radius - Cylinder radius to extrapolate track
1114 **: OUT:
1115 **:
1116 **:>------------------------------------------------------------------*/
1117 void FtfBaseTrack::updateToRadius ( double radius ) {
1118 
1119  double phiExtra, zExtra, rCircle, xCircleCenter, yCircleCenter ;
1120 
1121  int ok = extraRCyl ( radius, phiExtra, zExtra, rCircle, xCircleCenter, yCircleCenter ) ;
1122  if ( ok ) {
1123 // l3Log ( "FtfBaseTrack::updateToRadius: track %d does not intersect radius %f\n",
1124 // id, radius ) ;
1125  return ;
1126  }
1127 //
1128 // Check extrapolation falls inside volume
1129 //
1130 // if ( fabs(zExtra) > getPara()->zMax ) {
1131 // l3Log ( "problem extrapolating track \n" ) ;
1132 // return ;
1133 // }
1134  double xExtra = radius * cos(phiExtra) ;
1135  double yExtra = radius * sin(phiExtra) ;
1136 
1137  double tPhi = atan2(yExtra-yCircleCenter,xExtra-xCircleCenter);
1138 
1139 // if ( tPhi < 0 ) tPhi += 2. * M_PI ;
1140 
1141  if ( phiExtra < 0 ) phiExtra += 2 * M_PI ;
1142 
1143  double tPsi = tPhi - getPara()->bFieldPolarity * double(q) * 0.5 * M_PI / fabs((double)q) ;
1144  if ( tPsi > 2. * M_PI ) tPsi -= 2. * M_PI ;
1145  if ( tPsi < 0. ) tPsi += 2. * M_PI ;
1146 //
1147 // Update track parameters
1148 //
1149  r0 = radius ;
1150  phi0 = phiExtra ;
1151  z0 = zExtra ;
1152  psi = tPsi ;
1153 }
1154 /*:>--------------------------------------------------------------------
1155 **: METHOD: Updates track parameters to point of closest approach
1156 **:
1157 **:
1158 **: AUTHOR: ppy - P.P. Yepes, yepes@rice.edu
1159 **: ARGUMENTS:
1160 **: IN:
1161 **: xBeam - x Beam axis
1162 **: yBeam - y Beam axis
1163 **: rMax - radius of point of closest approach beyond which no update
1164 **:
1165 **:>------------------------------------------------------------------*/
1166 void FtfBaseTrack::updateToClosestApproach ( double xBeam, double yBeam, double rMax ) {
1167  double rc, xc, yc ;
1168  Ftf3DHit closest = getClosest ( xBeam, yBeam, rc, xc, yc ) ;
1169 // l3Log ( "FtfBaseTrack::updateClosestApproach: closest x y z %f %f %f \n",
1170 // closest.x, closest.y, closest.z ) ;
1171 
1172  double radius = sqrt(closest.x*closest.x+closest.y*closest.y);
1173  if ( radius > rMax ) return ;
1174 //
1175  double tPhi = atan2(closest.y-yc,closest.x-xc);
1176 
1177 // if ( tPhi < 0 ) tPhi += 2. * M_PI ;
1178 
1179 
1180  double tPsi = tPhi - getPara()->bFieldPolarity*double(q) * 0.5 * M_PI / fabs((double)q) ;
1181  if ( tPsi > 2. * M_PI ) tPsi -= 2. * M_PI ;
1182  if ( tPsi < 0. ) tPsi += 2. * M_PI ;
1183 //
1184 // Update track parameters
1185 //
1186  r0 = radius ;
1187  phi0 = atan2(closest.y,closest.x) ;
1188  if ( phi0 < 0 ) phi0 += 2. * M_PI ;
1189  z0 = closest.z ;
1190  psi = tPsi ;
1191 }
1192 
1193 
1194 /*:>--------------------------------------------------------------------
1195 **: METHOD: Extrapolation of a track to the given pathlenght
1196 **:
1197 **:
1198 **:
1199 **: AUTHOR: JB, Jens Berger, jberger@bnl.gov
1200 **: ARGUMENTS:
1201 **: IN:
1202 **: doubel pathlength: pathlength of the track, staring at x0,y0,z0
1203 **: OUT:
1204 **: one of pablos fancy Ftf3DHit
1205 **:
1206 **:>------------------------------------------------------------------*/
1207 Ftf3DHit FtfBaseTrack::extrapolate2PathLength(double pathlength)
1208 {
1209  // some helix para
1210 
1211  // BFilef scaled with 0.01
1212  double Bfield=fabs(getPara()->bField) * getPara()->bFieldPolarity * 0.01;
1213  double c=0.3;
1214  double lambda=atan(tanl);
1215  double kapa=(c*q*Bfield)/pt;
1216  double heli=-((q*Bfield)/fabs(q*Bfield));
1217  double phi=psi-heli*M_PI/2;
1218  // staring point
1219  double x0=r0*cos(phi0);
1220  double y0=r0*sin(phi0);
1221 
1222  Ftf3DHit CoordOfExtrapol;
1223  CoordOfExtrapol.x = x0 + (1/kapa)*(cos(phi+heli*pathlength*kapa*cos(lambda))-cos(phi));
1224  CoordOfExtrapol.y = y0 + (1/kapa)*(sin(phi+heli*pathlength*kapa*cos(lambda))-sin(phi));
1225  CoordOfExtrapol.z = z0 + pathlength*sin(lambda);
1226 
1227  // debug
1228  //cout<<"x0:"<<x0<<" y0:"<<y0<<" z0:"<<" lambda:"<<lambda<<z0<<" phi:"<<phi<<" h:"<<heli<<" kapa:"<<kapa<<endl;
1229  //cout<<" xs:"<<CoordOfExtrapol.x<<" ys:"<<CoordOfExtrapol.y<<" zs:"<<CoordOfExtrapol.z<<endl;
1230 
1231 
1232  // return coord of extrapolation
1233  return CoordOfExtrapol;
1234 }
1235 
1236 /*:>--------------------------------------------------------------------
1237 **: METHOD: Get the Radius of the track, helix at X,Y center
1238 **:
1239 **:
1240 **:
1241 **: AUTHOR: JB, Jens Berger, jberger@bnl.gov
1242 **: ARGUMENTS:
1243 **: IN:
1244 **: nada
1245 **: OUT:
1246 **: radius
1247 **:
1248 **:>------------------------------------------------------------------*/
1249 double FtfBaseTrack::getRadius()
1250 {
1251  double radius=pt / fabs( bFactor * getPara()->bField );
1252 
1253  return radius;
1254 }
1255 
1256 /*:>--------------------------------------------------------------------
1257 **: METHOD: Get y center of the corresponding radius of the track, helix
1258 **:
1259 **:
1260 **:
1261 **: AUTHOR: JB, Jens Berger, jberger@bnl.gov
1262 **: ARGUMENTS:
1263 **: IN:
1264 **: nada
1265 **: OUT:
1266 **: x center
1267 **:
1268 **:>------------------------------------------------------------------*/
1269 double FtfBaseTrack::getXCenter() {
1270 
1271  double tPhi0 = psi + getPara()->bFieldPolarity*double(q) * 0.5 * M_PI / fabs((double)q) ;
1272  // staring point
1273  double x0=r0*cos(phi0);
1274 
1275  return ( x0- getRadius() * cos(tPhi0) );
1276  }
1277 /*:>--------------------------------------------------------------------
1278 **: METHOD: Get y center of the corresponding radius of the track, helix
1279 **:
1280 **:
1281 **:
1282 **: AUTHOR: JB, Jens Berger, jberger@bnl.gov
1283 **: ARGUMENTS:
1284 **: IN:
1285 **: nada
1286 **: OUT:
1287 **: y center
1288 **:
1289 **:>------------------------------------------------------------------*/
1290 double FtfBaseTrack::getYCenter()
1291 {
1292 
1293  double tPhi0 = psi + getPara()->bFieldPolarity*double(q) * 0.5 * M_PI / fabs((double)q) ;
1294  // staring point
1295  double y0=r0*sin(phi0);
1296 
1297  return ( y0 - getRadius() * sin(tPhi0) );
1298 }
1299 /*:>---------------------------------------------------------------------------------------
1300 **: METHOD: Extrapolate to a plane
1301 **:
1302 **: Vector 'R' defines the position of the center and
1303 **: vector 'N' the normal vector of the plane.
1304 **: For a straight line there is a simple analytical
1305 **: solution. For curvatures > 0 the root is determined
1306 **: by Newton method. In case no valid s can be found
1307 **: the max. largest value for s is returned.
1308 **:
1309 **: THIS FUNCTION CAN ONLY BE USED WITH MAGNETIC FIELD > 0 !!!
1310 **:
1311 **:
1312 **: AUTHOR: JB, Jens Berger, jberger@bnl.gov, stolen from Thomas Ullrich's StarClassLibrary
1313 **:
1314 **:
1315 **: ARGUMENTS:
1316 **: IN:
1317 **: R(x,y,z) position of the plane, N(x,y,z) normal vector to plane
1318 **: OUT:
1319 **: plathlenght to plane
1320 **:
1321 **:>---------------------------------------------------------------------------------------*/
1322 double FtfBaseTrack::pathLength(double Rx, double Ry, double Rz, double Nx, double Ny, double Nz )
1323 {
1324  // THIS FUNCTION CAN ONLY BE USED WITH MAGNETIC FIELD > 0 !!!
1325 
1326  // BFilef scaled with 0.01
1327  double Bfield=fabs(getPara()->bField) * getPara()->bFieldPolarity * 0.01;
1328 
1329  // helicity
1330  int heli= (int) -((q*Bfield)/fabs(q*Bfield));
1331  int H = (heli>=0) ? 1 : -1;
1332 
1333  // origin
1334  double x0=r0*cos(phi0);
1335  double y0=r0*sin(phi0);
1336  // z0 = z0
1337 
1338  // dip angle == lambda
1339  double DipAngle = atan(tanl); // lambda
1340  double CosDipAngle = cos(DipAngle);
1341  double SinDipAngle = sin(DipAngle);
1342 
1343  // phase == phi
1344  double Phase = psi-heli*M_PI/2; // phi
1345  double CosPhase = cos(Phase);
1346  double SinPhase = sin(Phase);
1347  if (fabs(Phase) > M_PI) Phase = atan2(SinPhase, CosPhase); // force range [-pi,pi]
1348 
1349  // curvature == kapa
1350  double Curvature = (0.3*q*Bfield)/pt; // kapa
1351 
1352 
1353  // stolen part :->
1354  const double NoSolution = LONG_MAX ;
1355  const double MaxPrecisionNeeded = 0.0001; // micrometer in STAR coord.
1356  const int MaxIterations = 20;
1357 
1358  double A = Curvature*( (x0*Nx+y0*Ny+z0*Nz) - (Rx*Nx+Ry*Ny+Rz*Nz) ) -
1359  Nx*CosPhase -
1360  Ny*SinPhase;
1361  double t = H*Curvature*CosDipAngle;
1362 
1363  double a, f, fp, s;
1364  double sOld = s = 0;
1365  int i;
1366  for (i=0; i<MaxIterations; i++)
1367  {
1368  a = t*s+Phase;
1369  f = A +
1370  Nx*cos(a) +
1371  Ny*sin(a) +
1372  Nz*Curvature*SinDipAngle*s;
1373 
1374  fp = -Nx*sin(a)*t +
1375  Ny*cos(a)*t +
1376  Nz*Curvature*SinDipAngle;
1377  s -= f/fp;
1378  if (fabs(sOld-s) < MaxPrecisionNeeded) break;
1379  sOld = s;
1380  }
1381 
1382  if (i == MaxIterations) s = NoSolution;
1383 
1384  return s;
1385 }