14 #include "TRandomVector.h"
15 #include "StMatrixD.hh"
19 #include "THelixTrack_.h"
22 const TComplex Im(0,1);
24 inline static void spheric(
const double D[3]
25 ,
double &cosL,
double &sinL
26 ,
double &cosP,
double &sinP)
29 cosL = (1.-sinL)*(1+sinL);
30 cosL = (cosL<=0)? 0.:sqrt(cosL);
32 cosP = 1; sinP = 0; cosL = 1e-6;
34 cosP = D[0]/cosL; sinP = D[1]/cosL;
38 inline static void satlit(
const double &cosL,
const double &sinL
39 ,
const double &cosP,
const double &sinP
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;
48 inline static double dot(
const TComplex &a,
const TComplex &b)
49 {
return a.Re()*b.Re()+a.Im()*b.Im();}
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];}
54 inline static TComplex expOne(TComplex x)
56 double a = TComplex::Abs(x);
58 return 1.+x*((1/2.) + x*((1/6.)+ x*(1/24.)));
60 return (TComplex::Exp(x)-1.)/x;
64 inline static TComplex expOneD(TComplex x)
66 double a = TComplex::Abs(x);
68 return (1/2. + x*((1/6.)+ x*((1/24.)+x*(1/120.))));
70 return (TComplex::Exp(x)-1.-x)/(x*x);
75 void TCEmx_t_::Set(
const double *err)
76 {
if (err) {memcpy(
this,err,
sizeof(*
this));}
else {Clear();}}
79 void TCEmx_t_::Move(
const double F[3][3])
83 memcpy(oErr,Arr(),
sizeof(oErr));
87 void TCEmx_t_::Backward()
92 double TCEmx_t_::Sign()
const
94 const double *E = &mHH;
96 for (
int i=0,li=0;i<3;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));
108 void THEmx_t_::Set(
const double *errxy,
const double *errz)
111 memcpy(&mHH,errxy,
sizeof(mHH)*6);
112 mZZ = errz[0]; mZL =errz[1]; mLL =errz[2];
115 void THEmx_t_::Set(
const double *err)
116 {
if (err) {memcpy(
this,err,
sizeof(*
this));}
else {Clear();}}
118 void THEmx_t_::Backward()
120 mHA*=-1; mAC*=-1; mHZ*=-1; mCZ*=-1; mAL*=-1; mZL*=-1;
123 void THEmx_t_::Move(
const double F[5][5])
127 memcpy(oErr,Arr(),
sizeof(oErr));
131 void THEmx_t_::Print(
const char *tit)
const
133 static const char *N=
"HACZL";
135 printf(
"THEmx_t_::::Print(%s) ==\n",tit);
136 const double *e = &mHH;
137 for (
int i=0,li=0;i< 5;li+=++i) {
139 for (
int j=0;j<=i;j++) {
140 printf(
"%g\t",e[li+j]);}
145 double THEmx_t_::Sign()
const
147 const double *E = &mHH;
149 for (
int i=0,li=0;i<5;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));
161 const double Zero = 1.e-6;
162 static TComplex sgCX1,sgCX2,sgCD1,sgCD2,sgImTet,sgCOne,sgCf1;
163 static int SqEqu(
double *,
double *);
166 static int myEqu(
double *s,
int na,
double *b,
int nb)
169 double *m = &mtx(1,1);
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));
182 static void Eigen2(
const double err[3],
double lam[2],
double eig[2][2])
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;
190 lam[0] = 0.5*(spur+dis);
191 lam[1] = 0.5*(spur-dis);
193 eig[0][0] = 1; eig[0][1]=0;
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]);
198 eig[0][0] = 1; eig[0][1]= -err[1]/(err[2]-lam[0]);
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;
203 eig[1][0]=-eig[0][1]; eig[1][1]= eig[0][0];
206 static TComplex MyFactor(
double rho,
double drho,
double s)
216 arr[0] = 1.; arr[1] = 0.;
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;
224 arr[0]=arr[1]; arr[1]=arr[2];
232 THelixTrack_::THelixTrack_(
const double *xyz,
const double *dir,
double rho)
262 memcpy(fBeg,from.fBeg,fEnd-fBeg);
264 if (from.fEmx) SetEmx(from.fEmx->Arr());
272 if (from.fEmx) SetEmx(from.fEmx->Arr());
278 Set(fr->fX,fr->fP,fr->fRho);
281 THelixTrack_::~THelixTrack_()
282 {
delete fEmx;fEmx=0;}
284 THelixTrack_::THelixTrack_()
286 memset(fBeg,0,fEnd-fBeg);
289 void THelixTrack_::Set(
const double *xyz,
const double *dir,
double rho)
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];
297 void THelixTrack_::SetEmx(
const double* err2xy,
const double* err2sz)
300 fEmx->Set(err2xy,err2sz);
303 void THelixTrack_::SetEmx(
const double* err)
309 void THelixTrack_::StiEmx(
double err[21])
const
316 ,kTX,kTY,kTZ,kTE,kTP,kTT
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);
342 for (
int i=0;i<3;i++) { d[i]=-fP[i];}
344 if(fEmx) fEmx->Backward();
355 double my[3][3] = {{-fP[1]/fCosL, 0,fP[0]}
356 ,{ fP[0]/fCosL, 0,fP[1]}
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);
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) {
366 memcpy(tmp[0],T[0],
sizeof(T));
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};
376 void THelixTrack_::Build()
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; }
385 fCosL = ::sqrt(fabs((1.-fP[2])*(1.+fP[2])));
391 enum {kH=0,kA,kC,kZ,kL};
393 double S = step*fCosL;
394 memset(F[0],0,
sizeof(F[0][0])*5*5);
396 F[kH][kH] = sgCf1.Re()+1.;
397 double dSdH = sgCf1.Im();
399 F[kH][kA] = S*sgCOne.Re();
400 double dSdA = S*sgCOne.Im();
402 TComplex llCOneD = S*S*expOneD(-sgImTet);
403 F[kH][kC] = llCOneD.Re();
404 double dSdC = llCOneD.Im();
406 F[kA][kH] = -dSdH*fRho;
407 F[kA][kA] = 1-dSdA*fRho;
408 F[kA][kC] = S+dSdC*fRho;
411 double tanL = fP[2]/fCosL;
413 F[kZ][kH] = -dSdH*tanL;
414 F[kZ][kA] = -dSdA*tanL;
415 F[kZ][kC] = dSdC*tanL;
417 F[kZ][kL] = S/(fCosL*fCosL);
424 Eval(step,fX,fP,&fRho);
425 if (fEmx && fEmx->mHH>0) {
434 double xyz[3],dir[3],rho;
435 Eval(step,xyz,dir,&rho);
438 if (fEmx && fEmx->mHH>0) fEmx->Move(F);
444 double *xyz,
double *dir,
int nearest)
const
447 double s[10]={0,0,0,0,0,0,0,0,0,0},tmp=0;
448 memcpy(s,surf,nsurf*
sizeof(surf[0]));
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;
456 return Path(stmin,stmax,s,nsurf,xyz,dir,nearest);
462 double *xyz,
double *dir,
int nearest)
const
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}};
469 double myMax = 1./(fabs(fRho*fCosL)+1.e-10);
471 cos1t = 0.5*fRho*fCosL;
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;
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;
490 for (jp=0;jp+ip<3;jp++) {
491 f2 = poly[jx][jp];
if(!f2)
continue;
495 int nsol = SqEqu(tri,sol);
497 if (nsol<0)
return step;
499 if (nearest && nsol>1) {
500 if(fabs(sol[0])>fabs(sol[1])) sol[0]=sol[1];
503 if (nsol) step = sol[0];
504 if (step < stmin && nsol > 1) step = sol[1];
505 if (step < stmin || step > stmax) {
507 if (step>0) {step = stmax; stmin+=myMax/2;}
508 else {step = stmin; stmax-=myMax/2;}}
510 if (!nsol && fabs(step) < 0.1*myMax)
return 1.e+12;
511 if (fabs(step)>myMax) {step = (step<0)? -myMax:myMax; nsol=0;}
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);
525 stmax -=step; stmin -=step;
526 if (stmin>=stmax)
return 1.e+12;
534 double THelixTrack_::PathHZ(
const double *su,
int nsurf,
535 double *xyz,
double *dir,
int nearest)
const
537 double tri[3] = {0,0,0};
538 double f0,fc,fs,R,tet,tet0,tet1,tet2,costet,su45=0,fcs;
543 f0 = fX[0] - fP[1]*R;
547 tri[0] = su[0] + su[1]*f0;
551 su45 = 0.5*(su[4]+su[5]);
553 tri[0] += su45*f0*f0 + su45*fcs;
554 tri[1] += su45*2*f0*fc;
555 tri[2] += su45*2*f0*fs;
558 f0 = fX[1] + fP[0]*R;
567 tri[1] += su45*2*f0*fc;
568 tri[2] += su45*2*f0*fs;
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]);
577 if (tet1 > 2*M_PI) tet1 -= 2*M_PI;
578 if (tet2 > 2*M_PI) tet2 -= 2*M_PI;
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);
588 if (s1<=0) s1 += 2*M_PI*fabs(R);
590 if (s2<=0) s2 += 2*M_PI*fabs(R);
592 return Eval(s1,xyz,dir);
599 static const double kMinAng = 0.1,kDeltaL=1e-4;
602 double Rho1=thMe.GetRho()*thMe.GetCos();
603 double Rho2=thHe.GetRho()*thHe.GetCos();
605 for (
int ix=0;ix<3;ix++)
606 {
if (fabs(thMe.Pos()[ix]-thHe.Pos()[ix])>100)
return 3e33;}
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());
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;
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;
637 if (fabs(s1)>kDeltaL)
continue;
638 if (fabs(s2)>kDeltaL)
continue;
641 if (!conv)
return 3e33;
642 if(path2) *path2=sHe;
648 double ss1,ss2,dd,ss1Best,ss2Best,ddBest=1e33;
651 for (
int jk=0;jk<4;jk++) {
653 if (jk&1) th1.Backward();
655 ss1 = th1.Path(th2,&ss2);
656 if (ss1>=1e33)
continue;
657 if (ss2>=1e33)
continue;
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);
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;
678 return ht.Path(ar)/fCosL;
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};
691 if (fabs(fP[2]) > 0.01){
693 step[1] = (point[2]-fX[2])/fP[2];
699 if (fabs(cpnt.Re()*fRho) < 0.01) {
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;
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++;
723 double ds = step[1]-step[2];
724 if (zStep && fabs(ds)>1.e-5) {
725 double dz = ds*fP[2];
730 double xnear[6],ss=0;
double* pnear=xnear+3;
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();
737 lMax = (step[1]>step[2])? step[1]:step[2];
738 lMin = (step[1]>step[2])? step[2]:step[1];}
742 lMax-=step[0];lMin-=step[0];
743 local.Eval(0.,xnear,pnear);
746 double diff = (icut)? lMax-lMin: fabs(dstep);
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;
756 local.Eval(ss,xnear,pnear);
758 for (
int i=0;i<3;i++) {dstep += pnear[i]*(point[i]-xnear[i]);}
760 lMax = ss; dztep = -0.5*(lMax-lMin);
761 if (dstep<dztep || fabs(dstep)>0.7*oldStep) {icut=1;dstep = dztep;}
763 lMin = ss; dztep = 0.5*(lMax-lMin);
764 if (dstep>dztep || fabs(dstep)>0.7*oldStep) {icut=1;dstep = dztep;}
770 if (!iter){ printf(
"*** Problem in THElixTrack::Path(vtx) ***\n");
771 printf(
"double vtx[3]={%g,%g,%g};",point[0],point[1],point[2]);
775 return (xyz) ?
Eval(step[0],xyz,dir) : step[0];
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;
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];
800 double dir[3]={fP[0],fP[1],0};
802 if (fEmx) hlx.SetEmx(fEmx->Arr());
803 double vtx[3]={x,y,fX[2]};
804 return hlx.
Dca(vtx,dcaErr);
810 ,
double &dcaXY,
double &dcaZ,
double dcaEmx[3],
int kind)
const
821 assert(kind==2 || kind==3);
822 if (kind==3) s = Path(point);
823 else s = Path(point[0],point[1]);
827 const double *x=th.Pos();
828 const double *d=th.Dir();
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}
834 ,{ d[0]/nor, d[1]/nor, 0}};
836 dcaXY = T[0][0]*dif[0]+T[0][1]*dif[1];
838 if (!dcaEmx)
return s;
840 dcaEmx[0] = emx->mHH;
843 dcaEmx[2] = emx->mZZ*pow(th.GetCos(),4);
849 double THelixTrack_::GetPeriod()
const
851 double per = (fabs(fRho) > 1.e-10) ? fabs(2.*M_PI/fRho):1.e+10;
855 void THelixTrack_::Rot(
double angle)
857 Rot(cos(angle),sin(angle));
860 void THelixTrack_::Rot(
double cosa,
double sina)
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();
868 void THelixTrack_::Print(Option_t *)
const
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);
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");
882 void THelixTrack_::TestMtx()
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];
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;
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);
901 tc.Eval(step,X[1],Dir[1]);
903 memcpy(Fi[0],F[0],
sizeof(F));
905 TMatrixD one = TMatrixD(5,5,F[0])*TMatrixD(5,5,Fi[0]);
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);
918 X[2][0] += -Dir[0][1]*Del/cos(lam);
919 X[2][1] += Dir[0][0]*Del/cos(lam);
924 Dir[2][0] = cos(lam)*cos(alf+Del);
925 Dir[2][1] = cos(lam)*sin(alf+Del);
926 Dir[2][2] = sin(lam);
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);
947 double myStep = tcc.Path(X[1][0],X[1][1]);
948 tcc.Eval(myStep,X[3],Dir[3]);
950 for (
int jHAR=0;jHAR<5; jHAR++) {
951 if (jHAR==kC)
continue;
952 if (jHAR==kL)
continue;
955 Dif = (X[3][0]-X[1][0])*(-Dir[1][1])
956 + (X[3][1]-X[1][1])*( Dir[1][0]);
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;
966 Dif = X[3][2]-X[1][2];
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);
978 printf(
"TestMtx: %d errors maxEps=%g\n",nErr,maxEps);
982 int SqEqu(
double *cba,
double *sol)
1002 const double zero2=1.e-12;
1003 double swap,a,b,c,amx,dis,bdis;
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;
1015 if (fabs(dis) <= zero2) dis = 0;
1016 if (dis < 0.) { nsol = 0; dis = 0.;}
1018 dis = ::sqrt(dis); bdis = b + dis;
1019 if (fabs(c) > 1.e+10*bdis)
return -1;
1021 if (fabs(bdis) <= 0.)
return nsol;
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;}
1032 if (rho) *rho = fRho;
1034 if (xyz) memcpy(xyz,fX,
sizeof(fX));
1035 if (dir) memcpy(dir,fP,
sizeof(fP));
1039 double ztep = step*fCosL;
1040 double teta = ztep*fRho;
1042 sgCX1 = TComplex(fX[0] ,fX[1]);
1043 sgCD1 = TComplex(fP[0],fP[1])/fCosL;
1044 sgImTet = TComplex(0,teta);
1045 sgCOne = expOne(sgImTet);
1046 sgCf1 = sgImTet*sgCOne;
1047 sgCD2 = sgCD1*sgCf1+sgCD1;
1048 sgCX2 = sgCD1*sgCOne*ztep;
1051 xyz[0] = sgCX2.Re()+sgCX1.Re();
1052 xyz[1] = sgCX2.Im()+sgCX1.Im();
1053 xyz[2] = fX[2]+fP[2]*step;
1056 sgCD2/= TComplex::Abs(sgCD2);
1057 dir[0] = sgCD2.Re()*fCosL;
1058 dir[1] = sgCD2.Im()*fCosL;
1064 void THelixTrack_::Fill(
TCircle_ &circ)
const
1068 circ.fD[0]=fP[0]/fCosL;
1069 circ.fD[1]=fP[1]/fCosL;
1071 if (fEmx) circ.SetEmx(fEmx->Arr());
1074 void THelixTrack_::InvertMtx(
double F[5][5])
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]];
1085 void THelixTrack_::TestErr()
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];
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]);
1103 static TH1F *hXi2[2] = {0};
1104 for (
int jk=0;jk<2;jk++) {
1105 TString ts(
"Xi2_"); ts += jk;
1107 hXi2[jk]=
new TH1F(ts.Data(),ts.Data(),50,0,0);
1108 myCanvas[0]->cd(jk+1); hXi2[jk]->Draw();
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};
1115 hh[ih] =
new TH1F(tit[ih],tit[ih],100,0,0);
1116 myCanvas[1]->cd(ih+1); hh[ih]->Draw();
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};
1123 hrt[ih] =
new TH1F(tit[ih],tit[ih],100,0,0);
1124 myCanvas[2]->cd(ih+1); hrt[ih]->Draw();
1127 static TH1F * hcr[10]={0};
1129 static const char *tit[]={
"HP",
"HC",
"PC",
"HZ",
"PZ",
"CZ",
"HL",
"PL",
"CL",
"ZL"};
1130 for (
int ih=0;ih<10;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);
1139 TVector3 PbegV(PtGev,0,PtGev*3);
1141 PbegV.RotateZ(gRandom->Rndm()*3.14); PbegV.GetXYZ(Pbeg);
1142 TVector3 XbegV(Xbeg);
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];}
1151 auto &EMX = RV.GetMtx();
1152 auto &val = RV.GetLam();
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];
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]}};
1176 TH0.Eval(0,Xend,Pend);
1179 double tkDirE[3][3] = {{-d[1]/cosL,d[0]/cosL,0},{0,0,1},{d[0],d[1],d[2]}};
1181 auto *myEmx = TH0.Emx();
1182 const double *Gend = myEmx->Arr();
1184 for (
int i=0,li=0;i< 5;li+=++i) {
1185 GendD[i] = sqrt(Gend[li+i]);
1190 TVector3 PendV(Pend),XendV(Xend);
1193 for (
int iter=0;iter<nIter;iter++) {
1194 TVectorD delta = RV.Gaus();
1196 TCL::trasat(delta.GetMatrixArray(),GbegI,&chi2,1,5);
1198 hXi2[0]->Fill(chi2);
1200 for (
int ih=0;ih<myDiv[1];ih++) { hrt[ih]->Fill(delta[ih]/GbegD[ih]);}
1201 TVector3 P1begV = PbegV;
1202 TVector3 X1begV = XbegV;
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);
1214 double s = TH1.Path(Xend[0],Xend[1]);
1216 TH1.Eval(0,X1end,P1end);
1218 TVector3 X1endV(X1end),P1endV(P1end);
1220 TVector3 difX = X1endV-XendV;
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);
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);
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];
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];
1251 TCL::vscale(myG,1./nIter,myG,15);
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]);
1259 for (
int j=0;j<=i;j++) {
1260 printf(
"\t%g ",Gend[li+j]);
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]));
1272 for (
int i=0;myCanvas[i];i++) {
1273 if (!myCanvas[i])
continue;
1274 myCanvas[i]->Modified();myCanvas[i]->Update();}
1276 while(!gSystem->ProcessEvents()){gSystem->Sleep(200);};
1281 void THelixTrack_::Show(
double len,
const THelixTrack_ *other)
const
1283 static TCanvas *myCanvas = 0;
1284 int kolor[2]={kRed,kBlue};
1286 TGraph *ciGraph[2][2] = {{0}};
1287 TGraph *ptGraph[2][2] = {{0}};
1288 TGraph *szGraph[2] = {0};
1290 double x[100],y[100],z[100],l[100],xyz[3];
1291 double X[4],Y[4],Z[4],L[4];
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));
1298 if (step>fabs(len)*0.10) step=fabs(len)*0.1;
1299 if (step<fabs(len)*0.01) step=fabs(len)*0.01;
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];
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]);
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];
1325 szGraph[0] =
new TGraph(nH*2 , X, Y);
1326 szGraph[1] =
new TGraph(nH*2 , L, Z);
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");
1339 myCanvas->Modified();
1341 while(!gSystem->ProcessEvents()){gSystem->Sleep(200);};
1345 void THelixTrack_::Test1()
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;
1353 double s = TH.Path(100000,surf,4);
1354 printf(
"s=%g = 15.3589\n",s);
1357 void THelixTrack_::Test2()
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;
1366 double MyHit[3]= { -177.673, 41.305, 2.90798};
1369 printf(
"%s= %g %g %g\n",
"MyHit",MyHit[0],MyHit[1],MyHit[2]);
1370 double s = ht.Path(MyHit,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");
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");
1385 void THelixTrack_::Test3()
1387 double xyz[3] = {100,200,300};
1388 double dir[3] = {-0.224845,-0.491295,-0.841471};
1390 double sur[8]={-120,1,0,0,0,0,0};
1392 double newX[3],newD[3];
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]);
1398 printf(
"MustBe: s=56.1931 newX=(120 222.222 347.285) newD=(0.464979 0.275174 0.841471)\n\n");
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");
1407 void THelixTrack_::Test4()
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;
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);
1422 void THelixTrack_::Test5()
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}},
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]);
1435 double s1 = th1.Path(th2,&s2);
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);
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;
1455 double alf = iAlf/180.*M_PI,alf1 = alf;
1456 double lam = iLam/180.*M_PI,lam1 = lam;
1460 step = iR*M_PI * 1.0 / cos(lam);
1463 printf(
"TestDer: Angle=%d Lam=%d \tRad=%d Step=%d \n",iAlf,iLam,iR,
int(step));
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);
1469 TVector3 Xbeg1,Xend1;
1470 TVector3 Dbeg1,Dend1;
1472 THelixTrack_ hlx((
double*)&Xbeg[0],(
double*)&Dbeg[0],rho);
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]);
1480 for (
int JK=0;JK<5;JK++) {
1482 double delta = 1e-8;
1483 Xbeg1 = Xbeg; Dbeg1 = Dbeg;
1484 alf1 = alf; lam1 = lam;
1488 Xbeg1 += Hbeg*delta;
1506 Dbeg1 = TVector3(cos(lam1)*cos(alf1),cos(lam1)*sin(alf1),sin(lam1));
1507 THelixTrack_ hlxM((
double*)&Xbeg1[0],(
double*)&Dbeg1[0],rho1);
1509 double dL = hlxM.
Path(Xend[0],Xend[1]);
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;}
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"
1529 ,F[i][j],F1[i][j],(F1[i][j]-F[i][j]));
1534 void THelixTrack_::TestTwoHlx()
1536 TVector3 dif(0.1,0.,0.);
1537 double rnd = gRandom->Rndm();
1539 rnd = gRandom->Rndm();
1541 rnd = gRandom->Rndm();
1543 TVector3 D1 = dif.Orthogonal();
1544 rnd = gRandom->Rndm();
1546 TVector3 D2 = dif.Orthogonal();
1547 rnd = gRandom->Rndm();
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;
1555 double &p2 = dif[0];
1560 TVector3 P1(th1.Pos()),P2(th2.Pos());
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);
1572 th1.Move(shift1); th2.Move(shift2);
1574 s1 = th1.Path(th2,&s2);
1580 TVector3 P1(th1.Pos()),P2(th2.Pos());
1581 TVector3 dP = (P1-P2);
1582 double dist = dP.Mag();
1584 TVector3 D1(th1.Dir());
1585 TVector3 D2(th2.Dir());
1586 double eps1 = dP.Dot(D1);
1587 double eps2 = dP.Dot(D2);
1589 printf(
"TestTwoHlx: Eps1 = %g Eps2 = %g dist = %g\n",eps1,eps2,dist);
1591 printf(
"TestTwoHlx: s1=%g(%g),s2 = %g(%g)\n",s1,shift1,s2,shift2);
1596 void THelixTrack_::TestBak()
1599 double X0[3]={0,0,0},D0[3]={1,2,3},Rho0=1./100,L=100;
1600 double X1[3],D1[3],Rho1;
1602 TCL::ucopy(th.Dir(),D0,3);
1609 TCL::ucopy(th.Pos(),X1,3);
1610 TCL::ucopy(th.Dir(),D1,3);
1612 printf(
"Rho1=%g Xbak = 0 = %g %g %g\n",Rho1,X1[0],X1[1],X1[2]);
1625 TCircle_::TCircle_()
1631 TCircle_::~TCircle_()
1632 {
delete fEmx;fEmx=0;}
1635 TCircle_::TCircle_(
const double *x,
const double *d,
double rho)
1641 void TCircle_::Set(
const double *x,
const double *d,
double rho)
1643 fX[0]=0; fX[1]=0; fD[0]=0; fD[1]=0;
1644 if (x) {fX[0]=x[0];fX[1]=x[1];}
1646 fD[0]=d[0];fD[1]=d[1];
1647 double n = sqrt(fD[0]*fD[0]+fD[1]*fD[1]);
1653 TCircle_::TCircle_(
const TCircle_& fr)
1659 TCircle_::TCircle_(
const TCircle_* fr)
1662 Set(fr->fX,fr->fD,fr->fRho);
1667 Set(fr.fX,fr.fD,fr.fRho);
1668 if (fr.fEmx) SetEmx(fr.fEmx->Arr());
1673 void TCircle_::Clear(
const char *)
1675 if (fEmx) fEmx->Clear();
1676 memset(fX,0,(
char*)(&fEmx)-(
char*)fX);
1681 void TCircle_::SetEmx(
const double *err)
1687 void TCircle_::Nor(
double *norVec)
const
1691 norVec[0] = fD[1]; norVec[1] = -fD[0];
1692 if (fRho>=0)
return;
1693 norVec[0] = -norVec[0];norVec[1] = -norVec[1];
1696 void TCircle_::GetCenter(
double cent[3])
const
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;
1705 void TCircle_::Print(
const char* txt)
const
1708 printf(
"TCircle_(%s): x,y=%g %g dir=%g %g curv=%g\n",txt,fX[0],fX[1],fD[0],fD[1],fRho);
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);
1715 double TCircle_::Path(
const double pnt[2])
const
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;
1722 if (TComplex::Abs(CXPRho)>0.001) {
1723 s = TComplex::Log(1.+CXPRho).Im()/fRho;
1725 s = (CXP*(1.-CXPRho*(0.5-CXPRho*(1/3.-CXPRho*0.25)))).Im();
1734 double TCircle_::Path(
const double *pnt,
const double *exy)
const
1737 double s = Path(pnt);
1738 if (!exy || exy[0]<=0)
return s;
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]);
1747 double TCircle_::Path(
const TCircle_ &hlx,
double *S2)
const
1749 double s,s1=3e33,s2=3e33;
1750 const static TComplex Im(0.,1.);
1753 if (fabs(fRho) > fabs(hlx.fRho)) { one=two; two=
this; }
1754 double Rho1 = one->Rho();
1755 double Rho2 = two->Rho();
1757 if (fabs(Rho1) > 1e-4) kase+=1;
1758 if (fabs(Rho2) > 1e-4) kase+=2;
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;
1771 TComplex A = CP1/CP2*(Rho2/Rho1);
1772 TComplex B = 1.-CdX/CP2*(Im*Rho2) - CP1/CP2*(Rho2/Rho1);
1775 double alfa = A.Theta();
1776 double beta = B.Theta();
1777 double myCos = (1.-(a*a+b*b))/(2.*a*b);
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);
1786 s =(-myAng -(alfa-beta))/Rho1;
1787 if (s< 0) s+= 2.*M_PI/fabs(Rho1);
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);
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];
1804 if (fabs((CdX/CP1).Im())>fabs((CP2/CP1).Im())*1e6)
break;
1806 s = (CdX/CP2).Im()/(CP1/CP2).Im();
1818 if (s<0 && kase) s += 2.*M_PI/fabs(Rho2);
1823 if (one !=
this) {s=s1;s1=s2;s2=s;}
1828 void TCircle_::Test4()
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]);
1841 double s1 = tc1.Path(tc2,&s2);
1842 printf(
"s1=%g s2=%g \n",s1,s2);
1846 double TCircle_::Eval(
double step,
double *X,
double *D)
const
1849 sgCX1 =TComplex(fX[0],fX[1]);
1850 sgCD1 =TComplex(fD[0],fD[1]);
1851 sgImTet =TComplex(0,step*fRho);
1852 sgCOne =expOne(sgImTet);
1853 sgCf1 =sgImTet*sgCOne;
1855 sgCD2 = sgCD1*sgCf1+sgCD1;
1856 sgCX2 = sgCD1*sgCOne*step;
1858 X[0] = sgCX2.Re()+sgCX1.Re();
1859 X[1] = sgCX2.Im()+sgCX1.Im();
1862 sgCD2/= TComplex::Abs(sgCD2);
1869 double TCircle_::Move(
double step)
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;
1878 void TCircle_::MakeMtx(
double S,
double F[3][3])
1881 memset(F[0],0,
sizeof(F[0][0])*3*3);
1882 F[kH][kH] = sgCf1.Re()+1.;
1883 double dSdH = sgCf1.Im();
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();
1891 F[kA][kH] = -dSdH*fRho;
1892 F[kA][kA] = 1-dSdA*fRho;
1893 F[kA][kC] = S+dSdC*fRho;
1897 void TCircle_::MoveErrs(
double s)
1904 void TCircle_::Rot(
double angle)
1906 Rot(cos(angle),sin(angle));
1909 void TCircle_::Rot(
double cosa,
double sina)
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();
1918 void TCircle_::Backward()
1920 fRho=-fRho;fD[0]=-fD[0];fD[1]=-fD[1];
1921 if(fEmx) fEmx->Backward();
1925 void TCircle_::Test2()
1945 void TCircle_::Test3()
1978 void TCircle_::TestMtx()
1980 double Dir[8],X[8]={0},Rho[2],step,F[3][3],Del[3],Dif[3]={0};
1983 for (
int iR = 1010;iR>-1010;iR-=20) {
1985 int iAlf = 360*gRandom->Rndm();
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);
1993 step = iStep/180.*M_PI*abs(iR);
1994 tc.Eval(step,X+2,Dir+2);
1997 for (
int iHAR=0;iHAR<3;iHAR++) {
1998 double minFak = 1e-4;
1999 for (
double fak=1;fak>minFak;fak/=2) {
2001 memcpy(X +4,X ,
sizeof(X[0] )*2);
2002 memcpy(Dir+4,Dir,
sizeof(Dir[0])*2);
2006 X[4+0] = X[0]-Dir[1]*Del[0]*fak;
2007 X[4+1] = X[1]+Dir[0]*Del[0]*fak;
2011 Dir[4+0] = cos(iAlf/180.*M_PI+Del[1]*fak);
2012 Dir[4+1] = sin(iAlf/180.*M_PI+Del[1]*fak);
2016 Rho[1] = Rho[0]+Del[2]*fak;
2022 double myStep = tcc.Path(X+2);
2024 tcc.Eval(0,X+6,Dir+6);
2026 TCL::vsub(X+6,X+2,dX,2);
2028 myStep = -TCL::vdot(dX,Dir+2,2)/TCL::vdot(Dir+6,Dir+2,2);
2029 tcc.Eval(myStep,X+6,Dir+6);
2031 for (
int jHAR=0;jHAR<2; jHAR++) {
2034 Dif[0] = (X[6+0]-X[2+0])*(-Dir[2+1])
2035 + (X[6+1]-X[2+1])*( Dir[2+0]);
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;
2045 double mat = F[jHAR][iHAR];
2050 double est = Dif[jHAR]/(Del[iHAR]*fak);
2051 double min = Del[jHAR]/Del[iHAR]*0.001;
2055 if (fabs(est) < 1e-4) est = 0;
2056 if (fabs(mat) < 1e-4) mat = 0;
2059 double eps =(fabs(est-mat)*2)
2060 /(fabs(est)+fabs(mat)+min);
2062 if (eps>maxEps) maxEps=eps;
2065 if (fak > minFak*2)
continue;
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,
2073 printf(
"TestMtx: %d errors maxEps=%g\n",nErr,maxEps);
2080 TCircleFitter_::TCircleFitter_()
2086 void TCircleFitter_::Clear(
const char*)
2089 memset(fBeg,0,fEnd-fBeg+1);
2098 const double* TCircleFitter_::GetX(
int i)
const
2100 return &(fAux[i].x);
2103 double* TCircleFitter_::GetX(
int i)
2105 return &(fAux[i].x);
2108 void TCircleFitter_::Add(
double x,
double y,
const double *errs)
2111 int n = fN*TCircleFitterAux_::dSize();
2112 if (fArr.GetSize()<n) {fArr.Set(n*2);fAux=0;}
2113 if (!fAux) fAux = GetAux(0);
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);
2119 void TCircleFitter_::Add(
double x,
double y,
double z)
2122 int n = fN*TCircleFitterAux_::dSize();
2123 if (fArr.GetSize()<n) {fArr.Set(n*2);fAux=0;}
2124 if (!fAux) fAux = GetAux(0);
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;
2130 void TCircleFitter_::AddErr(
const double *errs,
double ezz)
2136 double spur = errs[0]+errs[2];
2138 double *e = aux->exy;
2139 memcpy(e,errs,
sizeof(aux->exy));
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]);
2149 void TCircleFitter_::AddErr(
double errhh,
double ezz)
2159 void TCircleFitter_::AddZ(
double z,
double ez)
2166 double TCircleFitter_::Fit()
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;
2175 if (fNuse < 3)
return 3e33;
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);
2182 fNor[0] = -fSin,fNor[1] = fCos;
2183 const double *exy=0;
2184 for (
int iter=0;iter<2;iter++) {
2186 memset(&fXgravity,0,
sizeof(
double)*(nAVERs+2));
2187 for (
int i=0; i<fN; i++) {
2188 if (aux[i].wt<0)
continue;
2190 if (aux[i].wt >0) kase+=2;
2191 if (aux[i].exy[0]>0) kase+=4;
2193 case 0: wt = 1;
break;
2194 case 2: ;
case 3: wt = aux[i].wt;
break;
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; }
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;
2211 fXgravity += aux[i].x *wt;
2212 fYgravity += aux[i].y *wt;
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;
2228 fXrr += xx*(xx2+yy2) *wt;
2229 fYrr += yy*(xx2+yy2) *wt;
2230 fRrrr += (xx2+yy2)*(xx2+yy2) *wt;
2233 for (
int i=0;i<nAVERs;i++) {dd[i]/=fWtot;}
2236 if (fNuse <= 3 && !fKase) fKase=1;
2237 if (!fKase) fKase =(fYy < fXx *(0.5)*(0.5)/210)? 1:2;
2238 SWIT:
switch(fKase) {
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;
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;
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);
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;
2289 xnom = (g-fG1)*(f-fG1)-h*h;
2292 if (xnom<1e-20) { fKase=1;
goto SWIT;}
2294 fXd = ( p*(g-fG1)-q*h )/xnom;
2295 fYd = (-p*h +q*(f-fG1))/xnom;
2301 fXCenter = fXd*fCos-fYd*fSin + fXgravity;
2302 fYCenter = fXd*fSin+fYd*fCos + fYgravity;
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);
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;
2321 fD[0] = fNy; fD[1] =-fNx;
2329 radiuc2 = fXd*fXd+fYd*fYd;
2330 radius2 = radiuc2+fG1;
2331 fR = ::sqrt(radius2);
2332 fRd = ::sqrt(radiuc2);
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;
2341 fD[0] = fNy; fD[1] =-fNx;
2356 if (fNdf>0) fChi2 *= fWtot/fNdf;
2357 tmp = fD[0]*(aux[0].x-fX[0])+fD[1]*(aux[0].y-fX[1]);
2360 if (tmp>0) {fD[0]*=-1;fD[1]*=-1;fRho*=-1;fBack=1;}
2364 void TCircleFitter_::MakeErrs()
2367 double F[3][3]; memset(F[0],0,
sizeof(F));
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;
2383 F[0][0] = sgB*fA*fC/(corrRB*fCorrB*fCorrR);
2384 F[0][1] = 0.5*sgB*fC*fC/(corrRB*corrRB*fCorrR);
2385 F[0][2] = 0.5*sgB*fC*fB/(corrRB*corrRB*fCorrR)
2387 F[1][0] = -1/(fCorrB*fCorrB);
2388 F[2][0] = - sgB*fA*fB/(corrR3);
2389 F[2][1] = -0.5*sgB*fC*fB/(corrR3)+sgB/fCorrR;
2390 F[2][2] = -0.5*sgB*fB*fB/(corrR3);
2391 myFact = (fCorrR*fCorrR);
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; }}
2403 double dRho = -fH/(fRd*fR);
2407 F[0][2] = -0.5*aRho;
2408 F[1][0] = -fNy*aRho;
2411 F[2][0] = -fXd*aRho3;
2412 F[2][1] = -fYd*aRho3;
2413 F[2][2] = -0.5*aRho3;
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);
2425 fX[0] = fXCenter -fNx*fR;
2426 fX[1] = fYCenter -fNy*fR;
2431 F[0][0] = ( fNx*fCos+fNy*fSin) -fXd*aRho;
2432 F[0][1] = (-fNx*fSin+fNy*fCos) -fYd*aRho;
2433 F[0][2] = -0.5*aRho;
2434 F[1][0] = (-fNy*fCos + fNx*fSin)*aRho;
2435 F[1][1] = ( fNy*fSin + fNx*fCos)*aRho;
2437 F[2][0] = -fXd*aRho3;
2438 F[2][1] = -fYd*aRho3;
2439 F[2][2] = -0.5*aRho3;
2447 TCL::vscale(fCov,myFact/fWtot,fCov,6);
2449 if (fBack) {fEmx->mHA*=-1;fEmx->mAC*=-1;}
2452 double TCircleFitter_::EvalChi2()
2454 if (!fNuse)
return 0;
2456 double sum = 0,wtot=0,wt;
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));
2464 sum+= (pow(p[0]-aux[i].x,2)+pow(p[1]-aux[i].y,2))*wt;
2467 if (fNdf) sum /= fNdf;
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)};
2490 dlt[0] = vals[0]-fX[0]; dlt[1] = vals[1]-fX[1];
2491 adj[0] = -dlt[0]*fD[1]+dlt[1]*fD[0];
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;
2501 adj[2] = vals[4]-fRho;
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]; } }
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;
2517 if (!(sel[i]&sel[j]))
continue;
2518 g[li+j] = (*fEmx)[li+j];
2525 for (
int i=0,li=0;i< 3;li+=++i) {
if (sel[i]) (*fEmx)[li+i]=0;}
2527 fX[0] += -adj[0]*fD[1];
2528 fX[1] += adj[0]*fD[0];
2533 double S = sin(adj[1]);
2534 double C = cos(adj[1]);
2536 fD[0] = d0*C-fD[1]*S;
2537 fD[1] = d0*S+fD[1]*C;
2541 fChi2 += (addXi2-fChi2*nFix)/fNdf;
2545 void TCircleFitter_::Skip(
int idx)
2547 fAux[idx].exy[0] = -1;
2551 void TCircleFitter_::SetNdf(
int ndf)
2553 fChi2*=fNdf;
if (ndf) fChi2/=ndf; fNdf=ndf;
2556 void TCircleFitter_::Print(
const char* txt)
const
2559 printf(
"TCircleFitter_::NPoints = %d method=%d",fN,fKase);
2560 if (fChi2) printf(
" Chi2 = %g",fChi2);
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){};
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);
2573 printf(
" \tExy: %g %g %g \tEz:%g "
2574 ,aux[ip].exy[0],aux[ip].exy[1],aux[ip].exy[2],aux[ip].ezz);
2579 const double *xy = GetX(0);
2580 double ds=circ.Path(xy);
2583 for (
int i=0;i<fN;i++) {
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"
2592 ,xy[0],circ.Pos()[0]
2593 ,xy[1],circ.Pos()[1]
2594 ,circ.Dir()[0],circ.Dir()[1]);
2599 void TCircleFitter_::Test(
int iTest)
2602 int myKase = (iTest/1 )%10;
2603 int negRad = (iTest/10 )%10;
2604 int bakPts = (iTest/100 )%10;
2605 int noShft = (iTest/1000)%10;
2609 double e[4],x[5],dir[2];
2611 aShift[0]=-acos(0.25);
2612 aShift[1]=-acos(0.50);
2614 aShift[3]= acos(0.25);
2615 aShift[5]= acos(0.50);
2616 memset(aShift,0,
sizeof(aShift));
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*);
2628 if(!myCanvas[0]) myCanvas[0]=
new TCanvas(
"TCircleFitter_Test0",
"",600,800);
2629 myCanvas[0]->Clear();
2630 myCanvas[0]->Divide(1,nPads);
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();
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);
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();
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);
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();
2663 static unsigned int seed=0;
2666 for (
int ir = 50; ir <= 50; ir +=5) {
2668 double len = 0.3*aR;
2669 for (
double ang0 = 0; ang0 <= 0; ang0+=0.05) {
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);
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};
2681 for (
int iter=0;iter<2;iter++) {
2682 static const int nEv = 100000;
2684 for (
int ev=0;ev<nEv;ev++) {
2687 for (
int is=0;is<nPts;is++) {
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];
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);
2699 x[0] = myX[0] + (R)*(S-S0);
2700 x[1] = myX[1] - (R)*(C-C0);
2704 helx.Add (x[0],x[1]);
2705 helx.AddErr (RERR*RERR);
2707 helx.SetCase(myKase);
2708 double Xi2 = helx.Fit();
2709 double Xj2 = helx.EvalChi2();
2710 assert(fabs(Xi2-Xj2) < 1e-2*(Xi2+Xj2+0.01));
2712 assert (!myKase || helx.GetCase()==myKase);
2716 if ((isgn=helx.Emx()->Sign())<0) {
2717 ::Warning(
"Test1",
"Negative errmtx %d",isgn);
continue;}
2719 if (helx.Rho()*idex.Rho() < 0) idex.Backward();
2721 double myShift = (aR*M_PI/180)*360*gRandom->Rndm();
2722 if (noShft) myShift=0;
2725 if ((isgn=helx.Emx()->Sign())<0) {
2726 ::Warning(
"Test2",
"Negative errmtx %d",isgn);
continue;}
2727 double s = idex.Path(helx.Pos());
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();
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];
2748 dd[3] = dd[0]/sqrt(corr[0]);
2749 dd[4] = dd[1]/sqrt(corr[2]);
2750 dd[5] = dd[2]/sqrt(corr[5]);
2752 dd[7] = sqrt(helx.Emx()->mHH)-RERR;
2754 for (
int ih=0;ih<nPads;ih++) { hh[ih]->Fill(dd[ih+3]);}
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]);
2765 for (
int ih=0;ih<cPads;ih++) { hc[ih]->Fill(cc[ih]);}
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]);}
2785 TCL::vscale(corr,1./nEv,corr,6);
2786 TCL::vscale(korr,1./nEv,korr,6);
2788 for (
int i=0,li=0;i< 3;li+=++i) {
2789 dia[i]=sqrt(corr[li+i]);
2791 for (
int j=0;j<=i;j++) {n+=printf(
"%15g",corr[li+j]/(dia[i]*dia[j]));}
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]));}
2804 for (
int i=0;myCanvas[i];i++) {
2805 myCanvas[i]->Modified();myCanvas[i]->Update();}
2807 while(!gSystem->ProcessEvents()){gSystem->Sleep(200);};
2812 void TCircleFitter_::TestCorr(
int kase)
2820 if (!(kase&3 ))kase+=1+2;
2821 if (!(kase&12))kase+=4+8;
2823 double e[4],x[3],ex[3];
2825 aShift[0]=-acos(0.25);
2826 aShift[1]=-acos(0.50);
2828 aShift[3]= acos(0.25);
2829 aShift[5]= acos(0.50);
2830 double RERR = 0.001;
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);
2837 myCanvas->Divide(1,6);
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();
2845 for (
int ir = 50; ir <= 1000; ir +=5) {
2847 double len = 100;
if (len>aR*3) len = aR*3;
2848 for (
double ang0 = -3; ang0 < 3.1; ang0+=0.05) {
2849 for (
int sgn = -1; sgn<=1; sgn+=2) {
2850 if ((sgn>0) && !(kase&4))
continue;
2851 if ((sgn<0) && !(kase&8))
continue;
2853 double dang = len/R/nPts;
2854 double C0 = cos(ang0);
2855 double S0 = sin(ang0);
2857 for (
int is=0;is<nPts;is++) {
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);
2868 x[0] = 100 + (R)*(S-S0);
2869 x[1] = 200 - (R)*(C-C0);
2872 helx.Add (ex[0],ex[1],e);
2875 if (!(helx.GetCase()&kase))
continue;
2879 if (kase&16) iFix +=1;
2880 if (kase&32) iFix +=4;
2883 TCL::ucopy(x,vals,3);
2886 helx.
FixAt(vals,iFix);
2890 double s = helx.Path(x);
2892 assert(fabs(s) < len);
2895 double dx = helx.Pos()[0]-x[0];
2896 double dy = helx.Pos()[1]-x[1];
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);
2911 for (
int ih=0;ih<6;ih++) { hh[ih]->Fill(hf[ih]);}
2915 myCanvas->Modified();
2917 while(!gSystem->ProcessEvents()){gSystem->Sleep(200);};
2921 void TCircle_::Show(
int nPts,
const double *Pts,
int pstep)
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]; }
2931 if(!myCanvas) myCanvas =
new TCanvas(
"TCircle_Show",
"",600,800);
2933 delete ptGraph;
delete ciGraph;
2935 ptGraph =
new TGraph(nPts , x, y);
2936 ptGraph->SetMarkerColor(kRed);
2937 ptGraph->Draw(
"A*");
2943 double s = tc.Path(xy);
2948 if (s<0) { tc.Backward(); s = tc.Path(xy);}
2950 for (
int i=0;i<100;i++) {x[i]=tc.Pos()[0];y[i]=tc.Pos()[1];tc.Move(ds);}
2952 ciGraph =
new TGraph(100 , x, y);
2953 ciGraph->Draw(
"Same CP");
2954 myCanvas->Modified();
2956 while(!gSystem->ProcessEvents()){gSystem->Sleep(200);};
2960 THelixFitter_::THelixFitter_():fPoli1Fitter(1)
2966 THelixFitter_::~THelixFitter_()
2969 void THelixFitter_::Clear(
const char*)
2971 fCircleFitter.Clear();
2972 fPoli1Fitter.Clear();
2973 fPoli1Fitter.SetCoefs(1);
2977 void THelixFitter_::Print(
const char*)
const
2979 THelixTrack_::Print();
2980 fCircleFitter.Print();
2981 fPoli1Fitter.Print();
2984 void THelixFitter_::Add (
double x,
double y,
double z)
2986 fCircleFitter.Add(x,y,z);
2989 void THelixFitter_::AddErr(
const double *err2xy,
double err2z)
2991 fCircleFitter.AddErr(err2xy,err2z);
2994 void THelixFitter_::AddErr(
double errhh,
double err2z)
2996 fCircleFitter.AddErr(errhh,err2z);
2999 double THelixFitter_::Fit()
3003 double Xi2xy = fCircleFitter.Fit();
3004 if (Xi2xy>1e11)
return Xi2xy;
3005 int ndfXY = fCircleFitter.Ndf();
3008 xy = &(myAux[nDat-1].x);
3010 double s1 = circ.Path(xy);
3014 double s = circ.Path(xy);
3016 double tanDip = (z1-z0)/(s1-s);
3020 for (
int iDat=0;iDat<nDat;iDat++) {
3023 double ds = circ.Path(xy,aux->exy);
3024 circ.Move(ds); s+=ds;
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);
3034 fPoli1Fitter.Add(s,aux->z,aux->ezz+corErr);
3036 double Xi2z = fPoli1Fitter.Fit();
3038 int ndfSz = fPoli1Fitter.Ndf();
3040 int ndf = ndfSz+ndfXY;
3041 fChi2 = Xi2xy*ndfXY+Xi2z*ndfSz;
3042 if (ndf) fChi2/=ndf;
3047 double THelixFitter_::FixAt(
const double val[5],
int flag)
3050 memcpy(xx,fX,
sizeof(xx));
3051 int move = (flag&1);
3053 s = fCircleFitter.Path(val);
3054 fCircleFitter.Move(s);
3055 fPoli1Fitter.Move(s);
3057 double Xi2c = fCircleFitter.FixAt(val,flag);
3058 if (flag&1) fPoli1Fitter.FixAt(0.,val[2]);
3061 s = fCircleFitter.Path(xx);
3062 fCircleFitter.Move(s);
3063 fPoli1Fitter.Move(s);
3067 double Xi2z = fPoli1Fitter.Chi2();
3068 int ndfc = fCircleFitter.Ndf();
3069 int ndfz = fPoli1Fitter.Ndf();
3071 int ndf = ndfc+ndfz;
3072 fChi2 = Xi2c*ndfc+Xi2z*ndfz;
3073 if (ndf) fChi2/=ndf;
3077 void THelixFitter_::Skip(
int idx)
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;
3088 void THelixFitter_::Update(
int kase)
3091 const double *pol = fPoli1Fitter.Coe();
3092 fCosL = 1./sqrt(pol[1]*pol[1]+1);
3093 double *haslet = fCircleFitter.Pos();
3097 fP[0] = haslet[2]*fCosL;
3098 fP[1] = haslet[3]*fCosL;
3099 fP[2] = pol[1]*fCosL;
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);
3111 void THelixFitter_::MakeErrs()
3113 fCircleFitter.MakeErrs();
3114 fPoli1Fitter.MakeErrs();
3118 double THelixFitter_::EvalChi2()
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);
3127 void THelixFitter_::Test(
int kase)
3137 if (!(kase&3 ))kase+=1+2;
3138 if (!(kase&12))kase+=4+8;
3140 enum {nPts=5,nHH=8};
3141 double e[4],x[10],xe[10];
3143 aShift[0]=-acos(0.25);
3144 aShift[1]=-acos(0.50);
3146 aShift[3]= acos(0.25);
3147 aShift[5]= acos(0.50);
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);
3158 for (
int i=0;i<nHH;i++) {
3159 double low = (i>=5)? 0:-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();
3166 static TH1F *h2h[4]={0,0,0,0};
3167 static const char *h2Nams[]={
"targYY",
"targZZ",
"targYZ",
"calcYZ",0};
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();
3179 static TH1F *h3h[4]={0,0,0,0};
3180 static const char *h3Nams[]={
"dcaXY",
"dcaXYNor",
"dcaZ",
"dcaZNor",0};
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();
3192 double spotSurf[4]= {-100,1,0,0};
3193 double spotAxis[3][3]= {{0,1,0},{0,0,1},{1,0,0}};
3197 for (
double idip=-1;idip<=1;idip+=0.2){
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) {
3205 double len = 100;
if (len>aR*3) len = aR*3;
3206 for (
double ang00 = -3; ang00 < 3.1; ang00+=0.2) {
3207 double ang0 = ang00;
3209 for (
int sgn = -1; sgn<=1; sgn+=2) {
3210 if(sgn>0 && !(kase&4))
continue;
3211 if(sgn<0 && !(kase&8))
continue;
3214 double dang = len/R/nPts;
3215 double C0 = cos(ang0);
3216 double S0 = sin(ang0);
3219 double trakPars[7]={100,200,300,C0*cosDip,S0*cosDip,sinDip,1/R};
3222 for (
int is=0;is<nPts;is++) {
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);
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);
3241 helx.Add (xe[0],xe[1],xe[2]);
3242 helx.AddErr(e,e[3]);
3244 double Xi2 =helx.Fit();
3245 if(!(kase&helx.GetCase()))
continue;
3248 if ((isgn=helx.Emx()->Sign())<0) {
3249 ::Warning(
"Test1",
"Negative errmtx %d",isgn);
continue;}
3251 if (kase&16) Xi2=helx.FixAt(x);
3256 TCL::ucopy(x,vals,3);vals[3]=0;vals[4]=1./R;
3257 Xi2=helx.FixAt(vals,4);
3259 if (kase&128) helx.Show();
3260 double Xi2E =helx.EvalChi2();
3262 trak.
Move(0.3*len/cosDip);
3263 memcpy(x,trak.Pos(),
sizeof(x));
3264 ang0 = atan2(trak.Dir()[1],trak.Dir()[0]);
3266 double s = helx.
Path(x);
3270 double pos[3],dir[3],rho;
3272 if ((isgn=helx.Emx()->Sign())<0) {
3273 ::Warning(
"Test2",
"Negative errmtx %d",isgn);
continue;}
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);
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);
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));
3300 for (
int ih=0;ih<nHH;ih++) { hh[ih]->Fill(hf[ih]);}
3303 double xIde[3],pIde[3],xFit[3],pFit[3],eSpot[3],hfil,sIde,sFit;
3308 { spotSurf[0] = -x[0]; closePoint=2006;}
3309 sIde = trak.
Path(200.,spotSurf,4, xIde,pIde,closePoint);
if (sIde){};
3311 if (fabs(spotSurf[0]+TCL::vdot(xIde,spotSurf+1,3))>0.001) {
3312 printf(
"***Wrong point found**\n");
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;
3322 hfil = (xFit[1]-xIde[1]); hfil/= sqrt(eSpot[0]);
3324 hfil = (xFit[2]-xIde[2]); hfil/= sqrt(eSpot[2]);
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]));
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]));
3347 for (
int ih=0;myCanvas[ih];ih++) {
3348 myCanvas[ih]->Modified();
3349 myCanvas[ih]->Update();
3351 while(!gSystem->ProcessEvents()){gSystem->Sleep(200);};
3354 void THelixFitter_::Show()
const
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];
3362 if (nPts>100) nPts=100;
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);
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];
3377 if(!myCanvas) myCanvas =
new TCanvas(
"THelixFitter_Show",
"",600,800);
3379 myCanvas->Divide(1,2);
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*");
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");
3395 myCanvas->Modified();
3397 while(!gSystem->ProcessEvents()){gSystem->Sleep(200);};
3401 double TCircleFitter_::f()
3403 return 4*((fG1-fRr)/2)*fR*fR;
3406 double TCircleFitter_::F()
3411 double TCircleFitter_::df(
int 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);
3423 double TCircleFitter_::d2f(
int i,
int j)
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;
3436 default: printf (
"Kase=%d\n",ij); assert(0);
3442 double TCircleFitter_::Rho2 () {
return fRho*fRho;}
3445 double TCircleFitter_::dRho2(
int i)
3447 double ans =fRho*fRho;
3450 case 0:
return 2*ans*fXd;
3451 case 1:
return 2*ans*fYd;
3458 double TCircleFitter_::d2Rho2(
int i,
int j)
3463 if (j>i) {
int jj = j; j = i; i = jj;}
3465 double rho2 = fRho*fRho,rho4 = rho2*rho2, rho6 = rho4*rho2;
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);
3477 double TCircleFitter_::dF(
int i)
3481 double ans = 1./4*(df(i)*Rho2() + f()*dRho2(i));
3485 double TCircleFitter_::d2F(
int i,
int j)
3489 double ans = 1./4*(d2f(i,j)*Rho2() +df(j)*dRho2(i)
3490 +df (i) *dRho2(j)+f() *d2Rho2(i,j));
static float * traat(const float *a, float *s, int m, int n)
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)
static float * trsa(const float *s, const float *a, float *b, int m, int n)
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)
double Move(double step)
Move along helix.
static float * trasat(const float *a, const float *s, float *r, int m, int n)
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)
double Dca(const double point[3], double *dcaErr=0) const
DCA to given space point (with error matrix)