181 #include "StFtpcTrack.hh"
182 #include "StFtpcTrackingParams.hh"
183 #include "StFormulary.hh"
184 #include "StFtpcVertex.hh"
185 #include "StFtpcPoint.hh"
186 #include "StFtpcConfMapPoint.hh"
188 #include "SystemOfUnits.h"
189 #include "PhysicalConstants.h"
190 #include "StMessMgr.h"
215 StFtpcTrack::StFtpcTrack(Int_t tracknumber)
220 SetTrackNumber(tracknumber);
224 StFtpcTrack::~StFtpcTrack()
229 delete mPointNumbers;
233 void StFtpcTrack::SetDefaults()
237 mPoints =
new TObjArray(0);
250 ComesFromMainVertex(kFALSE);
279 void StFtpcTrack::SetTrackNumber(Int_t number)
284 mTrackNumber = number;
286 for (Int_t i = 0; i < mPoints->GetEntriesFast(); i++) {
287 ((
StFtpcPoint*)mPoints->At(i))->SetTrackNumber(number);
298 mPointNumbers->AddLast(point->GetHitNumber());
299 mPoints->AddLast(point);
300 point->SetUsage(kTRUE);
301 point->SetTrackNumber(GetTrackNumber());
307 void StFtpcTrack::AddForwardPoint(
StFtpcPoint* point)
311 Int_t num = mPoints->GetEntriesFast();
312 mPoints->Expand(num+1);
314 for (Int_t i = num-1; i >= 0; i--) {
315 mPoints->AddAt(mPoints->At(i), i+1);
318 mPoints->AddFirst(point);
319 mPointNumbers->ShiftByOneAndAddAtFirst(point->GetHitNumber());
320 point->SetUsage(kTRUE);
321 point->SetTrackNumber(GetTrackNumber());
327 Int_t StFtpcTrack::GetHemisphere()
const
330 return (Int_t)TMath::Sign(1., ((
StFtpcPoint *)(GetHits()->First()))->GetZ());
334 Int_t StFtpcTrack::GetSector()
const
337 return ((
StFtpcPoint *)GetHits()->First())->GetSector();
341 Double_t StFtpcTrack::CalcAlpha0()
346 Double_t asin_arg = StFormulary::CheckASinArg((trackpoint->GetYt() - GetCenterY())/GetRadius());
347 Double_t alpha0 = 0.;
349 if (trackpoint->GetXt() >= GetCenterX() && trackpoint->GetYt() > GetCenterY()) {
350 alpha0 = TMath::ASin(asin_arg);
353 else if (trackpoint->GetXt() < GetCenterX() && trackpoint->GetYt() >= GetCenterY()) {
354 alpha0 = -TMath::ASin(asin_arg) + TMath::Pi();
357 else if (trackpoint->GetXt() <= GetCenterX() && trackpoint->GetYt() < GetCenterY()) {
358 alpha0 = TMath::ASin(-asin_arg) + TMath::Pi();
361 else if (trackpoint->GetXt() > GetCenterX() && trackpoint->GetYt() <= GetCenterY()) {
362 alpha0 = -TMath::ASin(-asin_arg) + 2 * TMath::Pi();
369 void StFtpcTrack::SetProperties(Bool_t usage, Int_t tracknumber)
377 for (Int_t i = 0; i < mPoints->GetEntriesFast(); i++) {
380 if (usage == kTRUE) {
381 mRowsWithPoints += (Int_t)TMath::Power(2., (Int_t)(((p->GetPadRow()-1)%StFtpcTrackingParams::Instance()->NumberOfPadRowsPerSide())+1));
388 p->SetNextHitNumber(-1);
393 p->SetNextHitNumber(-1);
397 p->SetTrackNumber(tracknumber);
404 void StFtpcTrack::SetPointDependencies()
410 for (Int_t i = 0; i < mPoints->GetEntriesFast(); i++) {
413 mRowsWithPoints += (Int_t)TMath::Power(2., (Int_t) (((p->GetPadRow()-1)%StFtpcTrackingParams::Instance()->NumberOfPadRowsPerSide())+1));
416 p->SetNextHitNumber(((
StFtpcPoint *)mPoints->At(i-1))->GetHitNumber());
420 p->SetNextHitNumber(-1);
430 void StFtpcTrack::CalculateNMax()
444 Double_t z2 = firstpoint->GetZ();
445 Double_t z1 = lastpoint->GetZ();
446 Double_t x2 = firstpoint->GetX();
447 Double_t x1 = lastpoint->GetX();
448 Double_t r2 = TMath::Sqrt((firstpoint->GetX() * firstpoint->GetX()) + (firstpoint->GetY() * firstpoint->GetY()));
449 Double_t r1 = TMath::Sqrt((lastpoint->GetX() * lastpoint->GetX()) + (lastpoint->GetY() * lastpoint->GetY()));
453 for (Int_t i = 0; i < StFtpcTrackingParams::Instance()->NumberOfPadRowsPerSide(); i++) {
454 r = (r2 - r1) / (z2 - z1) * (TMath::Sign(Double_t(StFtpcTrackingParams::Instance()->PadRowPosZ(i)), z1) - z1) + r1;
455 x = (x2 - x1) / (z2 - z1) * (TMath::Sign(Double_t(StFtpcTrackingParams::Instance()->PadRowPosZ(i)), z1) - z1) + x1;
460 Double_t ratio = x/r;
461 if (TMath::Abs(ratio) > 1.) {
462 if (ratio > 0) ratio = 1.;
466 mAlphaFirst = TMath::ACos(ratio);
472 Double_t ratio = x/r;
473 if (TMath::Abs(ratio) > 1.) {
474 if (ratio > 0) ratio = 1.;
478 mAlphaLast = TMath::ACos(ratio);
481 if (r < StFtpcTrackingParams::Instance()->OuterRadius() && r > StFtpcTrackingParams::Instance()->InnerRadius()) {
497 MomentumFit(primaryFit ? vertex : 0);
503 void StFtpcTrack::CalcResiduals(Bool_t primaryFit) {
508 for (Int_t i = 0; i < mPoints->GetEntriesFast(); i++) {
514 Double_t x_hel =
x(pl);
515 Double_t y_hel = y(pl);
516 Double_t x_hit = hit->GetX();
517 Double_t y_hit = hit->GetY();
520 hit->SetXPrimResidual(x_hit - x_hel);
521 hit->SetYPrimResidual(y_hit - y_hel);
522 hit->SetRPrimResidual(TMath::Sqrt(x_hit*x_hit + y_hit*y_hit) - TMath::Sqrt(x_hel*x_hel + y_hel*y_hel));
523 hit->SetPhiPrimResidual(TMath::ATan2(y_hit, x_hit) - TMath::ATan2(y_hel, x_hel));
527 hit->SetXGlobResidual(x_hit - x_hel);
528 hit->SetYGlobResidual(y_hit - y_hel);
529 hit->SetRGlobResidual(TMath::Sqrt(x_hit*x_hit + y_hit*y_hit) - TMath::Sqrt(x_hel*x_hel + y_hel*y_hel));
530 hit->SetPhiGlobResidual(TMath::ATan2(y_hit, x_hit) - TMath::ATan2(y_hel, x_hel));
538 void StFtpcTrack::Fit()
543 mP.SetX(momentum().
x());
544 mP.SetY(momentum().y());
545 mP.SetZ(momentum().z());
546 mChiSq[0] = chi2Rad();
547 mChiSq[1] = chi2Lin();
548 mTheta = momentum().theta();
554 void StFtpcTrack::Fit(
StFtpcVertex *vertex, Double_t max_Dca, Bool_t primary_fit)
576 if (mDca > max_Dca) {
577 mFromMainVertex = (Bool_t)kFALSE;
581 mFromMainVertex = (Bool_t)kTRUE;
587 if (mDca > max_Dca) {
589 mFromMainVertex = (Bool_t)kFALSE;
594 if (
pathLength(lastPoint, nv) >= NoSolution/2){
595 LOG_WARN <<
"NoSolution found for MomentumFit with primary vertex - set mFromMainVertex = kFALSE for track " <<mTrackNumber<< endm;
596 mFromMainVertex = (Bool_t)kFALSE;
602 mFromMainVertex = (Bool_t)kTRUE;
611 mP.SetX(momentum().
x());
612 mP.SetY(momentum().y());
613 mP.SetZ(momentum().z());
617 mL.SetX(
x(mTrackLength));
618 mL.SetY(y(mTrackLength));
619 mL.SetZ(z(mTrackLength));
621 mChiSq[0] = chi2Rad();
622 mChiSq[1] = chi2Lin();
623 mFitRadius = 1./curvature();
626 if (vertex->GetId() == 0) {
636 Double_t xWeight[11], yWeight[11];
637 Double_t xval[11], yval[11], zval[11];
638 Double_t xhelix[11], yhelix[11], zhelix[11];
647 mVertexPointOffset = 1;
650 xval[0] = vertex->GetX() * centimeter;
651 yval[0] = vertex->GetY() * centimeter;
652 zval[0] = vertex->GetZ() * centimeter;
655 xWeight[0] = (vertex->GetXerr() == 0.) ? 100. : 1./(vertex->GetXerr() * centimeter);
656 yWeight[0] = (vertex->GetYerr() == 0.) ? 100. : 1./(vertex->GetYerr() * centimeter);
661 mVertexPointOffset = 0;
664 Int_t backw_counter = 0;
667 for(i = 0; i < GetNumberOfPoints(); i++) {
668 backw_counter = GetNumberOfPoints() - 1 - i + mVertexPointOffset;
671 xval[backw_counter] = point->GetX() * centimeter;
672 yval[backw_counter] = point->GetY() * centimeter;
673 zval[backw_counter] = point->GetZ() * centimeter;
676 xWeight[backw_counter] = (point->GetXerr() == 0.) ? 100. : 1./(point->GetXerr() * centimeter);
677 yWeight[backw_counter] = (point->GetYerr() == 0.) ? 100. : 1./(point->GetYerr() * centimeter);
684 CircleFit(xval, yval, xWeight, yWeight, GetNumberOfPoints() + mVertexPointOffset);
685 LineFit(xval, yval, zval, xWeight, yWeight, GetNumberOfPoints() + mVertexPointOffset);
688 Double_t dipAngle = fabs(atan(1/(mFitRadius*mArcSlope)));
694 Double_t startPhase = atan((yval[0]-mYCenter)/(xval[0]-mXCenter));
696 if (xval[0]-mXCenter < 0) {
700 else if (yval[0]-mYCenter < 0) {
704 Int_t orientation = 1;
706 if (mArcSlope * zval[1] < 0) {
711 Double_t startAngle = mArcOffset + mArcSlope * zval[0];
712 Double_t startX = mXCenter + mFitRadius * cos(startAngle);
713 Double_t startY = mYCenter + mFitRadius * sin(startAngle);
716 setParameters(1/mFitRadius, dipAngle, startPhase, startHit, orientation);
719 Float_t pos[3] = {0., 0., 0.};
720 Float_t centralField[3];
721 StFtpcTrackingParams::Instance()->MagField()->
B3DField(pos, centralField);
722 centralField[0] *= kilogauss;
723 centralField[1] *= kilogauss;
724 centralField[2] *= kilogauss;
725 mZField = (Double_t) centralField[2];
731 mHelixMomentum = momentumAt(pl, mZField);
732 SetCharge(charge(mZField));
735 for(i = 0; i < GetNumberOfPoints() + mVertexPointOffset; i++) {
739 if (plength >= NoSolution/2) {
740 LOG_WARN <<
"Helix Fit found NoSolution for hit " << i <<
" - not possible to track helix momentum through measured field for this track"<< endm;
743 xhelix[i] =
x(plength);
744 yhelix[i] = y(plength);
745 zhelix[i] = z(plength);
754 yhelix[0 + mVertexPointOffset],
755 zhelix[0 + mVertexPointOffset]);
760 if (StFtpcTrackingParams::Instance()->MagFieldFactor()) {
765 for(i = 1 + mVertexPointOffset; i < GetNumberOfPoints() + mVertexPointOffset; i++) {
766 stepSize = (zval[i] - zval[i-1]) / mIterSteps;
769 for(j = 0; j < mIterSteps; j++) {
771 Double_t propagateXMomentum = currentMomentum.x();
772 Double_t propagateYMomentum = currentMomentum.y();
773 Double_t propagateZMomentum = currentMomentum.z();
776 Float_t positionArray[3] = {(Float_t) (currentPosition.x()),
777 (Float_t) (currentPosition.y()),
778 (Float_t) (currentPosition.z() + stepSize/2)};
779 Float_t localField[3];
780 StFtpcTrackingParams::Instance()->MagField()->
B3DField(positionArray, localField);
783 ((Double_t) localField[0] * kilogauss/tesla*c_light*nanosecond/meter,
784 (Double_t) localField[1] * kilogauss/tesla*c_light*nanosecond/meter,
785 (Double_t) localField[2] * kilogauss/tesla*c_light*nanosecond/meter);
788 Double_t absMomentum = abs(currentMomentum);
790 currentMomentum.cross(fieldVector) * (Double_t)mQ/absMomentum;
791 Double_t twistRadius = (absMomentum/abs(perpField)) * meter/GeV;
793 Double_t stepLength = stepSize/cos(currentMomentum.theta());
795 Double_t newMomentumCross = absMomentum*stepLength/twistRadius;
796 Double_t newMomentumParallel =
797 ::sqrt(absMomentum * absMomentum - newMomentumCross * newMomentumCross);
798 currentMomentum.setMagnitude(newMomentumParallel);
800 momentumChange.setMagnitude(newMomentumCross);
801 currentMomentum = currentMomentum+momentumChange;
804 propagateXMomentum = (propagateXMomentum + currentMomentum.x())/2;
805 propagateYMomentum = (propagateYMomentum + currentMomentum.y())/2;
806 propagateZMomentum = (propagateZMomentum + currentMomentum.z())/2;
807 currentPosition.setX(currentPosition.x() + stepSize *
808 (propagateXMomentum / propagateZMomentum));
809 currentPosition.setY(currentPosition.y() + stepSize *
810 (propagateYMomentum / propagateZMomentum));
811 currentPosition.setZ(currentPosition.z() + stepSize);
820 xval[i] += (
x(plength) - currentPosition.x());
821 yval[i] += (y(plength) - currentPosition.y());
825 xval[i] -= (
x(plength) - currentPosition.x());
826 yval[i] -= (y(plength) - currentPosition.y());
839 CircleFit(xval, yval, xWeight, yWeight, GetNumberOfPoints()+mVertexPointOffset);
840 LineFit(xval, yval, zval, xWeight, yWeight, GetNumberOfPoints()+mVertexPointOffset);
843 dipAngle = fabs(atan(1/(mFitRadius*mArcSlope)));
849 startPhase = atan((yval[0]-mYCenter)/(xval[0]-mXCenter));
851 if (xval[0] - mXCenter < 0) {
855 else if (yval[0]-mYCenter<0) {
861 if (mArcSlope * zval[1] < 0) {
866 startAngle = mArcOffset + mArcSlope * zval[0];
867 startX = mXCenter + mFitRadius * cos(startAngle);
868 startY = mYCenter + mFitRadius * sin(startAngle);
869 startHit.setX(startX);
870 startHit.setY(startY);
872 setParameters(1/mFitRadius, dipAngle, startPhase, startHit, orientation);
877 mFullMomentum = momentumAt(pl, mZField);
900 Int_t StFtpcTrack::CircleFit(Double_t x[],Double_t y[], Double_t xw[], Double_t yw[], Int_t num)
925 wei[i] = xw[i] + yw[i];
926 xav += x[i] * wei[i];
927 yav += y[i] * wei[i];
938 LOG_INFO <<
"from circle fitting program" << endm;
944 LOG_INFO <<
"x: " << x[i] <<
" y: " << y[i] <<
"xw: " << xw[i] <<
" yw: " << yw[i] << endm;
967 Double_t wgamma0 = 0;
970 for(i = 0; i < num; i++) {
971 F += wei[i] * (3 * x[i] * x[i] + y[i] * y[i]);
973 G += wei[i] * (x[i] * x[i] + 3 * y[i] * y[i]);
975 H += wei[i] * 2 * x[i] *y[i];
977 P += wei[i] * x[i] * (x[i] * x[i] + y[i] * y[i]);
979 Q += wei[i] * y[i] * (x[i] * x[i] + y[i] * y[i]);
981 T += wei[i] * (x[i] * x[i] + y[i] * y[i]) * (x[i] * x[i] + y[i] * y[i]);
983 gamma0 += wei[i] * (x[i] * x[i] + y[i] * y[i]);
987 gamma0 = gamma0/wgamma0;
996 Double_t B = F * G - T - H * H;
997 Double_t C = T * (F + G) - 2 * (P *P + Q * Q);
998 Double_t D = T * (H * H - F * G) + 2 * (P * P * G + Q * Q * F) - 4 * P * Q *H;
1000 Double_t A0 = A / gamma0;
1001 Double_t B0 = B / (gamma0*gamma0);
1002 Double_t C0 = C / (gamma0*gamma0*gamma0);
1003 Double_t D0 = D / (gamma0*gamma0*gamma0*gamma0);
1008 Int_t MaxIter = 100;
1011 Double_t f = 0., fp = 0.;
1012 Double_t xc = 0., yc = 0.;
1015 LOG_INFO <<
"Solving by Newton method" << endm;
1018 for(i = 0; i < MaxIter; i++) {
1019 f = w*w*w*w + A0 * w*w*w + B0 * w*w + C0 * w + D0;
1020 fp = 4 * w*w*w + 3 * A0 * w*w + 2 * B0 * w + C0;
1024 LOG_INFO <<
"Iteration Number" << i << endm;
1027 if ((wNew-w) < 10e-16 && (w-wNew) < 10e-16) {
1036 Double_t gamma = gamma0 * wNew;
1037 Double_t b = (Q - H * P / (F - gamma)) / (G - gamma - H * H / (F - gamma));
1038 Double_t a = (P - H * b) / (F - gamma);
1041 if ((wNew-w) < 10e-16 && (w-wNew) < 10e-16) {
1042 R = ::sqrt(a * a + b * b + gamma);
1049 Double_t variance = 0.;
1064 for (i = 0; i < num; i++) {
1068 Double_t err = R - ::sqrt((x[i] - xc) * (x[i] - xc) + (y[i] - yc) * (y[i] - yc));
1073 variance += 1 / (xw[i] * xw[i]) + 1 / (yw[i] * yw[i]);
1077 variance /= (num-1);
1088 void StFtpcTrack::LineFit(Double_t *xval, Double_t *yval, Double_t *zval, Double_t *xw, Double_t *yw, Int_t num)
1090 Double_t x_ss = 0., x_sang = 0., x_sz = 0., x_szang = 0., x_szz = 0.;
1093 Double_t angle = 0., lastangle = 0.;
1095 for(i = 0; i < num; i++) {
1097 angle = atan((yval[i]-mYCenter)/(xval[i]-mXCenter));
1099 if (xval[i] - mXCenter < 0) {
1103 else if (yval[i] - mYCenter < 0) {
1109 if (angle>lastangle+pi) angle -= twopi;
1110 if (angle<lastangle-pi) angle += twopi;
1116 weight = ::sqrt(xw[i] * xw[i] * cos(angle) * cos(angle)
1117 + yw[i] * yw[i] * sin(angle) * sin(angle));
1119 x_sang += weight * angle;
1120 x_sz += weight * zval[i];
1121 x_szang += weight * zval[i] * angle;
1122 x_szz += weight * zval[i] * zval[i];
1125 t = x_ss * x_szz - x_sz * x_sz;
1128 mArcOffset = ((x_szz * x_sang) - (x_sz * x_szang)) / t;
1129 mArcSlope = ((x_ss * x_szang) - (x_sz * x_sang)) / t;
1137 Double_t chi2 = 0., variance = 0.;
1139 for(i = 0; i < num; i++) {
1140 Double_t angle = atan((yval[i] - mYCenter) / (xval[i] - mXCenter));
1142 if (xval[i]-mXCenter<0) {
1146 else if (yval[i] -mYCenter < 0) {
1150 Double_t lastangle = mArcOffset + mArcSlope*zval[i];
1154 if (angle>lastangle+pi) angle-=twopi;
1155 if (angle<lastangle-pi) angle+=twopi;
1158 Double_t err = (angle - (mArcOffset + mArcSlope*zval[i]));
1163 Double_t temp= ((1 / xw[i] * 1 / xw[i]) + (1 / yw[i] * 1 / yw[i]))
1164 * ((mArcSlope * (zval[i] - zval[0])) * (mArcSlope * (zval[i] - zval[0])))
1165 / ((xval[i] - xval[0]) * (xval[i] - xval[0]) + (yval[i] - yval[0]) * (yval[i] - yval[0]));
1170 variance /= (num-1);
1175 void StFtpcTrack::CalcGlobResiduals()
1179 CalcResiduals((Bool_t)kFALSE);
1183 void StFtpcTrack::CalcPrimResiduals()
1187 CalcResiduals((Bool_t)kTRUE);
1191 Double_t StFtpcTrack::GetMeanAlpha()
1195 Double_t phi = mAlphaFirst+mAlphaLast;
1197 if (phi >= 2*TMath::Pi()) phi -= 2*TMath::Pi();
1198 else if (phi <= -2*TMath::Pi()) phi += 2*TMath::Pi();
1204 Double_t StFtpcTrack::GetPt()
const
1208 return TMath::Sqrt(mP.X() * mP.X() + mP.Y() * mP.Y());
1212 Double_t StFtpcTrack::GetP()
const
1216 return TMath::Sqrt(mP.X() * mP.X() + mP.Y() * mP.Y() + mP.Z() * mP.Z());
1220 Double_t StFtpcTrack::GetPseudoRapidity()
const
1224 return 0.5 * TMath::Log((GetP() + GetPz()) / (GetP() - GetPz()));
1228 Double_t StFtpcTrack::GetEta()
const
1232 return GetPseudoRapidity();
1236 Double_t StFtpcTrack::GetRapidity()
const
1240 return 0.5 * TMath::Log((M_PION_PLUS + GetPz()) / (M_PION_PLUS - GetPz()));
1248 return mHelixMomentum;
1254 return mFullMomentum;
1258 Double_t StFtpcTrack::chi2Rad()
const
1264 Double_t StFtpcTrack::chi2Lin()
const
1272 return momentumAt(s, mZField);
void setParameters(double c, double dip, double phase, const StThreeVector< double > &o, int h)
starting point
double x(double s) const
coordinates of helix at point s
virtual void B3DField(const Float_t x[], Float_t B[])
Bfield in Cartesian coordinates - 3D field.
double distance(const StThreeVector< double > &p, bool scanPeriods=true) const
minimal distance between point and helix
pair< double, double > pathLength(double r) const
path length at given r (cylindrical r)