35 #include "TGeoManager.h"
36 #include "TDatabasePDG.h"
42 #define MINSTEP 0.001 // minimum step [cm] for Runge Kutta and iteration to POCA
49 void RKTrackRep::Streamer(TBuffer &R__b)
53 if (R__b.IsReading()) {
54 R__b.ReadClassBuffer(RKTrackRep::Class(),
this);
60 R__b.WriteClassBuffer(RKTrackRep::Class(),
this);
65 RKTrackRep::RKTrackRep() :
GFAbsTrackRep(5), fDirection(0), fNoMaterial(
false), fPdg(0), fMass(0.), fCharge(-1), fCachePlane(), fCacheSpu(1), fSpu(1), fAuxInfo(1,2) {
72 const TVector3& poserr,
73 const TVector3& momerr,
75 GFAbsTrackRep(5), fDirection(0), fNoMaterial(
false), fCachePlane(), fCacheSpu(1), fAuxInfo(1,2) {
86 GFAbsTrackRep(5), fDirection(0), fNoMaterial(
false), fCachePlane(), fCacheSpu(1), fAuxInfo(1,2) {
93 static const double value(1.E4);
104 GFAbsTrackRep(5), fDirection(0), fNoMaterial(
false), fCachePlane(), fCacheSpu(1), fAuxInfo(1,2) {
115 TMatrixD cov6D = aGFTrackCandPtr->
getCovSeed();
118 if( cov6D[0][0] < 0.0 ){
119 posError.SetXYZ(sqrt(cov6D[0][0]),sqrt(cov6D[1][1]),sqrt(cov6D[2][2]));
120 momError.SetXYZ(sqrt(cov6D[3][3]),sqrt(cov6D[4][4]),sqrt(cov6D[5][5]));
122 posError.SetXYZ(sqrt(cov6D[0][0]),sqrt(cov6D[1][1]),sqrt(cov6D[2][2]));
123 momError.SetXYZ(sqrt(cov6D[3][3]),sqrt(cov6D[4][4]),sqrt(cov6D[5][5]));
126 TVector3
pos(state6D[0][0],state6D[1][0],state6D[2][0]);
127 TVector3
mom(state6D[3][0],state6D[4][0],state6D[5][0]);
133 memset(
fStateJac,0x00,(7+7*7)*
sizeof(
double));
134 memset(
fNoise,0x00,7*7*
sizeof(
double));
135 memset(
fStateJac,0x00,7*7*
sizeof(
double));
137 memset(
fJ_pM_5x7,0x00,5*7*
sizeof(
double));
138 memset(
fJ_pM_5x6,0x00,5*6*
sizeof(
double));
139 memset(
fJ_Mp_7x5,0x00,7*5*
sizeof(
double));
140 memset(
fJ_Mp_6x5,0x00,6*5*
sizeof(
double));
151 GFException exc(
"RKTrackRep::setData() was called with a reference plane which is not the same as the one from the last extrapolate(plane,state,cov).",__LINE__,__FILE__);
164 GFException exc(
"RKTrackRep::getAuxInfo() - Trying to get auxiliary information with planes mismatch (Information returned does not belong to requested plane)!",__LINE__,__FILE__);
176 TParticlePDG *
part = TDatabasePDG::Instance()->GetParticle(
fPdg);
178 GFException exc(
"RKTrackRep::setPDG ==> particle id not known to TDatabasePDG",__LINE__,__FILE__);
181 fMass = part->Mass();
189 const TVector3& poserr,
190 const TVector3& momerr){
194 double pw = mom.Mag();
204 (mom.X()*mom.X() * momerr.X()*momerr.X()+
205 mom.Y()*mom.Y() * momerr.Y()*momerr.Y()+
206 mom.Z()*mom.Z() * momerr.Z()*momerr.Z());
208 fCov(1,1) = pow((
fU.X()/pw -
fW.X()*pu/(pw*pw)),2.) * momerr.X()*momerr.X() +
209 pow((
fU.Y()/pw -
fW.Y()*pu/(pw*pw)),2.) * momerr.Y()*momerr.Y() +
210 pow((
fU.Z()/pw -
fW.Z()*pu/(pw*pw)),2.) * momerr.Z()*momerr.Z();
212 fCov(2,2) = pow((
fV.X()/pw -
fW.X()*pv/(pw*pw)),2.) * momerr.X()*momerr.X() +
213 pow((
fV.Y()/pw -
fW.Y()*pv/(pw*pw)),2.) * momerr.Y()*momerr.Y() +
214 pow((
fV.Z()/pw -
fW.Z()*pv/(pw*pw)),2.) * momerr.Z()*momerr.Z();
216 fCov(3,3) = poserr.X()*poserr.X() *
fU.X()*
fU.X() +
217 poserr.Y()*poserr.Y() *
fU.Y()*
fU.Y() +
218 poserr.Z()*poserr.Z() *
fU.Z()*
fU.Z();
220 fCov(4,4) = poserr.X()*poserr.X() *
fV.X()*
fV.X() +
221 poserr.Y()*poserr.Y() *
fV.Y()*
fV.Y() +
222 poserr.Z()*poserr.Z() *
fV.Z()*
fV.Z();
227 const TVector3&
mom){
257 state7[0] =
fO.X() + state5(3,0)*
fU.X() + state5(4,0)*
fV.X();
258 state7[1] =
fO.Y() + state5(3,0)*
fU.Y() + state5(4,0)*
fV.Y();
259 state7[2] =
fO.Z() + state5(3,0)*
fU.Z() + state5(4,0)*
fV.Z();
261 state7[3] = spu * (
fW.X() + state5(1,0)*
fU.X() + state5(2,0)*
fV.X());
262 state7[4] = spu * (
fW.Y() + state5(1,0)*
fU.Y() + state5(2,0)*
fV.Y());
263 state7[5] = spu * (
fW.Z() + state5(1,0)*
fU.Z() + state5(2,0)*
fV.Z());
266 double norm = 1. / sqrt(state7[3]*state7[3] + state7[4]*state7[4] + state7[5]*state7[5]);
267 for (
unsigned int i=3; i<6; ++i) state7[i] *= norm;
269 state7[6] = state5(0,0);
278 fPos.SetXYZ(state7[0], state7[1], state7[2]);
281 fDir.SetXYZ(state7[3], state7[4], state7[5]);
292 TMatrixD state5(5,1);
293 state5(0,0) = state7[6];
294 state5(1,0) =
fDir*
fU / AtW;
295 state5(2,0) =
fDir*
fV / AtW;
305 const GFDetPlane& pl,
const TMatrixD& state5,
const double& spu,
313 fpTilde.SetXYZ(spu * (
fW.X() + state5(1,0)*
fU.X() + state5(2,0)*
fV.X()),
314 spu * (
fW.Y() + state5(1,0)*
fU.Y() + state5(2,0)*
fV.Y()),
315 spu * (
fW.Z() + state5(1,0)*
fU.Z() + state5(2,0)*
fV.Z()));
318 const double pTildeMag =
fpTilde.Mag();
319 const double pTildeMag2 = pTildeMag*pTildeMag;
321 const double utpTildeOverpTildeMag2 =
fU*
fpTilde / pTildeMag2;
322 const double vtpTildeOverpTildeMag2 =
fV*
fpTilde / pTildeMag2;
337 double fact = spu / pTildeMag;
340 fJ_pM_5x7[12] = fact * (
fU.Z() -
fpTilde.Z()*utpTildeOverpTildeMag2 );
342 fJ_pM_5x7[17] = fact * (
fV.X() -
fpTilde.X()*vtpTildeOverpTildeMag2 );
343 fJ_pM_5x7[18] = fact * (
fV.Y() -
fpTilde.Y()*vtpTildeOverpTildeMag2 );
344 fJ_pM_5x7[19] = fact * (
fV.Z() -
fpTilde.Z()*vtpTildeOverpTildeMag2 );
350 const M5x5& in5x5_ = *((
M5x5*) in5x5.GetMatrixArray());
355 *Jac = TMatrixD(5,7, &(fJ_pM_5x7[0]));
361 const GFDetPlane& pl,
const TMatrixD& state5,
const double& spu,
368 fpTilde.SetXYZ(spu * (
fW.X() + state5(1,0)*
fU.X() + state5(2,0)*
fV.X()),
369 spu * (
fW.Y() + state5(1,0)*
fU.Y() + state5(2,0)*
fV.Y()),
370 spu * (
fW.Z() + state5(1,0)*
fU.Z() + state5(2,0)*
fV.Z()));
372 const double pTildeMag =
fpTilde.Mag();
373 const double pTildeMag2 = pTildeMag*pTildeMag;
375 const double utpTildeOverpTildeMag2 =
fU*
fpTilde / pTildeMag2;
376 const double vtpTildeOverpTildeMag2 =
fV*
fpTilde / pTildeMag2;
380 const double qop = state5(0,0);
384 double fact = -1. * p / (pTildeMag * qop);
389 fact = p * spu / pTildeMag;
392 fJ_pM_5x6[11] = fact * (
fU.Z() -
fpTilde.Z()*utpTildeOverpTildeMag2 );
394 fJ_pM_5x6[15] = fact * (
fV.X() -
fpTilde.X()*vtpTildeOverpTildeMag2 );
395 fJ_pM_5x6[16] = fact * (
fV.Y() -
fpTilde.Y()*vtpTildeOverpTildeMag2 );
396 fJ_pM_5x6[17] = fact * (
fV.Z() -
fpTilde.Z()*vtpTildeOverpTildeMag2 );
398 fJ_pM_5x6[18] =
fU.X();
399 fJ_pM_5x6[19] =
fU.Y();
400 fJ_pM_5x6[20] =
fU.Z();
402 fJ_pM_5x6[24] =
fV.X();
403 fJ_pM_5x6[25] =
fV.Y();
404 fJ_pM_5x6[26] =
fV.Z();
409 const M5x5& in5x5_ = *((
M5x5*) in5x5.GetMatrixArray());
414 *Jac = TMatrixD(5,6, &(fJ_pM_5x6[0]));
423 out5x5.ResizeTo(5, 5);
430 fDir.SetXYZ(state7[3], state7[4], state7[5]);
432 const double AtU =
fDir*
fU;
433 const double AtV =
fDir*
fV;
434 const double AtW =
fDir*
fW;
439 double fact = 1./(AtW*AtW);
440 fJ_Mp_7x5[16] = fact * (fU.X()*AtW - fW.X()*AtU);
441 fJ_Mp_7x5[21] = fact * (fU.Y()*AtW - fW.Y()*AtU);
442 fJ_Mp_7x5[26] = fact * (fU.Z()*AtW - fW.Z()*AtU);
444 fJ_Mp_7x5[17] = fact * (fV.X()*AtW - fW.X()*AtV);
445 fJ_Mp_7x5[22] = fact * (fV.Y()*AtW - fW.Y()*AtV);
446 fJ_Mp_7x5[27] = fact * (fV.Z()*AtW - fW.Z()*AtV);
450 fJ_Mp_7x5[3] = fU.X();
451 fJ_Mp_7x5[8] = fU.Y();
452 fJ_Mp_7x5[13] = fU.Z();
454 fJ_Mp_7x5[4] = fV.X();
455 fJ_Mp_7x5[9] = fV.Y();
456 fJ_Mp_7x5[14] = fV.Z();
462 M5x5& out5x5_ = *((
M5x5*) out5x5.GetMatrixArray());
467 *Jac = TMatrixD(7,5, &(fJ_Mp_7x5[0]));
476 out5x5.ResizeTo(5, 5);
483 fDir.SetXYZ(state7[3], state7[4], state7[5]);
485 const double AtU =
fDir*
fU;
486 const double AtV =
fDir*
fV;
487 const double AtW =
fDir*
fW;
491 const double qop = state7[6];
503 double fact = (-1.) * qop /
p;
508 fact = 1./(p*AtW*AtW);
509 fJ_Mp_6x5[16] = fact * (fU.X()*AtW - fW.X()*AtU);
510 fJ_Mp_6x5[21] = fact * (fU.Y()*AtW - fW.Y()*AtU);
511 fJ_Mp_6x5[26] = fact * (fU.Z()*AtW - fW.Z()*AtU);
513 fJ_Mp_6x5[17] = fact * (fV.X()*AtW - fW.X()*AtV);
514 fJ_Mp_6x5[22] = fact * (fV.Y()*AtW - fW.Y()*AtV);
515 fJ_Mp_6x5[27] = fact * (fV.Z()*AtW - fW.Z()*AtV);
519 M5x5& out5x5_ = *((
M5x5*) out5x5.GetMatrixArray());
524 *Jac = TMatrixD(6,5, &(fJ_Mp_6x5[0]));;
532 std::cout <<
"RKTrackRep::getPos()\n";
537 return TVector3(state7[0], state7[1], state7[2]);
543 std::cout <<
"RKTrackRep::getMom()\n";
549 TVector3
mom(state7[3], state7[4], state7[5]);
557 std::cout <<
"RKTrackRep::getPosMom()\n";
563 pos.SetXYZ(state7[0], state7[1], state7[2]);
564 mom.SetXYZ(state7[3], state7[4], state7[5]);
570 TMatrixD statePred(
fState);
571 TMatrixD covPred(
fCov);
583 cov6x6.ResizeTo(6, 6);
584 M6x6& cov6x6_ = *((
M6x6*) cov6x6.GetMatrixArray());
587 pos.SetXYZ(state7[0], state7[1], state7[2]);
588 mom.SetXYZ(state7[3], state7[4], state7[5]);
595 if (cov6x6.GetNcols()!=6 || cov6x6.GetNrows()!=6){
596 GFException exc(
"RKTrackRep::setPosMomCov ==> cov has to be 6x6 (x, y, z, px, py, pz)",__LINE__,__FILE__);
609 const M6x6& cov6x6_ = *((
M6x6*) cov6x6.GetMatrixArray());
618 TVector3& dirInPoca){
621 std::cout <<
"RKTrackRep::extrapolateToPoint()\n";
624 static const unsigned int maxIt(1000);
628 fDir.SetXYZ(state7[3], state7[4], state7[5]);
630 double step(0.), lastStep(0.), maxStep(1.E99), angle(0), distToPoca(0);
631 TVector3 lastDir(0,0,0);
634 unsigned int iterations(0);
641 step = this->
Extrap(pl, state7, NULL,
true, maxStep);
642 fDir.SetXYZ(state7[3], state7[4], state7[5]);
645 poca.SetXYZ(state7[0], state7[1], state7[2]);
646 angle = fabs(
fDir.Angle((pos-poca))-TMath::PiOver2());
647 distToPoca = (pos-poca).Mag();
648 if (angle*distToPoca < 0.1*
MINSTEP)
break;
649 if(++iterations == maxIt) {
650 GFException exc(
"RKTrackRep::extrapolateToPoint ==> extrapolation to point failed, maximum number of iterations reached",__LINE__,__FILE__);
656 if (lastStep*
step < 0){
658 maxStep = 0.5*fabs(lastStep);
662 dirInPoca.SetXYZ(state7[3], state7[4], state7[5]);
665 std::cout <<
"RKTrackRep::extrapolateToPoint(): Reached POCA after " << iterations+1 <<
" iterations. Distance: " << (pos-poca).Mag() <<
" cm. Angle deviation: " << dirInPoca.Angle((pos-poca))-TMath::PiOver2() <<
" rad \n";
672 TVector3 theWire = extr2-extr1;
673 if(theWire.Mag()<1.E-8){
674 GFException exc(
"RKTrackRep::poca2Line ==> try to find POCA between line and point, but the line is really just a point",__LINE__,__FILE__);
678 double t = 1./(theWire*theWire) * (point*theWire + extr1*extr1 - extr1*extr2);
679 return (extr1 + t*theWire);
684 const TVector3& point2,
687 TVector3& poca_onwire){
690 std::cout <<
"RKTrackRep::extrapolateToLine(), (x,y) = (" << point1.X() <<
", " << point1.Y() <<
")\n";
693 static const unsigned int maxIt(1000);
697 fDir.SetXYZ(state7[3], state7[4], state7[5]);
699 double step(0.), lastStep(0.), maxStep(1.E99), angle(0), distToPoca(0);
700 TVector3 lastDir(0,0,0);
703 unsigned int iterations(0);
711 pl.
setV(point2-point1);
712 step = this->
Extrap(pl, state7, NULL,
true, maxStep);
713 fDir.SetXYZ(state7[3], state7[4], state7[5]);
716 poca.SetXYZ(state7[0], state7[1], state7[2]);
717 poca_onwire =
poca2Line(point1,point2,poca);
718 angle = fabs(
fDir.Angle((poca_onwire-poca))-TMath::PiOver2());
719 distToPoca = (poca_onwire-poca).Mag();
720 if (angle*distToPoca < 0.1*
MINSTEP)
break;
721 if(++iterations == maxIt) {
722 GFException exc(
"RKTrackRep::extrapolateToLine ==> extrapolation to line failed, maximum number of iterations reached",__LINE__,__FILE__);
728 if (lastStep*
step <0){
730 maxStep = 0.5*fabs(lastStep);
734 dirInPoca.SetXYZ(state7[3], state7[4], state7[5]);
737 std::cout <<
"RKTrackRep::extrapolateToLine(): Reached POCA after " << iterations+1 <<
" iterations. Distance: " << (poca_onwire-poca).Mag() <<
" cm. Angle deviation: " << dirInPoca.Angle((poca_onwire-poca))-TMath::PiOver2() <<
" rad \n";
747 std::cout <<
"RKTrackRep::extrapolate(pl, statePred, covPred)\n";
756 double coveredDistance =
Extrap(pl, state7, &cov7x7);
758 statePred.ResizeTo(5,1);
762 covPred.ResizeTo(5,5);
765 return coveredDistance;
770 TMatrixD& statePred){
773 std::cout <<
"RKTrackRep::extrapolate(pl, statePred)\n";
778 double coveredDistance =
Extrap(pl, state7);
780 statePred.ResizeTo(5,1);
783 return coveredDistance;
790 std::cout <<
"RKTrackRep::stepalong()\n";
795 static const unsigned int maxIt(30);
796 double coveredDistance(0.);
802 unsigned int iterations(0);
805 pos.SetXYZ(state7[0], state7[1], state7[2]);
806 dir.SetXYZ(state7[3], state7[4], state7[5]);
809 dest = pos + (h - coveredDistance) * dir;
812 coveredDistance += this->
Extrap(pl, state7);
814 if(fabs(h - coveredDistance)<
MINSTEP)
break;
815 if(++iterations == maxIt) {
816 GFException exc(
"RKTrackRep::stepalong ==> maximum number of iterations reached",__LINE__,__FILE__);
821 pos.SetXYZ(state7[0], state7[1], state7[2]);
822 dir.SetXYZ(state7[3], state7[4], state7[5]);
824 return coveredDistance;
831 static const unsigned int maxNumIt(500);
832 unsigned int numIt(0);
834 const bool calcCov(cov!=NULL);
837 memcpy(
fStateJac, state7, 7*
sizeof(
double));
839 double coveredDistance(0.);
840 double sumDistance(0.);
845 std::cout <<
"\n============ RKTrackRep::Extrap loop nr. " << numIt <<
" ============\n";
848 if(numIt++ > maxNumIt){
849 GFException exc(
"RKTrackRep::Extrap ==> maximum number of iterations exceeded",__LINE__,__FILE__);
856 memset(&
fStateJac[7],0x00,49*
sizeof(
double));
857 for(
int i=0; i<7; ++i){
865 std::vector<GFPointPath> points;
867 bool checkJacProj =
true;
869 if( ! this->
RKutta(plane,
fStateJac, coveredDistance, points, checkJacProj, calcCov, onlyOneStep, maxStep) ) {
870 GFException exc(
"RKTrackRep::Extrap ==> Runge Kutta propagation failed",__LINE__,__FILE__);
879 std::cout<<
"Original points \n";
880 for (
unsigned int i=0; i<points.size(); ++i){
888 sumDistance+=coveredDistance;
892 if(points.size() > 2){
893 double firstStep(points[0].getPath());
894 for (
unsigned int i=points.size()-2; i>0; --i){
895 if (points[i].getPath() * firstStep < 0 || fabs(points[i].getPath()) <
MINSTEP){
896 points[i-1].addToPath(points[i].getPath());
897 points.erase(points.begin()+i);
902 std::cout<<
"Filtered points \n";
903 for (
unsigned int i=0; i<points.size(); ++i){
911 if(calcCov) memset(
fNoise,0x00,7*7*
sizeof(
double));
915 unsigned int nPoints(points.size());
929 std::cout <<
"momLoss: " << momLoss <<
" GeV; relative: " << momLoss/fabs(
fCharge/
fStateJac[6]) <<
"\n";
937 memcpy(
fOldCov, (*cov), 7*7*
sizeof(
double));
941 for(
unsigned int i=0; i<7*7; ++i){
942 if(fabs((*cov)[i]) > 1.E100){
943 GFException exc(
"RKTrackRep::Extrap ==> covariance matrix exceeds numerical limits",__LINE__,__FILE__);
956 for (
int i=0; i<7*7; ++i) cov_[i] +=
fNoise[i];
960 if (onlyOneStep)
break;
965 if (calcCov && !checkJacProj && nPoints>0){
967 std::cout <<
"Jacobian was not projected onto destination plane -> one more iteration. \n";
972 std::cout <<
"arrived at plane with a distance of " << plane.
distance(
fPos) <<
" cm left. \n";
979 memcpy(state7,
fStateJac, 7*
sizeof(
double));
1013 double& coveredDistance,
1014 std::vector<GFPointPath>& points,
1021 static const double EC = 0.000149896229;
1022 static const double P3 = 1./3.;
1023 static const int ND = 56;
1024 static const int ND1 = ND-7;
1026 static const double Wmax = 3000.;
1027 static const double AngleMax = 6.3;
1028 static const double Pmin = 4.E-3;
1029 static const unsigned int maxNumIt = 1000;
1033 M1x3 SA = {0.,0.,0.};
1034 double Pinv = P[6]*EC;
1036 bool atPlane =
false;
1037 bool momLossExceeded =
false;
1038 fPos.SetXYZ(R[0],R[1],R[2]);
1039 fDir.SetXYZ(A[0],A[1],A[2]);
1041 double relMomLoss = 0;
1042 double deltaAngle = 0.;
1043 double An(0), S(0), Sl(0), S3(0), S4(0), PS2(0), CBA(0);
1045 M1x4 SU = {0.,0.,0.,0.};
1046 M1x3 H0 = {0.,0.,0.}, H1 = {0.,0.,0.}, H2 = {0.,0.,0.}, r = {0.,0.,0.};
1047 double A0(0), A1(0),
A2(0), A3(0), A4(0), A5(0), A6(0);
1048 double B0(0), B1(0), B2(0), B3(0), B4(0), B5(0), B6(0);
1049 double C0(0), C1(0), C2(0), C3(0), C4(0), C5(0), C6(0);
1050 double dA0(0), dA2(0), dA3(0), dA4(0), dA5(0), dA6(0);
1051 double dB0(0), dB2(0), dB3(0), dB4(0), dB5(0), dB6(0);
1052 double dC0(0), dC2(0), dC3(0), dC4(0), dC5(0), dC6(0);
1055 std::cout <<
"RKTrackRep::RKutta \n";
1056 std::cout <<
"position: ";
fPos.Print();
1057 std::cout <<
"direction: ";
fDir.Print();
1058 std::cout <<
"momentum: " << momentum <<
" GeV\n";
1059 std::cout <<
"destination: "; plane.
Print();
1062 checkJacProj =
false;
1065 if(momentum < Pmin){
1066 std::ostringstream sstream;
1067 sstream <<
"RKTrackRep::RKutta ==> momentum too low: " << fabs(
fCharge/P[6])*1000. <<
" MeV";
1076 if(W*plane.
getO() > 0){SU[0] = W.X(); SU[1] = W.Y(); SU[2] = W.Z();}
1077 else {SU[0] = -1.*W.X(); SU[1] = -1.*W.Y(); SU[2] = -1.*W.Z(); }
1078 SU[3] = plane.
distance(0., 0., 0.);
1080 unsigned int counter(0);
1084 S =
estimateStep(points,
fPos,
fDir, SU,
fH, plane, momentum, relMomLoss, deltaAngle, momLossExceeded, atPlane, maxStep);
1085 if (fabs(S) < 0.001*
MINSTEP) {
1087 std::cout <<
" RKutta - step too small -> break \n";
1095 while (fabs(S) >=
MINSTEP || counter == 0) {
1097 if(++counter > maxNumIt){
1098 GFException exc(
"RKTrackRep::RKutta ==> maximum number of iterations exceeded",__LINE__,__FILE__);
1104 std::cout <<
"------ RKutta main loop nr. " << counter-1 <<
" ------\n";
1115 r[0] = R[0]; r[1] = R[1]; r[2]=R[2];
1116 fPos.SetXYZ(r[0], r[1], r[2]);
1118 H0[0] = PS2*
fH.X(); H0[1] = PS2*
fH.Y(); H0[2] = PS2*
fH.Z();
1119 A0 = A[1]*H0[2]-A[2]*H0[1]; B0 = A[2]*H0[0]-A[0]*H0[2]; C0 = A[0]*H0[1]-A[1]*H0[0];
1120 A2 = A[0]+A0 ; B2 = A[1]+B0 ; C2 = A[2]+C0 ;
1121 A1 =
A2+A[0] ; B1 = B2+A[1] ; C1 = C2+A[2] ;
1124 r[0] += A1*S4; r[1] += B1*S4; r[2] += C1*S4;
1125 fPos.SetXYZ(r[0], r[1], r[2]);
1127 H1[0] =
fH.X()*PS2; H1[1] =
fH.Y()*PS2; H1[2] =
fH.Z()*PS2;
1128 A3 = B2*H1[2]-C2*H1[1]+A[0]; B3 = C2*H1[0]-
A2*H1[2]+A[1]; C3 =
A2*H1[1]-B2*H1[0]+A[2];
1129 A4 = B3*H1[2]-C3*H1[1]+A[0]; B4 = C3*H1[0]-A3*H1[2]+A[1]; C4 = A3*H1[1]-B3*H1[0]+A[2];
1130 A5 = A4-A[0]+A4 ; B5 = B4-A[1]+B4 ; C5 = C4-A[2]+C4 ;
1133 r[0]=R[0]+S*A4; r[1]=R[1]+S*B4; r[2]=R[2]+S*C4;
1134 fPos.SetXYZ(r[0], r[1], r[2]);
1136 H2[0] =
fH.X()*PS2; H2[1] =
fH.Y()*PS2; H2[2] =
fH.Z()*PS2;
1137 A6 = B5*H2[2]-C5*H2[1]; B6 = C5*H2[0]-A5*H2[2]; C6 = A5*H2[1]-B5*H2[0];
1140 std::cout <<
"Mag field: ";
fH.Print();
1144 coveredDistance += S;
1149 std::ostringstream sstream;
1150 sstream <<
"RKTrackRep::RKutta ==> Total extrapolation length is longer than length limit : " << Way <<
" cm !";
1161 P[7] = 1; P[15] = 1; P[23] = 1;
1164 for(
int i=4*7; i<ND; i+=7) {
1169 if(i==ND1) {dA[0]*=P[6]; dA[1]*=P[6]; dA[2]*=P[6];}
1172 dA0 = H0[2]*dA[1]-H0[1]*dA[2];
1173 dB0 = H0[0]*dA[2]-H0[2]*dA[0];
1174 dC0 = H0[1]*dA[0]-H0[0]*dA[1];
1176 if(i==ND1) {dA0+=A0; dB0+=B0; dC0+=C0;}
1183 dA3 = dA[0]+dB2*H1[2]-dC2*H1[1];
1184 dB3 = dA[1]+dC2*H1[0]-dA2*H1[2];
1185 dC3 = dA[2]+dA2*H1[1]-dB2*H1[0];
1187 if(i==ND1) {dA3+=A3-A[0]; dB3+=B3-A[1]; dC3+=C3-A[2];}
1189 dA4 = dA[0]+dB3*H1[2]-dC3*H1[1];
1190 dB4 = dA[1]+dC3*H1[0]-dA3*H1[2];
1191 dC4 = dA[2]+dA3*H1[1]-dB3*H1[0];
1193 if(i==ND1) {dA4+=A4-A[0]; dB4+=B4-A[1]; dC4+=C4-A[2];}
1196 dA5 = dA4+dA4-dA[0];
1197 dB5 = dB4+dB4-dA[1];
1198 dC5 = dC4+dC4-dA[2];
1200 dA6 = dB5*H2[2]-dC5*H2[1];
1201 dB6 = dC5*H2[0]-dA5*H2[2];
1202 dC6 = dA5*H2[1]-dB5*H2[0];
1204 if(i==ND1) {dA6+=A6; dB6+=B6; dC6+=C6;}
1207 dR[0] += (dA2+dA3+dA4)*S3/P[6]; dA[0] = (dA0+dA3+dA3+dA5+dA6)*P3/P[6];
1208 dR[1] += (dB2+dB3+dB4)*S3/P[6]; dA[1] = (dB0+dB3+dB3+dB5+dB6)*P3/P[6];
1209 dR[2] += (dC2+dC3+dC4)*S3/P[6]; dA[2] = (dC0+dC3+dC3+dC5+dC6)*P3/P[6];
1212 dR[0] += (dA2+dA3+dA4)*S3; dA[0] = (dA0+dA3+dA3+dA5+dA6)*P3;
1213 dR[1] += (dB2+dB3+dB4)*S3; dA[1] = (dB0+dB3+dB3+dB5+dB6)*P3;
1214 dR[2] += (dC2+dC3+dC4)*S3; dA[2] = (dC0+dC3+dC3+dC5+dC6)*P3;
1222 R[0] += (
A2+A3+A4)*S3; A[0] += (SA[0]=(A0+A3+A3+A5+A6)*P3-A[0]);
1223 R[1] += (B2+B3+B4)*S3; A[1] += (SA[1]=(B0+B3+B3+B5+B6)*P3-A[1]);
1224 R[2] += (C2+C3+C4)*S3; A[2] += (SA[2]=(C0+C3+C3+C5+C6)*P3-A[2]);
1225 fPos.SetXYZ(R[0], R[1], R[2]);
1228 CBA = 1./sqrt(A[0]*A[0]+A[1]*A[1]+A[2]*A[2]);
1229 A[0] *= CBA; A[1] *= CBA; A[2] *= CBA;
1230 fDir.SetXYZ(A[0], A[1], A[2]);
1232 if (onlyOneStep)
return(
true);
1235 if (momLossExceeded) {
1237 std::cout<<
" momLossExceeded -> return(true); \n";
1244 S =
estimateStep(points,
fPos,
fDir, SU,
fH, plane, momentum, relMomLoss, deltaAngle, momLossExceeded, atPlane, maxStep);
1246 if (atPlane && fabs(S) <
MINSTEP) {
1248 std::cout<<
" (atPlane && fabs(S) < MINSTEP) -> break; \n";
1252 if (momLossExceeded && fabs(S) <
MINSTEP) {
1254 std::cout<<
" (momLossExceeded && fabs(S) < MINSTEP) -> return(true); \n";
1260 if (fabs(deltaAngle) > AngleMax){
1261 std::ostringstream sstream;
1262 sstream <<
"RKTrackRep::RKutta ==> Do not get to an active plane! Already extrapolated " << deltaAngle * 180 / TMath::Pi() <<
"°.";
1270 if (S *points[counter-1].getPath() < 0 &&
1271 points[counter-1].getPath()*points[counter-2].getPath() < 0 &&
1272 points[counter-2].getPath()*points[counter-3].getPath() < 0){
1273 GFException exc(
"RKTrackRep::RKutta ==> Do not get closer to plane!",__LINE__,__FILE__);
1287 if (fabs(Sl) > 0.001*
MINSTEP){
1289 std::cout <<
" RKutta - linear extrapolation to surface\n";
1294 SA[0]*=Sl; SA[1]*=Sl; SA[2]*=Sl;
1302 CBA = 1./sqrt(A[0]*A[0]+A[1]*A[1]+A[2]*A[2]);
1303 A[0] *= CBA; A[1] *= CBA; A[2] *= CBA;
1305 R[0] += S*(A[0]-0.5*S*SA[0]);
1306 R[1] += S*(A[1]-0.5*S*SA[1]);
1307 R[2] += S*(A[2]-0.5*S*SA[2]);
1311 std::cout <<
" RKutta - last stepsize too small -> can't do linear extrapolation! \n";
1319 if (checkJacProj && points.size()>0){
1320 GFException exc(
"RKTrackRep::Extrap ==> covariance is projected onto destination plane again",__LINE__,__FILE__);
1323 checkJacProj =
true;
1325 std::cout <<
" Project Jacobian of extrapolation onto destination plane\n";
1327 An = A[0]*SU[0] + A[1]*SU[1] + A[2]*SU[2];
1328 fabs(An) > 1.E-7 ? An=1./An : An = 0;
1330 for(
int i=7; i<ND; i+=7) {
1333 norm = (dR[0]*SU[0] + dR[1]*SU[1] + dR[2]*SU[2])*An;
1334 dR[0] -= norm*A [0]; dR[1] -= norm*A [1]; dR[2] -= norm*A [2];
1335 dA[0] -= norm*SA[0]; dA[1] -= norm*SA[1]; dA[2] -= norm*SA[2];
1339 coveredDistance += S;
1348 const TVector3&
pos,
1349 const TVector3& dir,
1351 const TVector3& MagField,
1356 bool& momLossExceeded,
1358 double maxStep)
const {
1360 static const double Smax = 10.;
1361 static const double dAngleMax = 0.05;
1363 bool improveEstimation (
true);
1365 momLossExceeded =
false;
1369 std::cout <<
" RKTrackRep::estimateStep \n";
1370 std::cout <<
" position: "; pos.Print();
1371 std::cout <<
" direction: "; dir.Print();
1376 double Dist = SU[3] - (pos.X()*SU[0] + pos.Y()*SU[1] + pos.Z()*SU[2]);
1377 double An = dir.X()*SU[0] + dir.Y()*SU[1] + dir.Z()*SU[2];
1379 if (fabs(An) > 1.E-10) Step = Dist/An;
1382 if (An<0) Step *= -1.;
1387 if (Step<0) StepSign = -1;
1390 std::cout <<
" Distance to plane: " << Dist <<
"\n";
1391 std::cout <<
" guess for Step: " << Step <<
"\n";
1392 if (StepSign>0) std::cout <<
" Direction is pointing towards surface.\n";
1393 else std::cout <<
" Direction is pointing away from surface.\n";
1397 double Hmag(MagField.Mag()), SmaxAngle(Smax),
radius(0), p_perp(0);
1399 p_perp = ( dir - MagField*((dir*MagField)/(Hmag*Hmag)) ).Mag() *
momentum;
1400 radius = p_perp/(0.3E-3*Hmag);
1401 double sinAngle = fabs(sin(dir.Angle(MagField)));
1402 if (sinAngle > 1E-10) SmaxAngle = fabs(dAngleMax *
radius / sinAngle);
1412 std::cout <<
" auto select direction. \n";
1416 else if ( fabs(Step) < 0.2*SmaxAngle ){
1418 std::cout <<
" straight line approximation is fine. Delta angle until surface is reached is approx " << Step/SmaxAngle * dAngleMax * 180 / TMath::Pi() <<
" deg \n";
1424 std::cout <<
" direction is pointing to active part of surface. \n";
1430 improveEstimation =
false;
1432 std::cout <<
" we are near the plane, but not pointing to the active area. make a big step! \n";
1439 improveEstimation =
false;
1441 std::cout <<
" select direction according to fDirection. \n";
1446 std::cout <<
" guess for Step (signed): " << Step <<
"\n";
1450 if (Step>=0) StepSign = 1;
1457 if (fabs(Step) > Smax) {
1458 Step = StepSign*Smax;
1459 improveEstimation =
false;
1461 if (fabs(Step) > maxStep) {
1462 Step = StepSign*maxStep;
1463 improveEstimation =
false;
1467 if (fabs(Step) > SmaxAngle) {
1468 Step = StepSign*SmaxAngle;
1469 improveEstimation =
false;
1473 std::cout <<
" limit from maxangle: " << SmaxAngle <<
", radius: " <<
radius <<
"\n";
1483 pos.X(), pos.Y(), pos.Z(),
1484 StepSign*dir.X(), StepSign*dir.Y(), StepSign*dir.Z(),
1488 if (fabs(Step) > StepMat) {
1489 Step = StepSign*StepMat;
1490 momLossExceeded =
true;
1494 std::cout <<
" limit from stepper: " << Step <<
"\n";
1500 if (!momLossExceeded && improveEstimation){
1504 if (Hmag > 1E-5 && fabs(Step) > 0.1*SmaxAngle){
1508 double S3 = Step/3.;
1509 double PS2 =
fCharge/momentum*0.000149896229 * Step;
1510 M1x3 H0 = {0.,0.,0.};
1511 double A0(0),
A2(0), A3(0), A4(0), A5(0), A6(0);
1512 double B0(0), B2(0), B3(0), B4(0), B5(0), B6(0);
1513 double C0(0), C2(0), C3(0), C4(0), C5(0), C6(0);
1516 H0[0] = PS2*MagField.X(); H0[1] = PS2*MagField.Y(); H0[2] = PS2*MagField.Z();
1517 A0 = dir.Y()*H0[2]-dir.Z()*H0[1]; B0 = dir.Z()*H0[0]-dir.X()*H0[2]; C0 = dir.X()*H0[1]-dir.Y()*H0[0];
1518 A2 = dir.X()+A0 ; B2 = dir.Y()+B0 ; C2 = dir.Z()+C0 ;
1521 A3 = B2*H0[2]-C2*H0[1]+dir.X(); B3 = C2*H0[0]-
A2*H0[2]+dir.Y(); C3 =
A2*H0[1]-B2*H0[0]+dir.Z();
1522 A4 = B3*H0[2]-C3*H0[1]+dir.X(); B4 = C3*H0[0]-A3*H0[2]+dir.Y(); C4 = A3*H0[1]-B3*H0[0]+dir.Z();
1523 A5 = A4-dir.X()+A4 ; B5 = B4-dir.Y()+B4 ; C5 = C4-dir.Z()+C4 ;
1526 A6 = B5*H0[2]-C5*H0[1]; B6 = C5*H0[0]-A5*H0[2]; C6 = A5*H0[1]-B5*H0[0];
1529 Dist = SU[3] - ((pos.X()+(
A2+A3+A4)*S3) * SU[0] +
1530 (pos.Y()+(B2+B3+B4)*S3) * SU[1] +
1531 (pos.Z()+(C2+C3+C4)*S3) * SU[2]);
1533 An = (A0+A3+A3+A5+A6)/3. * SU[0] +
1534 (B0+B3+B3+B5+B6)/3. * SU[1] +
1535 (C0+C3+C3+C5+C6)/3. * SU[2];
1540 std::cout <<
" Improved step estimation taking curvature into account: " << Step <<
"\n";
1546 deltaAngle += Step/SmaxAngle * dAngleMax;
1550 std::cout <<
" --> Step to be used: " << Step <<
"\n";