59 static constexpr float kDeg2Rad = M_PI / 180.f;
60 CADEBUG(
static constexpr float kSectAngle = 2 * M_PI / 18.f);
67 prop.SetMaterialTPC();
68 prop.SetPolynomialField(&
param.polynomialField);
69 prop.SetMaxSinPhi(maxSinPhi);
70 prop.SetToyMCEventsFlag(
param.par.toyMCEventsFlag);
72 ShiftZ2(
clusters, clustersXYZ, merger, N);
74 if (
param.rec.tpc.mergerInterpolateErrors) {
75 for (int32_t
i = 0;
i < N;
i++) {
80 const int32_t nWays =
param.rec.tpc.nWays;
81 const int32_t maxN = N;
82 int32_t ihitStart = 0;
84 float lastUpdateX = -1.f;
85 uint8_t lastRow = 255;
86 uint8_t lastSector = 255;
87 uint8_t storeOuter = 0;
89 for (int32_t iWay = 0; iWay < nWays; iWay++) {
90 int32_t nMissed = 0, nMissed2 = 0;
91 float sumInvSqrtCharge = 0.f;
92 int32_t nAvgCharge = 0;
94 if (iWay && storeOuter != 255 &&
param.rec.tpc.nWaysOuter && outerParam) {
96 if (iWay == nWays - 1) {
97 StoreOuter(outerParam, prop, 0);
98 if (merger->MergedTracks()[iTrk].Looper()) {
101 }
else if (iWay == nWays - 2 && merger->MergedTracks()[iTrk].Looper()) {
106 int32_t resetT0 = initResetT0();
107 const bool refit = (nWays == 1 || iWay >= 1);
108 const float maxSinForUpdate = CAMath::Sin(70.f * kDeg2Rad);
111 prop.SetSeedingErrors(!(refit && attempt == 0));
112 prop.SetFitInProjections(
param.rec.fitInProjections == -1 ? (iWay != 0) :
param.rec.fitInProjections);
113 prop.SetPropagateBzOnly(
param.rec.fitPropagateBzOnly > iWay);
114 prop.SetMatLUT((
param.rec.useMatLUT && iWay == nWays - 1) ? merger->GetConstantMem()->calibObjects.matLUT :
nullptr);
115 prop.SetTrack(
this, iWay ? prop.GetAlpha() : Alpha);
117 CADEBUG(printf(
"Fitting track %d way %d (sector %d, alpha %f)\n", iTrk, iWay, CAMath::Float2IntRn(prop.GetAlpha() / kSectAngle) + (mP[1] < 0 ? 18 : 0), prop.GetAlpha()));
121 const bool inFlyDirection = iWay & 1;
122 uint8_t lastLeg =
clusters[ihitStart].leg;
123 const int32_t wayDirection = (iWay & 1) ? -1 : 1;
125 bool noFollowCircle =
false, noFollowCircle2 =
false;
126 int32_t goodRows = 0;
127 for (int32_t ihit = ihitStart; ihit >= 0 && ihit < maxN; ihit += wayDirection) {
128 const bool crossCE = lastSector != 255 && ((lastSector < 18) ^ (
clusters[ihit].sector < 18));
131 noFollowCircle2 =
true;
136 StoreOuter(outerParam, prop, 1);
144 CADEBUG(printf(
"\tSkipping hit, %d hits rejected, flag %X\n", nMissed, (int32_t)
clusters[ihit].
state));
151 const bool allowModification = refit && (iWay == 0 || (((nWays - iWay) & 1) ? (ihit >= CAMath::Min(maxN / 2, 30)) : (ihit <= CAMath::Max(maxN / 2, maxN - 30))));
153 int32_t ihitMergeFirst = ihit;
154 uint8_t clusterState =
clusters[ihit].state;
157 if (
param.par.earlyTpcTransform) {
158 const float zOffset = (
clusters[ihit].sector < 18) == (
clusters[0].sector < 18) ? mTZOffset : -mTZOffset;
159 xx = clustersXYZ[ihit].x;
160 yy = clustersXYZ[ihit].y;
161 zz = clustersXYZ[ihit].z - zOffset;
164 merger->GetConstantMem()->calibObjects.fastTransformHelper->Transform(
clusters[ihit].sector,
clusters[ihit].
row, cl.getPad(), cl.getTime(), xx, yy, zz, mTZOffset);
167 CADEBUG(printf(
"\tHit %3d/%3d Row %3d: Cluster Alpha %8.3f %3d, X %8.3f - Y %8.3f, Z %8.3f (Missed %d)\n", ihit, maxN, (int32_t)
clusters[ihit].
row, clAlpha, (int32_t)
clusters[ihit].sector, xx, yy, zz, nMissed));
171 if (MergeDoubleRowClusters(ihit, wayDirection,
clusters, clustersXYZ, merger, prop, xx, yy, zz, maxN, clAlpha, clusterState, allowModification) == -1) {
177 if (
param.rec.tpc.rejectIFCLowRadiusCluster) {
178 const float r2 = xx * xx + yy * yy;
179 const float rmax = (83.5f +
param.rec.tpc.sysClusErrorMinDist);
180 if (r2 < rmax * rmax) {
185 const auto& cluster =
clusters[ihit];
187 bool changeDirection = (cluster.leg - lastLeg) & 1;
189 CADEBUG(
if (changeDirection) printf(
"\t\tChange direction\n"));
190 CADEBUG(printf(
"\tLeg %3d Sector %2d %4sTrack Alpha %8.3f %s, X %8.3f - Y %8.3f, Z %8.3f - QPt %7.2f (%7.2f), SP %5.2f (%5.2f) %28s --- Cov sY %8.3f sZ %8.3f sSP %8.3f sPt %8.3f - YPt %8.3f\n", (int32_t)cluster.leg, (int32_t)cluster.sector,
"", prop.GetAlpha(), (CAMath::Abs(prop.GetAlpha() - clAlpha) < 0.01 ?
" " :
" R!"), mX, mP[0], mP[1], mP[4], prop.GetQPt0(), mP[2], prop.GetSinPhi0(),
"", sqrtf(mC[0]), sqrtf(mC[2]), sqrtf(mC[5]), sqrtf(mC[14]), mC[10]));
192 if (allowModification && changeDirection && !noFollowCircle && !noFollowCircle2) {
193 bool tryFollow = lastRow != 255;
196 const float backupAlpha = prop.GetAlpha();
197 if (FollowCircle<0>(merger, prop, lastSector, lastRow, iTrk, clAlpha, xx, yy, cluster.
sector, cluster.
row, inFlyDirection)) {
198 CADEBUG(printf(
"Error during follow circle, resetting track!\n"));
200 prop.SetTrack(
this, backupAlpha);
201 noFollowCircle =
true;
206 MirrorTo(prop, yy, zz, inFlyDirection,
param, cluster.row, clusterState,
false, cluster.
sector);
208 lastLeg = cluster.leg;
209 lastSector = cluster.sector;
212 resetT0 = initResetT0();
215 CADEBUG(printf(
"\t%21sMirror Alpha %8.3f , X %8.3f - Y %8.3f, Z %8.3f - QPt %7.2f (%7.2f), SP %5.2f (%5.2f) %28s --- Cov sY %8.3f sZ %8.3f sSP %8.3f sPt %8.3f - YPt %8.3f\n",
"", prop.GetAlpha(), mX, mP[0], mP[1], mP[4], prop.GetQPt0(), mP[2], prop.GetSinPhi0(),
"", sqrtf(mC[0]), sqrtf(mC[2]), sqrtf(mC[5]), sqrtf(mC[14]), mC[10]));
219 }
else if (allowModification && lastRow != 255 && CAMath::Abs(cluster.row - lastRow) > 1) {
221 bool dodEdx =
param.dodEdxEnabled &&
param.rec.tpc.adddEdxSubThresholdClusters && iWay == nWays - 1 && CAMath::Abs(cluster.row - lastRow) == 2 && cluster.leg ==
clusters[maxN - 1].leg;
222 dodEdx = AttachClustersPropagate(merger, cluster.sector, lastRow, cluster.row, iTrk, cluster.leg ==
clusters[maxN - 1].leg, prop, inFlyDirection,
GPUCA_MAX_SIN_PHI, dodEdx);
224 dEdx.fillSubThreshold(lastRow - wayDirection);
226 dEdxAlt.fillSubThreshold(lastRow - wayDirection);
232 int32_t err = prop.PropagateToXAlpha(xx, clAlpha, inFlyDirection);
234 CADEBUG(
if (!CheckCov()){printf(
"INVALID COV AFTER PROPAGATE!!!\n");});
239 if (prop.PropagateToXAlpha(xx, prop.GetAlpha(), inFlyDirection) == 0) {
240 err = prop.PropagateToXAlpha(xx, clAlpha, inFlyDirection);
243 if (lastRow == 255 || CAMath::Abs((int32_t)lastRow - (int32_t)cluster.row) > 5 || lastSector != cluster.sector || (
param.rec.tpc.trackFitRejectMode < 0 && -nMissed <=
param.rec.tpc.trackFitRejectMode)) {
249 lastRow = cluster.row;
250 lastSector = cluster.
sector;
253 CADEBUG(printf(
"\t%21sPropaga Alpha %8.3f , X %8.3f - Y %8.3f, Z %8.3f - QPt %7.2f (%7.2f), SP %5.2f (%5.2f) --- Res %8.3f %8.3f --- Cov sY %8.3f sZ %8.3f sSP %8.3f sPt %8.3f - YPt %8.3f - Err %d",
"", prop.GetAlpha(), mX, mP[0], mP[1], mP[4], prop.GetQPt0(), mP[2], prop.GetSinPhi0(), mP[0] - yy, mP[1] - zz, sqrtf(mC[0]), sqrtf(mC[2]), sqrtf(mC[5]), sqrtf(mC[14]), mC[10], err));
257 if (
param.rec.tpc.addErrorsCECrossing) {
258 if (
param.rec.tpc.addErrorsCECrossing >= 2) {
259 AddCovDiagErrorsWithCorrelations(
param.rec.tpc.errorsCECrossing);
261 AddCovDiagErrors(
param.rec.tpc.errorsCECrossing);
263 }
else if (mC[2] < 0.5f) {
268 if (err == 0 && changeDirection) {
269 const float mirrordY = prop.GetMirroredYTrack();
270 CADEBUG(printf(
" -- MirroredY: %f --> %f", mP[0], mirrordY));
271 if (CAMath::Abs(yy - mP[0]) > CAMath::Abs(yy - mirrordY)) {
272 CADEBUG(printf(
" - Mirroring!!!"));
273 if (allowModification) {
274 AttachClustersMirror<0>(merger, cluster.sector, cluster.row, iTrk, yy, prop);
276 MirrorTo(prop, yy, zz, inFlyDirection,
param, cluster.row, clusterState,
true, cluster.
sector);
277 noFollowCircle =
false;
280 lastLeg = cluster.leg;
283 resetT0 = initResetT0();
286 CADEBUG(printf(
"\t%21sMirror Alpha %8.3f , X %8.3f - Y %8.3f, Z %8.3f - QPt %7.2f (%7.2f), SP %5.2f (%5.2f) %28s --- Cov sY %8.3f sZ %8.3f sSP %8.3f sPt %8.3f - YPt %8.3f\n",
"", prop.GetAlpha(), mX, mP[0], mP[1], mP[4], prop.GetQPt0(), mP[2], prop.GetSinPhi0(),
"", sqrtf(mC[0]), sqrtf(mC[2]), sqrtf(mC[5]), sqrtf(mC[14]), mC[10]));
292 float uncorrectedY = -1e6f;
293 if (allowModification) {
294 uncorrectedY = AttachClusters(merger, cluster.sector, cluster.row, iTrk, cluster.leg ==
clusters[maxN - 1].leg, prop);
297 const int32_t err2 = mNDF > 0 && CAMath::Abs(prop.GetSinPhi0()) >= maxSinForUpdate;
299 if (mC[0] >
param.rec.tpc.trackFitCovLimit || mC[2] >
param.rec.tpc.trackFitCovLimit) {
305 CADEBUG(printf(
" --- break (%d, %d)\n", err, err2));
311 float threshold = 3.f + (lastUpdateX >= 0 ? (CAMath::Abs(mX - lastUpdateX) / 2) : 0.f);
312 if (mNDF > 5 && (CAMath::Abs(yy - mP[0]) > threshold || CAMath::Abs(zz - mP[1]) > threshold)) {
315 int8_t rejectChi2 = attempt ? 0 : ((
param.rec.tpc.mergerInterpolateErrors && CAMath::Abs(ihit - ihitMergeFirst) <= 1) ? (refit ? (
GPUTPCGMPropagator::rejectInterFill + ((nWays - iWay) & 1)) : 0) : (allowModification && goodRows > 5));
316#if EXTRACT_RESIDUALS == 1
318 const float Iz0 = interpolation.
hit[ihit].
posY - mP[0];
319 const float Iz1 = interpolation.
hit[ihit].
posZ - mP[1];
320 float Iw0 = mC[2] + (float)interpolation.
hit[ihit].
errorZ;
321 float Iw2 = mC[0] + (float)interpolation.
hit[ihit].
errorY;
322 float Idet1 = 1.f / CAMath::Max(1e-10f, Iw0 * Iw2 - mC[1] * mC[1]);
323 const float Ik00 = (mC[0] * Iw0 + mC[1] * mC[1]) * Idet1;
324 const float Ik01 = (mC[0] * mC[1] + mC[1] * Iw2) * Idet1;
325 const float Ik10 = (mC[1] * Iw0 + mC[2] * mC[1]) * Idet1;
326 const float Ik11 = (mC[1] * mC[1] + mC[2] * Iw2) * Idet1;
327 const float ImP0 = mP[0] + Ik00 * Iz0 + Ik01 * Iz1;
328 const float ImP1 = mP[1] + Ik10 * Iz0 + Ik11 * Iz1;
329 const float ImC0 = mC[0] - Ik00 * mC[0] + Ik01 * mC[1];
330 const float ImC2 = mC[2] - Ik10 * mC[1] + Ik11 * mC[2];
331 auto& tup =
GPUROOTDump<TNtuple>::get(
"clusterres",
"row:clX:clY:clZ:angle:trkX:trkY:trkZ:trkSinPhi:trkDzDs:trkQPt:trkSigmaY2:trkSigmaZ2trkSigmaQPt2");
332 tup.Fill((
float)cluster.row, xx, yy, zz, clAlpha, mX, ImP0, ImP1, mP[2], mP[3], mP[4], ImC0, ImC2, mC[14]);
336 if (
param.rec.tpc.rejectEdgeClustersInTrackFit && uncorrectedY > -1e6f &&
param.rejectEdgeClusterByY(uncorrectedY, cluster.row, CAMath::Sqrt(mC[0]))) {
339 const float time = merger->GetConstantMem()->ioPtrs.clustersNative ? merger->GetConstantMem()->ioPtrs.clustersNative->clustersLinear[cluster.num].getTime() : -1.f;
340 const float invSqrtCharge = merger->GetConstantMem()->ioPtrs.clustersNative ? CAMath::InvSqrt(merger->GetConstantMem()->ioPtrs.clustersNative->clustersLinear[cluster.num].qMax) : 0.f;
341 const float invCharge = merger->GetConstantMem()->ioPtrs.clustersNative ? (1.f / merger->GetConstantMem()->ioPtrs.clustersNative->clustersLinear[cluster.num].qMax) : 0.f;
342 float invAvgCharge = (sumInvSqrtCharge += invSqrtCharge) / ++nAvgCharge;
343 invAvgCharge *= invAvgCharge;
344 retVal = prop.Update(yy, zz, cluster.row,
param, clusterState, rejectChi2, &interpolation.
hit[ihit], refit, cluster.sector,
time, invAvgCharge, invCharge
GPUCA_DEBUG_STREAMER_CHECK(, &debugVals));
347 merger->DebugStreamerUpdate(iTrk, ihit, xx, yy, zz, cluster, merger->GetConstantMem()->ioPtrs.clustersNative->clustersLinear[cluster.num], *
this, prop, interpolation.
hit[ihit], rejectChi2, refit,
retVal, sumInvSqrtCharge / nAvgCharge * sumInvSqrtCharge / nAvgCharge, yy, zz, clusterState, debugVals.retVal, debugVals.err2Y, debugVals.err2Z);
351 CADEBUG(
if (!CheckCov()) GPUError(
"INVALID COV AFTER UPDATE!!!"));
352 CADEBUG(printf(
"\t%21sFit Alpha %8.3f , X %8.3f - Y %8.3f, Z %8.3f - QPt %7.2f (%7.2f), SP %5.2f (%5.2f), DzDs %5.2f %16s --- Cov sY %8.3f sZ %8.3f sSP %8.3f sPt %8.3f - YPt %8.3f - Err %d\n",
"", prop.GetAlpha(), mX, mP[0], mP[1], mP[4], prop.GetQPt0(), mP[2], prop.GetSinPhi0(), mP[3],
"", sqrtf(mC[0]), sqrtf(mC[2]), sqrtf(mC[5]), sqrtf(mC[14]), mC[10],
retVal));
358 if (storeOuter == 1 && cluster.leg ==
clusters[maxN - 1].leg) {
359 StoreOuter(outerParam, prop, 2);
362 noFollowCircle2 =
false;
365 nMissed = nMissed2 = 0;
369 float dy = mP[0] - prop.Model().
Y();
370 float dz = mP[1] - prop.Model().
Z();
371 if (CAMath::Abs(mP[4]) *
param.qptB5Scaler > 10 && --resetT0 <= 0 && CAMath::Abs(mP[2]) < 0.15f && dy * dy + dz * dz > 1) {
372 CADEBUG(printf(
"Reinit linearization\n"));
373 prop.SetTrack(
this, prop.GetAlpha());
376 if (
param.dodEdxEnabled && iWay == nWays - 1 && cluster.leg ==
clusters[maxN - 1].leg) {
377 bool acc = (clusterState &
param.rec.tpc.dEdxClusterRejectionFlagMask) == 0, accAlt = (clusterState &
param.rec.tpc.dEdxClusterRejectionFlagMaskAlt) == 0;
379 float qtot = 0, qmax = 0, pad = 0, relTime = 0;
380 const int32_t clusterCount = (ihit - ihitMergeFirst) * wayDirection + 1;
381 for (int32_t iTmp = ihitMergeFirst; iTmp != ihit + wayDirection; iTmp += wayDirection) {
382 if (merger->GetConstantMem()->ioPtrs.clustersNative ==
nullptr) {
383 qtot += clustersXYZ[ihit].amp;
385 const ClusterNative& cl = merger->GetConstantMem()->ioPtrs.clustersNative->clustersLinear[cluster.num];
387 qmax = CAMath::Max<float>(qmax, cl.
qMax);
389 relTime += cl.getTime();
392 qtot /= clusterCount;
394 relTime /= clusterCount;
395 relTime = relTime - CAMath::Round(relTime);
397 dEdx.fillCluster(qtot, qmax, cluster.row, cluster.sector, mP[2], mP[3], merger->GetConstantMem()->calibObjects, zz, pad, relTime);
401 dEdxAlt.fillCluster(qtot, qmax, cluster.row, cluster.sector, mP[2], mP[3], merger->GetConstantMem()->calibObjects, zz, pad, relTime);
408 if (allowModification) {
410 }
else if (iWay == nWays - 1) {
419 if (((nWays - iWay) & 1) && (iWay != nWays - 1) && (
clusters[0].sector < 18) == (
clusters[maxN - 1].sector < 18)) {
420 ShiftZ2(
clusters, clustersXYZ, merger, maxN);
426 o2::utils::DebugStreamer::instance()->getStreamer(
"debug_accept_track",
"UPDATE") << o2::utils::DebugStreamer::instance()->getUniqueTreeName(
"debug_accept_track").data() <<
"iTrk=" << iTrk <<
"outerParam=" << *outerParam <<
"track=" <<
this <<
"ihitStart=" << ihitStart <<
"\n";
432 if (
param.rec.tpc.minNClustersFinalTrack != -1 && N + NTolerated <
param.rec.tpc.minNClustersFinalTrack) {
438 if (
param.par.dodEdx &&
param.dodEdxEnabled) {
439 dEdx.computedEdx(merger->MergedTracksdEdx()[iTrk],
param);
441 dEdxAlt.computedEdx(merger->MergedTracksdEdxAlt()[iTrk],
param);
444 Alpha = prop.GetAlpha();
445 MoveToReference(prop,
param, Alpha);
446 NormalizeAlpha(Alpha);
763GPUdic(0, 1) int32_t
GPUTPCGMTrackParam::FollowCircle(const
GPUTPCGMMerger*
GPUrestrict() Merger,
GPUTPCGMPropagator&
GPUrestrict() prop, int32_t sector, int32_t iRow, int32_t iTrack,
float toAlpha,
float toX,
float toY, int32_t toSector, int32_t toRow,
bool inFlyDirection,
bool phase2)
765 static constexpr float kSectAngle = 2 * M_PI / 18.f;
766 if (Merger->Param().rec.tpc.disableRefitAttachment & 4) {
770 if (inExtraPass && phase2 ==
false) {
771 StoreAttachMirror(Merger, sector, iRow, iTrack, toAlpha, toY, toX, toSector, toRow, inFlyDirection, prop.GetAlpha());
776 float dAlpha = toAlpha - prop.GetAlpha();
778 if (CAMath::Abs(dAlpha) > 0.001f) {
779 right = CAMath::Abs(dAlpha) < CAMath::Pi() ? (dAlpha > 0) : (dAlpha < 0);
783 bool up = (mP[2] < 0) ^
right;
785 float lrFactor = mP[2] < 0 ? -1.f : 1.f;
787 CADEBUG(printf(
"CIRCLE Track %d: Sector %d Alpha %f X %f Y %f Z %f SinPhi %f DzDs %f - Next hit: Sector %d Alpha %f X %f Y %f - Right %d Up %d dAlpha %f lrFactor %f\n", iTrack, sector, prop.GetAlpha(), mX, mP[0], mP[1], mP[2], mP[3], toSector, toAlpha, toX, toY, (int32_t)
right, (int32_t)up, dAlpha, lrFactor));
790 AttachClustersPropagate(Merger, sector, iRow, targetRow, iTrack,
false, prop, inFlyDirection, 0.7f);
791 if (prop.RotateToAlpha(prop.GetAlpha() + (CAMath::Pi() / 2.f) * lrFactor)) {
794 CADEBUG(printf(
"\tRotated: X %f Y %f Z %f SinPhi %f (Alpha %f / %f)\n", mP[0], mX, mP[1], mP[2], prop.GetAlpha(), prop.GetAlpha() + CAMath::Pi() / 2.f));
795 while (sector != toSector || FollowCircleChk(lrFactor, toY, toX, up,
right)) {
796 while ((sector != toSector) ? (CAMath::Abs(mX) <= CAMath::Abs(mP[0]) * CAMath::Tan(kSectAngle / 2.f)) : FollowCircleChk(lrFactor, toY, toX, up,
right)) {
797 int32_t err = prop.PropagateToXAlpha(mX + 1.f, prop.GetAlpha(), inFlyDirection);
799 CADEBUG(printf(
"\t\tpropagation error (%d)\n", err));
800 prop.RotateToAlpha(prop.GetAlpha() - (CAMath::Pi() / 2.f) * lrFactor);
803 CADEBUG(printf(
"\tPropagated to y = %f: X %f Z %f SinPhi %f\n", mX, mP[0], mP[1], mP[2]));
805 float rowX = GPUTPCGeometry::Row2X(
j);
806 if (CAMath::Abs(rowX - (-mP[0] * lrFactor)) < 1.5f) {
807 CADEBUG(printf(
"\t\tAttempt row %d (Y %f Z %f)\n",
j, mX * lrFactor, mP[1]));
808 AttachClusters(Merger, sector,
j, iTrack,
false, mX * lrFactor, mP[1]);
812 if (sector != toSector) {
814 if (++sector >= sectorSide + 18) {
818 if (--sector < sectorSide) {
822 CADEBUG(printf(
"\tRotating to sector %d\n", sector));
823 if (prop.RotateToAlpha(
param.Alpha(sector) + (CAMath::Pi() / 2.f) * lrFactor)) {
824 CADEBUG(printf(
"\t\trotation error\n"));
825 prop.RotateToAlpha(prop.GetAlpha() - (CAMath::Pi() / 2.f) * lrFactor);
828 CADEBUG(printf(
"\tAfter Rotatin Alpha %f Position X %f Y %f Z %f SinPhi %f\n", prop.GetAlpha(), mP[0], mX, mP[1], mP[2]));
831 CADEBUG(printf(
"\tRotating back\n"));
832 for (int32_t
i = 0;
i < 2;
i++) {
833 if (prop.RotateToAlpha(prop.GetAlpha() + (CAMath::Pi() / 2.f) * lrFactor) == 0) {
837 CADEBUG(printf(
"Final rotation failed\n"));
840 CADEBUG(printf(
"\tresetting physical model\n"));
841 prop.SetTrack(
this, prop.GetAlpha());
844 CADEBUG(printf(
"\tMirrored position: Alpha %f X %f Y %f Z %f SinPhi %f DzDs %f\n", prop.GetAlpha(), mX, mP[0], mP[1], mP[2], mP[3]));
846 float dx = toX - GPUTPCGeometry::Row2X(toRow);
847 if (up ^ (toX > mX)) {
849 while (iRow <
GPUCA_ROW_COUNT - 2 && GPUTPCGeometry::Row2X(iRow + 1) + dx <= mX) {
853 while (iRow > 1 && GPUTPCGeometry::Row2X(iRow - 1) + dx >= mX) {
857 prop.PropagateToXAlpha(GPUTPCGeometry::Row2X(iRow) + dx, prop.GetAlpha(), inFlyDirection);
858 AttachClustersPropagate(Merger, sector, iRow, toRow, iTrack,
false, prop, inFlyDirection);
860 if (prop.PropagateToXAlpha(toX, prop.GetAlpha(), inFlyDirection)) {
863 CADEBUG(printf(
"Final position: Alpha %f X %f Y %f Z %f SinPhi %f DzDs %f\n", prop.GetAlpha(), mX, mP[0], mP[1], mP[2], mP[3]));