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