9 #if ROOT_VERSION_CODE < 331013
17 #include "TRandomVector.h"
21 #include "THelixTrack.h"
22 #include "StMatrixD.hh"
27 static const double kMinErr = 1e-4, kBigErr=10;
28 static double *myQQQ = 0;
29 static double EmxSign(
int n,
const double *e);
32 const TComplex Im(0,1);
34 static void eigen2(
double G[3],
double lam[2],
double eig[2])
36 double spur = G[0]+G[2];
37 double det = G[0]*G[2]-G[1]*G[1];
38 double dis = spur*spur-4*det;
42 lam[0] = 0.5*(spur+dis);
43 lam[1] = 0.5*(spur-dis);
48 if (fabs(eig[1])>fabs(eig[0])) {eig[0]= -2*G[1];}
49 else {eig[1]= -2*G[1];}
50 double nor = sqrt(eig[0]*eig[0]+eig[1]*eig[1]);
52 if(eig[0]<0) nor = -nor;
53 eig[0]/=nor;eig[1]/=nor;}
61 inline static double dot(
const TComplex &a,
const TComplex &b)
62 {
return a.Re()*b.Re()+a.Im()*b.Im();}
64 inline static TComplex expOne(
const TComplex &x)
66 double a = TComplex::Abs(x);
68 return 1.+x*((1/2.) + x*((1/6.)+ x*(1/24.)));
70 return (TComplex::Exp(x)-1.)/x;
74 inline static TComplex expOneD(
const TComplex &x)
76 double a = TComplex::Abs(x);
78 return (1/2. + x*((1/6.)+ x*((1/24.)+x*(1/120.))));
80 return (TComplex::Exp(x)-1.-x)/(x*x);
86 void TCEmx_t::Set(
const double *err)
87 {
if (err) {memcpy(
this,err,
sizeof(*
this));}
else {Clear();}}
90 void TCEmx_t::Move(
const double F[3][3])
94 memcpy(oErr,Arr(),
sizeof(oErr));
98 void TCEmx_t::Backward()
103 double TCEmx_t::Sign()
const
105 const double *E = &mHH;
107 for (
int i=0,li=0;i<3;li+=++i) {
109 if (dia[i]<0)
return -(i+1)*11;
110 for (
int j=0;j<=i;j++) {
111 double dis = dia[i]*dia[j]-E[li+j]*E[li+j];
112 if (dis<0)
return -(i+1+10*(j+1));
118 double THEmx_t::MaxCorr()
const
120 if (mHH+mZZ<=0)
return 0;
121 double dia[5],maxCorr=0;
const double *e=&mHH;
123 for (
int i=0,li=0;i< 5;li+=++i) {
125 for (
int j=0;j<i;j++) {
126 double corr = (e[li+j]/dia[i])*(e[li+j]/dia[j]);
127 if (maxCorr<corr) maxCorr=corr;
129 return sqrt(maxCorr);
133 void THEmx_t::Set(
const double *errxy,
const double *errz)
136 memcpy(&mHH,errxy,
sizeof(mHH)*6);
137 mZZ = errz[0]; mZL =errz[1]; mLL =errz[2];
140 void THEmx_t::Set(
const double *err)
141 {
if (err) {memcpy(
this,err,
sizeof(*
this));}
else {Clear();}}
143 void THEmx_t::Backward()
145 mHA*=-1; mAC*=-1; mHZ*=-1; mCZ*=-1; mAL*=-1; mZL*=-1;
148 void THEmx_t::Move(
const double F[5][5])
152 memcpy(oErr,Arr(),
sizeof(oErr));
156 void THEmx_t::Print(
const char *tit)
const
158 static const char *N=
"HACZL";
160 printf(
"THEmx_t::::Print(%s) ==\n",tit);
161 const double *e = &mHH;
162 for (
int i=0,li=0;i< 5;li+=++i) {
164 for (
int j=0;j<=i;j++) {
165 printf(
"%g\t",e[li+j]);}
170 double THEmx_t::Sign()
const
172 const double *E = &mHH;
174 for (
int i=0,li=0;i<5;li+=++i) {
176 if (dia[i]<0)
return -(i+1)*11;
177 for (
int j=0;j<=i;j++) {
178 double dis = dia[i]*dia[j]-E[li+j]*E[li+j];
179 if (dis<0)
return -(i+1+10*(j+1));
186 const double Zero = 1.e-6;
187 static TComplex sgCX1,sgCX2,sgCD1,sgCD2,sgImTet,sgCOne,sgCf1;
188 static int SqEqu(
double *,
double *);
191 static int myEqu(
double *s,
int na,
double *b,
int nb)
194 double *m = &mtx(1,1);
198 if (ierr)
return ierr;
199 for (
int ib=0;ib<nb;ib++) {
200 TCL::vmatl(m,b+ib*na,s,na,na);
201 memcpy(b+ib*na,s,na*
sizeof(*b));
207 static void Eigen2(
const double err[3],
double lam[2],
double eig[2][2])
210 double spur = err[0]+err[2];
211 double det = err[0]*err[2]-err[1]*err[1];
212 double dis = spur*spur-4*det;
215 lam[0] = 0.5*(spur+dis);
216 lam[1] = 0.5*(spur-dis);
217 eig[0][0] = 1; eig[0][1]=0;
219 if (fabs(err[0]-lam[0])>fabs(err[2]-lam[0])) {
220 eig[0][1] = 1; eig[0][0]= -err[1]/(err[0]-lam[0]);
222 eig[0][0] = 1; eig[0][1]= -err[1]/(err[2]-lam[0]);
224 double tmp = sqrt(eig[0][0]*eig[0][0]+eig[0][1]*eig[0][1]);
225 eig[0][0]/=tmp; eig[0][1]/=tmp;
227 eig[1][0]=-eig[0][1]; eig[1][1]= eig[0][0];
230 static TComplex MyFactor(
double rho,
double drho,
double s)
240 arr[0] = 1.; arr[1] = 0.;
243 for (
int j=2;1;j++) {
244 arr[2] = -TComplex(0,1)*rho*(arr[1]+drho*arr[0])/
double(j);
245 ss *=s; add = ss*arr[2]; Sum += add;
246 if (1e-12*Sum.Rho2() > add.Rho2())
break;
248 arr[0]=arr[1]; arr[1]=arr[2];
282 Set(xyz,dir,rho,drho);
288 memcpy(fBeg,from.fBeg,fEnd-fBeg);
290 if (from.fEmx) SetEmx(from.fEmx->Arr());
303 Set(fr->fX,fr->fP,fr->fRho);
306 THelixTrack::~THelixTrack()
307 {
delete fEmx;fEmx=0;}
309 THelixTrack::THelixTrack()
311 memset(fBeg,0,fEnd-fBeg);
314 void THelixTrack::Set(
const double *xyz,
const double *dir,
double rho
317 fX[0] = xyz[0]; fX[1] = xyz[1]; fX[2] = xyz[2];
318 fP[0] = dir[0]; fP[1] = dir[1]; fP[2] = dir[2];
319 fRho = rho; fDRho=drho;
323 void THelixTrack::SetEmx(
const double* err2xy,
const double* err2sz)
326 fEmx->Set(err2xy,err2sz);
329 void THelixTrack::SetEmx(
const double* err)
335 void THelixTrack::StiEmx(
double err[21])
const
342 ,kTX,kTY,kTZ,kTE,kTP,kTT
345 memset(err,0,
sizeof(err[0])*kLN);
346 double cosCA = fP[0]/fCosL;
347 err[kYY] = fEmx->mHH/(cosCA*cosCA);
348 err[kZY] = fEmx->mHZ/(cosCA);
349 err[kZZ] = fEmx->mZZ;
350 err[kEY] = fEmx->mHA/cosCA;
351 err[kEZ] = fEmx->mAZ;
352 err[kEE] = fEmx->mAA;
353 err[kPY] = fEmx->mHC/cosCA;
354 err[kPZ] = fEmx->mCZ;
355 err[kPE] = fEmx->mAC;
356 err[kPP] = fEmx->mCC;
357 err[kTY] = fEmx->mHL/(cosCA*fCosL*fCosL);
358 err[kTZ] = fEmx->mZL/( fCosL*fCosL);
359 err[kTE] = fEmx->mAL/( fCosL*fCosL);
360 err[kTP] = fEmx->mCL/( fCosL*fCosL);
361 err[kTT] = fEmx->mLL/( fCosL*fCosL*fCosL*fCosL);
364 void THelixTrack::Set(
double rho,
double drho)
366 fRho = rho; fDRho=drho;
373 for (
int i=0;i<3;i++) { d[i]=-fP[i];}
374 Set(fX,d,-fRho,-fDRho);
375 if(fEmx) fEmx->Backward();
386 double my[3][3] = {{-fP[1]/fCosL, 0,fP[0]}
387 ,{ fP[0]/fCosL, 0,fP[1]}
390 double T[3][3],tmp[3][3],g[6],t[2][2];
391 TCL::mxmpy (axis[0],my[0],T[0],3,3,3);
394 if (fabs(g[0]-1)+fabs(g[1])+fabs(g[2]-1)
395 +fabs(g[3])+fabs(g[4])+fabs(g[5]-1)>1e-10) {
397 memcpy(tmp[0],T[0],
sizeof(T));
400 TCL::vlinco(T[0],1.,T[2],-T[0][2]/T[2][2],t[0],2);
401 TCL::vlinco(T[1],1.,T[2],-T[1][2]/T[2][2],t[1],2);
402 double myerr[3]={fEmx->mHH,fEmx->mHZ,fEmx->mZZ};
407 void THelixTrack::Build()
412 tmp = fP[0]*fP[0]+ fP[1]*fP[1]+ fP[2]*fP[2];
413 if (fabs(tmp-1.) > 1.e-12) {
414 tmp = ::sqrt(tmp); fP[0] /=tmp; fP[1] /=tmp; fP[2] /=tmp; }
416 fCosL = ::sqrt(fP[0]*fP[0]+fP[1]*fP[1]);
419 void THelixTrack::MakeMtx(
double step,
double F[5][5])
422 enum {kH=0,kA,kC,kZ,kL};
424 double S = step*fCosL;
425 memset(F[0],0,
sizeof(F[0][0])*5*5);
427 F[kH][kH] = sgCf1.Re()+1.;
428 double dSdH = sgCf1.Im();
430 F[kH][kA] = S*sgCOne.Re();
431 double dSdA = S*sgCOne.Im();
433 TComplex llCOneD = S*S*expOneD(-sgImTet);
434 F[kH][kC] = llCOneD.Re();
435 double dSdC = llCOneD.Im();
437 F[kA][kH] = -dSdH*fRho;
438 F[kA][kA] = 1-dSdA*fRho;
439 F[kA][kC] = S+dSdC*fRho;
442 double tanL = fP[2]/fCosL;
444 F[kZ][kH] = -dSdH*tanL;
445 F[kZ][kA] = -dSdA*tanL;
446 F[kZ][kC] = dSdC*tanL;
448 F[kZ][kL] = S/(fCosL*fCosL);
455 Eval(step,fX,fP,fRho);
456 if (fEmx && fEmx->mHH>0 && step) {
465 double xyz[3],dir[3],rho;
466 Eval(step,xyz,dir,rho);
467 Set(xyz,dir,rho,fDRho);
469 if (fEmx && fEmx->mHH>0 && step) fEmx->Move(F);
474 double THelixTrack::Step(
double stmax,
const double *surf,
int nsurf,
475 double *xyz,
double *dir,
int nearest)
const
478 double s[10]={0,0,0,0,0,0,0,0,0,0},tmp=0;
479 memcpy(s,surf,nsurf*
sizeof(surf[0]));
481 for(i=1;i<nsurf;i++) if (fabs(s[i])>tmp) tmp = fabs(s[i]);
482 if(fabs(tmp-1.)>0.1) {
for(i=0;i<nsurf;i++) s[i]/=tmp;}
483 double stmin = (nearest)? -stmax:0;
487 return Step(stmin,stmax,s,nsurf,xyz,dir,nearest);
492 double THelixTrack::Step(
double stmin,
double stmax,
const double *s,
int nsurf,
493 double *xyz,
double *dir,
int nearest)
const
496 double poly[4][3],tri[3],sol[2],cos1t,f1,f2,step,ss;
497 const double *sp[4][4] = {{s+0,s+1,s+2,s+3}, {s+1,s+4,s+7,s+9},
498 {s+2,s+7,s+5,s+8}, {s+3,s+9,s+8,s+6}};
500 double myMax = 1./(fabs(fRho*fCosL)+1.e-10);
502 cos1t = 0.5*fRho*fCosL;
505 double hXp[3]={-th.fP[1],th.fP[0],0};
506 poly[0][0]=1.;poly[0][1]=0.;poly[0][2]=0.;
507 tri[0]=tri[1]=tri[2]=0;
508 for(ix=1;ix<4;ix++) {
509 poly[ix][0] =th.fX [ix-1];
510 poly[ix][1] =th.fP [ix-1];
511 poly[ix][2] =hXp[ix-1]*cos1t;
514 nx = (nsurf<=4) ? 1:4;
515 for(ix=0;ix<nx;ix++) {
516 for(jx=ix;jx<4;jx++) {
517 ss = *sp[ix][jx];
if(!ss)
continue;
518 for (ip=0;ip<3;ip++) {
519 f1 = poly[ix][ip];
if(!f1)
continue;
521 for (jp=0;jp+ip<3;jp++) {
522 f2 = poly[jx][jp];
if(!f2)
continue;
526 int nsol = SqEqu(tri,sol);
528 if (nsol<0)
return step;
530 if (nearest && nsol>1) {
531 if(fabs(sol[0])>fabs(sol[1])) sol[0]=sol[1];
534 if (nsol) step = sol[0];
535 if (step < stmin && nsol > 1) step = sol[1];
536 if (step < stmin || step > stmax) {
538 if (step>0) {step = stmax; stmin+=myMax/2;}
539 else {step = stmin; stmax-=myMax/2;}}
541 if (!nsol && fabs(step) < 0.1*myMax)
return 1.e+12;
542 if (fabs(step)>myMax) {step = (step<0)? -myMax:myMax; nsol=0;}
547 ss = s[0]+s[1]*x[0]+s[2]*x[1]+s[3]*x[2];
548 if (nsurf > 4) ss += s[4]*x[0]*x[0]+s[5]*x[1]*x[1]+s[6]*x[2]*x[2];
549 if (nsurf > 7) ss += s[7]*x[0]*x[1]+s[8]*x[1]*x[2]+s[9]*x[2]*x[0];
550 if (fabs(ss)<1.e-7) {
551 if (xyz) memcpy(xyz,x,
sizeof(*xyz)*3);
552 if (dir) memcpy(dir,d,
sizeof(*dir)*3);
556 stmax -=step; stmin -=step;
557 if (stmin>=stmax)
return 1.e+12;
565 double THelixTrack::StepHZ(
const double *su,
int nsurf,
566 double *xyz,
double *dir,
int nearest)
const
568 double tri[3] = {0,0,0};
569 double f0,fc,fs,R,tet,tet0,tet1,tet2,costet,su45=0,fcs;
574 f0 = fX[0] - fP[1]*R;
578 tri[0] = su[0] + su[1]*f0;
582 su45 = 0.5*(su[4]+su[5]);
584 tri[0] += su45*f0*f0 + su45*fcs;
585 tri[1] += su45*2*f0*fc;
586 tri[2] += su45*2*f0*fs;
589 f0 = fX[1] + fP[0]*R;
598 tri[1] += su45*2*f0*fc;
599 tri[2] += su45*2*f0*fs;
601 costet = -tri[0]/::sqrt(tri[1]*tri[1]+tri[2]*tri[2]);
602 if(fabs(costet)>1.)
return 1.e+12;
603 tet0 = atan2(tri[2],tri[1]);
608 if (tet1 > 2*M_PI) tet1 -= 2*M_PI;
609 if (tet2 > 2*M_PI) tet2 -= 2*M_PI;
611 if (fabs(tet1)>fabs(tet1-2*M_PI)) tet1 -=2*M_PI;
612 if (fabs(tet1)>fabs(tet1+2*M_PI)) tet1 +=2*M_PI;
613 if (fabs(tet2)>fabs(tet2-2*M_PI)) tet2 -=2*M_PI;
614 if (fabs(tet2)>fabs(tet2+2*M_PI)) tet2 +=2*M_PI;
615 if (fabs(tet1)>fabs(tet2) ) tet1 =tet2;
616 return Step(tet1*R,xyz,dir);
619 if (s1<=0) s1 += 2*M_PI*fabs(R);
621 if (s2<=0) s2 += 2*M_PI*fabs(R);
623 return Step(s1,xyz,dir);
628 double THelixTrack::Path(
const THelixTrack &th,
double *path2)
const
630 static const double kMinAng = 0.1,kDeltaL=1e-4;
633 double Rho1=thMe.GetRho()*thMe.GetCos();
634 double Rho2=thHe.GetRho()*thHe.GetCos();
636 for (
int ix=0;ix<3;ix++)
637 {
if (fabs(thMe.Pos()[ix]-thHe.Pos()[ix])>100)
return 3e33;}
640 for (
int iter=0;iter<20; iter++) {
641 TVector3 P1(thMe.Pos());
642 TVector3 P2(thHe.Pos());
643 TVector3 D1(thMe.Dir());
644 TVector3 D2(thHe.Dir());
648 double dPDm = dP.Dot(Dm);
649 double dPDp = dP.Dot(Dp);
650 double DDm = Dm.Mag2();
651 double DDp = Dp.Mag2();
652 if (DDm<1e-10)
return 3e33;
653 double t1 = -(dPDm)/DDm;
654 double t2 = -(dPDp)/DDp;
658 if (fabs(s1*Rho1*F) > kMinAng) F = kMinAng/fabs(s1*Rho1);
659 if (fabs(s2*Rho2*F) > kMinAng) F = kMinAng/fabs(s2*Rho2);
660 if (F<1) {s1*=F; s2*=F;}
661 thMe.Move(s1); sMe+=s1;
662 thHe.
Move(s2); sHe+=s2;
664 if (fabs(s1)>kDeltaL)
continue;
665 if (fabs(s2)>kDeltaL)
continue;
668 if (!conv)
return 3e33;
669 if(path2) *path2=sHe;
675 double ss1,ss2,dd,ss1Best,ss2Best,ddBest=1e33;
678 for (
int jk=0;jk<4;jk++) {
680 if (jk&1) th1.Backward();
682 ss1 = th1.Path(th2,&ss2);
683 if (ss1>=1e33)
continue;
684 if (ss2>=1e33)
continue;
687 TCL::vsub(xx,xx+3,xx+6,3);
688 dd = TCL::vdot(xx+6,xx+6,3);
689 if (dd > ddBest)
continue;
690 ddBest = dd; jkBest=jk; ss1Best = ss1; ss2Best = ss2;
691 if (xyz) TCL::ucopy(xx,xyz,6);
693 if (jkBest<0) {
if(s2) *s2=3e33;
return 3e33; }
694 if (jkBest&1) ss1Best = -ss1Best;
695 if (jkBest&2) ss2Best = -ss2Best;
696 if (s2 ) *s2 = ss2Best;
697 if (dst) *dst = ddBest;
701 double THelixTrack::Path(
double x,
double y)
const
705 return ht.Path(ar)/fCosL;
708 double THelixTrack::Step(
const double *point,
double *xyz,
double *dir)
const
711 static int nCount=0; nCount++;
712 TComplex cpnt(point[0]-fX[0],point[1]-fX[1]);
713 TComplex cdir(fP[0],fP[1]); cdir /=TComplex::Abs(cdir);
714 double step[3]={0,0,0};
718 if (fabs(fP[2]) > 0.01){
720 step[1] = (point[2]-fX[2])/fP[2];
726 if (fabs(cpnt.Re()*fRho) < 0.01) {
730 for (
int i=0;i<2;i++) {
731 TComplex ctst = (1.+TComplex(0,1)*rho*cpnt);
732 ctst /=TComplex::Abs(ctst);
733 ctst = TComplex::Log(ctst);
734 step[2]= ctst.Im()/rho;
736 rho = fRho+ 0.5*fDRho*step[2];
743 double p = GetPeriod();
744 int nperd = (int)((step[1]-step[2])/p);
745 if (step[2]+nperd*p>step[1]) nperd--;
746 if (fabs(step[2]-step[1]+(nperd+0)*p)
747 >fabs(step[2]-step[1]+(nperd+1)*p)) nperd++;
752 double ds = step[1]-step[2];
753 if (zStep && fabs(ds)>1.e-5) {
754 double dz = ds*fP[2];
759 double xnear[6],ss=0;
double* pnear=xnear+3;
761 double dstep = 1.e+10,oldStep=dstep,dztep;
762 double lMax = step[0]+0.25*GetPeriod();
763 double lMin = step[0]-0.25*GetPeriod();
766 lMax = (step[1]>step[2])? step[1]:step[2];
767 lMin = (step[1]>step[2])? step[2]:step[1];}
771 lMax-=step[0];lMin-=step[0];
772 local.Step(0.,xnear,pnear);
775 double diff = (icut)? lMax-lMin: fabs(dstep);
777 if (diff < 1.e-6)
break;
778 double tmpxy = fabs(point[0]-xnear[0])+fabs(point[1]-xnear[1]);
779 double tmpz = fabs(point[2]-xnear[2]);
780 if (fabs(fCosL) *diff <tmpxy*1e-6
781 &&fabs(pnear[2])*diff <tmpz *1e-6)
break;
782 if (tmpxy+tmpz < 1.e-6)
break;
785 local.Step(ss,xnear,pnear);
787 for (
int i=0;i<3;i++) {dstep += pnear[i]*(point[i]-xnear[i]);}
789 lMax = ss; dztep = -0.5*(lMax-lMin);
790 if (dstep<dztep || fabs(dstep)>0.7*oldStep) {icut=1;dstep = dztep;}
792 lMin = ss; dztep = 0.5*(lMax-lMin);
793 if (dstep>dztep || fabs(dstep)>0.7*oldStep) {icut=1;dstep = dztep;}
799 if (!iter){ printf(
"*** Problem in THElixTrack::Step(vtx) ***\n");
800 printf(
"double vtx[3]={%g,%g,%g};",point[0],point[1],point[2]);
804 return (xyz) ?
Step(step[0],xyz,dir) : step[0];
809 double x[3],T[3][3],emx[3];
810 double s = Path(point,x,T[2]);
811 for (
int i=0;i<3;i++) {T[0][i]=point[i]-x[i];}
812 double dca = sqrt(T[0][0]*T[0][0]+T[0][1]*T[0][1]+T[0][2]*T[0][2]);
813 if (!dcaErr)
return dca;
815 for (
int i=0;i<3;i++) {T[0][i]/=dca;}
816 T[1][0]=T[0][1]*T[2][2]-T[2][1]*T[0][2];
817 T[1][1]=T[0][2]*T[2][0]-T[2][2]*T[0][0];
818 T[1][2]=T[0][0]*T[2][1]-T[2][0]*T[0][1];
829 double dir[3]={fP[0],fP[1],0};
831 if (fEmx) hlx.SetEmx(fEmx->Arr());
832 double vtx[3]={x,y,fX[2]};
833 return hlx.
Dca(vtx,dcaErr);
839 ,
double &dcaXY,
double &dcaZ,
double dcaEmx[3],
int kind)
const
850 assert(kind==2 || kind==3);
851 if (kind==3) s = Path(point);
852 else s = Path(point[0],point[1]);
856 const double *x=th.Pos();
857 const double *d=th.Dir();
859 for (
int i=0;i<3;i++) {dif[i]=x[i]-point[i];}
860 double nor = th.GetCos();
861 double T[3][3]={{-d[1]/nor, d[0]/nor, 0}
863 ,{ d[0]/nor, d[1]/nor, 0}};
865 dcaXY = T[0][0]*dif[0]+T[0][1]*dif[1];
867 if (!dcaEmx)
return s;
869 dcaEmx[0] = emx->mHH;
872 dcaEmx[2] = emx->mZZ*pow(th.GetCos(),4);
878 double THelixTrack::GetPeriod()
const
880 double per = (fabs(fRho) > 1.e-10) ? fabs(2.*M_PI/fRho):1.e+10;
884 void THelixTrack::Rot(
double angle)
886 Rot(cos(angle),sin(angle));
889 void THelixTrack::Rot(
double cosa,
double sina)
891 TComplex CX(fX[0],fX[1]),CP(fP[0],fP[1]);
892 TComplex A (cosa,sina);
893 CX *=A; fX[0] = CX.Re(); fX[1]=CX.Im();
894 CP *=A; fP[0] = CP.Re(); fP[1]=CP.Im();
897 void THelixTrack::Streamer(TBuffer &){}
899 void THelixTrack::Print(Option_t *)
const
901 printf(
"\n THelixTrack::this = %p\n",(
void*)
this);
902 printf(
" THelixTrack::fX[3] = { %f , %f ,%f }\n",fX[0],fX[1],fX[2]);
903 printf(
" THelixTrack::fP[3] = { %f , %f ,%f }\n",fP[0],fP[1],fP[2]);
904 printf(
" THelixTrack::fRho = %f \n\n",fRho);
906 printf(
"double xyz[3] = {%g,%g,%g};\n" ,fX[0],fX[1],fX[2]);
907 printf(
"double dir[3] = {%g,%g,%g};\n" ,fP[0],fP[1],fP[2]);
908 printf(
"double Rho = %g;\n" ,fRho);
909 printf(
"THelixTrack *ht = new THelixTrack(xyz,dir,Rho);\n");
913 void THelixTrack::TestMtx()
915 enum {kH=0,kA,kC,kZ,kL};
916 const static char* T=
"HACZL";
917 double Dir[4][3],X[4][3]={{0}},Rho[2],step,F[5][5],Del,Dif,Fi[5][5];
920 int iR = 10+ gRandom->Rndm()*100;
921 int iAlf=30+ gRandom->Rndm()*100;
922 int iLam=10+ gRandom->Rndm()*60;
923 step = gRandom->Rndm()*6*iR;
926 double alf = iAlf/180.*M_PI;
927 double lam = iLam/180.*M_PI;
928 Dir[0][0] = cos(lam)*cos(iAlf/180.*M_PI);
929 Dir[0][1] = cos(lam)*sin(iAlf/180.*M_PI);
930 Dir[0][2] = sin(lam);
932 tc.Eval(step,X[1],Dir[1]);
934 memcpy(Fi[0],F[0],
sizeof(F));
936 TMatrixD one = TMatrixD(5,5,F[0])*TMatrixD(5,5,Fi[0]);
939 printf(
"TestMtx: Angle=%d Lam=%d \tRad=%d Step=%d \n",iAlf,iLam,iR,
int(step));
941 for (
int iHAR=0;iHAR<5;iHAR++) {
942 memcpy(X[2] ,X[0] ,
sizeof(X[0][0]) *3);
943 memcpy(Dir[2],Dir[0],
sizeof(Dir[0][0])*3);
949 X[2][0] += -Dir[0][1]*Del/cos(lam);
950 X[2][1] += Dir[0][0]*Del/cos(lam);
955 Dir[2][0] = cos(lam)*cos(alf+Del);
956 Dir[2][1] = cos(lam)*sin(alf+Del);
957 Dir[2][2] = sin(lam);
970 Dir[2][0] = cos(lam+Del)*cos(alf);
971 Dir[2][1] = cos(lam+Del)*sin(alf);
972 Dir[2][2] = sin(lam+Del);
978 double myStep = tcc.Path(X[1][0],X[1][1]);
979 tcc.Eval(myStep,X[3],Dir[3]);
981 for (
int jHAR=0;jHAR<5; jHAR++) {
982 if (jHAR==kC)
continue;
983 if (jHAR==kL)
continue;
986 Dif = (X[3][0]-X[1][0])*(-Dir[1][1])
987 + (X[3][1]-X[1][1])*( Dir[1][0]);
991 Dif = atan2(Dir[3][1],Dir[3][0])
992 -atan2(Dir[1][1],Dir[1][0]);
993 if (Dif> M_PI) Dif-=2*M_PI;
994 if (Dif< -M_PI) Dif+=2*M_PI;
997 Dif = X[3][2]-X[1][2];
1000 double est = Dif/Del;
1001 double eps = fabs(est-F[jHAR][iHAR])*2
1002 /(fabs(est)+fabs(F[jHAR][iHAR]+1e-6));
1003 if (eps>maxEps) maxEps=eps;
1004 if (eps < 1e-2)
continue;
1006 printf(
" m%c%c \t%g \t%g \t%g\n",
1007 T[jHAR],T[iHAR],F[jHAR][iHAR],est,eps);
1010 printf(
"TestMtx: %d errors maxEps=%g\n",nErr,maxEps);
1015 int SqEqu(
double *cba,
double *sol)
1035 const double zero2=1.e-12;
1036 double swap,a,b,c,amx,dis,bdis;
1040 a = cba[2]; b = cba[1]*0.5; c = cba[0];
1041 if (b < 0.) {a = -a; b = -b; c = -c;}
1042 amx = fabs(a);
if (amx<b) amx = b;
if (amx<fabs(c)) amx = fabs(c);
1043 if (amx <= 0.)
return -1;
1044 a = a/amx; b = b/amx; c = c/amx;
1048 if (fabs(dis) <= zero2) dis = 0;
1049 if (dis < 0.) { nsol = 0; dis = 0.;}
1051 dis = ::sqrt(dis); bdis = b + dis;
1052 if (fabs(c) > 1.e+10*bdis)
return -1;
1054 if (fabs(bdis) <= 0.)
return nsol;
1056 if (dis <= 0.)
return nsol;
1057 if (bdis >= 1.e+10*fabs(a))
return nsol;
1058 nsol = 2; sol[1] = (-bdis/a);
1059 if (sol[0] > sol[1]) { swap = sol[0]; sol[0] = sol[1]; sol[1] = swap;}
1066 rho = fRho +(step*fCosL)*fDRho;
1073 double ztep = step*fCosL;
1074 double teta = ztep*(fRho+0.5*ztep*fDRho);
1076 sgCX1 = TComplex(fX[0] ,fX[1]);
1077 sgCD1 = TComplex(fP[0],fP[1])/fCosL;
1078 sgImTet = TComplex(0,teta);
1079 sgCOne = expOne(sgImTet);
1080 sgCf1 = sgImTet*sgCOne;
1081 sgCD2 = sgCD1*sgCf1+sgCD1;
1082 sgCX2 = sgCD1*sgCOne*ztep;
1085 xyz[0] = sgCX2.Re()+sgCX1.Re();
1086 xyz[1] = sgCX2.Im()+sgCX1.Im();
1087 xyz[2] = fX[2]+fP[2]*step;
1090 sgCD2/= TComplex::Abs(sgCD2);
1091 dir[0] = sgCD2.Re()*fCosL;
1092 dir[1] = sgCD2.Im()*fCosL;
1098 void THelixTrack::Fill(
TCircle &circ)
const
1102 circ.fD[0]=fP[0]/fCosL;
1103 circ.fD[1]=fP[1]/fCosL;
1105 if (fEmx) circ.SetEmx(fEmx->Arr());
1108 void THelixTrack::InvertMtx(
double F[5][5])
1110 static const int minus[][2] = {{0,1},{1,0},{1,2},{3,0},{3,2},{3,4},{-1,0}};
1111 for (
int i=0;minus[i][0]>=0;i++) {
1112 F[minus[i][0]][minus[i][1]] = -F[minus[i][0]][minus[i][1]];
1127 void THelixTrack::Show(
double len,
const THelixTrack *other)
const
1129 static TCanvas *myCanvas = 0;
1130 int kolor[2]={kRed,kBlue};
1132 TGraph *ciGraph[2][2] = {{0}};
1133 TGraph *ptGraph[2][2] = {{0}};
1134 TGraph *szGraph[2] = {0};
1136 double x[100],y[100],z[100],l[100],xyz[3];
1137 double X[4],Y[4],Z[4],L[4];
1139 int nH = (other)? 2:1;
1140 for (
int ih=0;ih<nH;ih++) {
1141 double rho = fabs(th[ih]->GetRho());
1142 double step = 0.01*(1./(rho+1e-10));
1144 if (step>fabs(len)*0.10) step=fabs(len)*0.1;
1145 if (step<fabs(len)*0.01) step=fabs(len)*0.01;
1148 int nPts = (int)(fabs(len)/step);
1149 step = fabs(len)/nPts;
1150 if (len<0) {len = -len; step = -step;}
1151 for (
int ipt=0; ipt<nPts; ipt++) {
1152 double s = ipt*step;
1153 th[ih]->
Eval(s,xyz);
1154 l[ipt]=s; x[ipt]=xyz[0]; y[ipt]=xyz[1], z[ipt]=xyz[2];
1156 ciGraph[ih][0] =
new TGraph(nPts , x, y);
1157 ciGraph[ih][1] =
new TGraph(nPts , l, z);
1158 ciGraph[ih][0]->SetLineColor(kolor[ih]);
1159 ciGraph[ih][1]->SetLineColor(kolor[ih]);
1160 ptGraph[ih][0] =
new TGraph( 1 , x, y);
1161 ptGraph[ih][1] =
new TGraph( 1 , l, z);
1162 ptGraph[ih][0]->SetMarkerColor(kolor[ih]);
1163 ptGraph[ih][1]->SetMarkerColor(kolor[ih]);
1165 X[ih*2+0]=x[0]; X[ih*2+1]=x[nPts-1];
1166 Y[ih*2+0]=y[0]; Y[ih*2+1]=y[nPts-1];
1167 Z[ih*2+0]=z[0]; Z[ih*2+1]=z[nPts-1];
1168 L[ih*2+0]=l[0]; L[ih*2+1]=l[nPts-1];
1171 szGraph[0] =
new TGraph(nH*2 , X, Y);
1172 szGraph[1] =
new TGraph(nH*2 , L, Z);
1174 myCanvas =
new TCanvas(
"THelixTrack_Show",
"",600,800);
1175 myCanvas->Divide(1,2);
1176 for (
int ipad=0;ipad<2;ipad++) {
1177 myCanvas->cd(ipad+1);
1178 szGraph[ipad]->Draw(
"AP");
1179 for (
int ih = 0;ih<nH;ih++) {
1180 ptGraph[ih][ipad]->Draw(
"same *");
1181 ciGraph[ih][ipad]->Draw(
"same CP");
1185 myCanvas->Modified();
1187 while(!gSystem->ProcessEvents()){gSystem->Sleep(200);};
1191 void THelixTrack::Test1()
1193 double surf[4] = {-11.32212856152224, 0.50109792630239824, -0.86539108263698283, 0.00078459561521909921};
1194 double xyz[3] = {-0.0206564,-0.0153429,0.0285582};
1195 double dir[3] = {0.450295,-0.596426,-0.664463};
1196 double Rho = 0.00678696;
1199 double s = TH.Step(100000,surf,4);
1200 printf(
"s=%g = 15.3589\n",s);
1203 void THelixTrack::Test2()
1207 double xyz[3] = {-60.0301,1.51445,-1.57283};
1208 double dir[3] = {-0.849461,0.526419,0.0360391};
1209 double Rho = 0.00363571;
1212 double MyHit[3]= { -177.673, 41.305, 2.90798};
1215 printf(
"%s= %g %g %g\n",
"MyHit",MyHit[0],MyHit[1],MyHit[2]);
1216 double s = ht.Step(MyHit,MyClo);
1218 TCL::vsub(MyClo,MyHit,diff,3);
1219 double MyDist = sqrt(TCL::vdot(diff,diff,3));
1220 printf(
"%s= %g %g %g\n",
"MyClo ",MyClo[0],MyClo[1],MyClo[2]);
1221 printf(
"MustBe= -177.661 41.4145 2.94559\n");
1223 printf(
"%s= %g %g %g\n",
"MyDif ",diff[0],diff[1],diff[2]);
1224 printf(
"MustBe= 0.0122709 0.109539 0.0376077\n");
1225 printf(
"%s=%g\n",
"MyS ",s);
1226 printf(
"MustBe=125.375\n");
1227 printf(
"%s= %g\n",
"MyDist",MyDist);
1228 printf(
"MustBe= 0.116463\n");
1231 void THelixTrack::Test3()
1233 double xyz[3] = {100,200,300};
1234 double dir[3] = {-0.224845,-0.491295,-0.841471};
1236 double sur[8]={-120,1,0,0,0,0,0};
1238 double newX[3],newD[3];
1240 double s = ht->Step(1000.,sur,4,newX,newD);
1241 printf(
"Result: s=%g newX=(%g %g %g) newD=(%g %g %g)\n"
1242 ,s,newX[0],newX[1],newX[2],newD[0],newD[1],newD[2]);
1244 printf(
"MustBe: s=56.1931 newX=(120 222.222 347.285) newD=(0.464979 0.275174 0.841471)\n\n");
1247 s = ht->Step(1000.,sur,7,newX,newD);
1248 printf(
"Result: s=%g newX=(%g %g %g) newD=(%g %g %g)\n"
1249 ,s,newX[0],newX[1],newX[2],newD[0],newD[1],newD[2]);
1250 printf(
"MustBe: s=55.9338 newX=(119.88 222.151 347.067) newD=(0.464206 0.276476 0.841471)\n\n");
1253 void THelixTrack::Test4()
1255 double surf[7] = {-100, 0, 0, 0, 1,1,0};
1256 double xyz[3] = {-0.0206564,-0.0153429,0.0285582};
1257 double dir[3] = {0.450295,-0.596426,-0.664463};
1258 double Rho = 0.00678696;
1262 double s = TH.Step(100000,surf,7,xnew);
1263 double dif = xnew[0]*xnew[0]+xnew[1]*xnew[1]-100;
1264 printf(
"s=%g dif=%g\n",s,dif);
1268 void THelixTrack::Test5()
1270 double pars[4][2][7] = {
1271 {{0,0,0, 1,1,1, -0.001},{0,0, 0, -1,1,-1,0.002}},
1272 {{0,0,1, 1,1,1, -0.001},{0,0,-1, -1,1,-1,0.002}},
1273 {{0,0,1, 1,1,1, -0.001},{0,0,-1, 1,1,-1,0.002}},
1275 for (
int ip=0;ip<3;ip++) {
1276 THelixTrack th1(pars[ip][0],pars[ip][0]+3,pars[ip][0][6]);
1277 THelixTrack th2(pars[ip][1],pars[ip][1]+3,pars[ip][1][8]);
1281 double s1 = th1.Path(th2,&s2);
1285 TCL::vsub(th1.Pos(),th2.Pos(),diff,3);
1286 double dist = sqrt(TCL::vdot(diff,diff,3));
1287 printf(
"s1=%g s2=%g dist=%g\n",s1,s2,dist);
1292 void THelixTrack::TestDer()
1294 enum {kH=0,kA,kC,kZ,kL};
1296 double D[5][3],X[5][3]={{0}},Rho[5],step,F[5][5];
1297 int iR = 10+ gRandom->Rndm()*100;
1298 int iAlf=30+ gRandom->Rndm()*100;
1299 int iLam=10+ gRandom->Rndm()*60;
1300 step = gRandom->Rndm()*6*iR;
1303 double alf = iAlf/180.*M_PI;
1304 double lam = iLam/180.*M_PI;
1305 D[0][0] = cos(lam)*cos(alf);
1306 D[0][1] = cos(lam)*sin(alf);
1311 hlx1.Eval(0,X[2],D[2]);
1312 Rho[2]=hlx1.GetRho();
1315 printf(
"TestDer: Angle=%d Lam=%d \tRad=%d Step=%d \n",iAlf,iLam,iR,
int(step));
1316 hlx0.Eval(0,X[1],D[1]); Rho[1]=hlx0.GetRho();
1318 double dH = iR *0.01 *(gRandom->Rndm()-0.5)*fak;
1319 double dAlf = M_PI/180*0.1 *(gRandom->Rndm()-0.5)*fak;
1320 double dRho = Rho[0] *0.1 *(gRandom->Rndm()-0.5)*fak;
1321 double dZ = (gRandom->Rndm()-0.5)*fak;
1322 double dLam = M_PI/180*0.1 *(gRandom->Rndm()-0.5)*fak;
1323 double dA[5] = {dH,dAlf,dRho,dZ ,dLam}, dB[5];
1324 D[1][0] = cos(lam+dLam)*cos(alf+dAlf);
1325 D[1][1] = cos(lam+dLam)*sin(alf+dAlf);
1326 D[1][2] = sin(lam+dLam);
1327 X[1][0] += -D[0][1]*dH/cos(lam);
1328 X[1][1] += D[0][0]*dH/cos(lam);
1333 double dL = hlxM.Path(X[2][0],X[2][1]);
1335 hlxM.Eval(0,X[3],D[3]); Rho[3]=hlxM.GetRho();
1337 TCL::vmatl(F[0],dA,dB,5,5);
1340 memcpy(X[4],X[2],3*
sizeof(
double));
1341 memcpy(D[4],D[2],3*
sizeof(
double));
1343 double myAlf = atan2(D[2][1],D[2][0]);
1344 double myLam = asin(D[2][2]) ;
1345 D[4][0] = cos(myLam+dB[kL])*cos(myAlf+dB[kA]);
1346 D[4][1] = cos(myLam+dB[kL])*sin(myAlf+dB[kA]);
1347 D[4][2] = sin(myLam+dB[kL]);
1348 X[4][0] += -D[2][1]*dB[kH]/cos(myLam);
1349 X[4][1] += D[2][0]*dB[kH]/cos(myLam);
1354 dL = hlxD.Path(X[2][0],X[2][1]);
1356 hlxD.Eval(0,X[4],D[4]);
1357 Rho[4]=hlxD.GetRho();
1363 dC[kH] = (-(X[3][0]-X[2][0])*D[2][1]+(X[3][1]-X[2][1])*D[2][0])/cos(myLam);
1364 dC[kA] = atan2(D[3][1],D[3][0])-atan2(D[2][1],D[2][0]);
1365 dC[kC] = Rho[3]-Rho[2];
1366 dC[kZ] = X[3][2]-X[2][2];
1367 dC[kL] = asin(D[3][2])-asin(D[2][2]);
1368 for (
int i=0;i<5;i++) {printf(
" %d - %g == %g\n",i,dB[i],dC[i]);}
1371 for (
int i=0;i<3;i++){myDelta+=pow(X[4][i]-X[3][i],2);}
1372 myDelta = sqrt(myDelta);
1375 for (
int i=0;i<3;i++){ihDelta+=pow(X[2][i]-X[3][i],2);}
1376 ihDelta = sqrt(ihDelta);
1377 printf(
"\n*** DELTA = %g << %g ***\n",myDelta,ihDelta);
1394 {
delete fEmx;fEmx=0;}
1397 TCircle::TCircle(
const double *x,
const double *d,
double rho)
1403 void TCircle::Set(
const double *x,
const double *d,
double rho)
1405 fX[0]=0; fX[1]=0; fD[0]=0; fD[1]=0;
1406 if (x) {fX[0]=x[0];fX[1]=x[1];}
1408 fD[0]=d[0];fD[1]=d[1];
1409 double n = sqrt(fD[0]*fD[0]+fD[1]*fD[1]);
1415 TCircle::TCircle(
const TCircle& fr)
1421 TCircle::TCircle(
const TCircle* fr)
1424 Set(fr->fX,fr->fD,fr->fRho);
1429 Set(fr.fX,fr.fD,fr.fRho);
1430 if (fr.fEmx) SetEmx(fr.fEmx->Arr());
1435 void TCircle::Clear(
const char *)
1437 if (fEmx) fEmx->Clear();
1438 memset(fX,0,(
char*)(&fEmx)-(
char*)fX);
1443 void TCircle::SetEmx(
const double *err)
1449 void TCircle::Nor(
double *norVec)
const
1453 norVec[0] = fD[1]; norVec[1] = -fD[0];
1454 if (fRho>=0)
return;
1455 norVec[0] = -norVec[0];norVec[1] = -norVec[1];
1458 void TCircle::GetCenter(
double cent[3])
const
1461 if (fabs(fRho) > 1e-10) { R = 1./fRho ;}
1462 else { R =( fRho>0) ? 1e10:-1e10;}
1463 cent[0] = fX[0]-fD[1]*R;
1464 cent[1] = fX[1]+fD[0]*R;
1467 void TCircle::Print(
const char* txt)
const
1470 printf(
"TCircle(%s): x,y=%g %g dir=%g %g curv=%g\n",txt,fX[0],fX[1],fD[0],fD[1],fRho);
1472 printf(
"Errs: %g\n" ,fEmx->mHH);
1473 printf(
" : %g \t%g\n" ,fEmx->mHA,fEmx->mAA);
1474 printf(
" : %g \t%g \t%g\n",fEmx->mHC,fEmx->mAC,fEmx->mCC);
1477 double TCircle::Path(
const double pnt[2])
const
1479 TComplex CX1(pnt[0]-fX[0],pnt[1]-fX[1]);
1480 TComplex CP(fD[0],fD[1]);
1481 TComplex CXP = TComplex(0,1)*CX1/CP;
1482 TComplex CXPRho = CXP*fRho;
1484 if (TComplex::Abs(CXPRho)>0.001) {
1485 s = TComplex::Log(1.+CXPRho).Im()/fRho;
1487 s = (CXP*(1.-CXPRho*(0.5-CXPRho*(1/3.-CXPRho*0.25)))).Im();
1496 double TCircle::Path(
const double *pnt,
const double *exy)
const
1499 double s = Path(pnt);
1500 if (!exy || exy[0]<=0)
return s;
1502 double k = (x[0]-pnt[0])*(d[1]) + (x[1]-pnt[1])*(-d[0]);
1503 double t =((d[1]*d[1]-d[0]*d[0])*exy[1]-d[1]*d[0]*(exy[2]-exy[0]))
1504 /( d[0]*d[0]*exy[2] -2*d[1]*d[0]*exy[1]+d[1]*d[1]*exy[0]);
1509 double TCircle::Path(
const TCircle &hlx,
double *S2)
const
1511 double s,s1=3e33,s2=3e33;
1512 const static TComplex Im(0.,1.);
1515 if (fabs(fRho) > fabs(hlx.fRho)) { one=two; two=
this; }
1516 double Rho1 = one->Rho();
1517 double Rho2 = two->Rho();
1519 if (fabs(Rho1) > 1e-4) kase+=1;
1520 if (fabs(Rho2) > 1e-4) kase+=2;
1523 TComplex CX1(one->Pos()[0],one->Pos()[1]);
1524 TComplex CX2(two->Pos()[0],two->Pos()[1]);
1525 TComplex CP1(one->Dir()[0],one->Dir()[1]);
1526 TComplex CP2(two->Dir()[0],two->Dir()[1]);
1527 TComplex CdX = CX2-CX1;
1533 TComplex A = CP1/CP2*(Rho2/Rho1);
1534 TComplex B = 1.-CdX/CP2*(Im*Rho2) - CP1/CP2*(Rho2/Rho1);
1537 double alfa = A.Theta();
1538 double beta = B.Theta();
1539 double myCos = (1.-(a*a+b*b))/(2.*a*b);
1541 if (myCos>= 1.) {nSol=1; myAng = 0. ;}
1542 else if (myCos<=-1.) {nSol=1; myAng = M_PI ;}
1543 else {nSol=2; myAng = acos(myCos) ;}
1544 s = ( myAng -(alfa-beta))/Rho1;
1545 if (s<0) s+= 2.*M_PI/fabs(Rho1);
1548 s =(-myAng -(alfa-beta))/Rho1;
1549 if (s< 0) s+= 2.*M_PI/fabs(Rho1);
1553 TComplex A = CP1/CP2*(Im*Rho2);
1554 TComplex B = 1.-CdX/CP2*(Im*Rho2);
1555 double cba[3]={B.Rho2()-1., 2*(A.Re()*B.Re()+A.Im()*B.Im()), A.Rho2()};
1556 nSol = SqEqu(cba, L);
1558 if (nSol==0) nSol=1;
1559 if (L[0]>0) s1=L[0];
1560 if (nSol>1 && L[1]>0 && L[1] <s1) s1 = L[1];
1566 if (fabs((CdX/CP1).Im())>fabs((CP2/CP1).Im())*1e6)
break;
1568 s = (CdX/CP2).Im()/(CP1/CP2).Im();
1580 if (s<0 && kase) s += 2.*M_PI/fabs(Rho2);
1585 if (one !=
this) {s=s1;s1=s2;s2=s;}
1590 void TCircle::Test4()
1592 double pars[4][2][5] = {
1593 {{0,0,1,0.,-0.001},{0,0.0,1,0,0.002}},
1594 {{0,0,1,0.,-0.001},{0,0.1,1,0,0.002}},
1595 {{0,0,1,0.,-0.001},{0,0.0,1,1,1e-8 }},
1596 {{0,0,1,0.,-1e-8 },{0,0.0,1,1,1e-8 }}};
1597 for (
int ip=0;ip<4;ip++) {
1598 TCircle tc1(pars[ip][0],pars[ip][0]+2,pars[ip][0][4]);
1599 TCircle tc2(pars[ip][1],pars[ip][1]+2,pars[ip][1][4]);
1603 double s1 = tc1.Path(tc2,&s2);
1604 printf(
"s1=%g s2=%g \n",s1,s2);
1608 double TCircle::Eval(
double step,
double *X,
double *D)
const
1611 sgCX1 =TComplex(fX[0],fX[1]);
1612 sgCD1 =TComplex(fD[0],fD[1]);
1613 sgImTet =TComplex(0,step*fRho);
1614 sgCOne =expOne(sgImTet);
1615 sgCf1 =sgImTet*sgCOne;
1617 sgCD2 = sgCD1*sgCf1+sgCD1;
1618 sgCX2 = sgCD1*sgCOne*step;
1620 X[0] = sgCX2.Re()+sgCX1.Re();
1621 X[1] = sgCX2.Im()+sgCX1.Im();
1624 sgCD2/= TComplex::Abs(sgCD2);
1631 double TCircle::Move(
double step)
1634 if (fEmx && fEmx->mHH>0 && step) MoveErrs(step);
1635 if (fabs(fD[0])>1) fD[0]=(fD[0]<0)? -1:1;
1636 if (fabs(fD[1])>1) fD[1]=(fD[1]<0)? -1:1;
1640 void TCircle::MakeMtx(
double S,
double F[3][3])
1643 memset(F[0],0,
sizeof(F[0][0])*3*3);
1644 F[kH][kH] = sgCf1.Re()+1.;
1645 double dSdH = sgCf1.Im();
1647 F[kH][kA] = S*sgCOne.Re();
1648 double dSdA = S*sgCOne.Im();
1649 TComplex llCOneD = S*S*expOneD(-sgImTet);
1650 F[kH][kC] = llCOneD.Re();
1651 double dSdC = llCOneD.Im();
1653 F[kA][kH] = -dSdH*fRho;
1654 F[kA][kA] = 1-dSdA*fRho;
1655 F[kA][kC] = S+dSdC*fRho;
1659 void TCircle::MoveErrs(
double s)
1667 void TCircle::Rot(
double angle)
1669 Rot(cos(angle),sin(angle));
1672 void TCircle::Rot(
double cosa,
double sina)
1674 TComplex CX(fX[0],fX[1]),CP(fD[0],fD[1]);
1675 TComplex A (cosa,sina);
1676 CX *=A; fX[0] = CX.Re(); fX[1]=CX.Im();
1677 CP *=A; CP/=TComplex::Abs(CP);
1678 fD[0] = CP.Re(); fD[1]=CP.Im();
1681 void TCircle::Backward()
1683 fRho=-fRho;fD[0]=-fD[0];fD[1]=-fD[1];
1684 if(fEmx) fEmx->Backward();
1688 void TCircle::Test2()
1708 void TCircle::Test3()
1741 void TCircle::TestMtx()
1743 double Dir[8],X[8]={0},Rho[2],step,F[3][3],Del[3],Dif[3]={0};
1746 for (
int iR = 1010;iR>-1010;iR-=20) {
1748 int iAlf = 360*gRandom->Rndm();
1750 Del[1] = M_PI/180*0.01;
1751 Del[2] = 1e-4+ Rho[0]*0.001;
1752 for (
int iStep=10;iStep<=350;iStep+=10){
1753 Dir[0] = cos(iAlf/180.*M_PI);
1754 Dir[1] = sin(iAlf/180.*M_PI);
1756 step = iStep/180.*M_PI*abs(iR);
1757 tc.Eval(step,X+2,Dir+2);
1760 for (
int iHAR=0;iHAR<3;iHAR++) {
1761 double minFak = 1e-4;
1762 for (
double fak=1;fak>minFak;fak/=2) {
1764 memcpy(X +4,X ,
sizeof(X[0] )*2);
1765 memcpy(Dir+4,Dir,
sizeof(Dir[0])*2);
1769 X[4+0] = X[0]-Dir[1]*Del[0]*fak;
1770 X[4+1] = X[1]+Dir[0]*Del[0]*fak;
1774 Dir[4+0] = cos(iAlf/180.*M_PI+Del[1]*fak);
1775 Dir[4+1] = sin(iAlf/180.*M_PI+Del[1]*fak);
1779 Rho[1] = Rho[0]+Del[2]*fak;
1783 TCircle tcc(X+4,Dir+4,Rho[1]);
1785 double myStep = tcc.Path(X+2);
1787 tcc.Eval(0,X+6,Dir+6);
1789 TCL::vsub(X+6,X+2,dX,2);
1791 myStep = -TCL::vdot(dX,Dir+2,2)/TCL::vdot(Dir+6,Dir+2,2);
1792 tcc.Eval(myStep,X+6,Dir+6);
1794 for (
int jHAR=0;jHAR<2; jHAR++) {
1797 Dif[0] = (X[6+0]-X[2+0])*(-Dir[2+1])
1798 + (X[6+1]-X[2+1])*( Dir[2+0]);
1801 Dif[1] = (atan2(Dir[6+1],Dir[6+0])
1802 - atan2(Dir[2+1],Dir[2+0]));
1803 if (Dif[1]> M_PI) Dif[1]-=2*M_PI;
1804 if (Dif[1]< -M_PI) Dif[1]+=2*M_PI;
1808 double mat = F[jHAR][iHAR];
1813 double est = Dif[jHAR]/(Del[iHAR]*fak);
1814 double min = Del[jHAR]/Del[iHAR]*0.001;
1818 if (fabs(est) < 1e-4) est = 0;
1819 if (fabs(mat) < 1e-4) mat = 0;
1822 double eps =(fabs(est-mat)*2)
1823 /(fabs(est)+fabs(mat)+min);
1825 if (eps>maxEps) maxEps=eps;
1828 if (fak > minFak*2)
continue;
1830 if (eps>maxEps) maxEps=eps;
1831 printf(
"%6d Mtx[%d][%d] \t%g \t%g \tAngle=%d \tRad=%d \tLen=%g\n",
1832 tally,jHAR,iHAR,F[jHAR][iHAR],est,
1836 printf(
"TestMtx: %d errors maxEps=%g\n",nErr,maxEps);
1843 TCircleFitter::TCircleFitter()
1849 void TCircleFitter::Clear(
const char*)
1852 memset(fBeg,0,fEnd-fBeg+1);
1861 const double* TCircleFitter::GetX(
int i)
const
1863 return &(fAux[i].x);
1866 double* TCircleFitter::GetX(
int i)
1868 return &(fAux[i].x);
1871 void TCircleFitter::Add(
double x,
double y,
const double *errs)
1874 int n = fN*TCircleFitterAux::dSize();
1875 if (fArr.GetSize()<n) {fArr.Set(n*2);fAux=0;}
1876 if (!fAux) fAux = GetAux(0);
1878 aux->x = x; aux->y=y; aux->exy[0]=0; aux->exy[2]=0; aux->ezz=1;aux->wt=0;
1879 if (errs) AddErr(errs);
1882 void TCircleFitter::Add(
double x,
double y,
double z)
1885 int n = fN*TCircleFitterAux::dSize();
1886 if (fArr.GetSize()<n) {fArr.Set(n*2);fAux=0;}
1887 if (!fAux) fAux = GetAux(0);
1889 aux->x = x; aux->y=y; aux->z=z;
1890 aux->exy[0]=0; aux->exy[1]=0; aux->exy[2]=0;aux->ezz=1;aux->wt=0;
1893 void TCircleFitter::AddErr(
const double *errs,
double ezz)
1896 double *e = aux->exy;
1897 memcpy(e,errs,
sizeof(aux->exy));
1905 void TCircleFitter::AddErr(
double errhh,
double ezz)
1911 aux->exy[0]= 0;aux->exy[2]= 0;
1915 void TCircleFitter::AddZ(
double z,
double ez)
1922 double TCircleFitter::Fit()
1924 static const int nAVERs = &fRr-&fXx;
1925 static int nCall=0; nCall++;
1926 double xx=0, yy=0, xx2=0, yy2=0;
1927 double f=0, g=0, h=0, p=0, q=0, t=0, g0=0, g02=0, d=0;
1928 double xroot=0, ff=0, fp=0;
1929 double dx=0, dy=0, xnom=0,wt=0,tmp=0,radius2=0,radiuc2=0;
1931 if (fNuse < 3)
return 3e33;
1935 double *mm = &fXgravity; memset(mm,0,
sizeof(*mm)*5);
1936 for (
int i=0; i<fN; i++) {
1937 double x=aux[i].x, y=aux[i].y;
1938 fXgravity+=x; fYgravity+=y;fXx+=x*x;fYy+=y*y;fXy+=x*y;}
1940 for (
int j=0;j<5;j++) {mm[j]/=fN;}
1941 fXx-=fXgravity*fXgravity;fYy-=fYgravity*fYgravity;fXy-=fXgravity*fYgravity;
1943 double eigVal[2]={0};
1944 eigen2(&fXx,eigVal,&fCos);
1945 int fastTrak = (eigVal[0]>10*eigVal[1]);
1946 fNor[0] = -fSin; fNor[1] = fCos;
1949 enum {kIter=1,kFast=2,kWeit=4,kErr=8};
1950 const double *exy=0;
1952 for (
int iter=0;iter<2;iter++) {
1954 memset(&fXgravity,0,
sizeof(
double)*(nAVERs+2));
1955 for (
int i=0; i<fN; i++) {
1956 if (aux[i].wt<0) {
if(!i) fNuse--;
continue;}
1958 if (fastTrak) kase|=2;
1959 if (aux[i].wt >0) kase+=4;
1960 if (aux[i].exy[0]>0 || aux[i].exy[2]>0) {wasErrs++;kase+=8;}
1972 wt = aux[i].wt;
break;
1974 case kIter|kWeit|kErr:;
1975 case kIter|kFast|kWeit|kErr:;
1977 fNor[0] = fXCenter - aux[i].x;
1978 fNor[1] = fYCenter - aux[i].y;
1979 tmp = sqrt(fNor[0]*fNor[0]+fNor[1]*fNor[1]);
1980 fNor[0]/=tmp; fNor[1]/=tmp;
1983 case kFast|kErr|kWeit:;
1986 wt = (fNor[0]*fNor[0]*exy[0]
1987 +fNor[0]*fNor[1]*exy[1]*2
1988 +fNor[1]*fNor[1]*exy[2]);
1989 if (wt<kMinErr*kMinErr) wt = kBigErr*kBigErr;
1998 fXgravity += aux[i].x *wt;
1999 fYgravity += aux[i].y *wt;
2005 for (
int i=0; i<fN; i++) {
2008 dx = aux[i].x-fXgravity;
2009 dy = aux[i].y-fYgravity;
2010 xx = dx*fCos + dy*fSin;
2011 yy = -dx*fSin + dy*fCos;
2017 fXrr += xx*(xx2+yy2) *wt;
2018 fYrr += yy*(xx2+yy2) *wt;
2019 fRrrr += (xx2+yy2)*(xx2+yy2) *wt;
2022 for (
int i=0;i<nAVERs;i++) {dd[i]/=fWtot;}
2025 if (fNuse <= 3 && !fKase) fKase=1;
2026 if (!fKase) fKase =(fastTrak)? 1:2;
2027 SWIT:
switch(fKase) {
2036 double myCof[3]={0};
2038 fPol[1] = 0; fPol[2] = 1./(2*sqrt(fXx));
2039 fPol[3] = fRr; fPol[4] = fXrr/(2*fXx); fPol[5] = 1.;
2040 double tmp = sqrt(fPol[3]*fPol[3]
2041 +fPol[4]*fPol[4]*(4*fXx )
2042 +fPol[5]*fPol[5]*(fRrrr )
2043 +fPol[3]*fPol[5]*(-fRr ) *2
2044 +fPol[4]*fPol[5]*(-2*fXrr) *2);
2045 fPol[3]/=tmp;fPol[4]/=tmp;fPol[5]/=tmp;
2047 myCof[1] = - (fPol[2]*(4*fXy));
2048 myCof[2] = - (fPol[4]*(4*fXy) + fPol[5]*(-2*fYrr));
2049 fC = myCof[0]*fPol[0]+myCof[1]*fPol[1]+myCof[2]*fPol[3];
2050 fA = myCof[1]*fPol[2]+myCof[2]*fPol[4];
2051 fB = myCof[2]*fPol[5];
2052 fYd = (fabs(fB)>1e-6) ? 1./fB : 1e6;
2068 fB = (f*g-t-h*h)/g02;
2069 fC = (t*(f+g)-2.*(p*p+q*q))/(g02*g0);
2070 d = (t*(h*h-f*g)+2.*(p*p*g+q*q*f)-4.*p*q*h)/(g02*g02);
2072 for (
int i=0; i<5; i++) {
2073 ff = (((xroot+fA)*xroot+fB)*xroot+fC)*xroot+d;
2074 fp = ((4.*xroot+3.*fA)*xroot+2.*fB)*xroot+fC;
2078 xnom = (g-fG1)*(f-fG1)-h*h;
2081 if (xnom<1e-20) { fKase=1;
goto SWIT;}
2083 fXd = ( p*(g-fG1)-q*h )/xnom;
2084 fYd = (-p*h +q*(f-fG1))/xnom;
2090 fXCenter = fXd*fCos-fYd*fSin + fXgravity;
2091 fYCenter = fXd*fSin+fYd*fCos + fYgravity;
2093 if (fastTrak || !wasErrs)
break;
2099 fCorrR = sqrt(1+fA*fA+fC*fB );
2100 fCorrB = sqrt(1+fA*fA );
2101 fRho = fabs(fB)/fCorrR;
2102 int sgB = (fB<0)? -1:1;
2103 fNy = sgB/sqrt(1+fA*fA);
2105 fH = -fC*sgB/(fCorrR+fCorrB);
2106 fChi2 = (4*fA*fXy +4*fYy- 2*fB*fYrr)/4;
2107 fChi2 /= (fCorrR*fCorrR);
2108 fX[0] = fNx*fH; fX[1] = fNy*fH;
2111 fD[0] = fNy; fD[1] =-fNx;
2119 radiuc2 = fXd*fXd+fYd*fYd;
2120 radius2 = radiuc2+fG1;
2121 fR = ::sqrt(radius2);
2122 fRd = ::sqrt(radiuc2);
2125 if (fRd>1e-6) { fNx = fXd/fRd; fNy = fYd/fRd;}
2126 else { fNx = 0; fNy = 1; fRd = 0; }
2127 fChi2 = (fG1-fRr)/2;
2128 fX[0] = fNx*fH; fX[1] = fNy*fH;
2131 fD[0] = fNy; fD[1] =-fNx;
2146 if (fNdf>0) fChi2 *= fWtot/fNdf;
2147 tmp = fD[0]*(aux[0].x-fX[0])+fD[1]*(aux[0].y-fX[1]);
2150 if (tmp>0) {fD[0]*=-1;fD[1]*=-1;fRho*=-1;fBack=1;}
2154 void TCircleFitter::MakeErrs()
2157 double F[3][3]; memset(F[0],0,
sizeof(F));
2161 fCov[0] = fPol[2]*fPol[2]+ fPol[4]*fPol[4];
2162 fCov[1] = fPol[4]*fPol[5];
2163 fCov[2] = fPol[5]*fPol[5];
2164 fCov[3] = fPol[1]*fPol[2]+ fPol[3]*fPol[4];
2165 fCov[4] = fPol[3]*fPol[5];
2166 fCov[5] = fPol[0]*fPol[0]+ fPol[1]*fPol[1]+fPol[3]*fPol[3];
2167 for (
int i=0;i<6;i++) {fCov[i]*=4;}
2168 int sgB = (fB<0)? -1:1;
2169 double corrRB = fCorrR+fCorrB;
2170 double corrR3 = fCorrR*fCorrR*fCorrR;
2173 F[0][0] = sgB*fA*fC/(corrRB*fCorrB*fCorrR);
2174 F[0][1] = 0.5*sgB*fC*fC/(corrRB*corrRB*fCorrR);
2175 F[0][2] = 0.5*sgB*fC*fB/(corrRB*corrRB*fCorrR)
2177 F[1][0] = -1/(fCorrB*fCorrB);
2178 F[2][0] = - sgB*fA*fB/(corrR3);
2179 F[2][1] = -0.5*sgB*fC*fB/(corrR3)+sgB/fCorrR;
2180 F[2][2] = -0.5*sgB*fB*fB/(corrR3);
2181 myFact = (fCorrR*fCorrR);
2186 double aRho = fabs(fRho),aRho2 = aRho*aRho,aRho3 = aRho*aRho2;
2187 for (
int i=0,li=0;i< 3;li+=++i) {
2188 for (
int j=0 ;j<=i;j++ ) {
2189 fCov[li+j] = d2F(i,j)*0.5; }}
2192 double dRho = -fH/(fRd*fR);
2196 F[0][2] = -0.5*aRho;
2197 F[1][0] = -fNy*aRho;
2200 F[2][0] = -fXd*aRho3;
2201 F[2][1] = -fYd*aRho3;
2202 F[2][2] = -0.5*aRho3;
2208 TCL::vscale(fCov,myFact/fWtot,fCov,6);
2210 if (fBack) {fEmx->mHA*=-1;fEmx->mAC*=-1;}
2213 double TCircleFitter::EvalChi2()
2215 if (!fNuse)
return 0;
2217 double sum = 0,wtot=0,wt;
2219 const double *p = M.Pos();
2220 for (
int i=0;i<fN;i++) {
2221 if (aux[i].wt<0)
continue;
2222 double s = M.Path(&(aux[i].x));
2225 sum+= (pow(p[0]-aux[i].x,2)+pow(p[1]-aux[i].y,2))*wt;
2228 if (fNdf) sum /= fNdf;
2245 double g[6]={1,0,1,0,0,1},c[6]={1,0,1,0,0,1}
2246 ,e[6],adj[3]={0},amda[3],dlt[2];
2247 int sel[3] ={!!(flag&1), !!(flag&2), !!(flag&4)};
2251 dlt[0] = vals[0]-fX[0]; dlt[1] = vals[1]-fX[1];
2252 adj[0] = -dlt[0]*fD[1]+dlt[1]*fD[0];
2256 adj[1] = vals[3]-atan2(fD[1],fD[0]);
2257 if (adj[1]< -M_PI) adj[1] += 2*M_PI;
2258 if (adj[1]> M_PI) adj[1] -= 2*M_PI;
2262 adj[2] = vals[4]-fRho;
2265 for (
int i=0,li=0;i< 3;li+=++i) {
2266 for (
int j=0 ;j<=i;j++ ) {
2267 if (!(sel[i]&sel[j]))
continue;
2268 c[li+j] = (*fEmx)[li+j]; } }
2274 for (
int i=0,li=0;i< 3;li+=++i) {
2275 for (
int j=0 ;j<=i;j++ ) {
2276 if (!(sel[i]|sel[j]))
continue;
2278 if (!(sel[i]&sel[j]))
continue;
2279 g[li+j] = (*fEmx)[li+j];
2286 for (
int i=0,li=0;i< 3;li+=++i) {
if (sel[i]) (*fEmx)[li+i]=0;}
2288 fX[0] += -adj[0]*fD[1];
2289 fX[1] += adj[0]*fD[0];
2294 double S = sin(adj[1]);
2295 double C = cos(adj[1]);
2297 fD[0] = d0*C-fD[1]*S;
2298 fD[1] = d0*S+fD[1]*C;
2302 fChi2 += (addXi2-fChi2*nFix)/fNdf;
2306 void TCircleFitter::Skip(
int idx)
2308 fAux[idx].exy[0] = -1;
2312 void TCircleFitter::SetNdf(
int ndf)
2314 fChi2*=fNdf;
if (ndf) fChi2/=ndf; fNdf=ndf;
2317 void TCircleFitter::Print(
const char* txt)
const
2320 printf(
"TCircleFitter::NPoints = %d method=%d",fN,fKase);
2321 if (fChi2) printf(
" Chi2 = %g",fChi2);
2325 int iP = (strchr(txt,
'P') || strchr(txt,
'p'));
2326 int iE = (strchr(txt,
'E') || strchr(txt,
'e'));
2327 int iF = (strchr(txt,
'F') || strchr(txt,
'f'));
2328 int iZ = (strchr(txt,
'Z') || strchr(txt,
'z'));
if(iZ){};
2331 for (
int ip=0;ip<fN;ip++) {
2332 printf(
"%3d - X: %g\tY:%g \tZ:%g",ip,aux[ip].x,aux[ip].y,aux[ip].z);
2334 printf(
" \tExy: %g %g %g \tEz:%g "
2335 ,aux[ip].exy[0],aux[ip].exy[1],aux[ip].exy[2],aux[ip].ezz);
2340 const double *xy = GetX(0);
2341 double ds=circ.Path(xy);
2344 for (
int i=0;i<fN;i++) {
2349 if (fabs( s)<1e-6) s=0;
2350 if (fabs(ds)<1e-6)ds=0;
2351 printf(
"%3d - S=%g(%g) \tX: %g=%g \tY:%g=%g \tdirX=%g dirY=%g\n"
2353 ,xy[0],circ.Pos()[0]
2354 ,xy[1],circ.Pos()[1]
2355 ,circ.Dir()[0],circ.Dir()[1]);
2360 void TCircleFitter::Test(
int iTest)
2363 int myKase = (iTest/1 )%10;
2364 int negRad = (iTest/10 )%10;
2365 int bakPts = (iTest/100 )%10;
2366 int noShft = (iTest/1000)%10;
2370 double e[4],x[3],dir[2];
2372 aShift[0]=-acos(0.25);
2373 aShift[1]=-acos(0.50);
2375 aShift[3]= acos(0.25);
2376 aShift[5]= acos(0.50);
2377 memset(aShift,0,
sizeof(aShift));
2382 static TCanvas* myCanvas[9]={0};
2383 static TH1F *hh[10]={0};
2384 static const char *hNams[]={
"pH",
"pA",
"pC",
"Xi2",
"dErr"};
2385 static const double lims[][2]={{-5 ,5},{-5 ,5 },{-5 ,5}
2386 ,{ 0 ,5},{-0.05,0.05}};
2387 const int nPads =
sizeof(hNams)/
sizeof(
void*);
2389 if(!myCanvas[0]) myCanvas[0]=
new TCanvas(
"TCircleFitter_Test0",
"",600,800);
2390 myCanvas[0]->Clear();
2391 myCanvas[0]->Divide(1,nPads);
2393 for (
int i=0;i<nPads;i++) {
2394 delete hh[i]; hh[i]=
new TH1F(hNams[i],hNams[i],100,lims[i][0],lims[i][1]);
2395 myCanvas[0]->cd(i+1); hh[i]->Draw();
2398 static TH1F *hc[10]={0};
2399 static const char *cNams[]={
"HHpull",
"HApull",
"AApull",
"HCpull",
"ACpull",
"CCpull"};
2400 static const int cPads=
sizeof(cNams)/
sizeof(
char*);
2401 if(!myCanvas[1]) myCanvas[1]=
new TCanvas(
"TCircleFitter_TestCorr1",
"",600,800);
2402 myCanvas[1]->Clear();
2403 myCanvas[1]->Divide(1,cPads);
2405 for (
int i=0;i<cPads;i++) {
2406 delete hc[i]; hc[i]=
new TH1F(cNams[i],cNams[i],100,-15,15);
2407 myCanvas[1]->cd(i+1); hc[i]->Draw();
2410 static TH1F *hl[10]={0};
2411 static const char *lNams[]={
"XP",
"YP",
"GP",
"XY",
"XG",
"YG"};
2412 static const int lPads=
sizeof(lNams)/
sizeof(
char*);
2413 if(!myCanvas[2]) myCanvas[2]=
new TCanvas(
"TCircleFitter_TestCorr2",
"",600,800);
2414 myCanvas[2]->Clear();
2415 myCanvas[2]->Divide(1,lPads);
2417 for (
int i=0;i<lPads;i++) {
2418 delete hl[i]; hl[i]=
new TH1F(lNams[i],lNams[i],100,-5,5);
2419 myCanvas[2]->cd(i+1); hl[i]->Draw();
2424 static unsigned int seed=0;
2427 for (
int ir = 50; ir <= 50; ir +=5) {
2429 double len = 0.3*aR*3;
2430 for (
double ang0 = 0; ang0 <= 0; ang0+=0.05) {
2431 double R = (negRad)? -aR:aR;
2432 double dang = len/R/(nPts-1);
2433 if (bakPts) dang*=-1;
2434 double C0 = cos(ang0);
2435 double S0 = sin(ang0);
2437 double myX[2]={0,0},myD[2]={C0,S0};
2438 xCenter[0] = myX[0]-myD[1]*R;
2439 xCenter[1] = myX[1]+myD[0]*R;
2440 double corr[6]={0},korr[6]={0};
2442 for (
int iter=0;iter<2;iter++) {
2443 static const int nEv = 100000;
2445 for (
int ev=0;ev<nEv;ev++) {
2448 for (
int is=0;is<nPts;is++) {
2449 double ang = ang0 + dang*is;
2450 double S = sin(ang),C = cos(ang);
2451 double eR = ran.Gaus(0,RERR);
2452 double shift = aShift[is%5];
2454 double SS = sin(ang+shift);
2455 double CC = cos(ang+shift);
2456 e[0] = pow(RERR*SS,2);
2457 e[1] =-pow(RERR ,2)*CC*SS;
2458 e[2] = pow(RERR*CC,2);
2460 x[0] = myX[0] + (R)*(S-S0);
2461 x[1] = myX[1] - (R)*(C-C0);
2465 helx.Add (x[0],x[1]);
2466 helx.AddErr (RERR*RERR);
2468 helx.SetCase(myKase);
2469 double Xi2 = helx.Fit();
2470 double Xj2 = helx.EvalChi2();
2471 assert(fabs(Xi2-Xj2) < 1e-2*(Xi2+Xj2+0.01));
2473 assert (!myKase || helx.GetCase()==myKase);
2477 if ((isgn=helx.Emx()->Sign())<0) {
2478 ::Warning(
"Test1",
"Negative errmtx %d",isgn);
continue;}
2480 if (helx.Rho()*idex.Rho() < 0) idex.Backward();
2482 double myShift = (aR*M_PI/180)*360*gRandom->Rndm();
2483 if (noShft) myShift=0;
2486 if ((isgn=helx.Emx()->Sign())<0) {
2487 ::Warning(
"Test2",
"Negative errmtx %d",isgn);
continue;}
2488 double s = idex.Path(helx.Pos());
2492 double dx = helx.Pos()[0]-x[0];
2493 double dy = helx.Pos()[1]-x[1];
2494 dd[0] = -dx*dir[1]+dy*dir[0];
2495 dd[1] = atan2(helx.Dir()[1],helx.Dir()[0])-atan2(dir[1],dir[0]);
2496 if (dd[1]> M_PI) dd[1]-=2*M_PI;
2497 if (dd[1]<-M_PI) dd[1]+=2*M_PI;
2498 dd[2] = helx.Rho()-idex.Rho();
2501 for (
int i=0,li=0;i< 3;li+=++i) {
2502 for (
int j=0;j<=i;j++) {
2503 corr[li+j]+= (*(helx.Emx()))[li+j];
2504 korr[li+j]+= dd[i]*dd[j];
2509 dd[3] = dd[0]/sqrt(corr[0]);
2510 dd[4] = dd[1]/sqrt(corr[2]);
2511 dd[5] = dd[2]/sqrt(corr[5]);
2513 dd[7] = sqrt(helx.Emx()->mHH)-RERR;
2515 for (
int ih=0;ih<nPads;ih++) { hh[ih]->Fill(dd[ih+3]);}
2518 double cc[6]={0},dia[3];
2519 for (
int i=0,li=0;i< 3;li+=++i) {
2520 dia[i] = corr[li+i];
2521 for (
int j=0;j<=i;j++) {
2522 cc[li+j] = (dd[i]*dd[j]-corr[li+j])/sqrt(dia[i]*dia[j]);
2526 for (
int ih=0;ih<cPads;ih++) { hc[ih]->Fill(cc[ih]);}
2529 myCenter[0]=xCenter[0]-helx.fXgravity;
2530 myCenter[1]=xCenter[1]-helx.fYgravity;
2531 double xx = myCenter[0];
2532 myCenter[0] = xx*helx.fCos + myCenter[1]*helx.fSin;
2533 myCenter[1] = -xx*helx.fSin + myCenter[1]*helx.fCos;
2534 myCenter[2] = R*R - (pow(myCenter[0],2)+pow(myCenter[1],2));
2535 for (
int j=0;j<3;j++) {dd[j]=(&(helx.fXd))[j]-myCenter[j];}
2536 dd[3+0] = dd[0]/sqrt(helx.fCov[0]);
2537 dd[3+1] = dd[1]/sqrt(helx.fCov[2]);
2538 dd[3+2] = dd[2]/sqrt(helx.fCov[5]);
2539 for (
int ih=0;ih<3;ih++) { hl[ih]->Fill(dd[ih+3]);}
2540 cc[0] = (dd[3+0]*dd[3+1]-helx.fCov[1])/sqrt(helx.fCov[0]*helx.fCov[2]);
2541 cc[1] = (dd[3+0]*dd[3+2]-helx.fCov[3])/sqrt(helx.fCov[0]*helx.fCov[5]);
2542 cc[2] = (dd[3+1]*dd[3+2]-helx.fCov[4])/sqrt(helx.fCov[2]*helx.fCov[5]);
2543 for (
int ih=0;ih<3;ih++) { hl[ih+3]->Fill(cc[ih]);}
2546 TCL::vscale(corr,1./nEv,corr,6);
2547 TCL::vscale(korr,1./nEv,korr,6);
2549 for (
int i=0,li=0;i< 3;li+=++i) {
2550 dia[i]=sqrt(corr[li+i]);
2552 for (
int j=0;j<=i;j++) {n+=printf(
"%15g",corr[li+j]/(dia[i]*dia[j]));}
2554 for (
int j=0;j< n;j++) {printf(
" ");}
2555 for (
int j=0;j<=i;j++) {n+=printf(
"%15g",korr[li+j]/(dia[i]*dia[j]));}
2564 for (
int i=0;myCanvas[i];i++) {
2565 myCanvas[i]->Modified();myCanvas[i]->Update();}
2567 while(!gSystem->ProcessEvents()){gSystem->Sleep(200);};
2572 void TCircleFitter::TestCorr(
int kase)
2580 if (!(kase&3 ))kase+=1+2;
2581 if (!(kase&12))kase+=4+8;
2583 double e[4],x[3],ex[3];
2585 aShift[0]=-acos(0.25);
2586 aShift[1]=-acos(0.50);
2588 aShift[3]= acos(0.25);
2589 aShift[5]= acos(0.50);
2590 double RERR = 0.001;
2592 static TCanvas* myCanvas=0;
2593 static TH1F *hh[6]={0,0,0,0,0,0};
2594 static const char *hNams[]={
"HA",
"HA-",
"HC",
"HC-",
"AC",
"AC-",0};
2595 if(!myCanvas) myCanvas=
new TCanvas(
"TCircleFitter_TestCorr",
"",600,800);
2597 myCanvas->Divide(1,6);
2599 for (
int i=0;i<6;i++) {
2600 delete hh[i]; hh[i]=
new TH1F(hNams[i],hNams[i],100,-1,1);
2601 myCanvas->cd(i+1); hh[i]->Draw();
2605 for (
int ir = 50; ir <= 1000; ir +=5) {
2607 double len = 100;
if (len>aR*3) len = aR*3;
2608 for (
double ang0 = -3; ang0 < 3.1; ang0+=0.05) {
2609 for (
int sgn = -1; sgn<=1; sgn+=2) {
2610 if ((sgn>0) && !(kase&4))
continue;
2611 if ((sgn<0) && !(kase&8))
continue;
2613 double dang = len/R/nPts;
2614 double C0 = cos(ang0);
2615 double S0 = sin(ang0);
2617 for (
int is=0;is<nPts;is++) {
2618 double ang = ang0 + dang*is;
2619 double S = sin(ang),C = cos(ang);
2620 double eR = ran.Gaus(0,RERR)*sgn;
2621 double shift = aShift[is%5];
2623 double SS = sin(ang+shift);
2624 double CC = cos(ang+shift);
2625 e[0] = pow(RERR*SS,2);
2626 e[1] =-pow(RERR ,2)*CC*SS;
2627 e[2] = pow(RERR*CC,2);
2629 x[0] = 100 + (R)*(S-S0);
2630 x[1] = 200 - (R)*(C-C0);
2633 helx.Add (ex[0],ex[1],e);
2636 if (!(helx.GetCase()&kase))
continue;
2640 if (kase&16) iFix +=1;
2641 if (kase&32) iFix +=4;
2644 TCL::ucopy(x,vals,3);
2647 helx.
FixAt(vals,iFix);
2651 double s = helx.Path(x);
2653 assert(fabs(s) < len);
2656 double dx = helx.Pos()[0]-x[0];
2657 double dy = helx.Pos()[1]-x[1];
2658 const TCEmx_t *emx = helx.Emx();
2659 dd[0] = -dx*S0+dy*C0;
2660 dd[1] = atan2(helx.Dir()[1],helx.Dir()[0])-ang0;
2661 if (dd[1]> M_PI) dd[1]-=2*M_PI;
2662 if (dd[1]<-M_PI) dd[1]+=2*M_PI;
2663 dd[2] = helx.Rho()-1./R;
2664 hf[0] = (dd[0]*dd[1]) *1e1/(RERR*RERR);
2665 hf[1] = (emx->mHA) *1e1/(RERR*RERR);
2666 hf[2] = dd[0]*dd[2] *1e3/(RERR*RERR);
2667 hf[3] = (emx->mHC) *1e3/(RERR*RERR);
2668 hf[4] = dd[1]*dd[2] *1e4/(RERR*RERR);
2669 hf[5] = (emx->mAC) *1e4/(RERR*RERR);
2672 for (
int ih=0;ih<6;ih++) { hh[ih]->Fill(hf[ih]);}
2676 myCanvas->Modified();
2678 while(!gSystem->ProcessEvents()){gSystem->Sleep(200);};
2682 void TCircle::Show(
int nPts,
const double *Pts,
int pstep)
const
2684 static TCanvas *myCanvas = 0;
2685 static TGraph *ptGraph = 0;
2686 static TGraph *ciGraph = 0;
2687 double x[100],y[100];
2688 if (nPts>100) nPts=100;
2689 for (
int i=0;i<nPts;i++) { x[i]=Pts[i*pstep+0]; y[i]=Pts[i*pstep+1]; }
2692 if(!myCanvas) myCanvas =
new TCanvas(
"TCircle_Show",
"",600,800);
2694 delete ptGraph;
delete ciGraph;
2696 ptGraph =
new TGraph(nPts , x, y);
2697 ptGraph->SetMarkerColor(kRed);
2698 ptGraph->Draw(
"A*");
2704 double s = tc.Path(xy);
2709 if (s<0) { tc.Backward(); s = tc.Path(xy);}
2711 for (
int i=0;i<100;i++) {x[i]=tc.Pos()[0];y[i]=tc.Pos()[1];tc.Move(ds);}
2713 ciGraph =
new TGraph(100 , x, y);
2714 ciGraph->Draw(
"Same CP");
2715 myCanvas->Modified();
2717 while(!gSystem->ProcessEvents()){gSystem->Sleep(200);};
2721 THelixFitter::THelixFitter():fPoli1Fitter(1)
2727 THelixFitter::~THelixFitter()
2730 void THelixFitter::Clear(
const char*)
2732 fCircleFitter.Clear();
2733 fPoli1Fitter.Clear();
2734 fPoli1Fitter.SetCoefs(1);
2738 void THelixFitter::Print(
const char*)
const
2740 THelixTrack::Print();
2741 fCircleFitter.Print();
2742 fPoli1Fitter.Print();
2745 void THelixFitter::Add (
double x,
double y,
double z)
2747 fCircleFitter.Add(x,y,z);
2750 void THelixFitter::AddErr(
const double *err2xy,
double err2z)
2752 fCircleFitter.AddErr(err2xy,err2z);
2755 void THelixFitter::AddErr(
double errhh,
double err2z)
2757 fCircleFitter.AddErr(errhh,err2z);
2760 double THelixFitter::Fit()
2764 double Xi2xy = fCircleFitter.Fit();
2765 if (Xi2xy>1e11)
return Xi2xy;
2767 int ndfXY = fCircleFitter.Ndf();
2768 double arho = fabs(fCircleFitter.Rho());
2769 double mm[4]={0},s=0;
2770 double z0 = myAux[nDat/2].z;
2771 for (
int ip=1;ip<nDat;ip++) {
2772 double z = myAux[ip].z-z0;
2773 double dx = myAux[ip].x - myAux[ip-1].x;
2774 double dy = myAux[ip].y - myAux[ip-1].y;
2775 double hord = sqrt(dx*dx+dy*dy);
2776 double t = 0.5*hord*arho;
2778 double ds = (fabs(t)<0.3)? hord*(1+t*t/6):2*asin(t)/arho;
2779 s+=ds; mm[0]+=s; mm[1]+=z;mm[2]+=s*s;mm[3]+=s*z;
2781 for (
int j=0;j<4;j++) { mm[j]/=nDat;}
2782 mm[2]-=mm[0]*mm[0]; mm[3]-= mm[0]*mm[1];
2785 double tanDip = mm[3]/mm[2];
2789 for (
int iDat=0;iDat<nDat;iDat++) {
2791 if (aux->wt<0)
continue;
2792 double ds = circ.Path(&(aux->x));
2793 circ.Move(ds); s+=ds;
2796 if (aux->exy[0]>0) {
2797 const double *dc = circ.Dir();
2798 corErr = tanDip*tanDip*
2799 (dc[0]*dc[0]*aux->exy[0]
2800 +dc[1]*dc[1]*aux->exy[2]
2801 +dc[0]*dc[1]*aux->exy[1]*2);
2803 fPoli1Fitter.Add(s,aux->z,aux->ezz+corErr);
2806 double Xi2z = fPoli1Fitter.Fit();
2808 int ndfSz = fPoli1Fitter.Ndf();
2810 int ndf = ndfSz+ndfXY;
2811 fChi2 = Xi2xy*ndfXY+Xi2z*ndfSz;
2812 if (ndf) fChi2/=ndf;
2817 double THelixFitter::FixAt(
const double val[5],
int flag)
2820 memcpy(xx,fX,
sizeof(xx));
2821 int move = (flag&1);
2823 s = fCircleFitter.Path(val);
2824 fCircleFitter.Move(s);
2825 fPoli1Fitter.Move(s);
2827 double Xi2c = fCircleFitter.FixAt(val,flag);
2828 if (flag&1) fPoli1Fitter.FixAt(0.,val[2]);
2831 s = fCircleFitter.Path(xx);
2832 fCircleFitter.Move(s);
2833 fPoli1Fitter.Move(s);
2837 double Xi2z = fPoli1Fitter.Chi2();
2838 int ndfc = fCircleFitter.Ndf();
2839 int ndfz = fPoli1Fitter.Ndf();
2841 int ndf = ndfc+ndfz;
2842 fChi2 = Xi2c*ndfc+Xi2z*ndfz;
2843 if (ndf) fChi2/=ndf;
2847 void THelixFitter::Skip(
int idx)
2849 fCircleFitter.Skip(idx);
2850 fPoli1Fitter.Skip(idx);
2851 int ndfc = fCircleFitter.Ndf();
2852 int ndfz = fPoli1Fitter.Ndf();
2853 int ndf = ndfc+ndfz;
2854 fChi2 = fCircleFitter.Chi2()*ndfc+fPoli1Fitter.Chi2()*ndfz;
2855 if (ndf) fChi2/=ndf;
2858 void THelixFitter::Update(
int kase)
2861 const double *pol = fPoli1Fitter.Coe();
2862 fCosL = 1./sqrt(pol[1]*pol[1]+1);
2863 double *haslet = fCircleFitter.Pos();
2867 fP[0] = haslet[2]*fCosL;
2868 fP[1] = haslet[3]*fCosL;
2869 fP[2] = pol[1]*fCosL;
2874 emx[0] = fPoli1Fitter.Emx()[0];
2875 emx[1] = fPoli1Fitter.Emx()[1]*fCosL*fCosL;
2876 emx[2] = fPoli1Fitter.Emx()[2]*fCosL*fCosL*fCosL*fCosL;
2877 fEmx->Set(fCircleFitter.Emx()->Arr(),emx);
2881 void THelixFitter::MakeErrs()
2883 fCircleFitter.MakeErrs();
2884 fPoli1Fitter.MakeErrs();
2888 double THelixFitter::EvalChi2()
2890 double Xi2c = fCircleFitter.EvalChi2();
2891 double Xi2z = fPoli1Fitter.EvalChi2();
2892 fChi2 = Xi2c*fCircleFitter.Ndf()+Xi2z*fPoli1Fitter.Ndf();
2893 fChi2/=(fCircleFitter.Ndf()+fPoli1Fitter.Ndf()+1e-10);
2897 void THelixFitter::Test(
int kase)
2907 if (!(kase&3 ))kase+=1+2;
2908 if (!(kase&12))kase+=4+8;
2910 enum {nPts=5,nHH=8};
2911 double e[4],x[10],xe[10];
2913 aShift[0]=-acos(0.25);
2914 aShift[1]=-acos(0.50);
2916 aShift[3]= acos(0.25);
2917 aShift[5]= acos(0.50);
2921 static TCanvas* myCanvas[9]={0};
2922 static TH1F *hh[nHH]={0};
2923 static const char *hNams[]={
"pH",
"pA",
"pC",
"pZ",
"pD",
"Xi2",
"Xi2E",
"Xi2d",0};
2924 if(!myCanvas[0]) myCanvas[0]=
new TCanvas(
"THelixFitter_TestC1",
"",600,800);
2925 myCanvas[0]->Clear();
2926 myCanvas[0]->Divide(1,nHH);
2928 for (
int i=0;i<nHH;i++) {
2929 double low = (i>=5)? 0:-5;
2931 delete hh[i]; hh[i]=
new TH1F(hNams[i],hNams[i],100,low,upp);
2932 myCanvas[0]->cd(i+1); hh[i]->Draw();
2936 static TH1F *h2h[4]={0,0,0,0};
2937 static const char *h2Nams[]={
"targYY",
"targZZ",
"targYZ",
"calcYZ",0};
2939 if(!myCanvas[1]) myCanvas[1]=
new TCanvas(
"THelixFitter_TestC2",
"",600,800);
2940 myCanvas[1]->Clear();
2941 myCanvas[1]->Divide(1,n2h);
2942 for (
int i=0;i<n2h;i++) {
2943 delete h2h[i]; h2h[i]=
new TH1F(h2Nams[i],h2Nams[i],100,-5,5);
2944 myCanvas[1]->cd(i+1); h2h[i]->Draw();
2949 static TH1F *h3h[4]={0,0,0,0};
2950 static const char *h3Nams[]={
"dcaXY",
"dcaXYNor",
"dcaZ",
"dcaZNor",0};
2952 if(!myCanvas[2]) myCanvas[2]=
new TCanvas(
"THelixFitter_TestC3",
"",600,800);
2953 myCanvas[2]->Clear();
2954 myCanvas[2]->Divide(1,n3h);
2955 for (
int i=0;i<n3h;i++) {
2956 delete h3h[i]; h3h[i]=
new TH1F(h3Nams[i],h3Nams[i],100,-5,5);
2957 myCanvas[2]->cd(i+1); h3h[i]->Draw();
2962 double spotSurf[4]= {-100,1,0,0};
2963 double spotAxis[3][3]= {{0,1,0},{0,0,1},{1,0,0}};
2968 for (
int idip=80;idip<=80;idip+=20){
2969 double dip = idip/180.*3.1415;
2971 double cosDip = cos(dip);
2972 double sinDip = sin(dip);
2973 double tanDip = tan(dip);
if(tanDip){};
2974 for (
int ir = 50; ir <= 1000; ir +=20) {
2976 double len = 100;
if (len>aR*3) len = aR*3;
2977 for (
double ang00 = -3; ang00 < 3.1; ang00+=0.2) {
2978 double ang0 = ang00;
2980 for (
int sgn = -1; sgn<=1; sgn+=2) {
2981 if(sgn>0 && !(kase&4))
continue;
2982 if(sgn<0 && !(kase&8))
continue;
2985 double dang = len/R/nPts;
2986 double C0 = cos(ang0);
2987 double S0 = sin(ang0);
2990 double trakPars[7]={100,200,300,C0*cosDip,S0*cosDip,sinDip,1/R};
2991 THelixTrack trak(trakPars+0,trakPars+3,trakPars[6]);
2993 for (
int is=0;is<nPts;is++) {
2994 double ang = ang0 + dang*is;
2995 double S = sin(ang),C = cos(ang);
2996 double eR = ran.Gaus(0,RERR)*sgn;
2997 double eZ = ran.Gaus(0,ZERR);
2998 double shift = aShift[is%5];
3000 double SS = sin(ang+shift);
3001 double CC = cos(ang+shift);
3002 e[0] = pow(RERR*SS,2);
3003 e[1] =-pow(RERR ,2)*CC*SS;
3004 e[2] = pow(RERR*CC,2);
3006 x[0] = 100 + (R)*(S-S0);
3007 x[1] = 200 - (R)*(C-C0);
3008 double len = (R)*(ang-ang0);
3009 x[2] = 300 + len*tan(dip);
3013 helx.Add (xe[0],xe[1],xe[2]);
3014 helx.AddErr(e,e[3]);
3016 double Xi2 =helx.Fit();
3017 if(!(kase&helx.GetCase()))
continue;
3020 if ((isgn=helx.Emx()->Sign())<0) {
3021 ::Warning(
"Test1",
"Negative errmtx %d",isgn);
continue;}
3023 if (kase&16) Xi2=helx.FixAt(x);
3028 TCL::ucopy(x,vals,3);vals[3]=0;vals[4]=1./R;
3029 Xi2=helx.FixAt(vals,4);
3031 if (kase&128) helx.Show();
3032 double Xi2E =helx.EvalChi2();
3034 trak.
Move(0.3*len/cosDip);
3035 memcpy(x,trak.Pos(),
sizeof(x));
3036 ang0 = atan2(trak.Dir()[1],trak.Dir()[0]);
3038 double s = helx.Path(x);
3042 double pos[3],dir[3],rho;
3044 if ((isgn=helx.Emx()->Sign())<0) {
3045 ::Warning(
"Test2",
"Negative errmtx %d",isgn);
continue;}
3047 helx.
Get (pos,dir,rho);
3048 double psi = atan2(dir[1],dir[0]);
3049 double sinPsi = sin(psi);
3050 double cosPsi = cos(psi);
3051 double tanPsi = sinPsi/cosPsi;
if(tanPsi){};
3052 double dd[10],hf[10];
3053 double dx = x[0]-pos[0];
3054 double dy = x[1]-pos[1];
3055 dd[0] = -dx*sinPsi+dy*cosPsi;
3056 hf[0] = dd[0]/sqrt(emx->mHH+1e-20);
3058 if (dd[2]> M_PI) dd[2]-=2*M_PI;
3059 if (dd[2]<-M_PI) dd[2]+=2*M_PI;
3060 hf[1] = dd[2]/sqrt(emx->mAA+1e-20);
3062 hf[2] = dd[4]/sqrt(emx->mCC+1e-20);
3063 dd[6] = (helx.Pos()[2]-x[2])/pow(helx.GetCos(),2);
3064 hf[3] = dd[6]/sqrt(emx->mZZ+1e-20);
3065 dd[8] = asin(dir[2])-dip;
3066 if (dd[8]> M_PI) dd[8]-=2*M_PI;
3067 if (dd[8]<-M_PI) dd[8]+=2*M_PI;
3068 hf[4] = dd[8]/(sqrt(emx->mLL));
3072 for (
int ih=0;ih<nHH;ih++) { hh[ih]->Fill(hf[ih]);}
3075 double xIde[3],pIde[3],xFit[3],pFit[3],eSpot[3],hfil,sIde,sFit;
3080 { spotSurf[0] = -x[0]; closePoint=2006;}
3081 sIde = trak.Step(200.,spotSurf,4, xIde,pIde,closePoint);
3083 if (fabs(spotSurf[0]+TCL::vdot(xIde,spotSurf+1,3))>0.001) {
3084 printf(
"***Wrong point found**\n");
3088 sFit = helx.Step(200.,spotSurf,4, xFit,pFit,closePoint);
3089 if (sFit>=1000 )
continue;
3090 if (fabs(pIde[0]-pFit[0])>0.1)
continue;
3094 hfil = (xFit[1]-xIde[1]); hfil/= sqrt(eSpot[0]);
3096 hfil = (xFit[2]-xIde[2]); hfil/= sqrt(eSpot[2]);
3098 hfil = (xFit[1]-xIde[1])*(xFit[2]-xIde[2]);
3099 h2h[2]->Fill(hfil*100);
3100 h2h[3]->Fill(hfil/sqrt(eSpot[0]*eSpot[2]));
3105 double dcaXY,dcaZ,dcaEmx[3];
3106 double sDca = helx.
Dca(trakPars,dcaXY,dcaZ,dcaEmx);
3107 if (fabs(sDca)<1000) {
3108 h3h[0]->Fill(dcaXY);
3109 h3h[1]->Fill(dcaXY/sqrt(dcaEmx[0]));
3110 h3h[2]->Fill(dcaZ );
3111 h3h[3]->Fill(dcaZ /sqrt(dcaEmx[2]));
3119 for (
int ih=0;myCanvas[ih];ih++) {
3120 myCanvas[ih]->Modified();
3121 myCanvas[ih]->Update();
3123 while(!gSystem->ProcessEvents()){gSystem->Sleep(200);};
3126 void THelixFitter::Show()
const
3128 static TCanvas *myCanvas = 0;
3129 static TGraph *ptGraph[2] = {0,0};
3130 static TGraph *ciGraph[2] = {0,0};
3131 double x[100],y[100],z[100],l[100]
3132 , X[100],Y[100],Z[100];
3134 if (nPts>100) nPts=100;
3137 double s = tc.Path(aux[0].x,aux[0].y); tc.
Move(s);
3138 s = tc.Path(aux[nPts-1].x,aux[nPts-1].y);
3142 for (
int i=0;i<nPts;i++) {
3143 if (i) {ds = tc.Path(aux[i].x,aux[i].y);tc.
Move(ds);l[i]=l[i-1]+ds;}
3144 x[i]=aux[i].x; y[i]=aux[i].y; z[i]=aux[i].z;
3145 X[i]=tc.Pos()[0];Y[i]=tc.Pos()[1];Z[i]=tc.Pos()[2];
3149 if(!myCanvas) myCanvas =
new TCanvas(
"THelixFitter_Show",
"",600,800);
3151 myCanvas->Divide(1,2);
3153 delete ptGraph[0];
delete ciGraph[0];
3154 ptGraph[0] =
new TGraph(nPts , x, y);
3155 ptGraph[0]->SetMarkerColor(kRed);
3156 myCanvas->cd(1); ptGraph[0]->Draw(
"A*");
3157 delete ptGraph[1];
delete ciGraph[1];
3158 ptGraph[1] =
new TGraph(nPts , l, z);
3159 ptGraph[1]->SetMarkerColor(kRed);
3160 myCanvas->cd(2); ptGraph[1]->Draw(
"A*");
3162 ciGraph[0] =
new TGraph(nPts , X, Y);
3163 myCanvas->cd(1); ciGraph[0]->Draw(
"Same CP");
3164 ciGraph[1] =
new TGraph(nPts , l, Z);
3165 myCanvas->cd(2); ciGraph[1]->Draw(
"Same CP");
3167 myCanvas->Modified();
3169 while(!gSystem->ProcessEvents()){gSystem->Sleep(200);};
3173 double TCircleFitter::f()
3175 return 4*((fG1-fRr)/2)*fR*fR;
3178 double TCircleFitter::F()
3183 double TCircleFitter::df(
int i)
3186 case 0:
return -4*(fXrr -2*fXx*fXd - 2*fXy*fYd);
3187 case 1:
return -4*(fYrr -2*fXy*fXd - 2*fYy*fYd);
3188 case 2:
return 2*(fG1 - fRr);
3195 double TCircleFitter::d2f(
int i,
int j)
3203 case 0:
return 8*fXx;
3204 case 01:
return 8*fXy;
3205 case 11:
return 8*fYy;
3206 case 02:;
case 12:
return 0;
3208 default: printf (
"Kase=%d\n",ij); assert(0);
3214 double TCircleFitter::Rho2 () {
return fRho*fRho;}
3217 double TCircleFitter::dRho2(
int i)
3219 double ans =fRho*fRho;
3222 case 0:
return 2*ans*fXd;
3223 case 1:
return 2*ans*fYd;
3230 double TCircleFitter::d2Rho2(
int i,
int j)
3235 if (j>i) {
int jj = j; j = i; i = jj;}
3237 double rho2 = fRho*fRho,rho4 = rho2*rho2, rho6 = rho4*rho2;
3239 case 0:
return 8*(rho6)*fXd*fXd-2*(rho4);;
3240 case 01:
return 8*(rho6)*fXd*fYd;
3241 case 11:
return 8*(rho6)*fYd*fYd-2*(rho4);
3242 case 02:
return 4*(rho6)*fXd;
3243 case 12:
return 4*(rho6)*fYd;
3244 case 22:
return 2*(rho6);
3245 default: printf (
"Kase=%d\n",ij); assert(0);
3249 double TCircleFitter::dF(
int i)
3253 double ans = 1./4*(df(i)*Rho2() + f()*dRho2(i));
3257 double TCircleFitter::d2F(
int i,
int j)
3261 double ans = 1./4*(d2f(i,j)*Rho2() +df(j)*dRho2(i)
3262 +df (i) *dRho2(j)+f() *d2Rho2(i,j));
3266 void THelixTrack::TestTwoHlx()
3268 TVector3 dif(0.1,0.,0.);
3269 double rnd = gRandom->Rndm();
3271 rnd = gRandom->Rndm();
3273 rnd = gRandom->Rndm();
3275 TVector3 D1 = dif.Orthogonal();
3276 rnd = gRandom->Rndm();
3278 TVector3 D2 = dif.Orthogonal();
3279 rnd = gRandom->Rndm();
3283 double R1=20,R2=100;
3284 double shift1 = R1*gRandom->Rndm()*0.1;
if (shift1>33) shift1=33;
3285 double shift2 = R2*gRandom->Rndm()*0.1;
if (shift2>33) shift2=33;
3287 double &p2 = dif[0];
3292 TVector3 P1(th1.Pos()),P2(th2.Pos());
3294 TVector3 dP = (P1-P2);
3295 TVector3 D1(th1.Dir());
3296 TVector3 D2(th2.Dir());
3297 double eps1 = dP.Dot(D1);
3298 double eps2 = dP.Dot(D2);
3299 printf(
"TestTwoHlx: Eps1 = %g Eps2 = %g\n",eps1,eps2);
3304 th1.
Move(shift1); th2.
Move(shift2);
3306 s1 = th1.Path(th2,&s2);
3312 TVector3 P1(th1.Pos()),P2(th2.Pos());
3313 TVector3 dP = (P1-P2);
3314 double dist = dP.Mag();
3316 TVector3 D1(th1.Dir());
3317 TVector3 D2(th2.Dir());
3318 double eps1 = dP.Dot(D1);
3319 double eps2 = dP.Dot(D2);
3321 printf(
"TestTwoHlx: Eps1 = %g Eps2 = %g dist = %g\n",eps1,eps2,dist);
3323 printf(
"TestTwoHlx: s1=%g(%g),s2 = %g(%g)\n",s1,shift1,s2,shift2);
3329 void TCircleFitter::Show()
const
3331 TCircle::Show(fN,&(fAux[0].x),
sizeof(fAux[0])/
sizeof(
double));
3337 myTHFits(
double h,
double z,
double c,
double a,
double l):mH(h),mZ(z),mC(c),mA(a),mL(l){}
3338 operator const double* ()
const {
return &mH;}
3339 operator double* () {
return &mH;}
3340 myTHFits() {memset(
this,0,
sizeof(*
this));}
3342 static const myTHFits& GetRange() {
return mgRange;}
3352 myTHFits myTHFits::mgRange(1,1,1,30*3.14/180,30*3.14/180);
3360 void operator+=(
const myTHFits &fp);
3361 operator const double *()
const {
return &_x;}
3362 operator double *() {
return &_x;}
3377 #include "TVector3.h"
3379 void myTHPars::operator+=(
const myTHFits &fp)
3381 _x += -_sinCA*fp.mH;
3385 double a = fp.mA,cA,sA;
3386 if (fabs(a) < 0.01) {sA = a*(1-a*a/6); cA = 1-a*a/2;}
3387 else {sA = sin(a); cA = cos(a) ;}
3389 double cosCA = _cosCA;
3390 _cosCA = cosCA*cA-_sinCA*sA;
3391 _sinCA = cosCA*sA+_sinCA*cA;
3395 double l = fp.mL,tL;
3396 if (fabs(l) < 0.1) {tL = l*(1+l*l/3);}
3397 else {tL = tan(l) ;}
3398 _tanl = (_tanl+tL)/(1.-_tanl*tL);
3399 if (fabs( _cosCA)>1 || fabs( _sinCA)>=1) { _cosCA = cos(_psi);
3400 _sinCA = sin(_psi);}
3405 const double *x = th.Pos();
3406 const double *d = th.Dir();
3407 _curv = th.GetRho();
3408 _x = x[0]; _y=x[1]; _z=x[2];
3410 double cL = th.GetCos();
3414 _psi = atan2(_sinCA,_cosCA);
3419 double d[3]={_cosCA,_sinCA,_tanl};
3420 th.Set(&_x,d,_curv);
3424 static double JoinTwo(
int nP1,
const double *P1,
const double *C1
3425 ,
int nP2,
const double *P2,
const double *C2
3426 ,
double *PJ,
double *CJ
3427 ,
int mode,
const double *range=0)
3433 int nC1 = nP1*(nP1+1)/2;
3434 int nC2 = nP2*(nP2+1)/2;
3436 double *a = ard.GetArray();
3438 double *sumCI = (a+=nC2);
3439 double *sumEI = (a+=nC2);
3440 double *C1P1 = (a+=nC2);
3441 double *subP = (a+=nC2);
3447 TCL::ucopy(C2,sumC, nC2);
3448 TCL::vadd (C1,sumC,sumC,nC1);
3449 if (CJ) TCL::ucopy(sumC,CJ,nC2);
3458 TCL::ucopy(P1,PJ+0 ,nP1 );
3459 TCL::vzero( PJ+nP1,nP2-nP1);
3464 assert(EmxSign(nP2,sumC)>1e-10);
3466 TCL::ucopy(P1,subP ,nP1);
3469 TCL::vsub(C2,sumEI,sumEI,nC2);
3473 if (!PJ)
return chi2;
3480 void THelixKFitter::Add (
const double x[3])
3482 fAux.resize(fAux.size()+1);
3485 for (
int i=0,li=0;i<3;li+=++i) {aux.e[li+i]=1;aux.x[i]=x[i];}
3488 void THelixKFitter::AddErr (
const double e[6])
3490 memcpy(fAux.back().e,e,6*
sizeof(e[0]));
3493 double THelixKFitter::Fit()
3496 static const int konv[15] ={0,6,9,3,8,5,1,7,4,2,10,13,12,11,14};
3497 double cmx[15]={0},tmp[15]={0};
3499 if (fFitingShow) fFitingShow->clear();
3502 double dir[3]={0},myXi2=0;
3503 TCL::vsub(fAux[1].x,fAux[0].x,dir,3);
3504 th.Set(fAux[0].x,dir,0.);
3507 double F[5][5]={{0}};
3508 for (
int ip=0;ip<(int)fAux.size();ip++) {
3509 double s = th.Path(fAux[ip].x[0],fAux[ip].x[1]);
3511 TMatrixD Fm(5,5,F[0]); Fm.Invert(); TCL::ucopy(Fm.GetMatrixArray(),F[0],5*5);
3513 TCL::ucopy(tmp,cmx,15);
3516 double T[2][3] = {{-P._sinCA,P.
_cosCA,0}
3519 double hG[3],
hit[3];
3523 TCL::vsub(fAux[ip].x,&P._x,hit,3);
3524 double hz[2]={ hit[0]*T[0][0]+hit[1]*T[0][1]
3528 double iG[15],oG[15];
3530 static const int kRho = 2;
3531 for (
int i=0,li=0;i<5;li+=++i) {
3532 if (i<kRho)
continue;
3534 if (i==kRho) cmx[li+kRho] = 1e-20;
3537 for (
int jj=0;jj<15;jj++) {iG[konv[jj]]=cmx[jj];}
3538 myXi2 = JoinTwo(2,hz,hG,5,0,iG,oF,oG,0,myTHFits::GetRange());
3539 for (
int jj=0;jj<15;jj++) {cmx[jj]=oG[konv[jj]];}
3541 fChi2+=myXi2; fAux[ip].xi2=myXi2;
3544 for (
int i=0;i<3;i++) {fFitingShow->push_back(P[i]);}}
3548 double s = th.Path(fAux[0].x);
3551 fChi2/= Ndf()+1e-10;
3555 void THelixKFitter::Test(
int nEv)
3557 static TCanvas* myCanvas[9]={0};
3558 static TH1F *hh[20]={0};
3559 static const char *hNams[]={
3560 "pHKalmn",
"pAKalmn",
"pCKalmn",
"pZKalmn",
"pLKalmn",
"Xi2Kalmn",
3561 "pHDubna",
"pADubna",
"pCDubna",
"pZDubna",
"pLDubna",
"Xi2Dubna"};
3563 static const double lims[][2]={{-20 ,20},{-20 ,20},{-20 ,20},{-20 ,20},{-20 ,20},{ 0 ,10}
3564 ,{-20 ,20},{-20 ,20},{-20 ,20},{-20 ,20},{-20 ,20},{ 0 ,10}};
3565 const int maxPads=3;
3566 const int nPads =
sizeof(hNams)/
sizeof(
void*);
3567 const int nCans = nPads/maxPads;
3568 for (
int jCan=0;jCan<nCans;jCan++) {
3569 if(!myCanvas[jCan]) {
3570 TString ts(
"THelixKKFitter_Test"); ts+=jCan;
3571 myCanvas[jCan]=
new TCanvas(ts,ts,600,800);
3573 myCanvas[jCan]->Clear(); myCanvas[jCan]->Divide(1,maxPads);
3577 for (
int jCan=0;jCan<nCans;jCan++) {
3578 for (
int jPad=0;jPad<maxPads;jPad++) {
3579 delete hh[jH]; hh[jH]=
new TH1F(hNams[jH],hNams[jH],100,lims[jH][0],lims[jH][1]);
3580 myCanvas[jCan]->cd(jPad+1); hh[jH]->Draw(); jH++;
3583 const int kHits = 50;
3584 double R = 50 + 100*gRandom->Rndm();
3586 int iPhi0 = 360*gRandom->Rndm();
3587 int iLam0 = 100*(gRandom->Rndm()-0.5);
3589 double ToRad = M_PI/180;
3590 double Phi0 = ToRad*iPhi0;
3591 double Lam0 = ToRad*iLam0;
3592 double CL = cos(Lam0), SL =sin(Lam0);
3593 double POS[3]={0.1,0.2,0.3};
3594 double DIR[3]={ CL*cos(Phi0),CL*sin(Phi0),SL};
3595 double NOR[2]={-sin(Phi0) ,cos(Phi0) };
3598 double HitErr[3]={0.1*0.1,0.1*0.1,0.2*0.2};
3600 const TMatrixDSym &HitEmx = RV.GetMtx();
3602 for (
int i=0,li=0;i<3;li+=++i) {
for (
int j=0;j<=i;++j){hitErr[li+j]=HitEmx[i][j];};}
3603 double step =S/kHits;
3605 double Xi2[2]={0},d[5],dif[5];
3606 for (
int iEv=0;iEv<nEv;iEv++) {
3610 for (
int ih=0;ih<kHits;ih++) {
3611 TVectorD res = RV.Gaus();
3613 for (
int jj=0;jj<3;jj++) {myHit[jj]=ht.Pos()[jj]+res[jj];}
3614 kf.Add(myHit); kf.AddErr(hitErr);
3615 hf.Add(myHit[0],myHit[1],myHit[2]); hf.AddErr(hitErr,hitErr[5]);
3619 if (!iEv) kf.SetFitingShow();
3620 myXi2[0] = kf.Fit();
3621 if (!iEv) kf.Show();
3623 myXi2[1] = hf.Fit();
3625 double ds = hf.Path(POS[0],POS[1]); hf.
Move(ds);
3626 ds = kf.Path(POS[0],POS[1]); kf.
Move(ds);
3629 for (
int jk=0;jk<2;jk++) {
3631 hh[jk*6+5]->Fill(myXi2[jk]);
3632 TCL::vadd(GG[jk+2],*hlx->Emx(),GG[jk+2],15);
3633 TCL::vsub(hlx->Pos(),POS,dif,3);
3634 d[0] = TCL::vdot(dif,NOR,2);
3635 d[1] = TVector3(hlx->Dir()).DeltaPhi(TVector3(DIR));
3636 d[2] = hlx->GetRho()-1./R;
3638 d[4] = -(TVector3(hlx->Dir()).Theta()-TVector3(DIR).Theta());
3639 if (d[4]<=-M_PI) d[4]+=M_PI*2;
3640 if (d[4]>= M_PI) d[4]-=M_PI*2;
3642 for (
int i=0,li=0;i<5;li+=++i) {
3643 double err = (*(hlx->Emx()))[li+i]; err = sqrt(err);
3644 hh[jk*6+i]->Fill( d[i]/err);
3645 for (
int j=0;j<=i;++j) {e[li+j]+=d[i]*d[j];}}
3651 for (
int jk=0;jk<4;jk++) {GG[jk]*=1./nEv;
if (jk<2) Xi2[jk]/=nEv;}
3654 printf(
"*** Compare KFit and DubnaFit Error matrices ***\n");
3655 printf(
"*** Average KXi2 =%g DXi2 = %g ***\n",Xi2[0],Xi2[1]);
3657 static const char *tit=
"HACZL";
3658 static const char *tsk[2]={
"KalmanFit",
"DubnaFit"};
3659 for (
int jk=0;jk<2;jk++) {
3660 printf(
"*** Test for %s Xi2=%g ***\n",tsk[jk],Xi2[jk]);
3661 double qA=0,qAmax=0;
3662 const double *eK = GG[jk ];
3663 const double *eD = GG[jk+2];
3665 for (
int i=0,li=0;i< 5;li+=++i) {
3666 dia[i]= (eK[li+i]+eD[li+i])/2;
3667 for (
int j=0;j<=i;j++) {
3668 double dif = (eK[li+j]-eD[li+j])/sqrt(dia[i]*dia[j]);
3669 printf(
"(%c%c) \t%g = \t%g \t%g\n",tit[i],tit[j],eK[li+j],eD[li+j],dif);
3671 qA+= (dif);
if (dif>qAmax) qAmax=dif;
3674 printf(
"Quality %g < %g < 1\n",qA,qAmax);
3677 for (
int i=0;myCanvas[i];i++) {
3678 myCanvas[i]->Modified();myCanvas[i]->Update();}
3680 while(!gSystem->ProcessEvents()){gSystem->Sleep(200);};
3685 void THelixKFitter::Print(
const char* txt)
const
3689 #include "StarRoot/StDraw3D.h"
3691 void THelixKFitter::Show()
const
3696 std::vector<double> Pts;
3697 std::vector<double> Fts;
3700 for (
int ip=0;ip<(int)fAux.size();ip++) {
3701 double s = th.Path(fAux[ip].x[0],fAux[ip].x[1]);
3702 for (
int i=0;i<3;i++) {Pts.push_back(fAux[ip].x[i]);}
3704 if (!ip) {th.
Move(s);
continue;}
3705 double delta = s/10;
3706 for (
int j=0;j<10;j++) {
3707 for (
int i=0;i<3;i++) {Fts.push_back(th.Pos()[i]);}
3711 if (fFitingShow) draw->
Points(*fFitingShow,kUnusedHit);
3712 draw->
Points(Pts,kUsedHit);
3713 draw->
Line(Fts,kGlobalTrack);
3714 draw->UpdateModified();
3718 #include "TMatrixT.h"
3719 #include "TMatrixTSym.h"
3720 #include "TVectorT.h"
3722 double EmxSign(
int n,
const double *e)
3726 for (
int i=0,li=0;i< n;li+=++i) {
3727 double qwe = e[li+i];
3728 if(qwe<=0)
return qwe;
3729 qwe = pow(2.,-
int(log(qwe)/(2*log(2))));
3731 for (
int j=0;j<=i;j++ ) {
3732 S[i][j]=e[li+j]*coe[i]*coe[j]; S[j][i]=S[i][j];
3734 TMatrixD EigMtx(n,n);
3736 EigMtx = S.EigenVectors(EigVal);
3737 TVectorD EigB = EigMtx*TVectorD(n,myQQQ);
3739 for (
int i=0;i<n;i++) {
if (EigVal[i]<ans) ans = EigVal[i];}
3740 if (ans>1e-10)
return ans;
3741 EigVal.Print(
"EigVal");
3743 TVectorD(n,myQQQ).Print();
static float * traat(const float *a, float *s, int m, int n)
double Eval(double step, double *xyz, double *dir, double &rho) const
Evaluate params with given step along helix.
double PathX(const THelixTrack &hlx, double *s2=0, double *dist=0, double *xyz=0) const
double _curv
signed curvature [sign = sign(-qB)]
virtual TObject * Line(int n, const double *xyz, Color_t col=Color_t(-1), Style_t sty=Style_t(-1), Size_t siz=Size_t(-1))
This is an overloaded member function, provided for convenience.
void Get(double *xyz, double *dir, double &rho) const
Get current parameters.
Class StDraw3D - to draw the 3D primitives like 3D points and 3D lines decorated with the STAR detect...
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)
static float * trqsq(const float *q, const float *s, float *r, int m)
void Backward()
Change direction.
static float * trsinv(const float *g, float *gi, int n)
virtual TObject * Points(int n, const float *xyz, EDraw3DStyle sty)
This is an overloaded member function, provided for convenience.
static float * trasat(const float *a, const float *s, float *r, int m, int n)
double _tanl
tangent of the track momentum dip angle
double _cosCA
sin and cosin of cross angle
static float * trupck(const float *u, float *s, int m)
double Move(double step)
Move along helix.
static float * tratsa(const float *a, const float *s, float *r, int m, int n)
virtual void Animate()
Animate the viewer from the gdb session.
void GetSpot(const double axis[3][3], double emx[3]) const
double FixAt(const double vals[5], int flag)
double Dca(const double point[3], double *dcaErr=0) const
DCA to given space point (with error matrix)