StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
THelixTrack.cxx
1 #include <stdlib.h>
2 #include <math.h>
3 #include "TError.h"
4 #include "TArrayD.h"
5 #include "TCanvas.h"
6 #include "TGraph.h"
7 #include "TSystem.h"
8 #include "TMath.h"
9 #if ROOT_VERSION_CODE < 331013
10 #include "TCL.h"
11 #else
12 #include "TCernLib.h"
13 #endif
14 #include "TVector3.h"
15 #include "TRandom.h"
16 #include "TRandom2.h"
17 #include "TRandomVector.h"
18 #include "TError.h"
19 #include "TMatrixD.h"
20 
21 #include "THelixTrack.h"
22 #include "StMatrixD.hh"
23 #include "TComplex.h"
24 #include "TH1.h"
25 #include <cassert>
26 
27 static const double kMinErr = 1e-4, kBigErr=10;
28 static double *myQQQ = 0;
29 static double EmxSign(int n,const double *e);
30 
31 // Complex numbers
32 const TComplex Im(0,1);
33 //_____________________________________________________________________________
34 static void eigen2(double G[3], double lam[2], double eig[2])
35 {
36  double spur = G[0]+G[2];
37  double det = G[0]*G[2]-G[1]*G[1];
38  double dis = spur*spur-4*det;
39  if (dis<0) dis = 0;
40  dis = sqrt(dis);
41  if (lam) {
42  lam[0] = 0.5*(spur+dis);
43  lam[1] = 0.5*(spur-dis);
44  }
45  if (eig) {
46  eig[1]=G[0]-G[2]-dis;
47  eig[0]=G[2]-G[0]-dis;
48  if (fabs(eig[1])>fabs(eig[0])) {eig[0]= -2*G[1];}
49  else {eig[1]= -2*G[1];}
50  double nor = sqrt(eig[0]*eig[0]+eig[1]*eig[1]);
51  if (nor>1e-11) {
52  if(eig[0]<0) nor = -nor;
53  eig[0]/=nor;eig[1]/=nor;}
54  else {
55  eig[0]=1;eig[1]=0;
56  }
57 
58  }
59 }
60 //_____________________________________________________________________________
61 inline static double dot(const TComplex &a,const TComplex &b)
62 {return a.Re()*b.Re()+a.Im()*b.Im();}
63 //_____________________________________________________________________________
64 inline static TComplex expOne(const TComplex &x)
65 {
66  double a = TComplex::Abs(x);
67  if (a<0.01) {
68  return 1.+x*((1/2.) + x*((1/6.)+ x*(1/24.)));
69  } else {
70  return (TComplex::Exp(x)-1.)/x;
71  }
72 }
73 //_____________________________________________________________________________
74 inline static TComplex expOneD(const TComplex &x)
75 {
76  double a = TComplex::Abs(x);
77  if (a<0.01) {
78  return (1/2. + x*((1/6.)+ x*((1/24.)+x*(1/120.))));
79  } else {
80  return (TComplex::Exp(x)-1.-x)/(x*x);
81  }
82 }
83 
84 
85 //______________________________________________________________________________
86 void TCEmx_t::Set(const double *err)
87 { if (err) {memcpy(this,err,sizeof(*this));} else {Clear();}}
88 
89 //______________________________________________________________________________
90 void TCEmx_t::Move(const double F[3][3])
91 {
92  assert(mHH);
93  double oErr[6];
94  memcpy(oErr,Arr(),sizeof(oErr));
95  TCL::trasat(F[0],oErr,Arr(),3,3);
96 }
97 //______________________________________________________________________________
98 void TCEmx_t::Backward()
99 {
100  mHA*=-1; mAC*=-1;
101 }
102 //______________________________________________________________________________
103 double TCEmx_t::Sign() const
104 {
105  const double *E = &mHH;
106  double dia[3];
107  for (int i=0,li=0;i<3;li+=++i) {
108  dia[i] = E[li+i];
109  if (dia[i]<0) return -(i+1)*11;
110  for (int j=0;j<=i;j++) {
111  double dis = dia[i]*dia[j]-E[li+j]*E[li+j];
112  if (dis<0) return -(i+1+10*(j+1));
113  } }
114  return 0;
115 
116 }
117 //_____________________________________________________________________________
118 double THEmx_t::MaxCorr() const
119 {
120  if (mHH+mZZ<=0) return 0;
121  double dia[5],maxCorr=0;const double *e=&mHH;
122 
123  for (int i=0,li=0;i< 5;li+=++i) {
124  dia[i]=e[li+i];
125  for (int j=0;j<i;j++) {
126  double corr = (e[li+j]/dia[i])*(e[li+j]/dia[j]);
127  if (maxCorr<corr) maxCorr=corr;
128  } }
129  return sqrt(maxCorr);
130 }
131 
132 //______________________________________________________________________________
133 void THEmx_t::Set(const double *errxy,const double *errz)
134 {
135  Clear();
136  memcpy(&mHH,errxy,sizeof(mHH)*6);
137  mZZ = errz[0]; mZL =errz[1]; mLL =errz[2];
138 }
139 //______________________________________________________________________________
140 void THEmx_t::Set(const double *err)
141 { if (err) {memcpy(this,err,sizeof(*this));} else {Clear();}}
142 //_____________________________________________________________________________
143 void THEmx_t::Backward()
144 {
145  mHA*=-1; mAC*=-1; mHZ*=-1; mCZ*=-1; mAL*=-1; mZL*=-1;
146 }
147 //______________________________________________________________________________
148 void THEmx_t::Move(const double F[5][5])
149 {
150  assert(mHH);
151  double oErr[15];
152  memcpy(oErr,Arr(),sizeof(oErr));
153  TCL::trasat(F[0],oErr,Arr(),5,5);
154 }
155 //______________________________________________________________________________
156 void THEmx_t::Print(const char *tit) const
157 {
158 static const char *N="HACZL";
159  if (!tit) tit = "";
160  printf("THEmx_t::::Print(%s) ==\n",tit);
161  const double *e = &mHH;
162  for (int i=0,li=0;i< 5;li+=++i) {
163  printf("%c ",N[i]);
164  for (int j=0;j<=i;j++) {
165  printf("%g\t",e[li+j]);}
166  printf("\n");
167  }
168 }
169 //______________________________________________________________________________
170 double THEmx_t::Sign() const
171 {
172  const double *E = &mHH;
173  double dia[5];
174  for (int i=0,li=0;i<5;li+=++i) {
175  dia[i] = E[li+i];
176  if (dia[i]<0) return -(i+1)*11;
177  for (int j=0;j<=i;j++) {
178  double dis = dia[i]*dia[j]-E[li+j]*E[li+j];
179  if (dis<0) return -(i+1+10*(j+1));
180  } }
181  return 0;
182 
183 }
184 
185 //______________________________________________________________________________
186 const double Zero = 1.e-6;
187 static TComplex sgCX1,sgCX2,sgCD1,sgCD2,sgImTet,sgCOne,sgCf1;
188 static int SqEqu(double *, double *);
189 #if 0
190 //_____________________________________________________________________________
191 static int myEqu(double *s, int na, double *b,int nb)
192 {
193  StMatrixD mtx(na,na);
194  double *m = &mtx(1,1);
195  TCL::trupck(s,m,na);
196  size_t ierr=0;
197  mtx.invert(ierr);
198  if (ierr) return ierr;
199  for (int ib=0;ib<nb;ib++) {
200  TCL::vmatl(m,b+ib*na,s,na,na);
201  memcpy(b+ib*na,s,na*sizeof(*b));
202  }
203  TCL::trpck(m,s,na);
204  return 0;
205 }
206 //_____________________________________________________________________________
207 static void Eigen2(const double err[3], double lam[2], double eig[2][2])
208 {
209 
210  double spur = err[0]+err[2];
211  double det = err[0]*err[2]-err[1]*err[1];
212  double dis = spur*spur-4*det;
213  if (dis<0) dis = 0;
214  dis = sqrt(dis);
215  lam[0] = 0.5*(spur+dis);
216  lam[1] = 0.5*(spur-dis);
217  eig[0][0] = 1; eig[0][1]=0;
218  if (dis>1e-6*spur) {// eigenvalues are different
219  if (fabs(err[0]-lam[0])>fabs(err[2]-lam[0])) {
220  eig[0][1] = 1; eig[0][0]= -err[1]/(err[0]-lam[0]);
221  } else {
222  eig[0][0] = 1; eig[0][1]= -err[1]/(err[2]-lam[0]);
223  }
224  double tmp = sqrt(eig[0][0]*eig[0][0]+eig[0][1]*eig[0][1]);
225  eig[0][0]/=tmp; eig[0][1]/=tmp;
226  }
227  eig[1][0]=-eig[0][1]; eig[1][1]= eig[0][0];
228 }
229 //_____________________________________________________________________________
230 static TComplex MyFactor(double rho,double drho,double s)
231 {
232 // Integral exp(i*Phi)*dL where Phi = rho*L + 0.5*drho*L**2
233 // Let it is equal exp(i*Phi)*A(L) + const
234 // then dA/dL + i*(rho+drho*L)*A = 1
235 // Solve this equation for Taylor representation of A(L)
236 // static int Iter=0;
237  TComplex arr[3],add;
238  TComplex Sum; //
239  Sum = 0.0;
240  arr[0] = 1.; arr[1] = 0.;
241  drho = drho/rho;
242  double ss = s;
243  for (int j=2;1;j++) {
244  arr[2] = -TComplex(0,1)*rho*(arr[1]+drho*arr[0])/double(j);
245  ss *=s; add = ss*arr[2]; Sum += add;
246  if (1e-12*Sum.Rho2() > add.Rho2()) break;
247 // printf(" Iter=%d %d %g\n",Iter++,j-1,TComplex::Abs(add));
248  arr[0]=arr[1]; arr[1]=arr[2];
249  }
250  return Sum;
251 }
252 #endif //0
253 
254 ClassImp(THelixTrack)
255 //_____________________________________________________________________________
256 THelixTrack::THelixTrack(const double *xyz,const double *dir,double rho
257  ,double drho)
258 {
259 // Made from GEANT3 ghelix by V.Perevoztchikov
260 //
261 // ******************************************************************
262 // * *
263 // * Performs the tracking of one step in a magnetic field *
264 // * The trajectory is assumed to be a helix in a constant field *
265 // * taken at the mid point of the step. *
266 // * Parameters: *
267 // * input *
268 // * STEP =arc length of the step asked *
269 // * VECT =input vector (position,direction cos and momentum) *
270 // * CHARGE= electric charge of the particle *
271 // * output *
272 // * VOUT = same as VECT after completion of the step *
273 // * *
274 // * ==>Called by : <USER>, GUSWIM *
275 // * Author M.Hansroul ********* *
276 // * Modified S.Egli, S.V.Levonian *
277 // * Modified V.Perevoztchikov
278 // * *
279 // ******************************************************************
280 //
281  fEmx=0;
282  Set(xyz,dir,rho,drho);
283 }
284 //_____________________________________________________________________________
285 THelixTrack &THelixTrack::operator=(const THelixTrack &from)
286 {
287  THEmx_t *save = fEmx;
288  memcpy(fBeg,from.fBeg,fEnd-fBeg);
289  fEmx=save;
290  if (from.fEmx) SetEmx(from.fEmx->Arr());
291  return *this;
292 }
293 //_____________________________________________________________________________
294 THelixTrack::THelixTrack(const THelixTrack &from)
295 {
296  fEmx=0;
297  *this = from;
298 }
299 //_____________________________________________________________________________
300 THelixTrack::THelixTrack(const THelixTrack *fr)
301 {
302  fEmx=0;
303  Set(fr->fX,fr->fP,fr->fRho);
304 }
305 //_____________________________________________________________________________
306 THelixTrack::~THelixTrack()
307 { delete fEmx;fEmx=0;}
308 //_____________________________________________________________________________
309 THelixTrack::THelixTrack()
310 {
311  memset(fBeg,0,fEnd-fBeg);
312 }
313 //_____________________________________________________________________________
314 void THelixTrack::Set(const double *xyz,const double *dir,double rho
315  ,double drho)
316 {
317  fX[0] = xyz[0]; fX[1] = xyz[1]; fX[2] = xyz[2];
318  fP[0] = dir[0]; fP[1] = dir[1]; fP[2] = dir[2];
319  fRho = rho; fDRho=drho;
320  Build();
321 }
322 //_____________________________________________________________________________
323 void THelixTrack::SetEmx(const double* err2xy,const double* err2sz)
324 {
325  if (!fEmx) fEmx = new THEmx_t;
326  fEmx->Set(err2xy,err2sz);
327 }
328 //_____________________________________________________________________________
329 void THelixTrack::SetEmx(const double* err)
330 {
331  if (!fEmx) fEmx = new THEmx_t;
332  fEmx->Set(err);
333 }
334 //_____________________________________________________________________________
335 void THelixTrack::StiEmx(double err[21]) const
336 {
337 enum {kXX
338  ,kYX,kYY
339  ,kZX,kZY,kZZ
340  ,kEX,kEY,kEZ,kEE
341  ,kPX,kPY,kPZ,kPE,kPP
342  ,kTX,kTY,kTZ,kTE,kTP,kTT
343  ,kLN
344  };
345  memset(err,0,sizeof(err[0])*kLN);
346  double cosCA = fP[0]/fCosL;
347  err[kYY] = fEmx->mHH/(cosCA*cosCA);
348  err[kZY] = fEmx->mHZ/(cosCA);
349  err[kZZ] = fEmx->mZZ;
350  err[kEY] = fEmx->mHA/cosCA;
351  err[kEZ] = fEmx->mAZ;
352  err[kEE] = fEmx->mAA;
353  err[kPY] = fEmx->mHC/cosCA;
354  err[kPZ] = fEmx->mCZ;
355  err[kPE] = fEmx->mAC;
356  err[kPP] = fEmx->mCC;
357  err[kTY] = fEmx->mHL/(cosCA*fCosL*fCosL);
358  err[kTZ] = fEmx->mZL/( fCosL*fCosL);
359  err[kTE] = fEmx->mAL/( fCosL*fCosL);
360  err[kTP] = fEmx->mCL/( fCosL*fCosL);
361  err[kTT] = fEmx->mLL/( fCosL*fCosL*fCosL*fCosL);
362 }
363 //_____________________________________________________________________________
364 void THelixTrack::Set(double rho,double drho)
365 {
366  fRho = rho; fDRho=drho;
367 }
368 //_____________________________________________________________________________
370 {
371 
372  double d[3];
373  for (int i=0;i<3;i++) { d[i]=-fP[i];}
374  Set(fX,d,-fRho,-fDRho);
375  if(fEmx) fEmx->Backward();
376 }
377 //_____________________________________________________________________________
378 void THelixTrack::GetSpot(const double axis[3][3],double emx[3]) const
379 {
384 
385 // transformation matrix from "helix" coordinate to global
386  double my[3][3] = {{-fP[1]/fCosL, 0,fP[0]}
387  ,{ fP[0]/fCosL, 0,fP[1]}
388  ,{ 0, 1,fP[2]}};
389 
390  double T[3][3],tmp[3][3],g[6],t[2][2];
391  TCL::mxmpy (axis[0],my[0],T[0],3,3,3);
392 // now account that matrix axis may be non orthogonal
393  TCL::traat(axis[0],g,3,3);
394  if (fabs(g[0]-1)+fabs(g[1])+fabs(g[2]-1)
395  +fabs(g[3])+fabs(g[4])+fabs(g[5]-1)>1e-10) {//non orthogonal case
396  TCL::trsinv(g,g,3);
397  memcpy(tmp[0],T[0],sizeof(T));
398  TCL::trsa (g,tmp[0],T[0],3,3);
399  }
400  TCL::vlinco(T[0],1.,T[2],-T[0][2]/T[2][2],t[0],2);
401  TCL::vlinco(T[1],1.,T[2],-T[1][2]/T[2][2],t[1],2);
402  double myerr[3]={fEmx->mHH,fEmx->mHZ,fEmx->mZZ};
403  TCL::trasat(t[0],myerr,emx,2,2);
404  return;
405 }
406 //_____________________________________________________________________________
407 void THelixTrack::Build()
408 {
409 
410  double tmp;
411 
412  tmp = fP[0]*fP[0]+ fP[1]*fP[1]+ fP[2]*fP[2];
413  if (fabs(tmp-1.) > 1.e-12) {
414  tmp = ::sqrt(tmp); fP[0] /=tmp; fP[1] /=tmp; fP[2] /=tmp; }
415 
416  fCosL = ::sqrt(fP[0]*fP[0]+fP[1]*fP[1]);
417 }
418 //______________________________________________________________________________
419 void THelixTrack::MakeMtx(double step,double F[5][5])
420 {
421 // H,A,C,Z,L
422  enum {kH=0,kA,kC,kZ,kL};
423 
424  double S = step*fCosL;
425  memset(F[0],0,sizeof(F[0][0])*5*5);
426 
427  F[kH][kH] = sgCf1.Re()+1.;
428  double dSdH = sgCf1.Im();
429 
430  F[kH][kA] = S*sgCOne.Re();
431  double dSdA = S*sgCOne.Im();
432 
433  TComplex llCOneD = S*S*expOneD(-sgImTet);
434  F[kH][kC] = llCOneD.Re();
435  double dSdC = llCOneD.Im();
436 
437  F[kA][kH] = -dSdH*fRho;
438  F[kA][kA] = 1-dSdA*fRho;
439  F[kA][kC] = S+dSdC*fRho;
440  F[kC][kC] = 1;
441 
442  double tanL = fP[2]/fCosL;
443 
444  F[kZ][kH] = -dSdH*tanL;
445  F[kZ][kA] = -dSdA*tanL;
446  F[kZ][kC] = dSdC*tanL;
447  F[kZ][kZ] = 1;
448  F[kZ][kL] = S/(fCosL*fCosL);
449  F[kL][kL] = 1;
450 }
451 //_____________________________________________________________________________
452 double THelixTrack::Move(double step)
453 {
454  double F[5][5];
455  Eval(step,fX,fP,fRho);
456  if (fEmx && fEmx->mHH>0 && step) {
457  MakeMtx(step,F);
458  fEmx->Move(F);
459  }
460  return step;
461 }
462 //_____________________________________________________________________________
463 double THelixTrack::Move(double step,double F[5][5])
464 {
465  double xyz[3],dir[3],rho;
466  Eval(step,xyz,dir,rho);
467  Set(xyz,dir,rho,fDRho);
468  MakeMtx(step,F);
469  if (fEmx && fEmx->mHH>0 && step) fEmx->Move(F);
470  return step;
471 }
472 
473 //_____________________________________________________________________________
474 double THelixTrack::Step(double stmax,const double *surf, int nsurf,
475  double *xyz, double *dir, int nearest) const
476 {
477  int i;
478  double s[10]={0,0,0,0,0,0,0,0,0,0},tmp=0;
479  memcpy(s,surf,nsurf*sizeof(surf[0]));
480 
481  for(i=1;i<nsurf;i++) if (fabs(s[i])>tmp) tmp = fabs(s[i]);
482  if(fabs(tmp-1.)>0.1) {for(i=0;i<nsurf;i++) s[i]/=tmp;}
483  double stmin = (nearest)? -stmax:0;
484 // if (!s[3] && !s[6] && !s[8] && !s[9] && fabs(s[4]-s[5])<1.e-12)
485 // return StepHZ(s,nsurf,xyz,dir,nearest);
486 // else return Step(stmin,stmax,s,nsurf,xyz,dir,nearest);
487  return Step(stmin,stmax,s,nsurf,xyz,dir,nearest);
488 }
489 
490 
491 //_____________________________________________________________________________
492 double THelixTrack::Step(double stmin,double stmax, const double *s, int nsurf,
493  double *xyz, double *dir, int nearest) const
494 {
495  int ix,jx,nx,ip,jp;
496  double poly[4][3],tri[3],sol[2],cos1t,f1,f2,step,ss;
497  const double *sp[4][4] = {{s+0,s+1,s+2,s+3}, {s+1,s+4,s+7,s+9},
498  {s+2,s+7,s+5,s+8}, {s+3,s+9,s+8,s+6}};
499 
500  double myMax = 1./(fabs(fRho*fCosL)+1.e-10);
501  THelixTrack th(fX,fP,fRho);
502  cos1t = 0.5*fRho*fCosL;
503  double totStep=0;
504  while (2005) {
505  double hXp[3]={-th.fP[1],th.fP[0],0};
506  poly[0][0]=1.;poly[0][1]=0.;poly[0][2]=0.;
507  tri[0]=tri[1]=tri[2]=0;
508  for(ix=1;ix<4;ix++) {
509  poly[ix][0] =th.fX [ix-1];
510  poly[ix][1] =th.fP [ix-1];
511  poly[ix][2] =hXp[ix-1]*cos1t;
512  }
513 
514  nx = (nsurf<=4) ? 1:4;
515  for(ix=0;ix<nx;ix++) {
516  for(jx=ix;jx<4;jx++) {
517  ss = *sp[ix][jx]; if(!ss) continue;
518  for (ip=0;ip<3;ip++) {
519  f1 = poly[ix][ip]; if(!f1) continue;
520  f1 *=ss;
521  for (jp=0;jp+ip<3;jp++) {
522  f2 = poly[jx][jp]; if(!f2) continue;
523  tri[ip+jp] += f1*f2;
524  } } } }
525 
526  int nsol = SqEqu(tri,sol);
527  step = 1.e+12;
528  if (nsol<0) return step;
529 
530  if (nearest && nsol>1) {
531  if(fabs(sol[0])>fabs(sol[1])) sol[0]=sol[1];
532  nsol = 1;
533  }
534  if (nsol) step = sol[0];
535  if (step < stmin && nsol > 1) step = sol[1];
536  if (step < stmin || step > stmax) {
537  nsol = 0;
538  if (step>0) {step = stmax; stmin+=myMax/2;}
539  else {step = stmin; stmax-=myMax/2;}}
540 
541  if (!nsol && fabs(step) < 0.1*myMax) return 1.e+12;
542  if (fabs(step)>myMax) {step = (step<0)? -myMax:myMax; nsol=0;}
543 
544  double x[3],d[3];
545  th.Step(step,x,d);
546  if (nsol) {//test it
547  ss = s[0]+s[1]*x[0]+s[2]*x[1]+s[3]*x[2];
548  if (nsurf > 4) ss += s[4]*x[0]*x[0]+s[5]*x[1]*x[1]+s[6]*x[2]*x[2];
549  if (nsurf > 7) ss += s[7]*x[0]*x[1]+s[8]*x[1]*x[2]+s[9]*x[2]*x[0];
550  if (fabs(ss)<1.e-7) {
551  if (xyz) memcpy(xyz,x,sizeof(*xyz)*3);
552  if (dir) memcpy(dir,d,sizeof(*dir)*3);
553  return totStep+step;
554  } }
555 
556  stmax -=step; stmin -=step;
557  if (stmin>=stmax) return 1.e+12;
558  totStep+=step;
559  th.Move(step);
560  }
561 
562 }
563 
564 //_____________________________________________________________________________
565 double THelixTrack::StepHZ(const double *su, int nsurf,
566  double *xyz, double *dir,int nearest) const
567 {
568  double tri[3] = {0,0,0};
569  double f0,fc,fs,R,tet,tet0,tet1,tet2,costet,su45=0,fcs;
570 
571 
572  R = 1./fRho/fCosL;
573 // X
574  f0 = fX[0] - fP[1]*R;
575  fc = fP[1]*R;
576  fs = fP[0]*R;
577 
578  tri[0] = su[0] + su[1]*f0;
579  tri[1] = su[1]*fc;
580  tri[2] = su[1]*fs;
581  if (nsurf >4) {
582  su45 = 0.5*(su[4]+su[5]);
583  fcs = fc*fc + fs*fs;
584  tri[0] += su45*f0*f0 + su45*fcs;
585  tri[1] += su45*2*f0*fc;
586  tri[2] += su45*2*f0*fs;
587  }
588 // Y
589  f0 = fX[1] + fP[0]*R;
590  fc = -fP[0]*R;
591  fs = fP[1]*R;
592 
593  tri[0] += su[2]*f0;
594  tri[1] += su[2]*fc;
595  tri[2] += su[2]*fs;
596 
597  if (nsurf >4) {
598  tri[1] += su45*2*f0*fc;
599  tri[2] += su45*2*f0*fs;
600  }
601  costet = -tri[0]/::sqrt(tri[1]*tri[1]+tri[2]*tri[2]);
602  if(fabs(costet)>1.) return 1.e+12;
603  tet0 = atan2(tri[2],tri[1]);
604  tet = acos(costet);
605  tet1 = tet + tet0;
606  tet2 = -tet + tet0;
607 
608  if (tet1 > 2*M_PI) tet1 -= 2*M_PI;
609  if (tet2 > 2*M_PI) tet2 -= 2*M_PI;
610  if (nearest) { //Select the neares solution
611  if (fabs(tet1)>fabs(tet1-2*M_PI)) tet1 -=2*M_PI;
612  if (fabs(tet1)>fabs(tet1+2*M_PI)) tet1 +=2*M_PI;
613  if (fabs(tet2)>fabs(tet2-2*M_PI)) tet2 -=2*M_PI;
614  if (fabs(tet2)>fabs(tet2+2*M_PI)) tet2 +=2*M_PI;
615  if (fabs(tet1)>fabs(tet2) ) tet1 =tet2;
616  return Step(tet1*R,xyz,dir);
617  } else { //forward seqrch
618  double s1 = tet1*R;
619  if (s1<=0) s1 += 2*M_PI*fabs(R);
620  double s2 = tet2*R;
621  if (s2<=0) s2 += 2*M_PI*fabs(R);
622  if (s1>s2) s1=s2;
623  return Step(s1,xyz,dir);
624  }
625 
626 }
627 //_____________________________________________________________________________
628 double THelixTrack::Path(const THelixTrack &th,double *path2) const
629 {
630 static const double kMinAng = 0.1,kDeltaL=1e-4;
631 
632  THelixTrack thMe(this),thHe(&th);
633  double Rho1=thMe.GetRho()*thMe.GetCos();
634  double Rho2=thHe.GetRho()*thHe.GetCos();
635 
636  for (int ix=0;ix<3;ix++)
637  {if (fabs(thMe.Pos()[ix]-thHe.Pos()[ix])>100)return 3e33;}
638  double sMe=0,sHe=0;
639  int conv = 0;
640  for (int iter=0;iter<20; iter++) {
641  TVector3 P1(thMe.Pos());
642  TVector3 P2(thHe.Pos());
643  TVector3 D1(thMe.Dir());
644  TVector3 D2(thHe.Dir());
645  TVector3 dP = P1-P2;
646  TVector3 Dm = D1-D2;
647  TVector3 Dp = D1+D2;
648  double dPDm = dP.Dot(Dm);
649  double dPDp = dP.Dot(Dp);
650  double DDm = Dm.Mag2();
651  double DDp = Dp.Mag2();
652  if (DDm<1e-10) return 3e33;
653  double t1 = -(dPDm)/DDm;
654  double t2 = -(dPDp)/DDp;
655  double F = 1;
656  double s1 = t1+t2;
657  double s2 = t1-t2;
658  if (fabs(s1*Rho1*F) > kMinAng) F = kMinAng/fabs(s1*Rho1);
659  if (fabs(s2*Rho2*F) > kMinAng) F = kMinAng/fabs(s2*Rho2);
660  if (F<1) {s1*=F; s2*=F;}
661  thMe.Move(s1); sMe+=s1;
662  thHe.Move(s2); sHe+=s2;
663  if (F<1) continue;
664  if (fabs(s1)>kDeltaL) continue;
665  if (fabs(s2)>kDeltaL) continue;
666  conv = 1; break;
667  }
668  if (!conv) return 3e33;
669  if(path2) *path2=sHe;
670  return sMe;
671 }
672 //_____________________________________________________________________________
673 double THelixTrack::PathX(const THelixTrack &th,double *s2, double *dst, double *xyz) const
674 {
675  double ss1,ss2,dd,ss1Best,ss2Best,ddBest=1e33;
676  double xx[9];
677  int jkBest=-1;
678  for (int jk=0;jk<4;jk++) {
679  THelixTrack th1(this),th2(&th);
680  if (jk&1) th1.Backward();
681  if (jk&2) th2.Backward();
682  ss1 = th1.Path(th2,&ss2);
683  if (ss1>=1e33) continue;
684  if (ss2>=1e33) continue;
685  th1.Eval(ss1,xx+0);
686  th2.Eval(ss2,xx+3);
687  TCL::vsub(xx,xx+3,xx+6,3);
688  dd = TCL::vdot(xx+6,xx+6,3);
689  if (dd > ddBest) continue;
690  ddBest = dd; jkBest=jk; ss1Best = ss1; ss2Best = ss2;
691  if (xyz) TCL::ucopy(xx,xyz,6);
692  }
693  if (jkBest<0) { if(s2) *s2=3e33; return 3e33; }
694  if (jkBest&1) ss1Best = -ss1Best;
695  if (jkBest&2) ss2Best = -ss2Best;
696  if (s2 ) *s2 = ss2Best;
697  if (dst) *dst = ddBest;
698  return ss1Best;
699 }
700 //_____________________________________________________________________________
701 double THelixTrack::Path(double x,double y) const
702 {
703  TCircle ht(fX,fP,fRho);
704  double ar[2]={x,y};
705  return ht.Path(ar)/fCosL;
706 }
707 //_____________________________________________________________________________
708 double THelixTrack::Step(const double *point,double *xyz, double *dir) const
709 {
710 
711  static int nCount=0; nCount++;
712  TComplex cpnt(point[0]-fX[0],point[1]-fX[1]);
713  TComplex cdir(fP[0],fP[1]); cdir /=TComplex::Abs(cdir);
714  double step[3]={0,0,0};
715 // Z estimated step
716 
717  int zStep=0;
718  if (fabs(fP[2]) > 0.01){ //Z approximation
719  zStep = 1;
720  step[1] = (point[2]-fX[2])/fP[2];
721  }
722 //angle approximation
723 // R estimated step
724  {
725  cpnt /= cdir;
726  if (fabs(cpnt.Re()*fRho) < 0.01) {
727  step[2]=cpnt.Re();
728  } else {
729  double rho = fRho;
730  for (int i=0;i<2;i++) {
731  TComplex ctst = (1.+TComplex(0,1)*rho*cpnt);
732  ctst /=TComplex::Abs(ctst);
733  ctst = TComplex::Log(ctst);
734  step[2]= ctst.Im()/rho;
735  if (!fDRho) break;
736  rho = fRho+ 0.5*fDRho*step[2];
737  }
738  }
739  step[2]/=fCosL;
740  }
741 
742  if (zStep) {
743  double p = GetPeriod();
744  int nperd = (int)((step[1]-step[2])/p);
745  if (step[2]+nperd*p>step[1]) nperd--;
746  if (fabs(step[2]-step[1]+(nperd+0)*p)
747  >fabs(step[2]-step[1]+(nperd+1)*p)) nperd++;
748  step[2]+=(nperd)*p;
749  }
750  step[0] = step[2];
751 
752  double ds = step[1]-step[2];
753  if (zStep && fabs(ds)>1.e-5) {
754  double dz = ds*fP[2];
755  step[0] += dz*dz/ds;
756  }
757 
758 
759  double xnear[6],ss=0; double* pnear=xnear+3;
760 // iterations
761  double dstep = 1.e+10,oldStep=dstep,dztep;
762  double lMax = step[0]+0.25*GetPeriod();
763  double lMin = step[0]-0.25*GetPeriod();
764 
765  if (zStep) {
766  lMax = (step[1]>step[2])? step[1]:step[2];
767  lMin = (step[1]>step[2])? step[2]:step[1];}
768  int iter=99,icut=1;
769  THelixTrack local(this);
770  local.Move(step[0]);
771  lMax-=step[0];lMin-=step[0];
772  local.Step(0.,xnear,pnear);
773  for (; iter; iter--)
774  {
775  double diff = (icut)? lMax-lMin: fabs(dstep);
776  if (diff < 0.1) {
777  if (diff < 1.e-6) break;
778  double tmpxy = fabs(point[0]-xnear[0])+fabs(point[1]-xnear[1]);
779  double tmpz = fabs(point[2]-xnear[2]);
780  if (fabs(fCosL) *diff <tmpxy*1e-6
781  &&fabs(pnear[2])*diff <tmpz *1e-6) break;
782  if (tmpxy+tmpz < 1.e-6) break;
783  }
784 
785  local.Step(ss,xnear,pnear);
786  dstep = 0; icut = 0;
787  for (int i=0;i<3;i++) {dstep += pnear[i]*(point[i]-xnear[i]);}
788  if(dstep<0) {
789  lMax = ss; dztep = -0.5*(lMax-lMin);
790  if (dstep<dztep || fabs(dstep)>0.7*oldStep) {icut=1;dstep = dztep;}
791  } else {
792  lMin = ss; dztep = 0.5*(lMax-lMin);
793  if (dstep>dztep || fabs(dstep)>0.7*oldStep) {icut=1;dstep = dztep;}
794  }
795  ss += dstep;
796  oldStep=fabs(dstep);
797  }
798 // printf("ITERS=%d dSTEP=%g \n",iter,dstep);
799  if (!iter){ printf("*** Problem in THElixTrack::Step(vtx) ***\n");
800  printf("double vtx[3]={%g,%g,%g};",point[0],point[1],point[2]);
801  Print();}
802  assert(iter);
803  step[0]+=ss;
804  return (xyz) ? Step(step[0],xyz,dir) : step[0];
805 }
806 //_____________________________________________________________________________
807 double THelixTrack::Dca(const double *point,double *dcaErr) const
808 {
809  double x[3],T[3][3],emx[3];
810  double s = Path(point,x,T[2]);
811  for (int i=0;i<3;i++) {T[0][i]=point[i]-x[i];}
812  double dca = sqrt(T[0][0]*T[0][0]+T[0][1]*T[0][1]+T[0][2]*T[0][2]);
813  if (!dcaErr) return dca;
814 
815  for (int i=0;i<3;i++) {T[0][i]/=dca;}
816  T[1][0]=T[0][1]*T[2][2]-T[2][1]*T[0][2];
817  T[1][1]=T[0][2]*T[2][0]-T[2][2]*T[0][0];
818  T[1][2]=T[0][0]*T[2][1]-T[2][0]*T[0][1];
819 
820  THelixTrack th(*this);
821  th.Move(s);
822  th.GetSpot(T,emx);
823  *dcaErr=emx[0];
824  return dca;
825 }
826 //_____________________________________________________________________________
827 double THelixTrack::Dca(double x,double y,double *dcaErr) const
828 {
829  double dir[3]={fP[0],fP[1],0};
830  THelixTrack hlx(fX,dir,fRho);
831  if (fEmx) hlx.SetEmx(fEmx->Arr());
832  double vtx[3]={x,y,fX[2]};
833  return hlx.Dca(vtx,dcaErr);
834 }
835 
836 
837 //_____________________________________________________________________________
838 double THelixTrack::Dca(const double point[3]
839  ,double &dcaXY,double &dcaZ,double dcaEmx[3],int kind) const
847 {
848  double dif[3];
849  double s = 0;
850  assert(kind==2 || kind==3);
851  if (kind==3) s = Path(point);
852  else s = Path(point[0],point[1]);
853 
854  THelixTrack th(*this);
855  th.Move(s);
856  const double *x=th.Pos();
857  const double *d=th.Dir();
858 
859  for (int i=0;i<3;i++) {dif[i]=x[i]-point[i];}
860  double nor = th.GetCos();
861  double T[3][3]={{-d[1]/nor, d[0]/nor, 0}
862  ,{ 0, 0, 1}
863  ,{ d[0]/nor, d[1]/nor, 0}};
864 
865  dcaXY = T[0][0]*dif[0]+T[0][1]*dif[1];
866  dcaZ = dif[2];
867  if (!dcaEmx) return s;
868  THEmx_t *emx =th.Emx();
869  dcaEmx[0] = emx->mHH;
870  dcaEmx[1] = 0;
871 // cos(Lambda) **4 to account that we are in the nearest point
872  dcaEmx[2] = emx->mZZ*pow(th.GetCos(),4);
873  return s;
874 }
875 
876 
877 //_____________________________________________________________________________
878 double THelixTrack::GetPeriod() const
879 {
880  double per = (fabs(fRho) > 1.e-10) ? fabs(2.*M_PI/fRho):1.e+10;
881  return per/fCosL;
882 }
883 //______________________________________________________________________________
884 void THelixTrack::Rot(double angle)
885 {
886  Rot(cos(angle),sin(angle));
887 }
888 //______________________________________________________________________________
889 void THelixTrack::Rot(double cosa,double sina)
890 {
891  TComplex CX(fX[0],fX[1]),CP(fP[0],fP[1]);
892  TComplex A (cosa,sina);
893  CX *=A; fX[0] = CX.Re(); fX[1]=CX.Im();
894  CP *=A; fP[0] = CP.Re(); fP[1]=CP.Im();
895 }
896 //_____________________________________________________________________________
897 void THelixTrack::Streamer(TBuffer &){}
898 //_____________________________________________________________________________
899 void THelixTrack::Print(Option_t *) const
900 {
901  printf("\n THelixTrack::this = %p\n",(void*)this);
902  printf(" THelixTrack::fX[3] = { %f , %f ,%f }\n",fX[0],fX[1],fX[2]);
903  printf(" THelixTrack::fP[3] = { %f , %f ,%f }\n",fP[0],fP[1],fP[2]);
904  printf(" THelixTrack::fRho = %f \n\n",fRho);
905 
906  printf("double xyz[3] = {%g,%g,%g};\n" ,fX[0],fX[1],fX[2]);
907  printf("double dir[3] = {%g,%g,%g};\n" ,fP[0],fP[1],fP[2]);
908  printf("double Rho = %g;\n" ,fRho);
909  printf("THelixTrack *ht = new THelixTrack(xyz,dir,Rho);\n");
910 
911 }
912 //______________________________________________________________________________
913 void THelixTrack::TestMtx()
914 {
915  enum {kH=0,kA,kC,kZ,kL};
916 const static char* T="HACZL";
917  double Dir[4][3],X[4][3]={{0}},Rho[2],step,F[5][5],Del,Dif,Fi[5][5];
918  double maxEps = 0;
919  int nErr=0;
920  int iR = 10+ gRandom->Rndm()*100;
921  int iAlf=30+ gRandom->Rndm()*100;
922  int iLam=10+ gRandom->Rndm()*60;
923  step = gRandom->Rndm()*6*iR;
924 iLam=80; //******* Tested for big lambda
925  Rho[0] = 1./iR;
926  double alf = iAlf/180.*M_PI;
927  double lam = iLam/180.*M_PI;
928  Dir[0][0] = cos(lam)*cos(iAlf/180.*M_PI);
929  Dir[0][1] = cos(lam)*sin(iAlf/180.*M_PI);
930  Dir[0][2] = sin(lam);
931  THelixTrack tc(X[0],Dir[0],Rho[0]);
932  tc.Eval(step,X[1],Dir[1]);
933  tc.Move(step,F);
934  memcpy(Fi[0],F[0],sizeof(F));
935  tc.InvertMtx(Fi);
936  TMatrixD one = TMatrixD(5,5,F[0])*TMatrixD(5,5,Fi[0]);
937  one.Print();
938 
939  printf("TestMtx: Angle=%d Lam=%d \tRad=%d Step=%d \n",iAlf,iLam,iR,int(step));
940 
941  for (int iHAR=0;iHAR<5;iHAR++) {
942  memcpy(X[2] ,X[0] ,sizeof(X[0][0]) *3);
943  memcpy(Dir[2],Dir[0],sizeof(Dir[0][0])*3);
944  Del = 0;
945  Rho[1]=Rho[0];
946  switch (iHAR) {
947  case kH: {
948  Del = 0.001*iR;
949  X[2][0] += -Dir[0][1]*Del/cos(lam);
950  X[2][1] += Dir[0][0]*Del/cos(lam);
951  break;}
952 
953  case kA: {
954  Del = M_PI/180*0.01;
955  Dir[2][0] = cos(lam)*cos(alf+Del);
956  Dir[2][1] = cos(lam)*sin(alf+Del);
957  Dir[2][2] = sin(lam);
958  break;}
959 
960  case kC: {
961  Del = Rho[0]*0.005;
962  Rho[1] = Rho[0]+Del;
963  break;}
964  case kZ: {
965  Del = 0.02;
966  X[2][2] += Del;
967  break;}
968  case kL: {
969  Del = M_PI/180*0.1;
970  Dir[2][0] = cos(lam+Del)*cos(alf);
971  Dir[2][1] = cos(lam+Del)*sin(alf);
972  Dir[2][2] = sin(lam+Del);
973  break;}
974  }//end switch
975 
976  THelixTrack tcc(X[2],Dir[2],Rho[1]);
977  tcc.Move(step);
978  double myStep = tcc.Path(X[1][0],X[1][1]);
979  tcc.Eval(myStep,X[3],Dir[3]);
980 
981  for (int jHAR=0;jHAR<5; jHAR++) {
982  if (jHAR==kC) continue;
983  if (jHAR==kL) continue;
984  switch(jHAR) {
985  case kH: {
986  Dif = (X[3][0]-X[1][0])*(-Dir[1][1])
987  + (X[3][1]-X[1][1])*( Dir[1][0]);
988  Dif/=cos(lam);
989  break;}
990  case kA: {
991  Dif = atan2(Dir[3][1],Dir[3][0])
992  -atan2(Dir[1][1],Dir[1][0]);
993  if (Dif> M_PI) Dif-=2*M_PI;
994  if (Dif< -M_PI) Dif+=2*M_PI;
995  break;}
996  case kZ: {
997  Dif = X[3][2]-X[1][2];
998  break;}
999  }
1000  double est = Dif/Del;
1001  double eps = fabs(est-F[jHAR][iHAR])*2
1002  /(fabs(est)+fabs(F[jHAR][iHAR]+1e-6));
1003  if (eps>maxEps) maxEps=eps;
1004  if (eps < 1e-2) continue;
1005  nErr++;
1006  printf(" m%c%c \t%g \t%g \t%g\n",
1007  T[jHAR],T[iHAR],F[jHAR][iHAR],est,eps);
1008 
1009  } }
1010  printf("TestMtx: %d errors maxEps=%g\n",nErr,maxEps);
1011 
1012 }
1013 
1014 //_____________________________________________________________________________
1015 int SqEqu(double *cba, double *sol)
1016 {
1017 //
1018 // made from fortran routine GVPSQR (Geant320)
1019 /*
1020 ************************************************************************
1021 * *
1022 * SUBROUTINE GVPSQR (CBA,SOL,NSOL) 870924 VP *
1023 * *
1024 * SOLVE QUADRATIC EQUATION *
1025 * *
1026 * ARGUMENTS: *
1027 * CBA Array of coeff's A0 + A1*x + A2*x**2 *
1028 * SOL Solutions *
1029 * NSOL Number of solutions : *
1030 * if zero - SOL[0]= extremum *
1031 * if -ve - No solution at all *
1032 * *
1033 ************************************************************************
1034 */
1035  const double zero2=1.e-12;
1036  double swap,a,b,c,amx,dis,bdis;
1037  int nsol;
1038 /*--------------------------------------------------------------------*/
1039 
1040  a = cba[2]; b = cba[1]*0.5; c = cba[0];
1041  if (b < 0.) {a = -a; b = -b; c = -c;}
1042  amx = fabs(a); if (amx<b) amx = b; if (amx<fabs(c)) amx = fabs(c);
1043  if (amx <= 0.) return -1;
1044  a = a/amx; b = b/amx; c = c/amx;
1045 
1046  dis = b*b - a*c;
1047  nsol = 1;
1048  if (fabs(dis) <= zero2) dis = 0;
1049  if (dis < 0.) { nsol = 0; dis = 0.;}
1050 
1051  dis = ::sqrt(dis); bdis = b + dis;
1052  if (fabs(c) > 1.e+10*bdis) return -1;
1053  sol[0] = 0.;
1054  if (fabs(bdis) <= 0.) return nsol;
1055  sol[0] = (-c/bdis);
1056  if (dis <= 0.) return nsol;
1057  if (bdis >= 1.e+10*fabs(a)) return nsol;
1058  nsol = 2; sol[1] = (-bdis/a);
1059  if (sol[0] > sol[1]) { swap = sol[0]; sol[0] = sol[1]; sol[1] = swap;}
1060  return nsol;
1061 }
1062 //_____________________________________________________________________________
1063 double THelixTrack::Eval(double step, double *xyz, double *dir,double &rho) const
1064 {
1065  Eval(step,xyz,dir);
1066  rho = fRho +(step*fCosL)*fDRho;
1067  return step;
1068 }
1069 //_____________________________________________________________________________
1070 double THelixTrack::Eval(double step, double *xyz, double *dir) const
1071 {
1072 
1073  double ztep = step*fCosL;
1074  double teta = ztep*(fRho+0.5*ztep*fDRho);
1075 
1076  sgCX1 = TComplex(fX[0] ,fX[1]);
1077  sgCD1 = TComplex(fP[0],fP[1])/fCosL;
1078  sgImTet = TComplex(0,teta);
1079  sgCOne = expOne(sgImTet); //(exp(I*Rho*L)-1)/(I*Rho*L)
1080  sgCf1 = sgImTet*sgCOne;
1081  sgCD2 = sgCD1*sgCf1+sgCD1; // exp(I*Fi0+I*Rho*L)
1082  sgCX2 = sgCD1*sgCOne*ztep; // exp(I*Fi0)*(exp(I*Rho*L)-1)/(I*Rho)
1083 
1084  if (xyz) {
1085  xyz[0] = sgCX2.Re()+sgCX1.Re();
1086  xyz[1] = sgCX2.Im()+sgCX1.Im();
1087  xyz[2] = fX[2]+fP[2]*step;
1088  }
1089  if (dir) {
1090  sgCD2/= TComplex::Abs(sgCD2);
1091  dir[0] = sgCD2.Re()*fCosL;
1092  dir[1] = sgCD2.Im()*fCosL;
1093  dir[2] = fP[2];
1094  }
1095  return step;
1096 }
1097 //_____________________________________________________________________________
1098 void THelixTrack::Fill(TCircle &circ) const
1099 {
1100  circ.fX[0]=fX[0];
1101  circ.fX[1]=fX[1];
1102  circ.fD[0]=fP[0]/fCosL;
1103  circ.fD[1]=fP[1]/fCosL;
1104  circ.fRho=fRho;
1105  if (fEmx) circ.SetEmx(fEmx->Arr());
1106 }
1107 //_____________________________________________________________________________
1108 void THelixTrack::InvertMtx(double F[5][5])
1109 {
1110 static const int minus[][2] = {{0,1},{1,0},{1,2},{3,0},{3,2},{3,4},{-1,0}};
1111  for (int i=0;minus[i][0]>=0;i++) {
1112  F[minus[i][0]][minus[i][1]] = -F[minus[i][0]][minus[i][1]];
1113  }
1114 }
1115 
1116 
1117 // //_____________________________________________________________________________
1118 // void THelixTrack::TestErr()
1119 // {
1120 // double hpar[7];
1121 // for (int i=0;i<7;i++) { hpar[i] = (gRandom->Rndm()-0.5)*100;
1122 // hpar[6] = 1./hpar[6];
1123 //
1124 // }
1125 
1126 //______________________________________________________________________________
1127 void THelixTrack::Show(double len, const THelixTrack *other) const
1128 {
1129 static TCanvas *myCanvas = 0;
1130  int kolor[2]={kRed,kBlue};
1131 
1132  TGraph *ciGraph[2][2] = {{0}};
1133  TGraph *ptGraph[2][2] = {{0}};
1134  TGraph *szGraph[2] = {0};
1135 
1136  double x[100],y[100],z[100],l[100],xyz[3];
1137  double X[4],Y[4],Z[4],L[4];
1138  const THelixTrack *th[]={this,other};
1139  int nH = (other)? 2:1;
1140  for (int ih=0;ih<nH;ih++) {
1141  double rho = fabs(th[ih]->GetRho());
1142  double step = 0.01*(1./(rho+1e-10));
1143 
1144  if (step>fabs(len)*0.10) step=fabs(len)*0.1;
1145  if (step<fabs(len)*0.01) step=fabs(len)*0.01;
1146 
1147 
1148  int nPts = (int)(fabs(len)/step);
1149  step = fabs(len)/nPts;
1150  if (len<0) {len = -len; step = -step;}
1151  for (int ipt=0; ipt<nPts; ipt++) {
1152  double s = ipt*step;
1153  th[ih]->Eval(s,xyz);
1154  l[ipt]=s; x[ipt]=xyz[0]; y[ipt]=xyz[1], z[ipt]=xyz[2];
1155  }
1156  ciGraph[ih][0] = new TGraph(nPts , x, y);
1157  ciGraph[ih][1] = new TGraph(nPts , l, z);
1158  ciGraph[ih][0]->SetLineColor(kolor[ih]);
1159  ciGraph[ih][1]->SetLineColor(kolor[ih]);
1160  ptGraph[ih][0] = new TGraph( 1 , x, y);
1161  ptGraph[ih][1] = new TGraph( 1 , l, z);
1162  ptGraph[ih][0]->SetMarkerColor(kolor[ih]);
1163  ptGraph[ih][1]->SetMarkerColor(kolor[ih]);
1164 
1165  X[ih*2+0]=x[0]; X[ih*2+1]=x[nPts-1];
1166  Y[ih*2+0]=y[0]; Y[ih*2+1]=y[nPts-1];
1167  Z[ih*2+0]=z[0]; Z[ih*2+1]=z[nPts-1];
1168  L[ih*2+0]=l[0]; L[ih*2+1]=l[nPts-1];
1169  }
1170 
1171  szGraph[0] = new TGraph(nH*2 , X, Y);
1172  szGraph[1] = new TGraph(nH*2 , L, Z);
1173 //
1174  myCanvas = new TCanvas("THelixTrack_Show","",600,800);
1175  myCanvas->Divide(1,2);
1176  for (int ipad=0;ipad<2;ipad++) {
1177  myCanvas->cd(ipad+1);
1178  szGraph[ipad]->Draw("AP");
1179  for (int ih = 0;ih<nH;ih++) {
1180  ptGraph[ih][ipad]->Draw("same *");
1181  ciGraph[ih][ipad]->Draw("same CP");
1182  } }
1183 
1184 
1185  myCanvas->Modified();
1186  myCanvas->Update();
1187  while(!gSystem->ProcessEvents()){gSystem->Sleep(200);};
1188 
1189 }
1190 //_____________________________________________________________________________
1191 void THelixTrack::Test1()
1192 {
1193 double surf[4] = {-11.32212856152224, 0.50109792630239824, -0.86539108263698283, 0.00078459561521909921};
1194 double xyz[3] = {-0.0206564,-0.0153429,0.0285582};
1195 double dir[3] = {0.450295,-0.596426,-0.664463};
1196 double Rho = 0.00678696;
1197 THelixTrack TH(xyz,dir,Rho);
1198 
1199 double s = TH.Step(100000,surf,4);
1200 printf("s=%g = 15.3589\n",s);
1201 }
1202 //_____________________________________________________________________________
1203 void THelixTrack::Test2()
1204 {
1205 double diff[3];
1206 
1207 double xyz[3] = {-60.0301,1.51445,-1.57283};
1208 double dir[3] = {-0.849461,0.526419,0.0360391};
1209 double Rho = 0.00363571;
1210 THelixTrack ht(xyz,dir,Rho);
1211 
1212 double MyHit[3]= { -177.673, 41.305, 2.90798};
1213 double MyClo[3];
1214 
1215 printf("%s= %g %g %g\n","MyHit",MyHit[0],MyHit[1],MyHit[2]);
1216 double s = ht.Step(MyHit,MyClo);
1217 ht.Step(s,MyClo);
1218 TCL::vsub(MyClo,MyHit,diff,3);
1219 double MyDist = sqrt(TCL::vdot(diff,diff,3));
1220 printf("%s= %g %g %g\n","MyClo ",MyClo[0],MyClo[1],MyClo[2]);
1221 printf("MustBe= -177.661 41.4145 2.94559\n");
1222 
1223 printf("%s= %g %g %g\n","MyDif ",diff[0],diff[1],diff[2]);
1224 printf("MustBe= 0.0122709 0.109539 0.0376077\n");
1225 printf("%s=%g\n","MyS ",s);
1226 printf("MustBe=125.375\n");
1227 printf("%s= %g\n","MyDist",MyDist);
1228 printf("MustBe= 0.116463\n");
1229 }
1230 //_____________________________________________________________________________
1231 void THelixTrack::Test3()
1232 {
1233 double xyz[3] = {100,200,300};
1234 double dir[3] = {-0.224845,-0.491295,-0.841471};
1235 double Rho = 0.02;
1236 double sur[8]={-120,1,0,0,0,0,0};
1237 THelixTrack *ht = new THelixTrack(xyz,dir,Rho);
1238 double newX[3],newD[3];
1239 ht->Backward();
1240 double s = ht->Step(1000.,sur,4,newX,newD);
1241 printf("Result: s=%g newX=(%g %g %g) newD=(%g %g %g)\n"
1242  ,s,newX[0],newX[1],newX[2],newD[0],newD[1],newD[2]);
1243 
1244 printf("MustBe: s=56.1931 newX=(120 222.222 347.285) newD=(0.464979 0.275174 0.841471)\n\n");
1245 
1246 sur[6]=1e-6;
1247  s = ht->Step(1000.,sur,7,newX,newD);
1248 printf("Result: s=%g newX=(%g %g %g) newD=(%g %g %g)\n"
1249  ,s,newX[0],newX[1],newX[2],newD[0],newD[1],newD[2]);
1250 printf("MustBe: s=55.9338 newX=(119.88 222.151 347.067) newD=(0.464206 0.276476 0.841471)\n\n");
1251 }
1252 //_____________________________________________________________________________
1253 void THelixTrack::Test4()
1254 {
1255 double surf[7] = {-100, 0, 0, 0, 1,1,0};
1256 double xyz[3] = {-0.0206564,-0.0153429,0.0285582};
1257 double dir[3] = {0.450295,-0.596426,-0.664463};
1258 double Rho = 0.00678696;
1259 double xnew[3];
1260 THelixTrack TH(xyz,dir,Rho);
1261 
1262 double s = TH.Step(100000,surf,7,xnew);
1263 double dif = xnew[0]*xnew[0]+xnew[1]*xnew[1]-100;
1264 printf("s=%g dif=%g\n",s,dif);
1265 
1266 }
1267 //_____________________________________________________________________________
1268 void THelixTrack::Test5()
1269 {
1270  double pars[4][2][7] = {
1271  {{0,0,0, 1,1,1, -0.001},{0,0, 0, -1,1,-1,0.002}},
1272  {{0,0,1, 1,1,1, -0.001},{0,0,-1, -1,1,-1,0.002}},
1273  {{0,0,1, 1,1,1, -0.001},{0,0,-1, 1,1,-1,0.002}},
1274  };
1275  for (int ip=0;ip<3;ip++) {
1276  THelixTrack th1(pars[ip][0],pars[ip][0]+3,pars[ip][0][6]);
1277  THelixTrack th2(pars[ip][1],pars[ip][1]+3,pars[ip][1][8]);
1278  th1.Move(-50);
1279  th2.Move(-50);
1280  double s2;
1281  double s1 = th1.Path(th2,&s2);
1282  th1.Move(s1);
1283  th2.Move(s2);
1284  double diff[3];
1285  TCL::vsub(th1.Pos(),th2.Pos(),diff,3);
1286  double dist = sqrt(TCL::vdot(diff,diff,3));
1287  printf("s1=%g s2=%g dist=%g\n",s1,s2,dist);
1288 
1289  }
1290 }
1291 //______________________________________________________________________________
1292 void THelixTrack::TestDer()
1293 {
1294  enum {kH=0,kA,kC,kZ,kL};
1295  double fak = 0.1;
1296  double D[5][3],X[5][3]={{0}},Rho[5],step,F[5][5];
1297  int iR = 10+ gRandom->Rndm()*100;
1298  int iAlf=30+ gRandom->Rndm()*100;
1299  int iLam=10+ gRandom->Rndm()*60;
1300  step = gRandom->Rndm()*6*iR;
1301 iLam=80; //*********Tested for big lamda
1302  Rho[0] = 1./iR;
1303  double alf = iAlf/180.*M_PI;
1304  double lam = iLam/180.*M_PI;
1305  D[0][0] = cos(lam)*cos(alf);
1306  D[0][1] = cos(lam)*sin(alf);
1307  D[0][2] = sin(lam);
1308  THelixTrack hlx0(X[0],D[0],Rho[0]);
1309  THelixTrack hlx1(hlx0);
1310  hlx1.Move(step,F);
1311  hlx1.Eval(0,X[2],D[2]);
1312  Rho[2]=hlx1.GetRho();
1313 
1314 
1315  printf("TestDer: Angle=%d Lam=%d \tRad=%d Step=%d \n",iAlf,iLam,iR,int(step));
1316  hlx0.Eval(0,X[1],D[1]); Rho[1]=hlx0.GetRho();
1317 
1318  double dH = iR *0.01 *(gRandom->Rndm()-0.5)*fak;
1319  double dAlf = M_PI/180*0.1 *(gRandom->Rndm()-0.5)*fak;
1320  double dRho = Rho[0] *0.1 *(gRandom->Rndm()-0.5)*fak;
1321  double dZ = (gRandom->Rndm()-0.5)*fak;
1322  double dLam = M_PI/180*0.1 *(gRandom->Rndm()-0.5)*fak;
1323  double dA[5] = {dH,dAlf,dRho,dZ ,dLam}, dB[5];
1324  D[1][0] = cos(lam+dLam)*cos(alf+dAlf);
1325  D[1][1] = cos(lam+dLam)*sin(alf+dAlf);
1326  D[1][2] = sin(lam+dLam);
1327  X[1][0] += -D[0][1]*dH/cos(lam);
1328  X[1][1] += D[0][0]*dH/cos(lam);
1329  X[1][2] += dZ;
1330  Rho[1]+=dRho;
1331  THelixTrack hlxM(X[1],D[1],Rho[1]);
1332  hlxM.Move(step);
1333  double dL = hlxM.Path(X[2][0],X[2][1]);
1334  hlxM.Move(dL);
1335  hlxM.Eval(0,X[3],D[3]); Rho[3]=hlxM.GetRho();
1336 
1337  TCL::vmatl(F[0],dA,dB,5,5);
1338 //TCL::vmatr(dA,F[0],dB,5,5);
1339 
1340  memcpy(X[4],X[2],3*sizeof(double));
1341  memcpy(D[4],D[2],3*sizeof(double));
1342  Rho[4]=Rho[2];
1343  double myAlf = atan2(D[2][1],D[2][0]);
1344  double myLam = asin(D[2][2]) ;
1345  D[4][0] = cos(myLam+dB[kL])*cos(myAlf+dB[kA]);
1346  D[4][1] = cos(myLam+dB[kL])*sin(myAlf+dB[kA]);
1347  D[4][2] = sin(myLam+dB[kL]);
1348  X[4][0] += -D[2][1]*dB[kH]/cos(myLam);
1349  X[4][1] += D[2][0]*dB[kH]/cos(myLam);
1350  X[4][2] += dB[kZ];
1351  Rho[4] += dB[kC];
1352 
1353  THelixTrack hlxD(X[4],D[4],Rho[4]);
1354  dL = hlxD.Path(X[2][0],X[2][1]);
1355  hlxD.Move(dL);
1356  hlxD.Eval(0,X[4],D[4]);
1357  Rho[4]=hlxD.GetRho();
1358 
1359 // hlx1.Print();
1360 // hlxM.Print();
1361 // hlxD.Print();
1362  double dC[5];
1363  dC[kH] = (-(X[3][0]-X[2][0])*D[2][1]+(X[3][1]-X[2][1])*D[2][0])/cos(myLam);
1364  dC[kA] = atan2(D[3][1],D[3][0])-atan2(D[2][1],D[2][0]);
1365  dC[kC] = Rho[3]-Rho[2];
1366  dC[kZ] = X[3][2]-X[2][2];
1367  dC[kL] = asin(D[3][2])-asin(D[2][2]);
1368  for (int i=0;i<5;i++) {printf(" %d - %g == %g\n",i,dB[i],dC[i]);}
1369 
1370  double myDelta = 0;
1371  for (int i=0;i<3;i++){myDelta+=pow(X[4][i]-X[3][i],2);}
1372  myDelta = sqrt(myDelta);
1373 
1374  double ihDelta = 0;
1375  for (int i=0;i<3;i++){ihDelta+=pow(X[2][i]-X[3][i],2);}
1376  ihDelta = sqrt(ihDelta);
1377  printf( "\n*** DELTA = %g << %g ***\n",myDelta,ihDelta);
1378 
1379 }
1380 
1381 //______________________________________________________________________________
1382 //______________________________________________________________________________
1383 //______________________________________________________________________________
1384 //______________________________________________________________________________
1385 ClassImp(TCircle)
1386 //______________________________________________________________________________
1387 TCircle::TCircle()
1388 {
1389  Set(0,0,0.);
1390  fEmx = 0;
1391 }
1392 //______________________________________________________________________________
1393 TCircle::~TCircle()
1394 {delete fEmx;fEmx=0;}
1395 
1396 //______________________________________________________________________________
1397 TCircle::TCircle(const double *x,const double *d,double rho)
1398 {
1399  Set(x,d,rho);
1400  fEmx = 0;
1401 }
1402 //______________________________________________________________________________
1403 void TCircle::Set(const double *x,const double *d,double rho)
1404 {
1405  fX[0]=0; fX[1]=0; fD[0]=0; fD[1]=0;
1406  if (x) {fX[0]=x[0];fX[1]=x[1];}
1407  if (d) {
1408  fD[0]=d[0];fD[1]=d[1];
1409  double n = sqrt(fD[0]*fD[0]+fD[1]*fD[1]);
1410  fD[0]/=n; fD[1]/=n;
1411  }
1412  fRho = rho;
1413 }
1414 //______________________________________________________________________________
1415 TCircle::TCircle(const TCircle& fr)
1416 {
1417  fEmx = 0;
1418  *this = fr;
1419 }
1420 //______________________________________________________________________________
1421 TCircle::TCircle(const TCircle* fr)
1422 {
1423  fEmx = 0;
1424  Set(fr->fX,fr->fD,fr->fRho);
1425 }
1426 //______________________________________________________________________________
1427 TCircle &TCircle::operator=(const TCircle& fr)
1428 {
1429  Set(fr.fX,fr.fD,fr.fRho);
1430  if (fr.fEmx) SetEmx(fr.fEmx->Arr());
1431  return *this;
1432 }
1433 
1434 //______________________________________________________________________________
1435 void TCircle::Clear(const char *)
1436 {
1437  if (fEmx) fEmx->Clear();
1438  memset(fX,0,(char*)(&fEmx)-(char*)fX);
1439 }
1440 
1441 
1442 //______________________________________________________________________________
1443 void TCircle::SetEmx(const double *err)
1444 {
1445  if(!fEmx) fEmx = new TCEmx_t;
1446  fEmx->Set(err);
1447 }
1448 //______________________________________________________________________________
1449 void TCircle::Nor(double *norVec) const
1450 {
1451 // direction from center of circle
1452 
1453  norVec[0] = fD[1]; norVec[1] = -fD[0];
1454  if (fRho>=0) return;
1455  norVec[0] = -norVec[0];norVec[1] = -norVec[1];
1456 }
1457 //______________________________________________________________________________
1458 void TCircle::GetCenter(double cent[3]) const
1459 {
1460  double R;
1461  if (fabs(fRho) > 1e-10) { R = 1./fRho ;}
1462  else { R =( fRho>0) ? 1e10:-1e10;}
1463  cent[0] = fX[0]-fD[1]*R;
1464  cent[1] = fX[1]+fD[0]*R;
1465 }
1466 //______________________________________________________________________________
1467 void TCircle::Print(const char* txt) const
1468 {
1469  if (!txt) txt="";
1470  printf("TCircle(%s): x,y=%g %g dir=%g %g curv=%g\n",txt,fX[0],fX[1],fD[0],fD[1],fRho);
1471  if (!fEmx) return;
1472  printf("Errs: %g\n" ,fEmx->mHH);
1473  printf(" : %g \t%g\n" ,fEmx->mHA,fEmx->mAA);
1474  printf(" : %g \t%g \t%g\n",fEmx->mHC,fEmx->mAC,fEmx->mCC);
1475 }
1476 //______________________________________________________________________________
1477 double TCircle::Path(const double pnt[2]) const
1478 {
1479  TComplex CX1(pnt[0]-fX[0],pnt[1]-fX[1]);
1480  TComplex CP(fD[0],fD[1]);
1481  TComplex CXP = TComplex(0,1)*CX1/CP;
1482  TComplex CXPRho = CXP*fRho;
1483  double s;
1484  if (TComplex::Abs(CXPRho)>0.001) {
1485  s = TComplex::Log(1.+CXPRho).Im()/fRho;
1486  } else {
1487  s = (CXP*(1.-CXPRho*(0.5-CXPRho*(1/3.-CXPRho*0.25)))).Im();
1488  }
1489 // Check
1490 // double x[2],d[2];
1491 // Eval(s,x,d) ;
1492 // assert(fabs((pnt[0]-x[0])*d[0]+(pnt[1]-x[1])*d[1])<1e-6);
1493  return s;
1494 }
1495 //______________________________________________________________________________
1496 double TCircle::Path(const double *pnt,const double *exy) const
1497 {
1498  double x[2],d[2];
1499  double s = Path(pnt);
1500  if (!exy || exy[0]<=0) return s;
1501  Eval(s,x,d);
1502  double k = (x[0]-pnt[0])*(d[1]) + (x[1]-pnt[1])*(-d[0]);
1503  double t =((d[1]*d[1]-d[0]*d[0])*exy[1]-d[1]*d[0]*(exy[2]-exy[0]))
1504  /( d[0]*d[0]*exy[2] -2*d[1]*d[0]*exy[1]+d[1]*d[1]*exy[0]);
1505 
1506  return s+k*t;
1507 }
1508 //_____________________________________________________________________________
1509 double TCircle::Path(const TCircle &hlx,double *S2) const
1510 {
1511  double s,s1=3e33,s2=3e33;
1512  const static TComplex Im(0.,1.);
1513  const TCircle *one = this;
1514  const TCircle *two = &hlx;
1515  if (fabs(fRho) > fabs(hlx.fRho)) { one=two; two=this; }
1516  double Rho1 = one->Rho();
1517  double Rho2 = two->Rho();
1518  int kase = 0;
1519  if (fabs(Rho1) > 1e-4) kase+=1;
1520  if (fabs(Rho2) > 1e-4) kase+=2;
1521 
1522  int nSol = 0;
1523  TComplex CX1(one->Pos()[0],one->Pos()[1]);
1524  TComplex CX2(two->Pos()[0],two->Pos()[1]);
1525  TComplex CP1(one->Dir()[0],one->Dir()[1]);
1526  TComplex CP2(two->Dir()[0],two->Dir()[1]);
1527  TComplex CdX = CX2-CX1;
1528  double L[2];
1529  switch(kase) {
1530  case 2:;
1531  case 3: {
1532  if (kase==3) {
1533  TComplex A = CP1/CP2*(Rho2/Rho1);
1534  TComplex B = 1.-CdX/CP2*(Im*Rho2) - CP1/CP2*(Rho2/Rho1);
1535  double a = A.Rho();
1536  double b = B.Rho();
1537  double alfa = A.Theta();
1538  double beta = B.Theta();
1539  double myCos = (1.-(a*a+b*b))/(2.*a*b);
1540  double myAng = 0;
1541  if (myCos>= 1.) {nSol=1; myAng = 0. ;}
1542  else if (myCos<=-1.) {nSol=1; myAng = M_PI ;}
1543  else {nSol=2; myAng = acos(myCos) ;}
1544  s = ( myAng -(alfa-beta))/Rho1;
1545  if (s<0) s+= 2.*M_PI/fabs(Rho1);
1546  s1 = s;
1547  if (nSol==2) {
1548  s =(-myAng -(alfa-beta))/Rho1;
1549  if (s< 0) s+= 2.*M_PI/fabs(Rho1);
1550  if (s<s1) s1 = s;
1551  }
1552  } else {
1553  TComplex A = CP1/CP2*(Im*Rho2);
1554  TComplex B = 1.-CdX/CP2*(Im*Rho2);
1555  double cba[3]={B.Rho2()-1., 2*(A.Re()*B.Re()+A.Im()*B.Im()), A.Rho2()};
1556  nSol = SqEqu(cba, L);
1557  if (nSol< 0) break;
1558  if (nSol==0) nSol=1;
1559  if (L[0]>0) s1=L[0];
1560  if (nSol>1 && L[1]>0 && L[1] <s1) s1 = L[1];
1561  }
1562 
1563  break;
1564  }// end case 3
1565  case 0: {
1566  if (fabs((CdX/CP1).Im())>fabs((CP2/CP1).Im())*1e6) break;
1567  nSol = 1;
1568  s = (CdX/CP2).Im()/(CP1/CP2).Im();
1569  if (s<0) break;
1570  s1 = s;
1571  break;
1572  }//end case 0
1573  default: assert(0);
1574  }
1575  if (nSol) {
1576  TCircle tc1(*one),tc2(*two);
1577  double xy[2];
1578  tc1.Eval(s1,xy);
1579  s = tc2.Path(xy);
1580  if (s<0 && kase) s += 2.*M_PI/fabs(Rho2);
1581  if (s>0 ) s2 = s;
1582  }
1583 
1584 
1585  if (one != this) {s=s1;s1=s2;s2=s;}
1586  if (S2) *S2=s2;
1587  return s1;
1588 }
1589 //_____________________________________________________________________________
1590 void TCircle::Test4()
1591 {
1592  double pars[4][2][5] = {
1593  {{0,0,1,0.,-0.001},{0,0.0,1,0,0.002}},
1594  {{0,0,1,0.,-0.001},{0,0.1,1,0,0.002}},
1595  {{0,0,1,0.,-0.001},{0,0.0,1,1,1e-8 }},
1596  {{0,0,1,0.,-1e-8 },{0,0.0,1,1,1e-8 }}};
1597  for (int ip=0;ip<4;ip++) {
1598  TCircle tc1(pars[ip][0],pars[ip][0]+2,pars[ip][0][4]);
1599  TCircle tc2(pars[ip][1],pars[ip][1]+2,pars[ip][1][4]);
1600  tc1.Move(-20);
1601  tc2.Move(-20);
1602  double s2=0;
1603  double s1 = tc1.Path(tc2,&s2);
1604  printf("s1=%g s2=%g \n",s1,s2);
1605  }
1606 }
1607 //______________________________________________________________________________
1608 double TCircle::Eval(double step,double *X, double *D) const
1609 {
1610 
1611  sgCX1 =TComplex(fX[0],fX[1]);
1612  sgCD1 =TComplex(fD[0],fD[1]); // exp(I*Fi0)
1613  sgImTet =TComplex(0,step*fRho); // I*Rho*L
1614  sgCOne =expOne(sgImTet); // (Exp(I*Rho*L)-1)/(I*Rho*L)
1615  sgCf1 =sgImTet*sgCOne; // (Exp(I*Rho*L)-1)
1616 
1617  sgCD2 = sgCD1*sgCf1+sgCD1; // exp(I*Fi0+I*Rho*L)
1618  sgCX2 = sgCD1*sgCOne*step; // exp(I*Fi0)*(exp(I*Rho*L)-1)/(I*Rho)
1619  if (X) {
1620  X[0] = sgCX2.Re()+sgCX1.Re();
1621  X[1] = sgCX2.Im()+sgCX1.Im();
1622  }
1623  if (D) {
1624  sgCD2/= TComplex::Abs(sgCD2);
1625  D[0] = sgCD2.Re();
1626  D[1] = sgCD2.Im();
1627  }
1628  return step;
1629 }
1630 //______________________________________________________________________________
1631 double TCircle::Move(double step)
1632 {
1633  Eval(step,fX,fD);
1634  if (fEmx && fEmx->mHH>0 && step) MoveErrs(step);
1635  if (fabs(fD[0])>1) fD[0]=(fD[0]<0)? -1:1;
1636  if (fabs(fD[1])>1) fD[1]=(fD[1]<0)? -1:1;
1637  return step;
1638 }
1639 //______________________________________________________________________________
1640 void TCircle::MakeMtx(double S,double F[3][3])
1641 {
1642  enum {kH=0,kA,kC};
1643  memset(F[0],0,sizeof(F[0][0])*3*3);
1644  F[kH][kH] = sgCf1.Re()+1.;
1645  double dSdH = sgCf1.Im();
1646 
1647  F[kH][kA] = S*sgCOne.Re();
1648  double dSdA = S*sgCOne.Im();
1649  TComplex llCOneD = S*S*expOneD(-sgImTet);
1650  F[kH][kC] = llCOneD.Re();
1651  double dSdC = llCOneD.Im();
1652 
1653  F[kA][kH] = -dSdH*fRho;
1654  F[kA][kA] = 1-dSdA*fRho;
1655  F[kA][kC] = S+dSdC*fRho;
1656  F[kC][kC] = 1;
1657 }
1658 //______________________________________________________________________________
1659 void TCircle::MoveErrs(double s)
1660 {
1661  double F[3][3];
1662  if (!s) return;
1663  MakeMtx(s,F);
1664  fEmx->Move(F);
1665 }
1666 //______________________________________________________________________________
1667 void TCircle::Rot(double angle)
1668 {
1669  Rot(cos(angle),sin(angle));
1670 }
1671 //______________________________________________________________________________
1672 void TCircle::Rot(double cosa,double sina)
1673 {
1674  TComplex CX(fX[0],fX[1]),CP(fD[0],fD[1]);
1675  TComplex A (cosa,sina);
1676  CX *=A; fX[0] = CX.Re(); fX[1]=CX.Im();
1677  CP *=A; CP/=TComplex::Abs(CP);
1678  fD[0] = CP.Re(); fD[1]=CP.Im();
1679 }
1680 //______________________________________________________________________________
1681 void TCircle::Backward()
1682 {
1683  fRho=-fRho;fD[0]=-fD[0];fD[1]=-fD[1];
1684  if(fEmx) fEmx->Backward();
1685 }
1686 
1687 //______________________________________________________________________________
1688 void TCircle::Test2()
1689 {
1690 // double xyz[4][3]= {{-39.530250549316406, -165.19537353515625, 184.05630493164062}
1691 // ,{-37.718906402587891, -167.19537353515625, 186.41175842285156}
1692 // ,{-35.468486785888672, -169.19537353515625, 189.05546569824219}
1693 // ,{-33.657142639160156, -171.19537353515625, 191.347900390625}};
1694 // double x[4],y[4];
1695 // for (int i=0;i<4;i++) { x[i]=xyz[i][0]; y[i]=xyz[i][1]; }
1696 //
1697 //
1698 //
1699 // TCircle TC;
1700 // double qa0 = TC.Approx(4,xyz[0],3);
1701 // double qa1 = TC.Resid (4,xyz[0],3);
1702 // printf("Approx qa0 = %g qa1=%g\n",qa0,qa1);
1703 // TC.Print();
1704 //
1705 
1706 }
1707 //______________________________________________________________________________
1708 void TCircle::Test3()
1709 {
1710 // enum {nPnts=4};
1711 // double xyz[nPnts][3] =
1712 // {{80.815544128417969, 159.77731323242188, 129.11553955078125}
1713 // ,{82.239913940429688, 161.25840759277344, 131.24034118652344}
1714 // ,{84.462181091308594, 162.28025817871094, 133.59538269042969}
1715 // ,{86.321846008300781, 163.51133728027344, 135.19621276855469}};
1716 //
1717 // double err[nPnts][4] =
1718 // {{0.0010703595155359307, 0.00061836299089800776, 0.00035723771589107141,0.0032088035791992191}
1719 // ,{0.0010505530116463389, 0.00060692047199979574, 0.00035062719848397145,0.0031350950603759769}
1720 // ,{0.0010286003088986414, 0.00059423806134026682, 0.00034330037672605356,0.0030533996126220703}
1721 // ,{0.0010136781863030494, 0.00058561716272119912, 0.00033831985920934062,0.0029978674575439454}};
1722 //
1723 //
1724 // double res;
1725 // TCircle circ;
1726 // res=circ.Approx(nPnts,xyz[0],3);
1727 // printf("res = %g \n",res);
1728 // circ.Print();
1729 // res=circ.Resid (nPnts,xyz[0],3);
1730 // printf("res = %g \n",res);
1731 // circ.Print();
1732 //
1733 // circ.Show(nPnts,xyz[0],3);
1734 // res = circ.Fit(nPnts,xyz[0],3,err[0],4);
1735 // printf("res = %g \n",res);
1736 // circ.Print();
1737 // circ.Show(nPnts,xyz[0],3);
1738 
1739 }
1740 //______________________________________________________________________________
1741 void TCircle::TestMtx()
1742 {
1743  double Dir[8],X[8]={0},Rho[2],step,F[3][3],Del[3],Dif[3]={0};
1744  double maxEps = 0;
1745  int nErr=0,tally=0;
1746  for (int iR = 1010;iR>-1010;iR-=20) {
1747  Rho[0] = 1./iR;
1748  int iAlf = 360*gRandom->Rndm();
1749  Del[0] = 0.001;
1750  Del[1] = M_PI/180*0.01;
1751  Del[2] = 1e-4+ Rho[0]*0.001;
1752  for (int iStep=10;iStep<=350;iStep+=10){
1753  Dir[0] = cos(iAlf/180.*M_PI);
1754  Dir[1] = sin(iAlf/180.*M_PI);
1755  TCircle tc(X,Dir,Rho[0]);
1756  step = iStep/180.*M_PI*abs(iR);
1757  tc.Eval(step,X+2,Dir+2);
1758  tc.MakeMtx(step,F);
1759 
1760  for (int iHAR=0;iHAR<3;iHAR++) {
1761  double minFak = 1e-4;
1762  for (double fak=1;fak>minFak;fak/=2) {//loop faktor/2
1763 
1764  memcpy(X +4,X ,sizeof(X[0] )*2);
1765  memcpy(Dir+4,Dir,sizeof(Dir[0])*2);
1766  Rho[1]=Rho[0];
1767  switch (iHAR) {
1768  case 0: {
1769  X[4+0] = X[0]-Dir[1]*Del[0]*fak;
1770  X[4+1] = X[1]+Dir[0]*Del[0]*fak;
1771  break;}
1772 
1773  case 1: {
1774  Dir[4+0] = cos(iAlf/180.*M_PI+Del[1]*fak);
1775  Dir[4+1] = sin(iAlf/180.*M_PI+Del[1]*fak);
1776  break;}
1777 
1778  case 2: {
1779  Rho[1] = Rho[0]+Del[2]*fak;
1780  break;}
1781  }//end switch
1782 
1783  TCircle tcc(X+4,Dir+4,Rho[1]);
1784  tcc.Move(step);
1785  double myStep = tcc.Path(X+2);
1786  tcc.Move(myStep);
1787  tcc.Eval(0,X+6,Dir+6);
1788  double dX[2];
1789  TCL::vsub(X+6,X+2,dX,2);
1790 
1791  myStep = -TCL::vdot(dX,Dir+2,2)/TCL::vdot(Dir+6,Dir+2,2);
1792  tcc.Eval(myStep,X+6,Dir+6);
1793 
1794  for (int jHAR=0;jHAR<2; jHAR++) {
1795  switch(jHAR) {
1796  case 0: {
1797  Dif[0] = (X[6+0]-X[2+0])*(-Dir[2+1])
1798  + (X[6+1]-X[2+1])*( Dir[2+0]);
1799  break;}
1800  case 1: {
1801  Dif[1] = (atan2(Dir[6+1],Dir[6+0])
1802  - atan2(Dir[2+1],Dir[2+0]));
1803  if (Dif[1]> M_PI) Dif[1]-=2*M_PI;
1804  if (Dif[1]< -M_PI) Dif[1]+=2*M_PI;
1805  break;}
1806  }
1807  tally++;
1808  double mat = F[jHAR][iHAR];
1809 // if (fabs(Dif[jHAR]) > 100*Del[jHAR] && fak > minFak*2) continue;
1810 // if (fabs(Dif[jHAR]) < 1e-3*Del[jHAR]) Dif[jHAR]=0;
1811 // if (fabs(mat*Del[iHAR]) < 1e-3*Del[jHAR]) mat=0;
1812 
1813  double est = Dif[jHAR]/(Del[iHAR]*fak);
1814  double min = Del[jHAR]/Del[iHAR]*0.001;
1815 
1816 
1817  if (jHAR==iHAR) {
1818  if (fabs(est) < 1e-4) est = 0;
1819  if (fabs(mat) < 1e-4) mat = 0;
1820  }
1821 
1822  double eps =(fabs(est-mat)*2)
1823  /(fabs(est)+fabs(mat)+min);
1824  if (eps < 1e-2) {
1825  if (eps>maxEps) maxEps=eps;
1826  break;
1827  }
1828  if (fak > minFak*2) continue;
1829  nErr++;
1830  if (eps>maxEps) maxEps=eps;
1831  printf("%6d Mtx[%d][%d] \t%g \t%g \tAngle=%d \tRad=%d \tLen=%g\n",
1832  tally,jHAR,iHAR,F[jHAR][iHAR],est,
1833  iAlf,iR,myStep);
1834 
1835  } } } } }
1836  printf("TestMtx: %d errors maxEps=%g\n",nErr,maxEps);
1837 
1838 }
1839 
1840 
1841 //______________________________________________________________________________
1842 //______________________________________________________________________________
1843 TCircleFitter::TCircleFitter()
1844 {
1845  Clear();
1846  SetEmx();
1847 }
1848 //______________________________________________________________________________
1849 void TCircleFitter::Clear(const char*)
1850 {
1851  fArr.Reset();
1852  memset(fBeg,0,fEnd-fBeg+1);
1853  TCircle::Clear();
1854 }
1855 //______________________________________________________________________________
1856 TCircleFitterAux* TCircleFitter::GetAux(int i) const
1857 {
1858  return (TCircleFitterAux*)(fArr.GetArray()+i*TCircleFitterAux::dSize());
1859 }
1860 //______________________________________________________________________________
1861 const double* TCircleFitter::GetX(int i) const
1862 {
1863  return &(fAux[i].x);
1864 }
1865 //______________________________________________________________________________
1866 double* TCircleFitter::GetX(int i)
1867 {
1868  return &(fAux[i].x);
1869 }
1870 //______________________________________________________________________________
1871 void TCircleFitter::Add(double x,double y,const double *errs)
1872 {
1873  fNuse =++fN;
1874  int n = fN*TCircleFitterAux::dSize();
1875  if (fArr.GetSize()<n) {fArr.Set(n*2);fAux=0;}
1876  if (!fAux) fAux = GetAux(0);
1877  TCircleFitterAux *aux = fAux+fN-1;
1878  aux->x = x; aux->y=y; aux->exy[0]=0; aux->exy[2]=0; aux->ezz=1;aux->wt=0;
1879  if (errs) AddErr(errs);
1880 }
1881 //______________________________________________________________________________
1882 void TCircleFitter::Add(double x,double y,double z)
1883 {
1884  fNuse =++fN;
1885  int n = fN*TCircleFitterAux::dSize();
1886  if (fArr.GetSize()<n) {fArr.Set(n*2);fAux=0;}
1887  if (!fAux) fAux = GetAux(0);
1888  TCircleFitterAux *aux = fAux+fN-1;
1889  aux->x = x; aux->y=y; aux->z=z;
1890  aux->exy[0]=0; aux->exy[1]=0; aux->exy[2]=0;aux->ezz=1;aux->wt=0;
1891 }
1892 //______________________________________________________________________________
1893 void TCircleFitter::AddErr(const double *errs,double ezz)
1894 {
1895  TCircleFitterAux *aux = fAux+fN-1;
1896  double *e = aux->exy;
1897  memcpy(e,errs,sizeof(aux->exy));
1898  assert(ezz>=0);
1899  assert(e[0]>=0);
1900  assert(e[2]>=0);
1901  aux->wt = 0;
1902  aux->ezz = ezz;
1903 }
1904 //______________________________________________________________________________
1905 void TCircleFitter::AddErr(double errhh,double ezz)
1906 {
1907  TCircleFitterAux *aux = fAux+fN-1;
1908  assert(ezz>=0);
1909  assert(errhh>0);
1910  aux->wt = 1./errhh;
1911  aux->exy[0]= 0;aux->exy[2]= 0;
1912  aux->ezz = ezz;
1913 }
1914 //______________________________________________________________________________
1915 void TCircleFitter::AddZ(double z,double ez)
1916 {
1917 // Must be called immediatelly after Add(...)
1918  fAux[fN-1].z =z;
1919  fAux[fN-1].ezz=ez;
1920 }
1921 //______________________________________________________________________________
1922 double TCircleFitter::Fit()
1923 {
1924 static const int nAVERs = &fRr-&fXx;
1925 static int nCall=0; nCall++;
1926  double xx=0, yy=0, xx2=0, yy2=0;
1927  double f=0, g=0, h=0, p=0, q=0, t=0, g0=0, g02=0, d=0;
1928  double xroot=0, ff=0, fp=0;
1929  double dx=0, dy=0, xnom=0,wt=0,tmp=0,radius2=0,radiuc2=0;
1930  fKase = fCase;
1931  if (fNuse < 3) return 3e33;
1932  TCircleFitterAux *aux = GetAux(0);
1933 
1934 // Loop over points,fill orientation
1935  double *mm = &fXgravity; memset(mm,0,sizeof(*mm)*5);
1936  for (int i=0; i<fN; i++) {
1937  double x=aux[i].x, y=aux[i].y;
1938  fXgravity+=x; fYgravity+=y;fXx+=x*x;fYy+=y*y;fXy+=x*y;}
1939 
1940  for (int j=0;j<5;j++) {mm[j]/=fN;}
1941  fXx-=fXgravity*fXgravity;fYy-=fYgravity*fYgravity;fXy-=fXgravity*fYgravity;
1942 
1943  double eigVal[2]={0};
1944  eigen2(&fXx,eigVal,&fCos);
1945  int fastTrak = (eigVal[0]>10*eigVal[1]);
1946  fNor[0] = -fSin; fNor[1] = fCos;
1947 
1948 
1949  enum {kIter=1,kFast=2,kWeit=4,kErr=8};
1950  const double *exy=0;
1951  int wasErrs = 0;
1952  for (int iter=0;iter<2;iter++) {// one or two iters
1953  fWtot = 0;
1954  memset(&fXgravity,0,sizeof(double)*(nAVERs+2));
1955  for (int i=0; i<fN; i++) {//Loop over points,fill wt and center of gravity
1956  if (aux[i].wt<0) { if(!i) fNuse--; continue;}
1957  int kase = iter;
1958  if (fastTrak) kase|=2;
1959  if (aux[i].wt >0) kase+=4; //weight defined
1960  if (aux[i].exy[0]>0 || aux[i].exy[2]>0) {wasErrs++;kase+=8;} //error matrix defined
1961  switch (kase) {
1962  case 0:;
1963  case kErr:;
1964  case kFast:;
1965 
1966  wt = 1; break; //assign Weight =1
1967 
1968  case kWeit:;
1969  case kWeit|kErr:;
1970  case kWeit|kFast:;
1971  case kWeit|kIter:;
1972  wt = aux[i].wt; break;
1973 
1974  case kIter|kWeit|kErr:;
1975  case kIter|kFast|kWeit|kErr:;
1976  { // slow error, calculate normal
1977  fNor[0] = fXCenter - aux[i].x;
1978  fNor[1] = fYCenter - aux[i].y;
1979  tmp = sqrt(fNor[0]*fNor[0]+fNor[1]*fNor[1]);
1980  fNor[0]/=tmp; fNor[1]/=tmp;
1981  }
1982  case kFast|kErr:;
1983  case kFast|kErr|kWeit:;
1984  { // fast errors
1985  exy = aux[i].exy;
1986  wt = (fNor[0]*fNor[0]*exy[0]
1987  +fNor[0]*fNor[1]*exy[1]*2
1988  +fNor[1]*fNor[1]*exy[2]);
1989  if (wt<kMinErr*kMinErr) wt = kBigErr*kBigErr;
1990  wt = 1/wt;
1991  break;
1992  }
1993  default: assert(0);
1994  }//end switch
1995  aux[i].wt = wt;
1996  if (wt<0) continue;
1997  fWtot += wt;
1998  fXgravity += aux[i].x *wt;
1999  fYgravity += aux[i].y *wt;
2000  }//End Loop over points
2001 
2002  fXgravity /= fWtot;
2003  fYgravity /= fWtot;
2004 
2005  for (int i=0; i<fN; i++) { //Calc all averages
2006  wt = aux[i].wt;
2007  if (wt<0) continue;
2008  dx = aux[i].x-fXgravity;
2009  dy = aux[i].y-fYgravity;
2010  xx = dx*fCos + dy*fSin;
2011  yy = -dx*fSin + dy*fCos;
2012  xx2 = xx*xx;
2013  yy2 = yy*yy;
2014  fXx += xx2 *wt;
2015  fYy += yy2 *wt;
2016  fXy += xx*yy *wt;
2017  fXrr += xx*(xx2+yy2) *wt;
2018  fYrr += yy*(xx2+yy2) *wt;
2019  fRrrr += (xx2+yy2)*(xx2+yy2) *wt;
2020  }
2021  double *dd = &fXx;
2022  for (int i=0;i<nAVERs;i++) {dd[i]/=fWtot;}
2023  fRr = fXx+fYy;
2024 
2025  if (fNuse <= 3 && !fKase) fKase=1;
2026  if (!fKase) fKase =(fastTrak)? 1:2;
2027 SWIT: switch(fKase) {
2028  case 1: { //Try 1st method
2029 
2030 // Variables v0=1, v1=2*x, v2 =-rr == -(x*x+y*y)
2031 // Orthogonal functions of these variables:
2032 // Nor0 = fPol[0]
2033 // Nor1 = fPol[1]+ v1*fPol[2]
2034 // Nor2 = fPol[3]+ v1*fPol[4]+ v2*fPol[5]
2035 
2036  double myCof[3]={0};
2037  fPol[0] = 1;
2038  fPol[1] = 0; fPol[2] = 1./(2*sqrt(fXx));
2039  fPol[3] = fRr; fPol[4] = fXrr/(2*fXx); fPol[5] = 1.;
2040  double tmp = sqrt(fPol[3]*fPol[3]
2041  +fPol[4]*fPol[4]*(4*fXx )
2042  +fPol[5]*fPol[5]*(fRrrr )
2043  +fPol[3]*fPol[5]*(-fRr ) *2
2044  +fPol[4]*fPol[5]*(-2*fXrr) *2);
2045  fPol[3]/=tmp;fPol[4]/=tmp;fPol[5]/=tmp;
2046  myCof[0] = 0;
2047  myCof[1] = - (fPol[2]*(4*fXy));
2048  myCof[2] = - (fPol[4]*(4*fXy) + fPol[5]*(-2*fYrr));
2049  fC = myCof[0]*fPol[0]+myCof[1]*fPol[1]+myCof[2]*fPol[3];
2050  fA = myCof[1]*fPol[2]+myCof[2]*fPol[4];
2051  fB = myCof[2]*fPol[5];
2052  fYd = (fabs(fB)>1e-6) ? 1./fB : 1e6;
2053  fXd = fA*fYd;
2054  }// end case 1
2055  break;
2056 
2057  case 2: { //Try 2nd method(Ososkov/Chernov)
2058 
2059  f = (3.*fXx+fYy);
2060  g = (fXx+3.*fYy);
2061  h = 2*fXy;
2062  p = fXrr;
2063  q = fYrr;
2064  t = fRrrr;
2065  g0 = (fXx+fYy);
2066  g02 = g0*g0;
2067  fA = -4.0;
2068  fB = (f*g-t-h*h)/g02;
2069  fC = (t*(f+g)-2.*(p*p+q*q))/(g02*g0);
2070  d = (t*(h*h-f*g)+2.*(p*p*g+q*q*f)-4.*p*q*h)/(g02*g02);
2071  xroot = 1.0;
2072  for (int i=0; i<5; i++) {
2073  ff = (((xroot+fA)*xroot+fB)*xroot+fC)*xroot+d;
2074  fp = ((4.*xroot+3.*fA)*xroot+2.*fB)*xroot+fC;
2075  xroot -= ff/fp;
2076  }
2077  fG1 = xroot*g0;
2078  xnom = (g-fG1)*(f-fG1)-h*h;
2079 
2080 // assert(xnom>3e-33);
2081  if (xnom<1e-20) { fKase=1; goto SWIT;}
2082 
2083  fXd = ( p*(g-fG1)-q*h )/xnom;
2084  fYd = (-p*h +q*(f-fG1))/xnom;
2085  }//end case 2
2086  break;
2087 
2088  default: assert(0);
2089  } //end switch
2090  fXCenter = fXd*fCos-fYd*fSin + fXgravity;
2091  fYCenter = fXd*fSin+fYd*fCos + fYgravity;
2092 
2093  if (fastTrak || !wasErrs) break; //if track fast,errs accounted or no errs, no more iters
2094  }// end iters
2095 
2096 // Update TCircle
2097  switch (fKase) {
2098  case 1: {//Big R approx
2099  fCorrR = sqrt(1+fA*fA+fC*fB );
2100  fCorrB = sqrt(1+fA*fA );
2101  fRho = fabs(fB)/fCorrR;
2102  int sgB = (fB<0)? -1:1;
2103  fNy = sgB/sqrt(1+fA*fA);
2104  fNx = fA*fNy;
2105  fH = -fC*sgB/(fCorrR+fCorrB);
2106  fChi2 = (4*fA*fXy +4*fYy- 2*fB*fYrr)/4;
2107  fChi2 /= (fCorrR*fCorrR);
2108  fX[0] = fNx*fH; fX[1] = fNy*fH;
2109 // let we are moving left --> right
2110 // remember to change sign of correlation related to H if fRho<0
2111  fD[0] = fNy; fD[1] =-fNx;
2112 //
2113  Rot(fCos,fSin);
2114  fX[0] += fXgravity;
2115  fX[1] += fYgravity;
2116  }
2117  break;
2118  case 2: {//Ososkov
2119  radiuc2 = fXd*fXd+fYd*fYd;
2120  radius2 = radiuc2+fG1;
2121  fR = ::sqrt(radius2);
2122  fRd = ::sqrt(radiuc2);
2123  fRho = 1./fR;
2124  fH = -fG1/(fR+fRd);
2125  if (fRd>1e-6) { fNx = fXd/fRd; fNy = fYd/fRd;}
2126  else { fNx = 0; fNy = 1; fRd = 0; }
2127  fChi2 = (fG1-fRr)/2;
2128  fX[0] = fNx*fH; fX[1] = fNy*fH;
2129 // let we are moving left --> right
2130 // remember to change sign of correlation related to H if fRho<0
2131  fD[0] = fNy; fD[1] =-fNx;
2132 //
2133  Rot(fCos,fSin);
2134  fX[0] += fXgravity;
2135  fX[1] += fYgravity;
2136 
2137 
2138 
2139 
2140 
2141  }
2142  break;
2143  default: assert(0);
2144  }
2145  fNdf = fNuse-3;
2146  if (fNdf>0) fChi2 *= fWtot/fNdf;
2147  tmp = fD[0]*(aux[0].x-fX[0])+fD[1]*(aux[0].y-fX[1]);
2148 // remember to change corrs related to rho and h
2149  fBack = 0;
2150  if (tmp>0) {fD[0]*=-1;fD[1]*=-1;fRho*=-1;fBack=1;}
2151  return fChi2;
2152 }
2153 //______________________________________________________________________________
2154 void TCircleFitter::MakeErrs()
2155 {
2156  fEmx->Clear();
2157  double F[3][3]; memset(F[0],0,sizeof(F));
2158  double myFact = 1.;
2159  switch (fKase) {
2160  case 1: { //For BigYC fit
2161  fCov[0] = fPol[2]*fPol[2]+ fPol[4]*fPol[4];
2162  fCov[1] = fPol[4]*fPol[5];
2163  fCov[2] = fPol[5]*fPol[5];
2164  fCov[3] = fPol[1]*fPol[2]+ fPol[3]*fPol[4];
2165  fCov[4] = fPol[3]*fPol[5];
2166  fCov[5] = fPol[0]*fPol[0]+ fPol[1]*fPol[1]+fPol[3]*fPol[3];
2167  for (int i=0;i<6;i++) {fCov[i]*=4;}
2168  int sgB = (fB<0)? -1:1;
2169  double corrRB = fCorrR+fCorrB;
2170  double corrR3 = fCorrR*fCorrR*fCorrR;
2171  // fH = -c*sgB/(fCorrR+fCorrB);
2172 
2173  F[0][0] = sgB*fA*fC/(corrRB*fCorrB*fCorrR); //dH/da
2174  F[0][1] = 0.5*sgB*fC*fC/(corrRB*corrRB*fCorrR); //dH/db
2175  F[0][2] = 0.5*sgB*fC*fB/(corrRB*corrRB*fCorrR) //dH/dc
2176  - sgB /(corrRB );
2177  F[1][0] = -1/(fCorrB*fCorrB); //dFi/da
2178  F[2][0] = - sgB*fA*fB/(corrR3); //d(aRho)/da
2179  F[2][1] = -0.5*sgB*fC*fB/(corrR3)+sgB/fCorrR; //d(aRho)/db
2180  F[2][2] = -0.5*sgB*fB*fB/(corrR3); //d(aRho)/dc
2181  myFact = (fCorrR*fCorrR);
2182  break;
2183  }
2184  case 2: { //For Ososkov/Chernov fit
2185 
2186  double aRho = fabs(fRho),aRho2 = aRho*aRho,aRho3 = aRho*aRho2;
2187  for (int i=0,li=0;i< 3;li+=++i) {
2188  for (int j=0 ;j<=i;j++ ) {
2189  fCov[li+j] = d2F(i,j)*0.5; }}
2190  TCL::trsinv(fCov,fCov ,3);
2191 
2192  double dRho = -fH/(fRd*fR);
2193  dRho = 1/fRd-1/fR;
2194  F[0][0] = fXd*dRho; // -dH /dXd
2195  F[0][1] = fYd*dRho; // -dH /dYd
2196  F[0][2] = -0.5*aRho; // -dH /dG1
2197  F[1][0] = -fNy*aRho; // dFi/dXd
2198  F[1][1] = fNx*aRho; // dFi/dYd
2199  F[1][2] = 0; // dFi/dG1
2200  F[2][0] = -fXd*aRho3; // dRho/dXd
2201  F[2][1] = -fYd*aRho3; // dRho/dYd
2202  F[2][2] = -0.5*aRho3; // dRho/dG1
2203 
2204  break;
2205  }
2206  default: assert(0);
2207  } // end switch
2208  TCL::vscale(fCov,myFact/fWtot,fCov,6);
2209  TCL::trasat(F[0],fCov,fEmx->Arr(),3,3);
2210  if (fBack) {fEmx->mHA*=-1;fEmx->mAC*=-1;}
2211 }
2212 //______________________________________________________________________________
2213 double TCircleFitter::EvalChi2()
2214 {
2215  if (!fNuse) return 0;
2216  TCircle M(this);
2217  double sum = 0,wtot=0,wt;
2218  TCircleFitterAux *aux = GetAux(0);
2219  const double *p = M.Pos();
2220  for (int i=0;i<fN;i++) {
2221  if (aux[i].wt<0) continue;
2222  double s = M.Path(&(aux[i].x));
2223  M.Move(s);
2224  wt = aux[i].wt;
2225  sum+= (pow(p[0]-aux[i].x,2)+pow(p[1]-aux[i].y,2))*wt;
2226  wtot +=wt;
2227  }
2228  if (fNdf) sum /= fNdf;
2229  fChi2 = sum;
2230  return sum;
2231 }
2232 //_____________________________________________________________________________
2233 double TCircleFitter::FixAt(const double vals[5],int flag)
2234 {
2242 
2243  assert(fEmx);
2244  assert(flag);
2245  double g[6]={1,0,1,0,0,1},c[6]={1,0,1,0,0,1}
2246  ,e[6],adj[3]={0},amda[3],dlt[2];
2247  int sel[3] ={!!(flag&1), !!(flag&2), !!(flag&4)};
2248  int nFix=0;
2249  if (sel[0]) { // h corr
2250  nFix++;
2251  dlt[0] = vals[0]-fX[0]; dlt[1] = vals[1]-fX[1];
2252  adj[0] = -dlt[0]*fD[1]+dlt[1]*fD[0];
2253  }
2254  if (sel[1]) { // angle corr
2255  nFix++;
2256  adj[1] = vals[3]-atan2(fD[1],fD[0]);
2257  if (adj[1]< -M_PI) adj[1] += 2*M_PI;
2258  if (adj[1]> M_PI) adj[1] -= 2*M_PI;
2259  }
2260  if (sel[2]) { //curv corr
2261  nFix++;
2262  adj[2] = vals[4]-fRho;
2263  }
2264 // calculate add to Chisq
2265  for (int i=0,li=0;i< 3;li+=++i) {
2266  for (int j=0 ;j<=i;j++ ) {
2267  if (!(sel[i]&sel[j])) continue;
2268  c[li+j] = (*fEmx)[li+j]; } }
2269  double addXi2=0;
2270  TCL::trsinv(c ,c ,3 );
2271  TCL::trasat(adj,c,&addXi2,1,3);
2272 
2273  TCL::trsinv(fEmx->Arr(),e,3);
2274  for (int i=0,li=0;i< 3;li+=++i) {
2275  for (int j=0 ;j<=i;j++ ) {
2276  if (!(sel[i]|sel[j])) continue;
2277  e[li+j] = (i==j);
2278  if (!(sel[i]&sel[j])) continue;
2279  g[li+j] = (*fEmx)[li+j];
2280  } }
2281  TCL::trsinv(g ,g ,3 );
2282  TCL::trsa (g ,adj ,amda,3,1);
2283  TCL::trsa (fEmx->Arr(),amda,adj ,3,1);
2284  TCL::trsinv(e ,fEmx->Arr(),3 );
2285 
2286  for (int i=0,li=0;i< 3;li+=++i) {if (sel[i]) (*fEmx)[li+i]=0;}
2287 // update x,y
2288  fX[0] += -adj[0]*fD[1];
2289  fX[1] += adj[0]*fD[0];
2290 // update direction
2291 // double S = adj[1]*(1-adj[1]*adj[1]/6);
2292 // double C = 1-adj[1]*adj[1]/2;
2293 // double S = sin(adj[1]);
2294  double S = sin(adj[1]);
2295  double C = cos(adj[1]);
2296  double d0 = fD[0];
2297  fD[0] = d0*C-fD[1]*S;
2298  fD[1] = d0*S+fD[1]*C;
2299 // update curvature
2300  fRho += adj[2];
2301  fNdf+=nFix;
2302  fChi2 += (addXi2-fChi2*nFix)/fNdf;
2303  return fChi2;
2304 }
2305 //_____________________________________________________________________________
2306 void TCircleFitter::Skip(int idx)
2307 {
2308  fAux[idx].exy[0] = -1;
2309  SetNdf(fNdf-1); //compensate increasing it inside FixAt(double*)
2310 }
2311 //_____________________________________________________________________________
2312 void TCircleFitter::SetNdf(int ndf)
2313 {
2314  fChi2*=fNdf; if (ndf) fChi2/=ndf; fNdf=ndf;
2315 }
2316 //______________________________________________________________________________
2317 void TCircleFitter::Print(const char* txt) const
2318 {
2319  if (!txt) txt="";
2320  printf("TCircleFitter::NPoints = %d method=%d",fN,fKase);
2321  if (fChi2) printf(" Chi2 = %g",fChi2);
2322  printf("\n");
2323  TCircle::Print();
2324 
2325  int iP = (strchr(txt,'P') || strchr(txt,'p'));
2326  int iE = (strchr(txt,'E') || strchr(txt,'e'));
2327  int iF = (strchr(txt,'F') || strchr(txt,'f'));
2328  int iZ = (strchr(txt,'Z') || strchr(txt,'z'));if(iZ){};
2329  TCircleFitterAux *aux = GetAux(0);
2330  if (iP) { //Print points
2331  for (int ip=0;ip<fN;ip++) {
2332  printf("%3d - X: %g\tY:%g \tZ:%g",ip,aux[ip].x,aux[ip].y,aux[ip].z);
2333  if (iE)
2334  printf(" \tExy: %g %g %g \tEz:%g "
2335  ,aux[ip].exy[0],aux[ip].exy[1],aux[ip].exy[2],aux[ip].ezz);
2336  printf("\n");
2337  }}
2338  if (iF) { //Print fit
2339  TCircle circ(this);
2340  const double *xy = GetX(0);
2341  double ds=circ.Path(xy);
2342  circ.Move(ds);
2343  double s=0;
2344  for (int i=0;i<fN;i++) {
2345  xy = GetX(i);
2346  ds = circ.Path(xy);
2347  s+=ds;
2348  circ.Move(ds);
2349  if (fabs( s)<1e-6) s=0;
2350  if (fabs(ds)<1e-6)ds=0;
2351  printf("%3d - S=%g(%g) \tX: %g=%g \tY:%g=%g \tdirX=%g dirY=%g\n"
2352  ,i,s,ds
2353  ,xy[0],circ.Pos()[0]
2354  ,xy[1],circ.Pos()[1]
2355  ,circ.Dir()[0],circ.Dir()[1]);
2356  }}
2357 
2358 }
2359 //______________________________________________________________________________
2360 void TCircleFitter::Test(int iTest)
2361 {
2362 // iTest fitterCase + negativeRadius*10 + backwardOrderFitPoints*100+1000*noShift
2363  int myKase = (iTest/1 )%10;
2364  int negRad = (iTest/10 )%10;
2365  int bakPts = (iTest/100 )%10;
2366  int noShft = (iTest/1000)%10;
2367 
2368 // enum {nPts=20};
2369  enum {nPts=5};
2370  double e[4],x[3],dir[2];
2371  double aShift[6];
2372  aShift[0]=-acos(0.25);
2373  aShift[1]=-acos(0.50);
2374  aShift[2]= 0;
2375  aShift[3]= acos(0.25);
2376  aShift[5]= acos(0.50);
2377  memset(aShift,0,sizeof(aShift));
2378  double xCenter[2];
2379  double RERR = 0.01;
2380 TRandom ran;
2381 
2382 static TCanvas* myCanvas[9]={0};
2383 static TH1F *hh[10]={0};
2384 static const char *hNams[]={"pH","pA","pC","Xi2","dErr"};
2385 static const double lims[][2]={{-5 ,5},{-5 ,5 },{-5 ,5}
2386  ,{ 0 ,5},{-0.05,0.05}};
2387 const int nPads = sizeof(hNams)/sizeof(void*);
2388 
2389  if(!myCanvas[0]) myCanvas[0]=new TCanvas("TCircleFitter_Test0","",600,800);
2390  myCanvas[0]->Clear();
2391  myCanvas[0]->Divide(1,nPads);
2392 
2393  for (int i=0;i<nPads;i++) {
2394  delete hh[i]; hh[i]= new TH1F(hNams[i],hNams[i],100,lims[i][0],lims[i][1]);
2395  myCanvas[0]->cd(i+1); hh[i]->Draw();
2396  }
2397 
2398 static TH1F *hc[10]={0};
2399 static const char *cNams[]={"HHpull","HApull","AApull","HCpull","ACpull","CCpull"};
2400 static const int cPads=sizeof(cNams)/sizeof(char*);
2401  if(!myCanvas[1]) myCanvas[1]=new TCanvas("TCircleFitter_TestCorr1","",600,800);
2402  myCanvas[1]->Clear();
2403  myCanvas[1]->Divide(1,cPads);
2404 
2405  for (int i=0;i<cPads;i++) {
2406  delete hc[i]; hc[i]= new TH1F(cNams[i],cNams[i],100,-15,15);
2407  myCanvas[1]->cd(i+1); hc[i]->Draw();
2408  }
2409 
2410 static TH1F *hl[10]={0};
2411 static const char *lNams[]={"XP","YP","GP","XY","XG","YG"};
2412 static const int lPads=sizeof(lNams)/sizeof(char*);
2413  if(!myCanvas[2]) myCanvas[2]=new TCanvas("TCircleFitter_TestCorr2","",600,800);
2414  myCanvas[2]->Clear();
2415  myCanvas[2]->Divide(1,lPads);
2416 
2417  for (int i=0;i<lPads;i++) {
2418  delete hl[i]; hl[i]= new TH1F(lNams[i],lNams[i],100,-5,5);
2419  myCanvas[2]->cd(i+1); hl[i]->Draw();
2420  }
2421 //================================================================================
2422 
2423  int nFit = 0,isgn;
2424  static unsigned int seed=0;
2425 
2426 
2427  for (int ir = 50; ir <= 50; ir +=5) {//loop over radius
2428  double aR = ir;
2429  double len = 0.3*aR*3;//????
2430  for (double ang0 = 0; ang0 <= 0; ang0+=0.05) {//loop over ang
2431  double R = (negRad)? -aR:aR;
2432  double dang = len/R/(nPts-1);
2433  if (bakPts) dang*=-1;
2434  double C0 = cos(ang0);
2435  double S0 = sin(ang0);
2436 
2437  double myX[2]={0,0},myD[2]={C0,S0};
2438  xCenter[0] = myX[0]-myD[1]*R;
2439  xCenter[1] = myX[1]+myD[0]*R;
2440  double corr[6]={0},korr[6]={0};
2441  seed++;
2442  for (int iter=0;iter<2;iter++) {
2443 static const int nEv = 100000;
2444  ran.SetSeed(seed);
2445  for (int ev=0;ev<nEv;ev++) {
2446  TCircleFitter helx;
2447  TCircle idex(myX,myD,1/R);;
2448  for (int is=0;is<nPts;is++) { //loop over points
2449  double ang = ang0 + dang*is;
2450  double S = sin(ang),C = cos(ang);
2451  double eR = ran.Gaus(0,RERR);
2452  double shift = aShift[is%5];
2453  shift=0;
2454  double SS = sin(ang+shift);
2455  double CC = cos(ang+shift);
2456  e[0] = pow(RERR*SS,2);
2457  e[1] =-pow(RERR ,2)*CC*SS;
2458  e[2] = pow(RERR*CC,2);
2459 
2460  x[0] = myX[0] + (R)*(S-S0);
2461  x[1] = myX[1] - (R)*(C-C0);
2462  x[0]+= -SS*eR;
2463  x[1]+= CC*eR;
2464 // helx.Add (x[0],x[1],e);
2465  helx.Add (x[0],x[1]);
2466  helx.AddErr (RERR*RERR);
2467  } //end points
2468  helx.SetCase(myKase); //VP
2469  double Xi2 = helx.Fit();
2470  double Xj2 = helx.EvalChi2();
2471  assert(fabs(Xi2-Xj2) < 1e-2*(Xi2+Xj2+0.01));
2472 
2473  assert (!myKase || helx.GetCase()==myKase);
2474 
2475  nFit++;
2476  helx.MakeErrs();
2477  if ((isgn=helx.Emx()->Sign())<0) {
2478  ::Warning("Test1","Negative errmtx %d",isgn);continue;}
2479 
2480  if (helx.Rho()*idex.Rho() < 0) idex.Backward();
2481 
2482  double myShift = (aR*M_PI/180)*360*gRandom->Rndm();
2483  if (noShft) myShift=0;
2484  helx.Move(myShift);
2485  idex.Move(myShift);
2486  if ((isgn=helx.Emx()->Sign())<0) {
2487  ::Warning("Test2","Negative errmtx %d",isgn);continue;}
2488  double s = idex.Path(helx.Pos());
2489  idex.Eval(s,x,dir);
2490 
2491  double dd[10];
2492  double dx = helx.Pos()[0]-x[0];
2493  double dy = helx.Pos()[1]-x[1];
2494  dd[0] = -dx*dir[1]+dy*dir[0];
2495  dd[1] = atan2(helx.Dir()[1],helx.Dir()[0])-atan2(dir[1],dir[0]);
2496  if (dd[1]> M_PI) dd[1]-=2*M_PI;
2497  if (dd[1]<-M_PI) dd[1]+=2*M_PI;
2498  dd[2] = helx.Rho()-idex.Rho();
2499 
2500  if (!iter) {
2501  for (int i=0,li=0;i< 3;li+=++i) {
2502  for (int j=0;j<=i;j++) {
2503  corr[li+j]+= (*(helx.Emx()))[li+j];
2504  korr[li+j]+= dd[i]*dd[j];
2505  } }
2506  continue;
2507  }
2508 
2509  dd[3] = dd[0]/sqrt(corr[0]);
2510  dd[4] = dd[1]/sqrt(corr[2]);
2511  dd[5] = dd[2]/sqrt(corr[5]);
2512  dd[6] = Xi2;
2513  dd[7] = sqrt(helx.Emx()->mHH)-RERR;
2514 
2515  for (int ih=0;ih<nPads;ih++) { hh[ih]->Fill(dd[ih+3]);}
2516 
2517 
2518  double cc[6]={0},dia[3];
2519  for (int i=0,li=0;i< 3;li+=++i) {
2520  dia[i] = corr[li+i];
2521  for (int j=0;j<=i;j++) {
2522  cc[li+j] = (dd[i]*dd[j]-corr[li+j])/sqrt(dia[i]*dia[j]);
2523  }
2524  }
2525 
2526  for (int ih=0;ih<cPads;ih++) { hc[ih]->Fill(cc[ih]);}
2527  //=====================================================================================
2528  double myCenter[3];
2529  myCenter[0]=xCenter[0]-helx.fXgravity;
2530  myCenter[1]=xCenter[1]-helx.fYgravity;
2531  double xx = myCenter[0];
2532  myCenter[0] = xx*helx.fCos + myCenter[1]*helx.fSin;
2533  myCenter[1] = -xx*helx.fSin + myCenter[1]*helx.fCos;
2534  myCenter[2] = R*R - (pow(myCenter[0],2)+pow(myCenter[1],2));
2535  for (int j=0;j<3;j++) {dd[j]=(&(helx.fXd))[j]-myCenter[j];}
2536  dd[3+0] = dd[0]/sqrt(helx.fCov[0]);
2537  dd[3+1] = dd[1]/sqrt(helx.fCov[2]);
2538  dd[3+2] = dd[2]/sqrt(helx.fCov[5]);
2539  for (int ih=0;ih<3;ih++) { hl[ih]->Fill(dd[ih+3]);}
2540  cc[0] = (dd[3+0]*dd[3+1]-helx.fCov[1])/sqrt(helx.fCov[0]*helx.fCov[2]);
2541  cc[1] = (dd[3+0]*dd[3+2]-helx.fCov[3])/sqrt(helx.fCov[0]*helx.fCov[5]);
2542  cc[2] = (dd[3+1]*dd[3+2]-helx.fCov[4])/sqrt(helx.fCov[2]*helx.fCov[5]);
2543  for (int ih=0;ih<3;ih++) { hl[ih+3]->Fill(cc[ih]);}
2544  } //end of events
2545  if (iter) break;
2546  TCL::vscale(corr,1./nEv,corr,6);
2547  TCL::vscale(korr,1./nEv,korr,6);
2548  double dia[3];
2549  for (int i=0,li=0;i< 3;li+=++i) {
2550  dia[i]=sqrt(corr[li+i]);
2551  int n = 0;
2552  for (int j=0;j<=i;j++) {n+=printf("%15g",corr[li+j]/(dia[i]*dia[j]));}
2553  n = 45-n;
2554  for (int j=0;j< n;j++) {printf(" ");}
2555  for (int j=0;j<=i;j++) {n+=printf("%15g",korr[li+j]/(dia[i]*dia[j]));}
2556  printf("\n");
2557  }
2558 
2559 
2560  } //end of iters
2561  } //end ang0
2562  } // curv
2563 
2564  for (int i=0;myCanvas[i];i++) {
2565  myCanvas[i]->Modified();myCanvas[i]->Update();}
2566 
2567  while(!gSystem->ProcessEvents()){gSystem->Sleep(200);};
2568 
2569 }
2570 
2571 //______________________________________________________________________________
2572 void TCircleFitter::TestCorr(int kase)
2573 {
2574 // 1=fit case 1 alowed
2575 // 2=fit case 2 alowed
2576 // 4=fit +ive curv alowed
2577 // 8=fit -ive curv alowed
2578 //16=fit -ive curv alowed
2579 
2580  if (!(kase&3 ))kase+=1+2;
2581  if (!(kase&12))kase+=4+8;
2582  enum {nPts=20};
2583  double e[4],x[3],ex[3];
2584  double aShift[6];
2585  aShift[0]=-acos(0.25);
2586  aShift[1]=-acos(0.50);
2587  aShift[2]= 0;
2588  aShift[3]= acos(0.25);
2589  aShift[5]= acos(0.50);
2590  double RERR = 0.001;
2591 TRandom ran;
2592 static TCanvas* myCanvas=0;
2593 static TH1F *hh[6]={0,0,0,0,0,0};
2594 static const char *hNams[]={"HA","HA-","HC","HC-","AC","AC-",0};
2595  if(!myCanvas) myCanvas=new TCanvas("TCircleFitter_TestCorr","",600,800);
2596  myCanvas->Clear();
2597  myCanvas->Divide(1,6);
2598 
2599  for (int i=0;i<6;i++) {
2600  delete hh[i]; hh[i]= new TH1F(hNams[i],hNams[i],100,-1,1);
2601  myCanvas->cd(i+1); hh[i]->Draw();
2602  }
2603 
2604  int nFit = 0;
2605  for (int ir = 50; ir <= 1000; ir +=5) {//loop over radius
2606  double aR = ir;
2607  double len = 100; if (len>aR*3) len = aR*3;
2608  for (double ang0 = -3; ang0 < 3.1; ang0+=0.05) {//loop over ang
2609  for (int sgn = -1; sgn<=1; sgn+=2) {//loop over signes of curv
2610 if ((sgn>0) && !(kase&4)) continue;
2611 if ((sgn<0) && !(kase&8)) continue;
2612  double R = sgn*aR;
2613  double dang = len/R/nPts;
2614  double C0 = cos(ang0);
2615  double S0 = sin(ang0);
2616  TCircleFitter helx;
2617  for (int is=0;is<nPts;is++) { //loop over points
2618  double ang = ang0 + dang*is;
2619  double S = sin(ang),C = cos(ang);
2620  double eR = ran.Gaus(0,RERR)*sgn;
2621  double shift = aShift[is%5];
2622 //shift=0;//???????????????????
2623  double SS = sin(ang+shift);
2624  double CC = cos(ang+shift);
2625  e[0] = pow(RERR*SS,2);
2626  e[1] =-pow(RERR ,2)*CC*SS;
2627  e[2] = pow(RERR*CC,2);
2628 
2629  x[0] = 100 + (R)*(S-S0);
2630  x[1] = 200 - (R)*(C-C0);
2631  ex[0]= x[0]-SS*eR;
2632  ex[1]= x[1]+CC*eR;
2633  helx.Add (ex[0],ex[1],e);
2634  } //end points
2635  helx.Fit();
2636 if (!(helx.GetCase()&kase)) continue;
2637  nFit++;
2638  helx.MakeErrs();
2639  int iFix = 0;
2640  if (kase&16) iFix +=1;
2641  if (kase&32) iFix +=4;
2642  if (iFix) {
2643  double vals[5];
2644  TCL::ucopy(x,vals,3);
2645  vals[3]=0;
2646  vals[4]=1./R;
2647  helx.FixAt(vals,iFix);
2648  }
2649  x[0] = 100 ;
2650  x[1] = 200 ;
2651  double s = helx.Path(x);
2652  assert(s<0);
2653  assert(fabs(s) < len);
2654  helx.Move(s);
2655  double dd[6],hf[6];
2656  double dx = helx.Pos()[0]-x[0];
2657  double dy = helx.Pos()[1]-x[1];
2658  const TCEmx_t *emx = helx.Emx();
2659  dd[0] = -dx*S0+dy*C0;
2660  dd[1] = atan2(helx.Dir()[1],helx.Dir()[0])-ang0;
2661  if (dd[1]> M_PI) dd[1]-=2*M_PI;
2662  if (dd[1]<-M_PI) dd[1]+=2*M_PI;
2663  dd[2] = helx.Rho()-1./R;
2664  hf[0] = (dd[0]*dd[1]) *1e1/(RERR*RERR);
2665  hf[1] = (emx->mHA) *1e1/(RERR*RERR);
2666  hf[2] = dd[0]*dd[2] *1e3/(RERR*RERR);
2667  hf[3] = (emx->mHC) *1e3/(RERR*RERR);
2668  hf[4] = dd[1]*dd[2] *1e4/(RERR*RERR);
2669  hf[5] = (emx->mAC) *1e4/(RERR*RERR);
2670 
2671 
2672  for (int ih=0;ih<6;ih++) { hh[ih]->Fill(hf[ih]);}
2673  } //end sign
2674  } //end ang0
2675  } // curv
2676  myCanvas->Modified();
2677  myCanvas->Update();
2678  while(!gSystem->ProcessEvents()){gSystem->Sleep(200);};
2679 
2680 }
2681 //______________________________________________________________________________
2682 void TCircle::Show(int nPts,const double *Pts,int pstep) const
2683 {
2684 static TCanvas *myCanvas = 0;
2685 static TGraph *ptGraph = 0;
2686 static TGraph *ciGraph = 0;
2687  double x[100],y[100];
2688  if (nPts>100) nPts=100;
2689  for (int i=0;i<nPts;i++) { x[i]=Pts[i*pstep+0]; y[i]=Pts[i*pstep+1]; }
2690 
2691 
2692  if(!myCanvas) myCanvas = new TCanvas("TCircle_Show","",600,800);
2693  myCanvas->Clear();
2694  delete ptGraph; delete ciGraph;
2695 
2696  ptGraph = new TGraph(nPts , x, y);
2697  ptGraph->SetMarkerColor(kRed);
2698  ptGraph->Draw("A*");
2699 
2700  TCircle tc(this);
2701  double xy[2];
2702  xy[0] = x[0];
2703  xy[1] = y[0];
2704  double s = tc.Path(xy);
2705  tc.Move(s);
2706  xy[0] = x[nPts-1];
2707  xy[1] = y[nPts-1];
2708  s = tc.Path(xy);
2709  if (s<0) { tc.Backward(); s = tc.Path(xy);}
2710  double ds = s/99;
2711  for (int i=0;i<100;i++) {x[i]=tc.Pos()[0];y[i]=tc.Pos()[1];tc.Move(ds);}
2712 
2713  ciGraph = new TGraph(100 , x, y);
2714  ciGraph->Draw("Same CP");
2715  myCanvas->Modified();
2716  myCanvas->Update();
2717  while(!gSystem->ProcessEvents()){gSystem->Sleep(200);};
2718 
2719 }
2720 //______________________________________________________________________________
2721 THelixFitter::THelixFitter():fPoli1Fitter(1)
2722 {
2723  Clear();
2724  SetEmx();
2725 }
2726 //______________________________________________________________________________
2727 THelixFitter::~THelixFitter()
2728 {;}
2729 //______________________________________________________________________________
2730 void THelixFitter::Clear(const char*)
2731 {
2732  fCircleFitter.Clear();
2733  fPoli1Fitter.Clear();
2734  fPoli1Fitter.SetCoefs(1);
2735  fChi2=0;
2736 }
2737 //______________________________________________________________________________
2738 void THelixFitter::Print(const char*) const
2739 {
2740  THelixTrack::Print();
2741  fCircleFitter.Print();
2742  fPoli1Fitter.Print();
2743 }
2744 //______________________________________________________________________________
2745 void THelixFitter::Add (double x,double y,double z)
2746 {
2747  fCircleFitter.Add(x,y,z);
2748 }
2749 //______________________________________________________________________________
2750 void THelixFitter::AddErr(const double *err2xy,double err2z)
2751 {
2752  fCircleFitter.AddErr(err2xy,err2z);
2753 }
2754 //______________________________________________________________________________
2755 void THelixFitter::AddErr(double errhh,double err2z)
2756 {
2757  fCircleFitter.AddErr(errhh,err2z);
2758 }
2759 //______________________________________________________________________________
2760 double THelixFitter::Fit()
2761 {
2762  TCircleFitterAux* myAux= GetAux(0);
2763  int nDat = Size();
2764  double Xi2xy = fCircleFitter.Fit();
2765  if (Xi2xy>1e11) return Xi2xy;
2766 
2767  int ndfXY = fCircleFitter.Ndf();
2768  double arho = fabs(fCircleFitter.Rho());
2769  double mm[4]={0},s=0; //mm[s,z,ss,sz]
2770  double z0 = myAux[nDat/2].z;
2771  for (int ip=1;ip<nDat;ip++) {
2772  double z = myAux[ip].z-z0;
2773  double dx = myAux[ip].x - myAux[ip-1].x;
2774  double dy = myAux[ip].y - myAux[ip-1].y;
2775  double hord = sqrt(dx*dx+dy*dy);
2776  double t = 0.5*hord*arho;
2777  if (t>0.9) t=0;
2778  double ds = (fabs(t)<0.3)? hord*(1+t*t/6):2*asin(t)/arho;
2779  s+=ds; mm[0]+=s; mm[1]+=z;mm[2]+=s*s;mm[3]+=s*z;
2780  }
2781  for (int j=0;j<4;j++) { mm[j]/=nDat;}
2782  mm[2]-=mm[0]*mm[0]; mm[3]-= mm[0]*mm[1];
2783 
2784 // estimation of tan(dip) to correct z errs
2785  double tanDip = mm[3]/mm[2];
2786  TCircle circ(fCircleFitter);
2787 // set lengths
2788  s = 0;
2789  for (int iDat=0;iDat<nDat;iDat++) {
2790  TCircleFitterAux* aux = myAux+iDat;
2791  if (aux->wt<0) continue;
2792  double ds = circ.Path(&(aux->x));
2793  circ.Move(ds); s+=ds;
2794 // correct errors
2795  double corErr = 0;
2796  if (aux->exy[0]>0) {
2797  const double *dc = circ.Dir();
2798  corErr = tanDip*tanDip*
2799  (dc[0]*dc[0]*aux->exy[0]
2800  +dc[1]*dc[1]*aux->exy[2]
2801  +dc[0]*dc[1]*aux->exy[1]*2);
2802  }
2803  fPoli1Fitter.Add(s,aux->z,aux->ezz+corErr);
2804  }
2805 
2806  double Xi2z = fPoli1Fitter.Fit();
2807 // Now set THelixTrack
2808  int ndfSz = fPoli1Fitter.Ndf();
2809  Update(1);
2810  int ndf = ndfSz+ndfXY;
2811  fChi2 = Xi2xy*ndfXY+Xi2z*ndfSz;
2812  if (ndf) fChi2/=ndf;
2813  return fChi2;
2814 
2815 }
2816 //_____________________________________________________________________________
2817 double THelixFitter::FixAt(const double val[5],int flag)
2818 {
2819  double xx[3],s;
2820  memcpy(xx,fX,sizeof(xx));
2821  int move = (flag&1);
2822  if (move) {
2823  s = fCircleFitter.Path(val);
2824  fCircleFitter.Move(s);
2825  fPoli1Fitter.Move(s);
2826  }
2827  double Xi2c = fCircleFitter.FixAt(val,flag);
2828  if (flag&1) fPoli1Fitter.FixAt(0.,val[2]);
2829 // Update(1+2);
2830  if (move) {
2831  s = fCircleFitter.Path(xx);
2832  fCircleFitter.Move(s);
2833  fPoli1Fitter.Move(s);
2834  }
2835  Update(1+2);
2836 // double Xi2c = fCircleFitter.EvalChi2();
2837  double Xi2z = fPoli1Fitter.Chi2();
2838  int ndfc = fCircleFitter.Ndf();
2839  int ndfz = fPoli1Fitter.Ndf();
2840 
2841  int ndf = ndfc+ndfz;
2842  fChi2 = Xi2c*ndfc+Xi2z*ndfz;
2843  if (ndf) fChi2/=ndf;
2844  return fChi2;
2845 }
2846 //_____________________________________________________________________________
2847 void THelixFitter::Skip(int idx)
2848 {
2849  fCircleFitter.Skip(idx);
2850  fPoli1Fitter.Skip(idx);
2851  int ndfc = fCircleFitter.Ndf();
2852  int ndfz = fPoli1Fitter.Ndf();
2853  int ndf = ndfc+ndfz;
2854  fChi2 = fCircleFitter.Chi2()*ndfc+fPoli1Fitter.Chi2()*ndfz;
2855  if (ndf) fChi2/=ndf;
2856 }
2857 //______________________________________________________________________________
2858 void THelixFitter::Update(int kase)
2859 {
2860  if(kase&1) {
2861  const double *pol = fPoli1Fitter.Coe();
2862  fCosL = 1./sqrt(pol[1]*pol[1]+1);
2863  double *haslet = fCircleFitter.Pos();
2864  fX[0] = haslet[0];
2865  fX[1] = haslet[1];
2866  fX[2] = pol[0];
2867  fP[0] = haslet[2]*fCosL;
2868  fP[1] = haslet[3]*fCosL;
2869  fP[2] = pol[1]*fCosL;
2870  fRho = haslet[4];
2871  }
2872  if(kase&2) {
2873  double emx[3];
2874  emx[0] = fPoli1Fitter.Emx()[0];
2875  emx[1] = fPoli1Fitter.Emx()[1]*fCosL*fCosL;
2876  emx[2] = fPoli1Fitter.Emx()[2]*fCosL*fCosL*fCosL*fCosL;
2877  fEmx->Set(fCircleFitter.Emx()->Arr(),emx);
2878  }
2879 }
2880 //______________________________________________________________________________
2881 void THelixFitter::MakeErrs()
2882 {
2883  fCircleFitter.MakeErrs();
2884  fPoli1Fitter.MakeErrs();
2885  Update(2);
2886 }
2887 //______________________________________________________________________________
2888 double THelixFitter::EvalChi2()
2889 {
2890  double Xi2c = fCircleFitter.EvalChi2();
2891  double Xi2z = fPoli1Fitter.EvalChi2();
2892  fChi2 = Xi2c*fCircleFitter.Ndf()+Xi2z*fPoli1Fitter.Ndf();
2893  fChi2/=(fCircleFitter.Ndf()+fPoli1Fitter.Ndf()+1e-10);
2894  return fChi2;
2895 }
2896 //______________________________________________________________________________
2897 void THelixFitter::Test(int kase)
2898 {
2899 // 1=fit case 1 alowed
2900 // 2=fit case 2 alowed
2901 // 4=fit +ive curv alowed
2902 // 8=fit -ive curv alowed
2903 // 16=fix last point
2904 // 32=fix curvature
2905 // 64=fix angle (not implemented in test)
2906 //128=show each track
2907  if (!(kase&3 ))kase+=1+2;
2908  if (!(kase&12))kase+=4+8;
2909 // enum {nPts=20,nHH=8};
2910  enum {nPts=5,nHH=8};
2911  double e[4],x[10],xe[10];
2912  double aShift[6];
2913  aShift[0]=-acos(0.25);
2914  aShift[1]=-acos(0.50);
2915  aShift[2]= 0;
2916  aShift[3]= acos(0.25);
2917  aShift[5]= acos(0.50);
2918  double RERR = 0.1;
2919  double ZERR = 0.1;
2920 TRandom ran;
2921 static TCanvas* myCanvas[9]={0};
2922 static TH1F *hh[nHH]={0};
2923 static const char *hNams[]={"pH","pA","pC","pZ","pD","Xi2","Xi2E","Xi2d",0};
2924  if(!myCanvas[0]) myCanvas[0]=new TCanvas("THelixFitter_TestC1","",600,800);
2925  myCanvas[0]->Clear();
2926  myCanvas[0]->Divide(1,nHH);
2927 
2928  for (int i=0;i<nHH;i++) {
2929  double low = (i>=5)? 0:-5;
2930  double upp = 5;
2931  delete hh[i]; hh[i]= new TH1F(hNams[i],hNams[i],100,low,upp);
2932  myCanvas[0]->cd(i+1); hh[i]->Draw();
2933  }
2934 
2935 // Init Second histo group
2936 static TH1F *h2h[4]={0,0,0,0};
2937 static const char *h2Nams[]={"targYY","targZZ","targYZ","calcYZ",0};
2938  int n2h=4;
2939  if(!myCanvas[1]) myCanvas[1]=new TCanvas("THelixFitter_TestC2","",600,800);
2940  myCanvas[1]->Clear();
2941  myCanvas[1]->Divide(1,n2h);
2942  for (int i=0;i<n2h;i++) {
2943  delete h2h[i]; h2h[i]= new TH1F(h2Nams[i],h2Nams[i],100,-5,5);
2944  myCanvas[1]->cd(i+1); h2h[i]->Draw();
2945  }
2946 // End Init Second histo group
2947 
2948 // Init 3rd histo group
2949 static TH1F *h3h[4]={0,0,0,0};
2950 static const char *h3Nams[]={"dcaXY","dcaXYNor","dcaZ","dcaZNor",0};
2951  int n3h=4;
2952  if(!myCanvas[2]) myCanvas[2]=new TCanvas("THelixFitter_TestC3","",600,800);
2953  myCanvas[2]->Clear();
2954  myCanvas[2]->Divide(1,n3h);
2955  for (int i=0;i<n3h;i++) {
2956  delete h3h[i]; h3h[i]= new TH1F(h3Nams[i],h3Nams[i],100,-5,5);
2957  myCanvas[2]->cd(i+1); h3h[i]->Draw();
2958  }
2959 // End Init 3rd histo group
2960 
2961 
2962  double spotSurf[4]= {-100,1,0,0};
2963  double spotAxis[3][3]= {{0,1,0},{0,0,1},{1,0,0}};
2964 
2965 
2966  int nFit = 0,isgn;
2967 //??for (double idip=-80;idip<=80;idip+=20){
2968 for (int idip=80;idip<=80;idip+=20){
2969  double dip = idip/180.*3.1415;
2970 
2971  double cosDip = cos(dip);
2972  double sinDip = sin(dip);
2973  double tanDip = tan(dip); if(tanDip){};
2974  for (int ir = 50; ir <= 1000; ir +=20) {//loop over radius
2975  double aR = ir;
2976  double len = 100; if (len>aR*3) len = aR*3;
2977  for (double ang00 = -3; ang00 < 3.1; ang00+=0.2) {//loop over ang
2978  double ang0 = ang00;
2979 // ang0 = 0;
2980  for (int sgn = -1; sgn<=1; sgn+=2) {//loop over signes of curv
2981 if(sgn>0 && !(kase&4)) continue;
2982 if(sgn<0 && !(kase&8)) continue;
2983 
2984  double R = sgn*aR;
2985  double dang = len/R/nPts;
2986  double C0 = cos(ang0);
2987  double S0 = sin(ang0);
2988  THelixFitter helx;
2989 
2990  double trakPars[7]={100,200,300,C0*cosDip,S0*cosDip,sinDip,1/R};
2991  THelixTrack trak(trakPars+0,trakPars+3,trakPars[6]);
2992 
2993  for (int is=0;is<nPts;is++) { //loop over points
2994  double ang = ang0 + dang*is;
2995  double S = sin(ang),C = cos(ang);
2996  double eR = ran.Gaus(0,RERR)*sgn;
2997  double eZ = ran.Gaus(0,ZERR);
2998  double shift = aShift[is%5];
2999 //shift=0;//???????????????????
3000  double SS = sin(ang+shift);
3001  double CC = cos(ang+shift);
3002  e[0] = pow(RERR*SS,2);
3003  e[1] =-pow(RERR ,2)*CC*SS;
3004  e[2] = pow(RERR*CC,2);
3005  e[3] = pow(ZERR,2);
3006  x[0] = 100 + (R)*(S-S0);
3007  x[1] = 200 - (R)*(C-C0);
3008  double len = (R)*(ang-ang0);
3009  x[2] = 300 + len*tan(dip);
3010  xe[0]= x[0]-SS*eR;
3011  xe[1]= x[1]+CC*eR;
3012  xe[2]= x[2]+eZ;
3013  helx.Add (xe[0],xe[1],xe[2]);
3014  helx.AddErr(e,e[3]);
3015  } //end points
3016  double Xi2 =helx.Fit();
3017 if(!(kase&helx.GetCase())) continue;
3018 
3019  helx.MakeErrs();
3020  if ((isgn=helx.Emx()->Sign())<0) {
3021  ::Warning("Test1","Negative errmtx %d",isgn);continue;}
3022  nFit++;
3023 if (kase&16) Xi2=helx.FixAt(x);
3024 
3025 
3026 if (kase&32) {
3027  double vals[5];
3028  TCL::ucopy(x,vals,3);vals[3]=0;vals[4]=1./R;
3029  Xi2=helx.FixAt(vals,4);
3030  }
3031 if (kase&128) helx.Show();
3032  double Xi2E =helx.EvalChi2();
3033 
3034  trak.Move(0.3*len/cosDip);
3035  memcpy(x,trak.Pos(),sizeof(x));
3036  ang0 = atan2(trak.Dir()[1],trak.Dir()[0]);
3037 // double s = helx.Path(x[0],x[1]);
3038  double s = helx.Path(x);
3039 // assert(s<0);
3040 // assert(fabs(s) < len*1.1);
3041 
3042  double pos[3],dir[3],rho;
3043  helx.Move(s);
3044  if ((isgn=helx.Emx()->Sign())<0) {
3045  ::Warning("Test2","Negative errmtx %d",isgn);continue;}
3046  THEmx_t *emx = helx.Emx();
3047  helx.Get (pos,dir,rho);
3048  double psi = atan2(dir[1],dir[0]);
3049  double sinPsi = sin(psi);
3050  double cosPsi = cos(psi);
3051  double tanPsi = sinPsi/cosPsi; if(tanPsi){};
3052  double dd[10],hf[10];
3053  double dx = x[0]-pos[0];
3054  double dy = x[1]-pos[1];
3055  dd[0] = -dx*sinPsi+dy*cosPsi;
3056  hf[0] = dd[0]/sqrt(emx->mHH+1e-20);
3057  dd[2] = psi-ang0;
3058  if (dd[2]> M_PI) dd[2]-=2*M_PI;
3059  if (dd[2]<-M_PI) dd[2]+=2*M_PI;
3060  hf[1] = dd[2]/sqrt(emx->mAA+1e-20);
3061  dd[4] = rho-1./R;
3062  hf[2] = dd[4]/sqrt(emx->mCC+1e-20);
3063  dd[6] = (helx.Pos()[2]-x[2])/pow(helx.GetCos(),2);
3064  hf[3] = dd[6]/sqrt(emx->mZZ+1e-20);
3065  dd[8] = asin(dir[2])-dip;
3066  if (dd[8]> M_PI) dd[8]-=2*M_PI;
3067  if (dd[8]<-M_PI) dd[8]+=2*M_PI;
3068  hf[4] = dd[8]/(sqrt(emx->mLL));
3069  hf[5] = Xi2;
3070  hf[6] = Xi2E;
3071  hf[7] = Xi2E-Xi2+1;
3072  for (int ih=0;ih<nHH;ih++) { hh[ih]->Fill(hf[ih]);}
3073 
3074 // Fill 2nd histo group
3075  double xIde[3],pIde[3],xFit[3],pFit[3],eSpot[3],hfil,sIde,sFit;
3076 // if(fabs(dip)>1) continue;
3077  int closePoint=0;
3078  spotSurf[0] = -110;
3079 
3080  { spotSurf[0] = -x[0]; closePoint=2006;}
3081  sIde = trak.Step(200.,spotSurf,4, xIde,pIde,closePoint);
3082 
3083  if (fabs(spotSurf[0]+TCL::vdot(xIde,spotSurf+1,3))>0.001) {
3084  printf("***Wrong point found**\n");
3085  trak.Print();
3086  assert(0);
3087  }
3088  sFit = helx.Step(200.,spotSurf,4, xFit,pFit,closePoint);
3089  if (sFit>=1000 ) continue;
3090  if (fabs(pIde[0]-pFit[0])>0.1) continue;
3091  helx.Move(sFit);
3092  emx = helx.Emx();
3093  helx.GetSpot(spotAxis,eSpot);
3094  hfil = (xFit[1]-xIde[1]); hfil/= sqrt(eSpot[0]);
3095  h2h[0]->Fill(hfil);
3096  hfil = (xFit[2]-xIde[2]); hfil/= sqrt(eSpot[2]);
3097  h2h[1]->Fill(hfil);
3098  hfil = (xFit[1]-xIde[1])*(xFit[2]-xIde[2]);
3099  h2h[2]->Fill(hfil*100);
3100  h2h[3]->Fill(hfil/sqrt(eSpot[0]*eSpot[2]));
3101 // h2h[3]->Fill(eSpot[1]*100);
3102 // End 2nd histo group
3103 
3104 // Fill 3rd histo group
3105  double dcaXY,dcaZ,dcaEmx[3];
3106  double sDca = helx.Dca(trakPars,dcaXY,dcaZ,dcaEmx);
3107  if (fabs(sDca)<1000) {
3108  h3h[0]->Fill(dcaXY);
3109  h3h[1]->Fill(dcaXY/sqrt(dcaEmx[0]));
3110  h3h[2]->Fill(dcaZ );
3111  h3h[3]->Fill(dcaZ /sqrt(dcaEmx[2]));
3112  }
3113 // End 3rd histo group
3114 
3115  } //end sign
3116  } //end ang0
3117  } // curv
3118 } // dip
3119  for (int ih=0;myCanvas[ih];ih++) {
3120  myCanvas[ih]->Modified();
3121  myCanvas[ih]->Update();
3122  }
3123  while(!gSystem->ProcessEvents()){gSystem->Sleep(200);};
3124 }
3125 //______________________________________________________________________________
3126 void THelixFitter::Show() const
3127 {
3128 static TCanvas *myCanvas = 0;
3129 static TGraph *ptGraph[2] = {0,0};
3130 static TGraph *ciGraph[2] = {0,0};
3131  double x[100],y[100],z[100],l[100]
3132  , X[100],Y[100],Z[100];
3133  int nPts = Size();
3134  if (nPts>100) nPts=100;
3135  TCircleFitterAux* aux=GetAux(0);
3136  THelixTrack tc(this);
3137  double s = tc.Path(aux[0].x,aux[0].y); tc.Move(s);
3138  s = tc.Path(aux[nPts-1].x,aux[nPts-1].y);
3139  if (s<0) { tc.Backward();}
3140  l[0]=0;
3141  double ds=0;
3142  for (int i=0;i<nPts;i++) {
3143  if (i) {ds = tc.Path(aux[i].x,aux[i].y);tc.Move(ds);l[i]=l[i-1]+ds;}
3144  x[i]=aux[i].x; y[i]=aux[i].y; z[i]=aux[i].z;
3145  X[i]=tc.Pos()[0];Y[i]=tc.Pos()[1];Z[i]=tc.Pos()[2];
3146  }
3147 
3148 
3149  if(!myCanvas) myCanvas = new TCanvas("THelixFitter_Show","",600,800);
3150  myCanvas->Clear();
3151  myCanvas->Divide(1,2);
3152 
3153  delete ptGraph[0]; delete ciGraph[0];
3154  ptGraph[0] = new TGraph(nPts , x, y);
3155  ptGraph[0]->SetMarkerColor(kRed);
3156  myCanvas->cd(1); ptGraph[0]->Draw("A*");
3157  delete ptGraph[1]; delete ciGraph[1];
3158  ptGraph[1] = new TGraph(nPts , l, z);
3159  ptGraph[1]->SetMarkerColor(kRed);
3160  myCanvas->cd(2); ptGraph[1]->Draw("A*");
3161 
3162  ciGraph[0] = new TGraph(nPts , X, Y);
3163  myCanvas->cd(1); ciGraph[0]->Draw("Same CP");
3164  ciGraph[1] = new TGraph(nPts , l, Z);
3165  myCanvas->cd(2); ciGraph[1]->Draw("Same CP");
3166 
3167  myCanvas->Modified();
3168  myCanvas->Update();
3169  while(!gSystem->ProcessEvents()){gSystem->Sleep(200);};
3170 
3171 }
3172 //______________________________________________________________________________
3173 double TCircleFitter::f()
3174 { //f*Rho2 = 4*F
3175 return 4*((fG1-fRr)/2)*fR*fR;
3176 }
3177 //______________________________________________________________________________
3178 double TCircleFitter::F()
3179 { //f*Rho2 = 4*F
3180 return (fG1-fRr)/2;
3181 }
3182 //______________________________________________________________________________
3183 double TCircleFitter::df(int i)
3184 {
3185  switch (i) {
3186  case 0: return -4*(fXrr -2*fXx*fXd - 2*fXy*fYd);
3187  case 1: return -4*(fYrr -2*fXy*fXd - 2*fYy*fYd);
3188  case 2: return 2*(fG1 - fRr);
3189  default: assert(0);
3190  }
3191  assert(0);
3192 return 0;
3193 }
3194 //______________________________________________________________________________
3195 double TCircleFitter::d2f(int i,int j)
3196 {
3197 // d2f/dA/dA = 4*XX
3198 // d2f/dA/dB = 4*XY ;d2f/dB/dB = 4*YY
3199 // d2f/dA/dG = 0 ;d2f/dB/dG = 0 ;d2f/dG/dG = 1
3200  assert(j<=i);
3201  int ij = i+10*j;
3202  switch(ij) {
3203  case 0: return 8*fXx;
3204  case 01: return 8*fXy;
3205  case 11: return 8*fYy;
3206  case 02:; case 12: return 0;
3207  case 22: return 2;
3208  default: printf ("Kase=%d\n",ij); assert(0);
3209  assert(0);
3210  }
3211  return 0;
3212 }
3213 //______________________________________________________________________________
3214 double TCircleFitter::Rho2 () { return fRho*fRho;}
3215 //______________________________________________________________________________
3216 //______________________________________________________________________________
3217 double TCircleFitter::dRho2(int i)
3218 {
3219  double ans =fRho*fRho;
3220  ans *= -ans;
3221  switch (i) {
3222  case 0: return 2*ans*fXd; //-2*Rh2**2*x
3223  case 1: return 2*ans*fYd; //-2*Rh2**2*y
3224  case 2: return ans; //- Rh2**2
3225  }
3226  assert(0);
3227  return 0;
3228 }
3229 //______________________________________________________________________________
3230 double TCircleFitter::d2Rho2(int i,int j)
3231 {
3232 // d2(Rho2)/dA/dA = 8*(Rho6)*A*A-2*(Rho4);
3233 // d2(Rho2)/dA/dB = 8*(Rho6)*A*B ;d2(Rho2)/dB/dB = 8*(Rho6)*B*B -2*(Rho4)
3234 // d2(Rho2)/dA/dG = 4*(Rho6)*A ;d2(Rho2)/dB/dG = 4*(Rho6)*B; d2(Rho2)/dG/dG = 2*(Rho6);
3235  if (j>i) { int jj = j; j = i; i = jj;}
3236  int ij = i+10*j;
3237  double rho2 = fRho*fRho,rho4 = rho2*rho2, rho6 = rho4*rho2;
3238  switch(ij) {
3239  case 0: return 8*(rho6)*fXd*fXd-2*(rho4);;
3240  case 01: return 8*(rho6)*fXd*fYd;
3241  case 11: return 8*(rho6)*fYd*fYd-2*(rho4);
3242  case 02: return 4*(rho6)*fXd;
3243  case 12: return 4*(rho6)*fYd;
3244  case 22: return 2*(rho6);
3245  default: printf ("Kase=%d\n",ij); assert(0);
3246  }
3247 }
3248 //______________________________________________________________________________
3249 double TCircleFitter::dF(int i)
3250 {
3251 // 1./4*(df(P,i)*Rho2(P)+f(P)*dRho2(P,i));}
3252 
3253 double ans = 1./4*(df(i)*Rho2() + f()*dRho2(i));
3254 return ans;
3255 }
3256 //______________________________________________________________________________
3257 double TCircleFitter::d2F(int i,int j)
3258 {
3259 // 1./4*(df(P,i)*Rho2(P)+f(P)*dRho2(P,i));}
3260 
3261 double ans = 1./4*(d2f(i,j)*Rho2() +df(j)*dRho2(i)
3262  +df (i) *dRho2(j)+f() *d2Rho2(i,j));
3263 return ans;
3264 }
3265 //______________________________________________________________________________
3266 void THelixTrack::TestTwoHlx()
3267 {
3268  TVector3 dif(0.1,0.,0.);
3269  double rnd = gRandom->Rndm();
3270  dif.RotateX(rnd);
3271  rnd = gRandom->Rndm();
3272  dif.RotateY(rnd);
3273  rnd = gRandom->Rndm();
3274  dif.RotateZ(rnd);
3275  TVector3 D1 = dif.Orthogonal();
3276  rnd = gRandom->Rndm();
3277  D1.Rotate(rnd,dif);
3278  TVector3 D2 = dif.Orthogonal();
3279  rnd = gRandom->Rndm();
3280  D2.Rotate(rnd,dif);
3281  double pos[3]={0};
3282  double &d1 = D1[0];
3283  double R1=20,R2=100;
3284  double shift1 = R1*gRandom->Rndm()*0.1; if (shift1>33) shift1=33;
3285  double shift2 = R2*gRandom->Rndm()*0.1; if (shift2>33) shift2=33;
3286  THelixTrack th1(pos,&d1,1./R1);
3287  double &p2 = dif[0];
3288  double &d2 = D2[0];
3289  THelixTrack th2(&p2,&d2,1./R2);
3290 
3291  {
3292  TVector3 P1(th1.Pos()),P2(th2.Pos());
3293 // TVector3 dP = (P1-P2).Unit();
3294  TVector3 dP = (P1-P2);
3295  TVector3 D1(th1.Dir());
3296  TVector3 D2(th2.Dir());
3297  double eps1 = dP.Dot(D1);
3298  double eps2 = dP.Dot(D2);
3299  printf("TestTwoHlx: Eps1 = %g Eps2 = %g\n",eps1,eps2);
3300  }
3301 
3302 
3303 
3304  th1.Move(shift1); th2.Move(shift2);
3305  double s1=0,s2=0;
3306  s1 = th1.Path(th2,&s2);
3307  th1.Move(s1);
3308  th2.Move(s2);
3309 
3310  {
3311 
3312  TVector3 P1(th1.Pos()),P2(th2.Pos());
3313  TVector3 dP = (P1-P2);
3314  double dist = dP.Mag();
3315  dP = dP.Unit();
3316  TVector3 D1(th1.Dir());
3317  TVector3 D2(th2.Dir());
3318  double eps1 = dP.Dot(D1);
3319  double eps2 = dP.Dot(D2);
3320 
3321  printf("TestTwoHlx: Eps1 = %g Eps2 = %g dist = %g\n",eps1,eps2,dist);
3322 
3323  printf("TestTwoHlx: s1=%g(%g),s2 = %g(%g)\n",s1,shift1,s2,shift2);
3324  }
3325 
3326 }
3327 //______________________________________________________________________________
3328 //______________________________________________________________________________
3329 void TCircleFitter::Show() const
3330 {
3331  TCircle::Show(fN,&(fAux[0].x),sizeof(fAux[0])/sizeof(double));
3332 }
3333 
3334 //______________________________________________________________________________
3335 class myTHFits {
3336 public:
3337 myTHFits(double h,double z,double c,double a,double l):mH(h),mZ(z),mC(c),mA(a),mL(l){}
3338 operator const double* () const {return &mH;}
3339 operator double* () {return &mH;}
3340 myTHFits() {memset(this,0,sizeof(*this));}
3341 public:
3342 static const myTHFits& GetRange() { return mgRange;}
3343 public:
3344 double mH; // direction perpendicular movement and Z
3345 double mZ; // Z, direction
3346 double mC; // curvature with sign
3347 double mA; // Angle in XY. cos(A),sin(A),T moving direction
3348 double mL; // Angle lambda in Rxy/Z
3349 static myTHFits mgRange;
3350 };
3351 
3352 myTHFits myTHFits::mgRange(1,1,1,30*3.14/180,30*3.14/180);
3353 
3354 
3355 //______________________________________________________________________________
3356 class myTHPars {
3357 public:
3358  void Set(const THelixTrack &th);
3359  void Get( THelixTrack &th);
3360 void operator+=(const myTHFits &fp);
3361 operator const double *() const {return &_x;}
3362 operator double *() {return &_x;}
3363 public:
3365  double _cosCA;
3366  double _sinCA;
3367  double _x;;
3368  double _y;
3369  double _z;
3370  double _psi;
3372  double _curv;
3374  double _tanl;
3375 };
3376 
3377 #include "TVector3.h"
3378 //______________________________________________________________________________
3379 void myTHPars::operator+=(const myTHFits &fp)
3380 {
3381  _x += -_sinCA*fp.mH;
3382  _y += _cosCA*fp.mH;
3383  _z += fp.mZ;
3384 
3385  double a = fp.mA,cA,sA;
3386  if (fabs(a) < 0.01) {sA = a*(1-a*a/6); cA = 1-a*a/2;}
3387  else {sA = sin(a); cA = cos(a) ;}
3388  _psi += a;
3389  double cosCA = _cosCA;
3390  _cosCA = cosCA*cA-_sinCA*sA;
3391  _sinCA = cosCA*sA+_sinCA*cA;
3392 
3393  _curv += fp.mC;
3394 
3395  double l = fp.mL,tL;
3396  if (fabs(l) < 0.1) {tL = l*(1+l*l/3);}
3397  else {tL = tan(l) ;}
3398  _tanl = (_tanl+tL)/(1.-_tanl*tL);
3399  if (fabs( _cosCA)>1 || fabs( _sinCA)>=1) { _cosCA = cos(_psi);
3400  _sinCA = sin(_psi);}
3401 }
3402 //______________________________________________________________________________
3403 void myTHPars::Set(const THelixTrack &th)
3404 {
3405  const double *x = th.Pos();
3406  const double *d = th.Dir();
3407  _curv = th.GetRho();
3408  _x = x[0]; _y=x[1]; _z=x[2];
3409  double sL = d[2];
3410  double cL = th.GetCos();
3411  _cosCA = d[0]/cL;
3412  _sinCA = d[1]/cL;
3413  _tanl = sL/cL;
3414  _psi = atan2(_sinCA,_cosCA);
3415 }
3416 //______________________________________________________________________________
3417 void myTHPars::Get(THelixTrack &th)
3418 {
3419 double d[3]={_cosCA,_sinCA,_tanl};
3420 th.Set(&_x,d,_curv);
3421 }
3422 
3423 //______________________________________________________________________________
3424 static double JoinTwo(int nP1,const double *P1,const double *C1
3425  ,int nP2,const double *P2,const double *C2
3426  , double *PJ, double *CJ
3427  ,int mode,const double *range=0)
3428 {
3429 // mode=0 normal case
3430 // mode=1 assign to vertex where 1st nP1 words of PJ must be == P1
3431  assert(nP1<=nP2);
3432  assert(!P2); //must be zero
3433  int nC1 = nP1*(nP1+1)/2;
3434  int nC2 = nP2*(nP2+1)/2;
3435  TArrayD ard(nC2*6);
3436  double *a = ard.GetArray();
3437  double *sumC = (a);
3438  double *sumCI = (a+=nC2);
3439  double *sumEI = (a+=nC2);
3440  double *C1P1 = (a+=nC2);
3441  double *subP = (a+=nC2);
3442 
3443  double chi2=3e33;
3444 
3445 
3446 // Join Covariant marices
3447  TCL::ucopy(C2,sumC, nC2);
3448  TCL::vadd (C1,sumC,sumC,nC1);
3449  if (CJ) TCL::ucopy(sumC,CJ,nC2);
3450 // if (range) {
3451 // for (int i=0,li=0;i<nP2;li+=++i) {
3452 // if (i<nP1) continue;
3453 // sumC[li+i]+=0.01/(range[i]*range[i]);
3454 // } }
3455 
3456  if (C2[0]<=0) { //C2 covariant matrix ==0
3457  if (!PJ) return 0;;
3458  TCL::ucopy(P1,PJ+0 ,nP1 );
3459  TCL::vzero( PJ+nP1,nP2-nP1);
3460  return 0;
3461  } else {
3462  TCL::trsa(C1 ,P1 ,C1P1,nP1,1);
3463  myQQQ = C1P1;
3464  assert(EmxSign(nP2,sumC)>1e-10);
3465  TCL::trsinv(sumC,sumCI,nP2); // 1/ (1/C1+1/C2)
3466  TCL::ucopy(P1,subP ,nP1);
3467 
3468  TCL::trqsq (C2 ,sumCI,sumEI,nP2);
3469  TCL::vsub(C2,sumEI,sumEI,nC2); //sumEi = 1/(E1+E2)==C2-C2/CJ*C2
3470  TCL::trasat(subP,sumEI,&chi2,1,nP1);
3471 
3472 // Join params
3473  if (!PJ) return chi2;
3474  TCL::trsa(C1 ,P1 ,C1P1,nP1,1);
3475  TCL::trsa(sumCI,C1P1,PJ ,nP2,1);
3476  }
3477  return chi2;
3478 }
3479 //______________________________________________________________________________
3480 void THelixKFitter::Add (const double x[3])
3481 {
3482 fAux.resize(fAux.size()+1);
3483  THelixKFitterAux &aux = fAux.back();
3484  memset(&aux,0,sizeof(THelixKFitterAux));
3485  for (int i=0,li=0;i<3;li+=++i) {aux.e[li+i]=1;aux.x[i]=x[i];}
3486 }
3487 //______________________________________________________________________________
3488 void THelixKFitter::AddErr (const double e[6])
3489 {
3490  memcpy(fAux.back().e,e,6*sizeof(e[0]));
3491 }
3492 //______________________________________________________________________________
3493 double THelixKFitter::Fit()
3494 {
3495 
3496 static const int konv[15] ={0,6,9,3,8,5,1,7,4,2,10,13,12,11,14};
3497  double cmx[15]={0},tmp[15]={0};
3498 
3499  if (fFitingShow) fFitingShow->clear();
3500  myTHPars P;
3501  THelixTrack th;
3502  double dir[3]={0},myXi2=0;
3503  TCL::vsub(fAux[1].x,fAux[0].x,dir,3);
3504  th.Set(fAux[0].x,dir,0.);
3505  fChi2=0;
3506 
3507  double F[5][5]={{0}};
3508  for (int ip=0;ip<(int)fAux.size();ip++) {
3509  double s = th.Path(fAux[ip].x[0],fAux[ip].x[1]);
3510  th.Move(s,F);
3511  TMatrixD Fm(5,5,F[0]); Fm.Invert(); TCL::ucopy(Fm.GetMatrixArray(),F[0],5*5);
3512  TCL::tratsa(F[0],cmx,tmp,5,5);
3513  TCL::ucopy(tmp,cmx,15);
3514 
3515  P.Set(th);
3516  double T[2][3] = {{-P._sinCA,P._cosCA,0}
3517  ,{ 0, 0,1}};
3518 
3519  double hG[3], hit[3];
3520  TCL::trasat(T[0],fAux[ip].e,hG,2,3);
3521  TCL::trsinv(hG,hG,2);
3522 
3523  TCL::vsub(fAux[ip].x,&P._x,hit,3);
3524  double hz[2]={ hit[0]*T[0][0]+hit[1]*T[0][1]
3525  , hit[2] };
3526 
3527  myTHFits oF;
3528  double iG[15],oG[15];
3529  if (ip==1) {//Two points not enought for calc curvature.
3530  static const int kRho = 2;
3531  for (int i=0,li=0;i<5;li+=++i) {
3532  if (i<kRho) continue;
3533  cmx[li+kRho]=0;
3534  if (i==kRho) cmx[li+kRho] = 1e-20;
3535  } }
3536 
3537  for (int jj=0;jj<15;jj++) {iG[konv[jj]]=cmx[jj];}
3538  myXi2 = JoinTwo(2,hz,hG,5,0,iG,oF,oG,0,myTHFits::GetRange());
3539  for (int jj=0;jj<15;jj++) {cmx[jj]=oG[konv[jj]];}
3540 
3541  fChi2+=myXi2; fAux[ip].xi2=myXi2;
3542  P+= oF; P.Get(th);
3543  if (fFitingShow) { //fill xyz of local fit
3544  for (int i=0;i<3;i++) {fFitingShow->push_back(P[i]);}}
3545  }
3546  TCL::trsinv(cmx,cmx,5);
3547  th.SetEmx(cmx);
3548  double s = th.Path(fAux[0].x);
3549  th.Move(s);
3550  *((THelixTrack*)this) = th;
3551  fChi2/= Ndf()+1e-10;
3552  return fChi2;
3553 }
3554 //______________________________________________________________________________
3555 void THelixKFitter::Test(int nEv)
3556 {
3557 static TCanvas* myCanvas[9]={0};
3558 static TH1F *hh[20]={0};
3559 static const char *hNams[]={
3560 "pHKalmn","pAKalmn","pCKalmn","pZKalmn","pLKalmn","Xi2Kalmn",
3561 "pHDubna","pADubna","pCDubna","pZDubna","pLDubna","Xi2Dubna"};
3562 
3563 static const double lims[][2]={{-20 ,20},{-20 ,20},{-20 ,20},{-20 ,20},{-20 ,20},{ 0 ,10}
3564  ,{-20 ,20},{-20 ,20},{-20 ,20},{-20 ,20},{-20 ,20},{ 0 ,10}};
3565 const int maxPads=3;
3566 const int nPads = sizeof(hNams)/sizeof(void*);
3567 const int nCans = nPads/maxPads;
3568  for (int jCan=0;jCan<nCans;jCan++) {
3569  if(!myCanvas[jCan]) {
3570  TString ts("THelixKKFitter_Test"); ts+=jCan;
3571  myCanvas[jCan]=new TCanvas(ts,ts,600,800);
3572  }
3573  myCanvas[jCan]->Clear(); myCanvas[jCan]->Divide(1,maxPads);
3574  }
3575 
3576  int jH=0;
3577  for (int jCan=0;jCan<nCans;jCan++) {
3578  for (int jPad=0;jPad<maxPads;jPad++) {
3579  delete hh[jH]; hh[jH]= new TH1F(hNams[jH],hNams[jH],100,lims[jH][0],lims[jH][1]);
3580  myCanvas[jCan]->cd(jPad+1); hh[jH]->Draw(); jH++;
3581  } }
3582 
3583 const int kHits = 50;
3584  double R = 50 + 100*gRandom->Rndm();
3585  double S = 2*R;
3586  int iPhi0 = 360*gRandom->Rndm();
3587  int iLam0 = 100*(gRandom->Rndm()-0.5);
3588 iLam0 = 80;
3589  double ToRad = M_PI/180;
3590  double Phi0 = ToRad*iPhi0;
3591  double Lam0 = ToRad*iLam0;
3592  double CL = cos(Lam0), SL =sin(Lam0);
3593  double POS[3]={0.1,0.2,0.3};
3594  double DIR[3]={ CL*cos(Phi0),CL*sin(Phi0),SL};
3595  double NOR[2]={-sin(Phi0) ,cos(Phi0) };
3596 
3597  THelixTrack BAS(POS,DIR,1./R);
3598  double HitErr[3]={0.1*0.1,0.1*0.1,0.2*0.2};
3599  TRandomVector RV(TVectorD(3,HitErr));
3600  const TMatrixDSym &HitEmx = RV.GetMtx();
3601  double hitErr[6];
3602  for (int i=0,li=0;i<3;li+=++i) { for (int j=0;j<=i;++j){hitErr[li+j]=HitEmx[i][j];};}
3603  double step =S/kHits;
3604  THEmx_t GG[4];
3605  double Xi2[2]={0},d[5],dif[5];
3606  for (int iEv=0;iEv<nEv;iEv++) {// Events
3607  THelixKFitter kf;
3608  THelixFitter hf;
3609  THelixTrack ht(BAS);
3610  for (int ih=0;ih<kHits;ih++) {
3611  TVectorD res = RV.Gaus();
3612  double myHit[3];
3613  for (int jj=0;jj<3;jj++) {myHit[jj]=ht.Pos()[jj]+res[jj];}
3614  kf.Add(myHit); kf.AddErr(hitErr);
3615  hf.Add(myHit[0],myHit[1],myHit[2]); hf.AddErr(hitErr,hitErr[5]);
3616  ht.Move(step);
3617  }
3618  double myXi2[2];
3619  if (!iEv) kf.SetFitingShow();
3620  myXi2[0] = kf.Fit();
3621  if (!iEv) kf.Show();
3622 
3623  myXi2[1] = hf.Fit();
3624  hf.MakeErrs();
3625  double ds = hf.Path(POS[0],POS[1]); hf.Move(ds);
3626  ds = kf.Path(POS[0],POS[1]); kf.Move(ds);
3627 
3628  THelixTrack *hlx = &kf;
3629  for (int jk=0;jk<2;jk++) {
3630  Xi2[jk]+=myXi2[jk];
3631  hh[jk*6+5]->Fill(myXi2[jk]);
3632  TCL::vadd(GG[jk+2],*hlx->Emx(),GG[jk+2],15);
3633  TCL::vsub(hlx->Pos(),POS,dif,3);
3634  d[0] = TCL::vdot(dif,NOR,2); //dH of helix
3635  d[1] = TVector3(hlx->Dir()).DeltaPhi(TVector3(DIR)); //dPhi of helix
3636  d[2] = hlx->GetRho()-1./R; //dRho of helix
3637  d[3] = dif[2]; //dZ of helix
3638  d[4] = -(TVector3(hlx->Dir()).Theta()-TVector3(DIR).Theta());
3639  if (d[4]<=-M_PI) d[4]+=M_PI*2;
3640  if (d[4]>= M_PI) d[4]-=M_PI*2; //dLam of helix
3641  double *e = GG[jk];
3642  for (int i=0,li=0;i<5;li+=++i) {
3643  double err = (*(hlx->Emx()))[li+i]; err = sqrt(err);
3644  hh[jk*6+i]->Fill( d[i]/err);
3645  for (int j=0;j<=i;++j) {e[li+j]+=d[i]*d[j];}}
3646  hlx = &hf;
3647  }
3648 
3649  }
3650 // Now print the result
3651  for (int jk=0;jk<4;jk++) {GG[jk]*=1./nEv;if (jk<2) Xi2[jk]/=nEv;}
3652 
3653 
3654  printf("*** Compare KFit and DubnaFit Error matrices ***\n");
3655  printf("*** Average KXi2 =%g DXi2 = %g ***\n",Xi2[0],Xi2[1]);
3656 
3657 static const char *tit="HACZL";
3658 static const char *tsk[2]={"KalmanFit","DubnaFit"};
3659  for (int jk=0;jk<2;jk++) {
3660  printf("*** Test for %s Xi2=%g ***\n",tsk[jk],Xi2[jk]);
3661  double qA=0,qAmax=0;
3662  const double *eK = GG[jk ];
3663  const double *eD = GG[jk+2];
3664  double dia[5];
3665  for (int i=0,li=0;i< 5;li+=++i) {
3666  dia[i]= (eK[li+i]+eD[li+i])/2;
3667  for (int j=0;j<=i;j++) {
3668  double dif = (eK[li+j]-eD[li+j])/sqrt(dia[i]*dia[j]);
3669  printf("(%c%c) \t%g = \t%g \t%g\n",tit[i],tit[j],eK[li+j],eD[li+j],dif);
3670  dif = fabs(dif);
3671  qA+= (dif); if (dif>qAmax) qAmax=dif;
3672  } }
3673  qA/=15;
3674  printf("Quality %g < %g < 1\n",qA,qAmax);
3675  }
3676 
3677  for (int i=0;myCanvas[i];i++) {
3678  myCanvas[i]->Modified();myCanvas[i]->Update();}
3679 
3680  while(!gSystem->ProcessEvents()){gSystem->Sleep(200);};
3681 
3682 
3683 }
3684 //______________________________________________________________________________
3685 void THelixKFitter::Print(const char* txt) const
3686 { if(txt){}; }
3687 //______________________________________________________________________________
3688 
3689 #include "StarRoot/StDraw3D.h"
3690 //______________________________________________________________________________
3691 void THelixKFitter::Show() const
3692 {
3693 static StDraw3D *draw = new StDraw3D("");
3694 
3695 
3696 std::vector<double> Pts;
3697 std::vector<double> Fts;
3698 
3699  THelixTrack th(*this);
3700  for (int ip=0;ip<(int)fAux.size();ip++) {
3701  double s = th.Path(fAux[ip].x[0],fAux[ip].x[1]);
3702  for (int i=0;i<3;i++) {Pts.push_back(fAux[ip].x[i]);}
3703 
3704  if (!ip) {th.Move(s);continue;}
3705  double delta = s/10;
3706  for (int j=0;j<10;j++) {
3707  for (int i=0;i<3;i++) {Fts.push_back(th.Pos()[i]);}
3708  th.Move(delta);
3709  }
3710  }
3711  if (fFitingShow) draw->Points(*fFitingShow,kUnusedHit);
3712  draw->Points(Pts,kUsedHit);
3713  draw->Line(Fts,kGlobalTrack);
3714  draw->UpdateModified();
3715  draw->Animate();
3716 
3717 }
3718 #include "TMatrixT.h"
3719 #include "TMatrixTSym.h"
3720 #include "TVectorT.h"
3721 //_____________________________________________________________________________
3722 double EmxSign(int n,const double *e)
3723 {
3724  TMatrixDSym S(n);
3725  TVectorD coe(n);
3726  for (int i=0,li=0;i< n;li+=++i) {
3727  double qwe = e[li+i];
3728  if(qwe<=0) return qwe;
3729  qwe = pow(2.,-int(log(qwe)/(2*log(2))));
3730  coe[i]=qwe;
3731  for (int j=0;j<=i;j++ ) {
3732  S[i][j]=e[li+j]*coe[i]*coe[j]; S[j][i]=S[i][j];
3733  } }
3734  TMatrixD EigMtx(n,n);
3735  TVectorD EigVal(n);
3736  EigMtx = S.EigenVectors(EigVal);
3737  TVectorD EigB = EigMtx*TVectorD(n,myQQQ);
3738  double ans = 3e33;
3739  for (int i=0;i<n;i++) {if (EigVal[i]<ans) ans = EigVal[i];}
3740  if (ans>1e-10) return ans;
3741  EigVal.Print("EigVal");
3742  EigB.Print("EigB");
3743  TVectorD(n,myQQQ).Print();
3744  return ans;
3745 }
3746 //______________________________________________________________________________
3747 //______________________________________________________________________________
3748 /***************************************************************************
3749  *
3750  * $Id: THelixTrack.cxx,v 1.82 2020/03/09 17:56:16 perev Exp $
3751  *
3752  * Author: Victor Perev, Mar 2006
3753  * Rewritten Thomas version. Error hangling added
3754  * Author: Thomas Ullrich, Dec 1999
3755  ***************************************************************************
3756  *
3757  * Description:
3758  *
3759  * Fast fitting routine using a iterational linear regression
3760  * method (ILRM). Reference: N.Chernov, G.A.Ososkov, Computer
3761  * Physics Communication 33 (1984) 329-333.
3762  *
3763  ***************************************************************************
3764  *
3765  * $Log: THelixTrack.cxx,v $
3766  * Revision 1.82 2020/03/09 17:56:16 perev
3767  * Out old version back
3768  *
3769  * Revision 1.78 2017/06/27 23:45:39 perev
3770  * Coverity
3771  *
3772  * Revision 1.77 2015/05/21 23:37:01 perev
3773  * CheckCpp fixes. No real bugs
3774  *
3775  * Revision 1.76 2015/04/28 20:36:37 perev
3776  * Crossing of two helices rewritten
3777  *
3778  * Revision 1.75 2014/06/02 18:28:22 perev
3779  * Chec XX and YY for non zero error matrix
3780  *
3781  * Revision 1.74 2013/06/10 15:50:10 perev
3782  * fabs(eigen) + TComplex &x added
3783  *
3784  * Revision 1.72 2013/05/16 20:04:09 perev
3785  * Init all variables to 0
3786  *
3787  * Revision 1.71 2013/05/02 02:00:12 perev
3788  * Defence aginst strait track along X
3789  *
3790  * Revision 1.70 2013/05/01 17:33:34 perev
3791  * method TCirleFitter::Show added
3792  *
3793  * Revision 1.69 2013/05/01 15:58:52 perev
3794  * Some pre fit analisys improved to avoid crashes for Stv
3795  *
3796  * Revision 1.66 2013/04/23 01:47:16 perev
3797  * add Show() ++ defence against abnormal cases
3798  *
3799  * Revision 1.65 2013/04/20 03:37:11 perev
3800  * Reorganization to account non standard cases
3801  *
3802  * Revision 1.64 2013/04/17 03:01:32 perev
3803  * Special case xy1st ~= xyLst
3804  *
3805  * Revision 1.63 2013/04/17 02:12:20 perev
3806  * More accurate fast track estimation 2
3807  *
3808  * Revision 1.62 2013/04/16 18:54:20 perev
3809  * More accurate fast track estimation
3810  *
3811  * Revision 1.61 2013/02/20 02:01:44 perev
3812  * Cleanup
3813  *
3814  * Revision 1.60 2012/12/07 17:47:42 perev
3815  * Cleanup
3816  *
3817  * Revision 1.59 2012/07/21 18:46:38 perev
3818  * Method MaxCorr() added
3819  *
3820  * Revision 1.58 2012/06/19 23:50:42 perev
3821  * Fix KFit::Test
3822  *
3823  * Revision 1.57 2012/05/28 02:26:31 perev
3824  * Helix Kalman fitter added
3825  *
3826  * Revision 1.56 2012/04/19 16:16:14 perev
3827  * Cleanup
3828  *
3829  * Revision 1.55 2012/01/30 17:27:19 perev
3830  * Improve Errors
3831  *
3832  * Revision 1.54 2011/07/19 19:29:19 perev
3833  * set hh & zz errors
3834  *
3835  * Revision 1.53 2011/04/01 20:10:32 perev
3836  * +Check for 0 array
3837  *
3838  * Revision 1.52 2010/12/07 16:59:27 perev
3839  * Cleanup
3840  *
3841  * Revision 1.51 2010/12/07 16:50:32 perev
3842  * THelixTrack::Path(x,y) TCircle inside
3843  *
3844  * Revision 1.50 2010/10/31 23:36:35 perev
3845  * TestDer() Test deiivates added
3846  *
3847  * Revision 1.49 2010/10/14 17:45:49 perev
3848  * Inversion of derivative matrix added
3849  *
3850  * Revision 1.48 2010/07/16 20:31:38 perev
3851  * Put back some ctr(this) to ctr(*this)
3852  *
3853  * Revision 1.47 2010/07/15 18:08:43 perev
3854  * TestMtx added
3855  *
3856  * Revision 1.46 2010/06/01 20:54:54 perev
3857  * Correlation HZ accounted now
3858  *
3859  * Revision 1.45 2010/04/23 22:51:27 perev
3860  * Method Move with derivatives adde
3861  *
3862  * Revision 1.44 2009/11/09 19:58:58 perev
3863  * FitZ removed everywhere
3864  *
3865  * Revision 1.43 2009/09/07 04:32:50 fine
3866  * workaround for the bug #1628
3867  *
3868  * Revision 1.42 2009/08/28 16:38:55 fine
3869  * fix the compilation issues under SL5_64_bits gcc 4.3.2
3870  *
3871  * Revision 1.41 2009/08/24 23:40:33 perev
3872  * operator=() added
3873  *
3874  * Revision 1.40 2009/08/22 00:11:59 perev
3875  * Full error matrix + derivatives matrix
3876  *
3877  * Revision 1.39 2009/07/18 00:12:56 perev
3878  * method PatX(helx,,,) added
3879  *
3880  * Revision 1.38 2009/07/01 21:48:39 perev
3881  * Fix -tive errors & remove obsolete
3882  *
3883  * Revision 1.37 2009/04/06 17:51:32 perev
3884  * Replace assert(wt>0) by error condition
3885  *
3886  * Revision 1.36 2008/10/29 19:36:25 perev
3887  * flag 2d and 3d dca added
3888  *
3889  * Revision 1.35 2007/12/20 00:47:27 perev
3890  * WarnOff
3891  *
3892  * Revision 1.34 2007/12/18 23:11:05 perev
3893  * Distance to helix & circle added
3894  *
3895  * Revision 1.33 2007/10/24 22:43:24 perev
3896  * Implementation was forgotten. Thanx Adam
3897  *
3898  * Revision 1.32 2007/09/10 02:05:37 perev
3899  * Misstype fixed
3900  *
3901  * Revision 1.31 2007/07/13 18:17:10 perev
3902  * remove member fMax from THelixTrack
3903  *
3904  * Revision 1.30 2007/07/12 00:22:29 perev
3905  * TCircleFitter::Fit case 1 if case 2 failed
3906  *
3907  * Revision 1.29 2007/06/25 19:26:40 perev
3908  * Cleanup
3909  *
3910  * Revision 1.28 2007/04/26 04:20:18 perev
3911  * Some improvements
3912  *
3913  * Revision 1.27 2007/03/21 17:41:32 fisyak
3914  * replace complex by TComplex
3915  *
3916  * Revision 1.26 2007/01/26 19:56:24 perev
3917  * tune up
3918  *
3919  * Revision 1.25 2006/08/10 04:09:50 perev
3920  * Test cleanup
3921  *
3922  * Revision 1.23 2006/06/28 18:39:07 perev
3923  * cos(dip)**4 added to Dca(...) to account z err in the nearest point
3924  *
3925  * Revision 1.22 2006/06/26 19:09:21 perev
3926  * DcaXY & DcaZ with errors added
3927  *
3928  * Revision 1.21 2006/06/09 19:53:51 perev
3929  * double Dca(double x,double y,double *dcaErr=0) added
3930  *
3931  * Revision 1.2 2003/09/02 17:59:34 perev
3932  * gcc 3.2 updates + WarnOff
3933  *
3934  * Revision 1.1 1999/12/21 16:28:48 ullrich
3935  * Initial Revision
3936  *
3937  **************************************************************************/
3938 
static float * traat(const float *a, float *s, int m, int n)
Definition: TCernLib.cxx:293
double Eval(double step, double *xyz, double *dir, double &rho) const
Evaluate params with given step along helix.
double PathX(const THelixTrack &hlx, double *s2=0, double *dist=0, double *xyz=0) const
double _curv
signed curvature [sign = sign(-qB)]
virtual TObject * Line(int n, const double *xyz, Color_t col=Color_t(-1), Style_t sty=Style_t(-1), Size_t siz=Size_t(-1))
This is an overloaded member function, provided for convenience.
Definition: StDraw3D.cxx:807
void Get(double *xyz, double *dir, double &rho) const
Get current parameters.
Definition: THelixTrack.h:245
Class StDraw3D - to draw the 3D primitives like 3D points and 3D lines decorated with the STAR detect...
Definition: StDraw3D.h:165
static float * trpck(const float *s, float *u, int n)
Definition: TCernLib.cxx:1010
static float * trsa(const float *s, const float *a, float *b, int m, int n)
Definition: TCernLib.cxx:1111
static float * trqsq(const float *q, const float *s, float *r, int m)
Definition: TCernLib.cxx:1045
void Backward()
Change direction.
static float * trsinv(const float *g, float *gi, int n)
Definition: TCernLib.cxx:1160
virtual TObject * Points(int n, const float *xyz, EDraw3DStyle sty)
This is an overloaded member function, provided for convenience.
Definition: StDraw3D.cxx:596
static float * trasat(const float *a, const float *s, float *r, int m, int n)
Definition: TCernLib.cxx:540
double _tanl
tangent of the track momentum dip angle
double _cosCA
sin and cosin of cross angle
static float * trupck(const float *u, float *s, int m)
Definition: TCernLib.cxx:1248
double Move(double step)
Move along helix.
static float * tratsa(const float *a, const float *s, float *r, int m, int n)
Definition: TCernLib.cxx:677
Definition: AgUStep.h:71
virtual void Animate()
Animate the viewer from the gdb session.
Definition: StDraw3D.cxx:1624
void GetSpot(const double axis[3][3], double emx[3]) const
double FixAt(const double vals[5], int flag)
double Dca(const double point[3], double *dcaErr=0) const
DCA to given space point (with error matrix)