627 #include "TCernLib.h"
629 #include "StiDetector.h"
630 #include "StiPlacement.h"
631 #include "StiMaterial.h"
632 #include "StiShape.h"
633 #include "StiPlanarShape.h"
634 #include "StiCylindricalShape.h"
635 #include "StiKalmanTrackNode.h"
636 #include "StiElossCalculator.h"
637 #include "StDetectorDbMaker/StiTrackingParameters.h"
638 #include "StDetectorDbMaker/StiKalmanTrackFinderParameters.h"
639 #include "StDetectorDbMaker/StiHitErrorCalculator.h"
640 #include "StiTrackNodeHelper.h"
641 #include "StiFactory.h"
645 #if ROOT_VERSION_CODE < 331013
648 #include "TCernLib.h"
650 #include "THelixTrack.h"
651 #include "StThreeVector.hh"
652 #include "StThreeVectorF.hh"
653 #include "StarMagField.h"
655 #include "StMessMgr.h"
657 #define PrP(A) { LOG_INFO << "\t" << (#A) << " = \t" << ( A ) }
658 #define PrPP(A,B) {LOG_INFO << "=== StiKalmanTrackNode::" << (#A); PrP((B)); LOG_INFO << endm;}
667 static const double kMaxEta = 1.25;
668 static const double kMaxSinEta = sin(kMaxEta);
669 static const double kMaxCur = 0.2;
670 static const double kFarFromBeam = 10.;
671 static const Double_t kMaxZ = 250;
672 static const Double_t kMaxR = 250;
676 static const int idx33[3][3] = {{0,1,3},{1,2,4},{3,4,5}};
677 static const int idx55[5][5] =
678 {{0,1,3,6,10},{1,2,4,7,11},{3,4,5, 8,12},{6,7, 8, 9,13},{10,11,12,13,14}};
679 static const int idx55tpt[5][5] =
680 {{0,1,2,3, 4},{1,5,6,7, 8},{2,6,9,10,11},{3,7,10,12,13},{ 4, 8,11,13,14}};
682 static const int idx66[6][6] =
683 {{ 0, 1, 3, 6,10,15},{ 1, 2, 4, 7,11,16},{ 3, 4, 5, 8,12,17}
684 ,{ 6, 7, 8, 9,13,18},{10,11,12,13,14,19},{15,16,17,18,19,20}};
686 bool StiKalmanTrackNode::useCalculatedHitError =
true;
687 TString StiKalmanTrackNode::comment(
"Legend: \tE - extapolation\tM Multiple scattering\tV at Vertex\tB at beam\tR at Radius\tU Updated\n");
688 TString StiKalmanTrackNode::commentdEdx(
"");
692 #ifdef STI_DERIV_TEST
693 int StiKalmanTrackNode::fDerivTestOn=0;
695 #ifndef STI_DERIV_TEST
696 int StiKalmanTrackNode::fDerivTestOn=-10;
699 double StiKalmanTrackNode::fDerivTest[kNPars][kNPars];
708 int StiKalmanTrackNode::_debug = 0;
709 int StiKalmanTrackNode::_laser = 0;
714 static int myCount=0;
715 StiTrackNode::reset();
716 memset(_beg,0,_end-_beg+1);
720 StiDebug::Break(mId);
723 void StiKalmanTrackNode::unset()
731 static const double DY=0.3,DZ=0.3,DEta=0.03,DPti=1.,DTan=0.05;
741 for (
int i=0;i<kNErrs;i++) mFE.G()[i] *=fak;
758 nullCount = n->nullCount;
759 contiguousHitCount = n->contiguousHitCount;
760 contiguousNullCount = n->contiguousNullCount;
780 xRef = getRefPosition();
781 memcpy(x,mFP.P,kNPars*
sizeof(mFP.x()));
782 memcpy(e,mFE.G(),
sizeof(mFE));
797 assert(!std::isnan(mFP.ptin()));
798 return (fabs(mFP.ptin())<1e-3) ? 1e3: 1./fabs(mFP.ptin());
803 mFP.ptin()=parent->mFP.ptin();
804 mFP.curv()=getHz()*mFP.ptin();
816 static const double EC = 2.99792458e-4,ZEROHZ = 2e-6;
817 if (fabs(mHz)<999)
return mHz;
820 StarMagField::Instance()->BField(&(getGlobalPoint().x()),h);
822 if (fabs(h[2]) < ZEROHZ) h[2]=ZEROHZ;
859 void StiKalmanTrackNode::getMomentum(
double p[3],
double e[6])
const
863 enum {jX=0,jY,jZ,jE,jP,jT};
866 p[0] = pt*mFP._cosCA;
867 p[1] = pt*mFP._sinCA;
868 p[2] = pt*mFP.tanl();
873 double F[3][kNPars]; memset(F,0,
sizeof(F));
874 double dPtdPi = -pt*pt;
if (mFP.ptin()<0) dPtdPi=-dPtdPi;
875 F[jX][jE] = -pt *mFP._sinCA;
876 F[jX][jP] = dPtdPi*mFP._cosCA;
879 F[jY][jE] = pt *mFP._cosCA;
880 F[jY][jP] = dPtdPi*mFP._sinCA;
884 F[jZ][jP] = dPtdPi*mFP.tanl();
912 enum {jRad=0,jPhi,jZ,jTan,jPsi,jCur, kX=0,kY,kZ,kE,kC,kT};
913 double alpha,xRef,chi2;
914 double xx[kNPars],ee[kNErrs];
916 get(alpha,xRef,xx,ee,chi2);
918 x[jRad] = sqrt(pow(xx[kX],2)+pow(xx[kY],2));
919 x[jPhi] = atan2(xx[kY],xx[kX]) + alpha;
922 x[jPsi] = xx[kE] + alpha;
926 double F[kNErrs][kNErrs]; memset(F,0,
sizeof(F));
929 if (fabs(xx[kY])>1e-5) F[jPhi][kX] = -1./(xx[kY]);
930 if (fabs(xx[kX])>1e-5) F[jPhi][kY] = 1./(xx[kX]);
935 memset(e,0,
sizeof(*e)*15);
936 for (
int k1=0;k1<kNPars;k1++) {
937 for (
int k2=0;k2<kNPars;k2++) {
938 double cc = mFE.G()[idx66[k1][k2]];
939 for (
int j1=jPhi;j1<= 5;j1++){
940 for (
int j2=jPhi;j2<=j1;j2++){
941 e[idx55[j1-1][j2-1]]+= cc*F[j1][k1]*F[j2][k2];
981 enum {jRad=0,jPhi,jZ,jTan,jPsi,jCur,jPt=jCur};
982 static const double DEG = 180./M_PI;
983 static double fak[6] = {1,0,1,1,DEG,0};
986 getGlobalRadial(xx,ee);
988 fak[jPhi] = DEG*xx[jRad];
989 fak[jPt] = (double(getCharge())/pt)/xx[jCur];
991 for (
int i=0;i<6;i++) {x[i] = (float)(fak[i]*xx[i]);}
994 for (
int j1=jPhi;j1<= 5;j1++){
995 for (
int j2=jPhi;j2<=j1;j2++){
996 e[idx55tpt[j1-1][j2-1]] = (float)fak[j1]*fak[j2]*ee[idx55[j1-1][j2-1]];
1006 return getPsi()-getHelicity()*M_PI/2;
1010 double StiKalmanTrackNode::getPsi()
const
1012 return nice(mFP.eta()+_alpha);
1031 void StiKalmanTrackNode::getGlobalMomentum(
double p[3],
double e[6])
const
1034 enum {jXX=0,jXY,jYY};
1043 double cosAlpha = cos(_alpha);
1044 double sinAlpha = sin(_alpha);
1045 p[0] = cosAlpha*px - sinAlpha*py;
1046 p[1] = sinAlpha*px + cosAlpha*py;
1051 double cXX = e[jXX];
1052 double cXY = e[jXY];
1053 double cYY = e[jYY];
1054 double cc = cosAlpha*cosAlpha;
1055 double ss = sinAlpha*sinAlpha;
1056 double cs = cosAlpha*sinAlpha;
1057 e[jXX] = cc*cXX - 2.*cs*cXY + ss*cYY;
1058 e[jYY] = ss*cXX + 2.*cs*cXY + cc*cYY;
1059 e[jXY] = cs*cXX + (cc-ss)*cXY - cs*cYY;
1082 static int nCall=0; nCall++;
1083 StiDebug::Break(nCall);
1087 if (mFP._cosCA <-1e-5)
return -1;
1088 if (debug()) ResetComment(::Form(
"%40s ",tDet->
getName().c_str()));
1091 double nNormalRadius = place->getNormalRadius();
1094 int shapeCode = sh->getShapeCode();
1095 double endVal,dAlpha;
1096 switch (shapeCode) {
1098 case kPlanar: endVal = nNormalRadius;
1100 dAlpha = place->getNormalRefAngle();
1101 dAlpha = nice(dAlpha - _alpha);
1103 position = rotate(dAlpha);
1104 if (position)
return -10;
1108 case kCylindrical: endVal = nNormalRadius;
1111 double rxy = nNormalRadius;
1112 double rxy2P = mFP.rxy2();
1113 int outside = (rxy2P>rxy*rxy);
1114 int nSol = StiTrackNode::cylCross(mFP.P,&mFP._cosCA,mFP.curv(),rxy,dir,out);
1115 if (!nSol)
return -11;
1116 double *ou = out[0];
1118 int kaze = outside + 2*dir;
1121 case 1: ou = out[1];
break;
1122 case 2: ou = out[1];
break;
1126 dAlpha = atan2(ou[1],ou[0]);
1127 position = rotate(dAlpha);
1128 if (position)
return -11;
1134 position = propagate(endVal,shapeCode,dir);
1136 if (position)
return position;
1137 assert(mFP.x() > 0.);
1138 if (mFP[0]*mFP._cosCA+mFP[1]*mFP._sinCA<0)
return kEnded;
1140 if (debug() & 8) { PrintpT(
"E");}
1143 if (StiKalmanTrackFinderParameters::instance()->mcsCalculated() && getHz())
1144 propagateMCS(pNode,tDet);
1145 if (debug() & 8) { PrintpT(
"M");}
1162 static int nCall=0; nCall++;
1163 StiDebug::Break(nCall);
1165 setState(parentNode);
1166 TCircle tc(&mFP.x(),&mFP._cosCA,mFP.curv());
1167 double xy[2]; xy[0]=vertex->
x(),xy[1]=vertex->y();
1168 double s = tc.
Path(xy); tc.Move(s);
1169 double ang = atan2(tc.Dir()[1],tc.Dir()[0]);
1172 if (debug()) ResetComment(::Form(
"Vtx:%8.3f %8.3f %8.3f",vertex->
x(),vertex->y(),vertex->z()));
1173 if (propagate(vertex->
x(),kPlanar,dir))
return false;
1185 setState(parentNode);
1187 if (parentNode->getDetector())
1188 ResetComment(::Form(
"%40s ",parentNode->getDetector()->
getName().c_str()));
1189 else ResetComment(
"Unknown Detector");
1191 if (propagate(0., kPlanar,dir))
return false;
1194 if (mFE.zign()<0)
return false;
1195 if (debug() & 8) { PrintpT(
"B"); PrintStep();}
1208 if (debug()) ResetComment(::Form(
"%40s ",pNode->getDetector()->
getName().c_str()));
1209 position = propagate(radius,kCylindrical,dir);
1210 if (position<0)
return position;
1212 if (debug() & 8) { PrintpT(
"R"); PrintStep();}
1230 static int nCall=0; nCall++;
1231 StiDebug::Break(nCall);
1235 mgP.x1=mFP.x(); mgP.y1=mFP.y(); mgP.cosCA1 =mFP._cosCA; mgP.sinCA1 =mFP._sinCA;
1236 double rho = mFP.curv();
1239 mgP.dx=mgP.x2-mgP.x1;
1240 double test = (dir)? mgP.dx:-mgP.dx;
1244 double dsin = mFP.curv()*mgP.dx;
1245 mgP.sinCA2=mgP.sinCA1 + dsin;
1247 if (fabs(mgP.sinCA2)>kMaxSinEta)
return -4;
1248 mgP.cosCA2 = ::sqrt((1.-mgP.sinCA2)*(1.+mgP.sinCA2));
1250 test = (2*dir-1)*mgP.dx*mgP.cosCA1;
1251 if (test<0) mgP.cosCA2 = -mgP.cosCA2;
1253 int nIt = (mgP.cosCA2 <0)? 2:1;
1256 for (
int iIt=0; iIt<nIt; iIt++) {
1259 mgP.cosCA2 = (!iIt)? fabs(mgP.cosCA2):-fabs(mgP.cosCA2);
1260 mgP.sumSin = mgP.sinCA1+mgP.sinCA2;
1261 mgP.sumCos = mgP.cosCA1+mgP.cosCA2;
1262 if (fabs(mgP.sumCos)<1e-6)
continue;
1263 mgP.dy = mgP.dx*(mgP.sumSin/mgP.sumCos);
1264 mgP.y2 = mgP.y1+mgP.dy;
1267 mgP.dl0 = mgP.cosCA1*mgP.dx+mgP.sinCA1*mgP.dy;
1268 double sind = mgP.dl0*rho;
1270 if (fabs(dsin) < 0.02 ) {
1271 mgP.dl = mgP.dl0*(1.+sind*sind/6);
1274 double cosd = mgP.cosCA2*mgP.cosCA1+mgP.sinCA2*mgP.sinCA1;
1275 mgP.dl = atan2(sind,cosd)/rho;
1277 if (mgP.y2*mgP.y2+mgP.x2*mgP.x2>kMaxR*kMaxR)
return -5;
1278 mFP.z() += mgP.dl*mFP.tanl();
1279 if (fabs(mFP.z()) > kMaxZ)
return -6;
1281 mFP.eta() = nice(mFP.eta()+rho*mgP.dl);
1283 mFP._sinCA = mgP.sinCA2;
1284 mFP._cosCA = mgP.cosCA2;
1288 if (ians)
return kFailed;
1289 if (fabs(mFP.eta())>kMaxEta)
return kFailed;
1290 if (mFP.x()> kFarFromBeam) {
1291 if (mFP.x()*mgP.cosCA2+mFP.y()*mgP.sinCA2<=0)
return kEnded;
1294 mFP.curv() = mFP.hz()*mFP.ptin();
1302 int StiKalmanTrackNode::nudge(
StiHit *hitp)
1305 if (!hit) hit = getHit();
1307 if (hit) { deltaX = hit->
x()-mFP.x();}
1308 else {
if (_detector) deltaX = _detector->getPlacement()->getNormalRadius()-mFP.x();}
1309 if(fabs(deltaX)>5)
return -1;
1310 if (fabs(deltaX) <1.e-3)
return 0;
1311 double deltaS = mFP.curv()*(deltaX);
1312 double sCA2 = mFP._sinCA + deltaS;
1313 if (fabs(sCA2)>0.99)
return -2;
1314 double cCA2,deltaY,deltaL,sind;
1315 if (fabs(deltaS) < 1e-3 && fabs(mFP.eta())<1) {
1316 cCA2= mFP._cosCA - mFP._sinCA/mFP._cosCA*deltaS;
1317 if (cCA2> 1) cCA2= 1;
1318 if (cCA2<-1) cCA2=-1;
1319 deltaY = deltaX*(mFP._sinCA+sCA2)/(mFP._cosCA+cCA2);
1320 deltaL = deltaX*mFP._cosCA + deltaY*mFP._sinCA;
1321 sind = deltaL*mFP.curv();
1322 deltaL = deltaL*(1.+sind*sind/6);
1324 cCA2= sqrt((1.-sCA2)*(1.+sCA2));
1325 if (mFP._cosCA <0) cCA2 = -cCA2;
1326 deltaY = deltaX*(mFP._sinCA+sCA2)/(mFP._cosCA+cCA2);
1327 deltaL = deltaX*mFP._cosCA + deltaY*mFP._sinCA;
1328 sind = deltaL*mFP.curv();
1329 deltaL = asin(sind)/mFP.curv();
1331 double deltaZ = mFP.tanl()*(deltaL);
1332 mFP._sinCA = mgP.sinCA2 = sCA2;
1333 mFP._cosCA = mgP.cosCA2 = cCA2;
1334 mgP.sumSin = mgP.sinCA1+mgP.sinCA2;
1335 mgP.sumCos = mgP.cosCA1+mgP.cosCA2;
1339 mFP.eta() += deltaL*mFP.curv();
1347 if (fabs(mFP._sinCA)>=1) {
1348 LOG_DEBUG << Form(
"StiKalmanTrackNode::nudge WRONG WRONG WRONG sinCA=%g",mFP._sinCA)
1353 assert(fabs(mFP._cosCA) <= 1.);
1363 double fYE= mgP.dx*(1.+mgP.cosCA1*mgP.cosCA2+mgP.sinCA1*mgP.sinCA2)/(mgP.sumCos*mgP.cosCA2);
1365 double fEC = mgP.dx/mgP.cosCA2;
1367 double fYC=(mgP.dy*mgP.sinCA2+mgP.dx*mgP.cosCA2)/mgP.sumCos*fEC;
1369 double dang = mgP.dl*mFP.curv();
1370 double C2LDX = mgP.dl*mgP.dl*(
1371 0.5*mgP.sinCA2*pow((1+pow(dang/2,2)*sinX(dang/2)),2) +
1372 mgP.cosCA2*dang*sinX(dang));
1374 double fZC = mFP.tanl()*C2LDX/mgP.cosCA2;
1376 double dLdEta = mgP.dy/mgP.cosCA2;
1377 double fZE = mFP.tanl()*dLdEta;
1381 double hz = getHz(); fEC *=hz; fYC*=hz; fZC*=hz;
1384 if (mMtx().A[0][0]) { ca = mMtx().A[0][0]+1.;sa = mMtx().A[0][1];}
1387 mMtx().A[0][0] = -1;
1388 mMtx().A[1][0] = -mgP.sinCA2/mgP.cosCA2;
1389 mMtx().A[2][0] = -mFP.tanl() /mgP.cosCA2;
1390 mMtx().A[3][0] = -mFP.curv() /mgP.cosCA2;
1392 mMtx().A[1][3]=fYE; mMtx().A[1][4]=fYC; mMtx().A[2][3]=fZE;
1393 mMtx().A[2][4]=fZC; mMtx().A[2][5]=fZT; mMtx().A[3][4]=fEC;
1395 double fYX = mMtx().A[1][0];
1396 mMtx().A[1][0] = fYX*ca-sa;
1397 mMtx().A[1][1] = fYX*sa+ca-1;
1408 static int nCall=0; nCall++;
1409 StiDebug::Break(nCall);
1411 errPropag6(mFE.G(),mMtx().A,kNPars);
1412 int force = (fabs(mgP.dl) > StiNodeErrs::kBigLen);
1414 mFE._cXX = mFE._cYX= mFE._cZX = mFE._cEX = mFE._cPX = mFE._cTX = 0;
1416 if (_hit) setHitErrors();
1444 getGlobalPoint() - oNode->getGlobalPoint();
1445 double R = getCurvature();
1447 return length(delta, R);
1454 double m = delta.perp();
1455 double as = 0.5*m*fabs(curv);
1458 cout <<
"StiKalmanTrackNode::length m = " << m <<
" curv = " << curv <<
" as = " << as <<
" illegal. reset to 1" << endl;
1462 if (fabs(as)<0.01) { lxy = m*(1.+as*as/24);}
1463 else { lxy = 2.*asin(as)/fabs(curv);}
1464 return sqrt(lxy*lxy+delta.z()*delta.z());
1483 double r00, r01,r11;
1486 double dsin =mFP.curv()*(hit->
x()-mFP.x());
1487 if (fabs(mFP._sinCA+dsin)>0.99 )
return 1e41;
1488 if (fabs(mFP.eta()) >kMaxEta)
return 1e41;
1489 if (fabs(mFP.curv()) >kMaxCur)
return 1e41;
1490 if (mHrr.hYY>1000*mFE._cYY
1491 && mHrr.hZZ>1000*mFE._cZZ)
return 1e41;
1493 r00=mHrr.hYY+mFE._cYY;
1494 r01=mHrr.hZY+mFE._cZY;
1495 r11=mHrr.hZZ+mFE._cZZ;
1497 _det=r00*r11 - r01*r01;
1498 if (_det<r00*r11*1.e-5) {
1499 LOG_DEBUG << Form(
"StiKalmanTrackNode::evalChi2 *** zero determinant %g",_det)<< endm;
1502 double tmp=r00; r00=r11; r11=tmp; r01=-r01;
1503 double deltaX = hit->
x()-mFP.x();
1504 double deltaL = deltaX/mFP._cosCA;
1505 double deltaY = mFP._sinCA *deltaL;
1506 double deltaZ = mFP.tanl() *deltaL;
1507 double dyt=(mFP.y()-hit->y()) + deltaY;
1508 double dzt=(mFP.z()-hit->z()) + deltaZ;
1509 double cc= (dyt*r00*dyt + 2*r01*dyt*dzt + dzt*r11*dzt)/_det;
1510 if (debug() & 8) {comment += Form(
" chi2 = %6.2f",cc);}
1514 int StiKalmanTrackNode::isEnded()
const
1517 if(fabs(mFP.eta() )<=kMaxEta)
return 0;
1521 int StiKalmanTrackNode::isDca()
const
1523 return (fabs(mFP.x())<=0);
1537 static const int keepElossBug = StiDebug::iFlag(
"keepElossBug");
1539 static int nCall=0; nCall++;
1540 propagateCurv(previousNode);
1541 double pt = getPt();
1543 mPP() = mFP; mPE() = mFE;
1546 double relRadThickness;
1548 double pL1,pL2,pL3,d1,d2,d3,dxEloss=0;
1549 pL1=previousNode->pathlength()/2.;
1551 pL3=pathlength()/2.;
1553 pL2= pathLToNode(previousNode);
1557 double x0p =1e11,x0Gas=1e11,x0=1e11;
1559 if (pt > 0.350 && TMath::Abs(getHz()) < 1e-3) pt = 0.350;
1560 double p2=(1.+mFP.tanl()*mFP.tanl())*pt*pt;
1561 double m=StiKalmanTrackFinderParameters::instance()->massHypothesis();
1567 d1 = previousNode->getDensity();
1568 x0p = previousNode->
getX0();
1570 x0 = tDet->getMaterial()->
getX0();
1578 x0Gas = tDet->getGas()->
getX0();
1584 d2 = previousNode->getGasDensity();
1586 relRadThickness = 0.;
1590 relRadThickness += pL1/x0p;
1595 relRadThickness += pL2/x0Gas;
1600 relRadThickness += pL3/x0;
1606 relRadThickness = 0.;
1610 relRadThickness += pL1/x0p;
1615 relRadThickness += pL3/x0;
1620 double theta2=mcs2(relRadThickness,beta2,p2);
1622 double pti = mFP.ptin(), tanl = mFP.tanl();
1624 double cos2Li = (1.+ tanl*tanl);
1626 mFE._cEE += cos2Li *theta2;
1627 mFE._cPP += tanl*tanl*pti*pti *theta2;
1628 mFE._cTP += pti*tanl*cos2Li *theta2;
1629 mFE._cTT += cos2Li*cos2Li *theta2;
1632 double sign = (mgP.dx>0)? 1:-1;
1637 double eloss = calculator->
calculate(1.,m, beta2);
1638 dE = sign*dxEloss*eloss;
1643 if (TMath::Abs(dE)>0)
1646 commentdEdx = Form(
"%6.3g cm(%5.2f) %6.3g keV %6.3f GeV",mgP.dx,100*relRadThickness,1e6*dE,TMath::Sqrt(e2)-m);
1648 double correction =1. + ::sqrt(e2)*dE/p2;
1649 if (correction>1.1) correction = 1.1;
1650 else if (correction<0.9) correction = 0.9;
1651 mFP.curv() = mFP.curv()*correction;
1652 mFP.ptin() = mFP.ptin()*correction;
1654 mPP() = mFP; mPE() = mFE;
1658 const StiDetector *preDet = previousNode->getDetector();
1659 const StiMaterial *preMat = preDet->getMaterial();
1661 d1 =(preLos) ? preLos->
calculate(1.,m, beta2):0;
1662 x0p = preMat->
getX0();
1666 d3 =(curLos) ? curLos->
calculate(1.,m, beta2):0;
1667 x0 = curMat->
getX0();
1668 double sign = (mgP.dx>0)? 1:-1;
1671 const StiMaterial *gasMat = (sign>0)? tDet->getGas() : preDet->getGas();
1672 x0Gas = gasMat->
getX0();
1674 d2 =(gasLos) ? gasLos->
calculate(1.,m, beta2):0;
1676 pL2=pL2-pL1-pL3;
if (pL2<0) pL2=0;
1677 relRadThickness = pL1/x0p+pL2/x0Gas+pL3/x0;
1678 dxEloss = d1*pL1+ d2*pL2 + d3*pL3;
1681 double theta2=mcs2(relRadThickness,beta2,p2);
1683 double pti = mFP.ptin(), tanl = mFP.tanl();
1685 double cos2Li = (1.+ tanl*tanl);
1687 mFE._cEE += cos2Li *theta2;
1688 mFE._cPP += tanl*tanl*pti*pti *theta2;
1689 mFE._cTP += pti*tanl*cos2Li *theta2;
1690 mFE._cTT += cos2Li*cos2Li *theta2;
1695 assert(mFE.zign()>0);
1697 double dE = sign*dxEloss;
1700 mELoss[0].mELoss = 2*d3*pL3;
1701 mELoss[0].mLen = 2*pL3;
1704 mELoss[1].mELoss = 2*d2*pL2;
1705 mELoss[1].mLen = 2*pL2;
1707 mELoss[1].mX0 = x0Gas;
1711 double correction =1. + ::sqrt(e2)*dE/p2;
1712 if (correction>1.1) correction = 1.1;
1713 else if (correction<0.9) correction = 0.9;
1714 mFP.curv() = mFP.curv()*correction;
1715 mFP.ptin() = mFP.ptin()*correction;
1717 mPP() = mFP; mPE() = mFE;
1746 static int nCall=0; nCall++;
1748 assert(mFE.zign()>0);
1749 assert(mFE._cXX<1e-8);
1751 r00 = mHrr.hYY + mFE._cYY;
1752 r01 = mHrr.hZY + mFE._cZY;
1753 r11 = mHrr.hZZ + mFE._cZZ;
1754 _det=r00*r11 - r01*r01;
1755 if (!finite(_det) || _det<(r00*r11)*1.e-5) {
1756 LOG_DEBUG << Form(
"StiKalmanTrackNode::updateNode *** zero determinant %g",_det)
1761 double tmp=r00; r00=r11/_det; r11=tmp/_det; r01=-r01/_det;
1763 double k00=mFE._cYY*r00+mFE._cZY*r01, k01=mFE._cYY*r01+mFE._cZY*r11;
1764 double k10=mFE._cZY*r00+mFE._cZZ*r01, k11=mFE._cZY*r01+mFE._cZZ*r11;
1765 double k20=mFE._cEY*r00+mFE._cEZ*r01, k21=mFE._cEY*r01+mFE._cEZ*r11;
1766 double k30=mFE._cPY*r00+mFE._cPZ*r01, k31=mFE._cPY*r01+mFE._cPZ*r11;
1767 double k40=mFE._cTY*r00+mFE._cTZ*r01, k41=mFE._cTY*r01+mFE._cTZ*r11;
1768 double dyt = getHit()->y() - mFP.y();
1769 double dzt = getHit()->z() - mFP.z();
1770 double dp3 = k30*dyt + k31*dzt;
1771 double dp2 = k20*dyt + k21*dzt;
1772 double dp4 = k40*dyt + k41*dzt;
1773 double eta = nice(mFP.eta() + dp2);
1774 if (fabs(eta)>kMaxEta)
return -14;
1775 double pti = mFP.ptin() + dp3;
1776 if (fabs(pti) < 1e-3) pti=1e-3;
1777 double cur = pti*getHz();
1778 if (fabs(cur)>kMaxCur)
return -16;
1779 assert(finite(cur));
1780 double tanl = mFP.tanl() + dp4;
1782 double p0 = mFP.y() + k00*dyt + k01*dzt;
1786 LOG_DEBUG <<
"updateNode()[1] -W- _y:"<<mFP.y()<<
" _z:"<<mFP.z()<<endm;
1789 double p1 = mFP.z() + k10*dyt + k11*dzt;
1792 LOG_DEBUG <<
"updateNode()[2] -W- _y:"<<mFP.y()<<
" _z:"<<mFP.z()<<endm;
1796 double sinCA = sin(eta);
1802 if (mFP.isZeroH()) { mFP.ready(); pti = mFP.ptin(); cur = mFP.curv();}
1808 mFP._cosCA = ::sqrt((1.-mFP._sinCA)*(1.+mFP._sinCA));
1809 assert(!_detector || mFP.x() > 0.);
1812 double c00=mFE._cYY;
1813 double c10=mFE._cZY, c11=mFE._cZZ;
1814 double c20=mFE._cEY, c21=mFE._cEZ;
1815 double c30=mFE._cPY, c31=mFE._cPZ;
1816 double c40=mFE._cTY, c41=mFE._cTZ;
1817 mFE._cYY-=k00*c00+k01*c10;
1818 mFE._cZY-=k10*c00+k11*c10;mFE._cZZ-=k10*c10+k11*c11;
1819 mFE._cEY-=k20*c00+k21*c10;mFE._cEZ-=k20*c10+k21*c11;mFE._cEE-=k20*c20+k21*c21;
1820 mFE._cPY-=k30*c00+k31*c10;mFE._cPZ-=k30*c10+k31*c11;mFE._cPE-=k30*c20+k31*c21;mFE._cPP-=k30*c30+k31*c31;
1821 mFE._cTY-=k40*c00+k41*c10;mFE._cTZ-=k40*c10+k41*c11;mFE._cTE-=k40*c20+k41*c21;mFE._cTP-=k40*c30+k41*c31;mFE._cTT-=k40*c40+k41*c41;
1843 if (fabs(alpha)<1.e-6)
return 0;
1846 _alpha = nice(_alpha);
1851 mgP.sinCA1 = mFP._sinCA;
1852 mgP.cosCA1 = mFP._cosCA;
1853 double ca = cos(alpha);
1854 double sa = sin(alpha);
1855 mFP.x() = xt1*ca + yt1*sa;
1856 mFP.y()= -xt1*sa + yt1*ca;
1857 mFP._cosCA = mgP.cosCA1*ca+mgP.sinCA1*sa;
1858 mFP._sinCA = -mgP.cosCA1*sa+mgP.sinCA1*ca;
1859 double nor = 0.5*(mFP._sinCA*mFP._sinCA+mFP._cosCA*mFP._cosCA +1);
1863 mFP.eta()= nice(mFP.eta()-alpha);
1864 mFP._sinCA = sin(mFP.eta());
1865 mFP._cosCA = cos(mFP.eta());
1867 assert(fabs(mFP._sinCA)<=1.);
1868 assert(fabs(mFP._cosCA)<=1.);
1869 memset(mMtx().A,0,
sizeof(mMtx()));
1870 mMtx().A[0][0]= ca-1;
1873 mMtx().A[1][1]= ca-1;
1887 if (det) os <<
"Det:"<<n.getDetector()->
getName();
1888 else os <<
"Det:UNknown";
1889 os <<
" a:" << 180*n._alpha/M_PI<<
" degs"
1890 <<
"\tx:" << n.mFP.x()
1891 <<
" p0:" << n.mFP.y()
1892 <<
" p1:" << n.mFP.z()
1893 <<
" p2:" << n.mFP.eta()
1894 <<
" p3:" << n.mFP.ptin()
1895 <<
" p4:" << n.mFP.tanl()
1896 <<
" c00:" <<n.
mFE._cYY<<
" c11:"<<n.
mFE._cZZ
1897 <<
" pT:" << n.
getPt() << endl;
1898 if (n.debug() & 2) {
1899 StiHit * hit = n.getHit();
1900 if (hit) os <<
"\thas hit with chi2 = " << n.getChi2()
1901 <<
" n:"<<n.hitCount
1902 <<
" null:"<<n.nullCount
1903 << endl<<
"\t hit:"<<*hit;
1910 double StiKalmanTrackNode::getWindowY()
1914 double searchWindowScale = parameters->getSearchWindowScale();
1915 double minSearchWindow = parameters->getMinSearchWindow();
1916 double maxSearchWindow = parameters->getMaxSearchWindow();
1921 double window = searchWindowScale*::sqrt(mFE._cYY+myEyy);
1922 if (window<minSearchWindow) window = minSearchWindow;
1923 else if (window>maxSearchWindow) window = maxSearchWindow;
1928 double StiKalmanTrackNode::getWindowZ()
1932 double searchWindowScale = parameters->getSearchWindowScale();
1933 double minSearchWindow = parameters->getMinSearchWindow();
1934 double maxSearchWindow = parameters->getMaxSearchWindow();
1940 double window = searchWindowScale*::sqrt(mFE._cZZ+myEzz);
1941 if (window<minSearchWindow) window = minSearchWindow;
1942 else if (window>maxSearchWindow) window = maxSearchWindow;
1950 double xt0 = mFP.x()-mFP._sinCA/mFP.curv();
1951 double yt0 = mFP.y()+mFP._cosCA/(mFP.curv());
1952 double zt0 = mFP.z()+mFP.tanl()*asin(mFP._sinCA)/mFP.curv();
1953 double cosAlpha = cos(_alpha);
1954 double sinAlpha = sin(_alpha);
1959 int StiKalmanTrackNode::locate()
1961 double yOff, zOff,ang;
1964 if (!tDet)
return 0;
1966 const StiShape *sh = tDet->getShape();
1968 if (fabs(mFP.z())>kMaxZ || mFP.rxy()> kMaxR)
return -1;
1972 Int_t shapeCode = sh->getShapeCode();
1973 switch (shapeCode) {
1978 ang = atan2(mFP.y(),mFP.x());
1979 yOff = nice(ang +_alpha - place->getLayerAngle());
1980 if (fabs(yOff)>sh->getOpeningAngle()/2)
return -1;
1983 yOff = mFP.y() - place->getNormalYoffset();
1984 if (fabs(yOff)> sh->getHalfWidth())
return -1;
1986 default: assert(0 &&
"Wrong Shape code");
1988 zOff = mFP.z() - place->getZcenter();
1989 if (fabs(zOff)>sh->getHalfDepth())
return -1;
1999 double cosp = _detector->getCos();
2000 double sinp = _detector->getSin();
2001 double dirl[3] = {0,0,dirg[2]};
2002 dirl[0] = cosp*dirg[0] + sinp*dirg[1];
2003 dirl[1] =-sinp*dirg[0] + cosp*dirg[1];
2004 if (fabs(dirl[0])>=1.) {dirl[0] = 1; dirl[1]=0;}
2005 if (fabs(dirl[1])>=1.) {dirl[1] = 1; dirl[0]=0;}
2006 mFP._cosCA = dirl[0];
2007 mFP._sinCA = dirl[1];
2008 mFP.P[StiNodePars::kPhi] = atan2(dirl[1],dirl[0]);
2009 mFP.P[StiNodePars::kTan] = dirl[2];
2023 _alpha = _detector->getPlacement()->getNormalRefAngle();
2041 _alpha = _detector->getPlacement()->getNormalRefAngle();
2048 _ext=0; _inf=0 ; *
this = n;
2053 StiTrackNode::operator=(n);
2054 memcpy(_beg,n._beg,_end-_beg+1);
2055 if (n._ext) { extend();*_ext = *n._ext;}
2056 else {
if(_ext) _ext->reset(); }
2057 if (n._inf) { extinf();*_inf = *n._inf;}
2062 void StiKalmanTrackNode::setHitErrors(
const StiHit *hit)
2064 if (!hit) hit = _hit;
2066 StiTrackNodeHelper::getHitErrors(hit,&mFP,&mHrr);
2072 StiTrackNodeHelper::getHitErrors(hit,&mFP,&hr);
2078 int StiKalmanTrackNode::testError(
double *emx,
int begend)
2084 static int nCall=0; nCall++;
2085 static const double dia[6] = { 1000.,1000., 1000.,1000.,1000,1000.};
2086 static double emxBeg[kNErrs];
2088 if (!begend) { memcpy(emxBeg,emx,
sizeof(emxBeg));}
2089 int ians=0,j1,j2,jj;
2090 for (j1=0; j1<5;j1++){
2092 if (!(emx[jj]>0)) {;
2093 LOG_DEBUG << Form(
"<StiKalmanTrackNode::testError> Negative diag %g[%d][%d]",emx[jj],j1,j1)
2096 if (emx[jj]<=10*dia[j1] )
continue;
2097 assert(finite(emx[jj]));
2098 LOG_DEBUG << Form(
"<StiKalmanTrackNode::testError> Huge diag %g[%d][%d]",emx[jj],j1,j1)
2104 for (j1=0; j1< 5;j1++){
2105 for (j2=0; j2<j1;j2++){
2107 assert(finite(emx[jj]));
2108 double cormax = emx[idx55[j1][j1]]*emx[idx55[j2][j2]];
2109 if (emx[jj]*emx[jj]<cormax)
continue;
2110 cormax= sqrt(cormax);
2117 void StiKalmanTrackNode::numeDeriv(
double val,
int kind,
int shape,
int dir)
2119 double maxStep[kNPars]={0.1,0.1,0.1,0.01,0.001,0.01};
2120 if (fDerivTestOn<0)
return;
2125 double *pars = &myNode.mFP.x();
2128 if (fabs(mFP.curv())> 0.02)
goto FAIL;
2130 for (ipar=1;ipar<kNPars;ipar++)
2132 for (
int is=-1;is<=1;is+=2) {
2135 double step = 0.1*sqrt((mFE.G())[idx66[ipar][ipar]]);
2136 if (step>maxStep[ipar]) step = maxStep[ipar];
2139 pars[ipar] +=step*is;
2141 myNode.mFP._sinCA = sin(myNode.mFP.eta());
2142 if (fabs(myNode.mFP._sinCA) > 0.9)
goto FAIL;
2143 myNode.mFP.
_cosCA = cos(myNode.mFP.eta());
2147 state = myNode.
propagate(val,shape,dir);
break;
2149 state = myNode.
rotate(val);
break;
2152 if(state )
goto FAIL;
2154 for (
int jpar=1;jpar<kNPars;jpar++) {
2156 fDerivTest[jpar][ipar]= pars[jpar];
2158 double tmp = fDerivTest[jpar][ipar];
2159 fDerivTest[jpar][ipar] = (pars[jpar]-tmp)/(2.*step);
2160 if (ipar==jpar) fDerivTest[jpar][ipar]-=1.;
2165 fDerivTestOn=1;backStatics(save);
return;
2167 fDerivTestOn=0;backStatics(save);
return;
2170 int StiKalmanTrackNode::testDeriv(
double *der)
2172 if (fDerivTestOn!=1)
return 0;
2173 double *num = fDerivTest[0];
2175 for (
int i=1;i<kNErrs;i++) {
2176 int ipar = i/kNPars;
2177 int jpar = i%kNPars;
2178 if (ipar==jpar)
continue;
2179 if (ipar==0)
continue;
2180 if (jpar==0)
continue;
2181 double dif = fabs(num[i]-der[i]);
2182 if (fabs(dif) <= 1.e-5)
continue;
2183 if (fabs(dif) <= 0.2*0.5*fabs(num[i]+der[i]))
continue;
2185 LOG_DEBUG << Form(
"***Wrong deriv [%d][%d] = %g %g %g",ipar,jpar,num[i],der[i],dif)
2192 void StiKalmanTrackNode::saveStatics(
double *sav)
2210 void StiKalmanTrackNode::backStatics(
double *sav)
2217 mgP.cosCA1= sav[ 6];
2218 mgP.sinCA1= sav[ 7];
2219 mgP.cosCA2= sav[ 8];
2220 mgP.sinCA2= sav[ 9];
2221 mgP.sumSin= sav[10];
2222 mgP.sumCos= sav[11];
2228 void StiKalmanTrackNode::PrintpT(
const Char_t *opt)
const {
2240 Double_t dpTOverpT = 100*TMath::Sqrt(mFE._cPP/(mFP.ptin()*mFP.ptin()));
2241 if (dpTOverpT > 9999.9) dpTOverpT = 9999.9;
2242 comment += ::Form(
" %s pT %8.3f+-%6.1f sy %6.4f",opt,getPt(),dpTOverpT,TMath::Sqrt(mFE._cYY));
2245 void StiKalmanTrackNode::PrintStep() {
2246 LOG_INFO << comment.Data() <<
"\t" << commentdEdx.Data() << endm;
2252 static const char *txt =
"xyzeptchrXYZED";
2256 static const char *hhh =
"uvwUVW";
2257 static const char *HHH =
"xyzXYZ";
2258 if (!opt || !opt[0]) opt =
"2xh";
2261 if (!isValid()) ts+=
"*";
2262 if (hit) {ts+=(getChi2()>1e3)?
"h":
"H";}
2263 if (hit && strchr(opt,
'H')) {
2264 printf(
"%p(%s=%p)",(
void*)
this,ts.Data(),hit);
2266 printf(
"%p(%s)",(
void*)
this,ts.Data());
2269 if (strchr(opt,
'2')) printf(
"\t%s=%g",
"ch2",getChi2());
2271 for (
int i=0;txt[i];i++) {
2272 if (!strchr(opt,txt[i]))
continue;
2274 case 0:;
case 1:;
case 2:;
case 3:;
case 4:;
case 5:;
case 6:;
case 7:;
2275 val = mFP[i];
break;
2276 case 8: val = mFP.rxy();
break;
2277 case 9: val = x_g();
break;
2278 case 10: val = y_g();
break;
2279 case 11: val = z_g();
break;
2280 case 12: val = getPsi();
break;
2281 case 13: val = mFP._cosCA*mFP[0]+mFP._sinCA*mFP[1];
2284 printf(
"\t%c=%g",txt[i],val);
2287 for (
int i=0;hit && hhh[i];i++) {
2288 if (!strchr(opt,hhh[i]))
continue;
2290 case 0:val = hit->
x();
break;
2291 case 1:val = hit->y();
break;
2292 case 2:val = hit->z();
break;
2293 case 3:val = hit->
x_g();
break;
2294 case 4:val = hit->y_g();
break;
2295 case 5:val = hit->z_g();
break;
2297 printf(
"\th%c=%g",HHH[i],val);
2299 if (isValid()) printf(
" valid");
2300 if (getDetector()) {printf(
" %s",getDetector()->getName().c_str());}
2305 StiNodeExt *StiKalmanTrackNode::nodeExtInstance()
2310 extFactory->setMaxIncrementCount(400000);
2311 extFactory->setFastDelete();
2316 StiNodeInf *StiKalmanTrackNode::nodeInfInstance()
2321 infFactory->setMaxIncrementCount(40000);
2322 infFactory->setFastDelete();
2327 void StiKalmanTrackNode::extend()
2330 _ext = nodeExtInstance();
2333 void StiKalmanTrackNode::extinf()
2336 _inf = nodeInfInstance();
2339 void StiKalmanTrackNode::saveInfo(
int kase)
2349 void StiKalmanTrackNode::reduce()
2365 double ca = cos(_alpha),sa=sin(_alpha);
2370 double StiKalmanTrackNode::x_g()
const
2372 return cos(_alpha)*mFP.x()-sin(_alpha)*mFP.y();
2376 double StiKalmanTrackNode::y_g()
const
2378 return sin(_alpha)*mFP.x()+cos(_alpha)*mFP.y();
2382 double StiKalmanTrackNode::z_g()
const
2388 void StiKalmanTrackNode::setUntouched()
2390 mUnTouch.set(mPP(),mPE());
2393 double StiKalmanTrackNode::getTime()
const
2395 static const double smax = 1e3;
2398 double d = sqrt(mFP.x()*mFP.x()+mFP.y()*mFP.y());
2399 double sn = fabs(mFP._cosCA*mFP.y() - mFP._sinCA*mFP.x())/d;
2400 if (sn> 0.99) sn = 0.99;
2406 d *= sqrt(1.+mFP.tanl()*mFP.tanl());
2408 double pt = fabs(mFP.ptin());
2411 double p2=(1.+mFP.tanl()*mFP.tanl())*pt*pt;
2412 double m=StiKalmanTrackFinderParameters::instance()->massHypothesis();
2416 beta = TMath::Sqrt(beta2);
2418 time = d/(TMath::Ccgs()*beta*1e-6);
2420 if (TMath::Abs(mFP.z()) > 20.0) {
2421 static const double Radius = 197.;
2422 static const int nsurf = 6;
2423 static const double surf[6] = {-Radius*Radius, 0, 0, 0, 1, 1};
2424 double dir[3] = {mFP._cosCA,mFP._sinCA,mFP.tanl()};
2426 double s = tc.
Path(smax, surf, nsurf,0,0,1);
2427 if (TMath::Abs(s) < smax)
2428 time = TMath::Abs(s)/(TMath::Ccgs()*1e-6);
2437 if (!_inf)
return 1e41;
2441 StiTrackNodeHelper::getHitErrors(hit,&myFP,&myHrr);
2443 double r00, r01,r11,det;
2446 double dsin =myFP.curv()*(hit->
x()-myFP.x());
2447 if (fabs(myFP._sinCA+dsin)>0.99)
return 1e41;
2448 if (fabs(myFP.eta()) >kMaxEta)
return 1e41;
2449 if (fabs(myFP.curv()) >kMaxCur)
return 1e41;
2450 if (myHrr.hYY>1000*myFE._cYY
2451 && myHrr.hZZ>1000*myFE._cZZ)
return 1e41;
2452 r00=myHrr.hYY+myFE._cYY;
2453 r01=myHrr.hZY+myFE._cZY;
2454 r11=myHrr.hZZ+myFE._cZZ;
2456 det=r00*r11 - r01*r01;
2457 if (det<r00*r11*1.e-5) {
2458 LOG_DEBUG << Form(
"StiKalmanTrackNode::evalChi2 *** zero determinant %g",_det)<< endm;
2461 double tmp=r00; r00=r11; r11=tmp; r01=-r01;
2462 double deltaX = hit->
x()-myFP.x();
2463 double deltaL = deltaX/myFP.
_cosCA;
2464 double deltaY = myFP._sinCA *deltaL;
2465 double deltaZ = myFP.tanl() *deltaL;
2466 double dyt=(myFP.y()-hit->y()) + deltaY;
2467 double dzt=(myFP.z()-hit->z()) + deltaZ;
2468 double cc= (dyt*r00*dyt + 2*r01*dyt*dzt + dzt*r11*dzt)/det;
2476 double StiKalmanTrackNode::StiKalmanTrackNode::pathlength()
const
2479 if (!det)
return 0.;
2480 double c = mFP._cosCA;
2481 if (det->getShape()->getShapeCode()!=kPlanar) {
2482 double CA = mFP.eta()-atan2(mFP.y(),mFP.x());
2485 double thickness = det->getShape()->getThickness();
2486 return (thickness*::sqrt(1.+mFP.tanl()*mFP.tanl())) / fabs(c);
void setState(const StiKalmanTrackNode *node)
Sets the Kalman state of this node equal to that of the given node.
int propagate(StiKalmanTrackNode *p, const StiDetector *tDet, int dir)
Propagates a track encapsulated by the given node "p" to the given detector "tDet".
int propagateToRadius(StiKalmanTrackNode *pNode, double radius, int dir)
void getGlobalRadial(double x[6], double e[15])
Extract state information from this node in Radial representation.
bool propagateToBeam(const StiKalmanTrackNode *p, int dir)
const Float_t & x() const
Return the local x, y, z values.
void reset()
Resets the node to a "null" un-used state.
void rotate(double angle)
const StiDetector * detector() const
double pathLToNode(const StiKalmanTrackNode *const oNode)
Float_t x_g() const
Return the global x, y, z values.
virtual void calculateError(Double_t _z, Double_t _eta, Double_t _tanl, Double_t &ecross, Double_t &edip, Double_t fudgeFactor=1) const
coeff[6] = 0:intrinsicY 1: driftY 2: crossY 3:intrinsicZ 4: driftZ 5: crossZ
StiElossCalculator * getElossCalculator() const
Get Eloss calculator.
int print(const char *opt) const
rotation angle of local coordinates wrt global coordinates
StThreeVector< double > getHelixCenter() const
Return center of helix circle in global coordinates.
double getPt() const
Calculates and returns the transverse momentum of the track at this node.
double calculate(double charge2, double m, double beta2) const
static void Free(void *obj)
Free an object for reuse.
static float * trasat(const float *a, const float *s, float *r, int m, int n)
double _cosCA
sine and cosine of cross angle
void resetError(double fak=0)
Resets errors for refit.
Abstract * getInstance()
Get a pointer to instance of objects served by this factory.
double evaluateChi2(const StiHit *hit)
void getGlobalTpt(float x[6], float e[15])
Extract state information from this node in TPT representation.
double getX0() const
Get the radiation length in centimeter.
virtual TString Path() const
return the full path of this data set
void propagateMCS(StiKalmanTrackNode *previousNode, const StiDetector *tDet)
void get(double &alpha, double &xRef, double x[kNPars], double cc[kNErrs], double &chi2)
Extract state information from this node.
StiNodeErrs mFE
covariance matrix of the track parameters
double evaluateChi2Info(const StiHit *hit) const
double getDensity() const
Get the material density in grams/cubic centimeter.
void initialize(StiHit *h)
Initialize this node with the given hit information.
const string & getName() const
Get the name of the object.