15#define GPUCA_CADEBUG 0
16#define DEBUG_SINGLE_TRACK -1
35#include "GPUParam.inc"
38#ifdef GPUCA_CADEBUG_ENABLED
43#ifndef GPUCA_GPUCODE_DEVICE
53 static constexpr float kDeg2Rad = M_PI / 180.f;
54 CADEBUG(
static constexpr float kSectAngle = 2 * M_PI / 18.f);
61 prop.SetMaterialTPC();
62 prop.SetPolynomialField(&
param.polynomialField);
63 prop.SetMaxSinPhi(maxSinPhi);
64 if (
param.rec.tpc.mergerInterpolateErrors) {
65 for (int32_t
i = 0;
i < N;
i++) {
70 const int32_t nWays =
param.rec.tpc.nWays;
71 const int32_t maxN = N;
72 int32_t ihitStart = 0;
74 float lastUpdateX = -1.f;
75 uint8_t lastRow = 255;
76 uint8_t lastSector = 255;
79 for (int32_t iWay = 0; iWay < nWays; iWay++) {
80 int32_t nMissed = 0, nMissed2 = 0;
81 float sumInvSqrtCharge = 0.f;
82 int32_t nAvgCharge = 0;
84 if (iWay && (iWay & 1) == 0) {
85 StoreOuter(&track.OuterParam(), prop.GetAlpha());
88 int32_t resetT0 = initResetT0();
89 const bool refit = (nWays == 1 || iWay >= 1);
90 const bool finalOutInFit = iWay + 2 >= nWays;
91 const bool finalFit = iWay == nWays - 1;
92 const float maxSinForUpdate = CAMath::Sin(70.f * kDeg2Rad);
95 prop.SetSeedingErrors(!(refit && attempt == 0));
96 prop.SetFitInProjections(
true);
97 prop.SetPropagateBzOnly(
param.rec.fitPropagateBzOnly == -1 ? !finalFit :
param.rec.fitPropagateBzOnly);
98 prop.SetMatLUT((
param.rec.useMatLUT && finalFit) ? merger->GetConstantMem()->calibObjects.matLUT :
nullptr);
99 prop.SetTrack(
this, iWay ? prop.GetAlpha() : Alpha);
101 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()));
105 const bool inFlyDirection = iWay & 1;
106 const int32_t wayDirection = (iWay & 1) ? -1 : 1;
108 int32_t goodRows = 0;
109 for (int32_t ihit = ihitStart; ihit >= 0 && ihit < maxN; ihit += wayDirection) {
110 const bool crossCE = lastSector != 255 && ((lastSector < 18) ^ (
clusters[ihit].sector < 18));
116 CADEBUG(printf(
"\tSkipping hit %d, %d hits rejected, flag %X\n", ihit, nMissed, (int32_t)
clusters[ihit].
state));
123 const bool allowChangeClusters = finalOutInFit && (nWays == 1 || ((iWay & 1) ? (ihit <= CAMath::Max(maxN / 2, maxN - 30)) : (ihit >= CAMath::Min(maxN / 2, 30))));
125 int32_t ihitMergeFirst = ihit;
126 uint8_t clusterState =
clusters[ihit].state;
131 merger->GetConstantMem()->calibObjects.fastTransformHelper->Transform(
clusters[ihit].sector,
clusters[ihit].
row, cl.getPad(), cl.getTime(), xx, yy, zz, mTOffset);
134 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));
138 if (MergeDoubleRowClusters(ihit, wayDirection,
clusters, merger, prop, xx, yy, zz, maxN, clAlpha, clusterState, allowChangeClusters) == -1) {
144 if (
param.rec.tpc.rejectIFCLowRadiusCluster) {
145 const float r2 = xx * xx + yy * yy;
146 const float rmax = (83.5f +
param.rec.tpc.sysClusErrorMinDist);
147 if (r2 < rmax * rmax) {
153 const auto& cluster =
clusters[ihit];
156 CADEBUG(printf(
"\tSector %2d %11sTrack 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.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]));
158 if (allowChangeClusters && lastRow != 255 && CAMath::Abs(cluster.row - lastRow) > 1) {
160 bool dodEdx =
param.dodEdxEnabled &&
param.rec.tpc.adddEdxSubThresholdClusters && finalFit && CAMath::Abs(cluster.row - lastRow) == 2;
161 dodEdx = AttachClustersPropagate(merger, cluster.sector, lastRow, cluster.row, iTrk, track.Leg() == 0, prop, inFlyDirection,
GPUCA_MAX_SIN_PHI, dodEdx);
163 dEdx.fillSubThreshold(lastRow - wayDirection);
165 dEdxAlt.fillSubThreshold(lastRow - wayDirection);
171 int32_t retValProp = prop.PropagateToXAlpha(xx, clAlpha, inFlyDirection);
173 CADEBUG(
if (!CheckCov()){printf(
"INVALID COV AFTER PROPAGATE!!!\n");});
175 if (retValProp == -2)
178 if (prop.PropagateToXAlpha(xx, prop.GetAlpha(), inFlyDirection) == 0) {
179 retValProp = prop.PropagateToXAlpha(xx, clAlpha, inFlyDirection);
182 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)) {
187 if (retValProp == 0) {
188 lastRow = cluster.row;
189 lastSector = cluster.
sector;
192 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 - PErr %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], retValProp));
196 if (
param.rec.tpc.addErrorsCECrossing) {
197 if (
param.rec.tpc.addErrorsCECrossing >= 2) {
198 AddCovDiagErrorsWithCorrelations(
param.rec.tpc.errorsCECrossing);
200 AddCovDiagErrors(
param.rec.tpc.errorsCECrossing);
202 }
else if (mC[2] < 0.5f) {
207 float uncorrectedY = -1e6f;
208 if (allowChangeClusters) {
209 uncorrectedY = AttachClusters(merger, cluster.sector, cluster.row, iTrk, track.Leg() == 0, prop);
212 const bool sinPhiErr = mNDF > 0 && CAMath::Abs(prop.GetSinPhi0()) >= maxSinForUpdate;
213 if (mNDF >= 0 && (mC[0] >
param.rec.tpc.trackFitCovLimit || mC[2] >
param.rec.tpc.trackFitCovLimit)) {
216 if (retValProp || sinPhiErr) {
220 CADEBUG(printf(
", %d --- break\n", (int32_t)sinPhiErr));
225 int32_t retValUpd = 0, retValInt = 0;
226 float threshold = 3.f + (lastUpdateX >= 0 ? (CAMath::Abs(mX - lastUpdateX) / 2) : 0.f);
227 if (mNDF > (int32_t)
param.rec.tpc.mergerNonInterpolateRejectMinNDF && (CAMath::Abs(yy - mP[0]) > threshold || CAMath::Abs(zz - mP[1]) > threshold)) {
230 int8_t rejectChi2 = 0;
232 if (
param.rec.tpc.mergerInterpolateErrors && CAMath::Abs(ihit - ihitMergeFirst) <= 1) {
233 if (iWay == nWays - 3) {
235 }
else if (iWay == nWays - 2) {
237 }
else if (iWay == nWays - 1) {
241 rejectChi2 = allowChangeClusters && goodRows > 5;
246 const float time = merger->GetConstantMem()->ioPtrs.clustersNative ? merger->GetConstantMem()->ioPtrs.clustersNative->clustersLinear[cluster.num].getTime() : -1.f;
247 const float invSqrtCharge = merger->GetConstantMem()->ioPtrs.clustersNative ? CAMath::InvSqrt(merger->GetConstantMem()->ioPtrs.clustersNative->clustersLinear[cluster.num].qMax) : 0.f;
248 const float invCharge = merger->GetConstantMem()->ioPtrs.clustersNative ? (1.f / merger->GetConstantMem()->ioPtrs.clustersNative->clustersLinear[cluster.num].qMax) : 0.f;
249 float invAvgCharge = (sumInvSqrtCharge += invSqrtCharge) / ++nAvgCharge;
250 invAvgCharge *= invAvgCharge;
251 prop.GetErr2(err2Y, err2Z,
param, zz, cluster.row, clusterState, cluster.sector,
time, invAvgCharge, invCharge);
257 retValInt = prop.InterpolateReject(
param, yy, zz, clusterState, rejectChi2, &interpolation.
hit[ihit], err2Y, err2Z, deltaZ);
261 if (
param.rec.tpc.rejectEdgeClustersInTrackFit && uncorrectedY > -1e6f &&
param.rejectEdgeClusterByY(uncorrectedY, cluster.row, CAMath::Sqrt(mC[0]))) {
264 retValUpd = prop.Update(yy, zz, cluster.row,
param, clusterState, rejectChi2, refit, err2Y, err2Z);
267 merger->DebugStreamerUpdate(iTrk, ihit, xx, yy, zz, cluster, merger->GetConstantMem()->ioPtrs.clustersNative->clustersLinear[cluster.num], *
this, prop, interpolation.
hit[ihit], rejectChi2, refit, retValUpd, sumInvSqrtCharge / nAvgCharge * sumInvSqrtCharge / nAvgCharge, yy, zz, clusterState, retValInt, err2Y, err2Z);
271 CADEBUG(
if (!CheckCov()) GPUError(
"INVALID COV AFTER UPDATE!!!"));
272 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 - FErr %d %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], retValUpd, retValInt));
276 if (!retValUpd && !retValInt)
280 nMissed = nMissed2 = 0;
284 float dy = mP[0] - prop.Model().
Y();
285 float dz = mP[1] - prop.Model().
Z();
286 if (CAMath::Abs(mP[4]) *
param.qptB5Scaler > 10 && --resetT0 <= 0 && CAMath::Abs(mP[2]) < 0.15f && dy * dy + dz * dz > 1) {
287 CADEBUG(printf(
"Reinit linearization\n"));
288 prop.SetTrack(
this, prop.GetAlpha());
291 if (
param.dodEdxEnabled && finalFit) {
292 bool acc = (clusterState &
param.rec.tpc.dEdxClusterRejectionFlagMask) == 0, accAlt = (clusterState &
param.rec.tpc.dEdxClusterRejectionFlagMaskAlt) == 0;
294 float qtot = 0, qmax = 0, pad = 0, relTime = 0;
295 const int32_t clusterCount = (ihit - ihitMergeFirst) * wayDirection + 1;
296 for (int32_t iTmp = ihitMergeFirst; iTmp != ihit + wayDirection; iTmp += wayDirection) {
297 const ClusterNative& cl = merger->GetConstantMem()->ioPtrs.clustersNative->clustersLinear[cluster.num];
299 qmax = CAMath::Max<float>(qmax, cl.
qMax);
301 relTime += cl.getTime();
303 qtot /= clusterCount;
305 relTime /= clusterCount;
306 relTime = relTime - CAMath::Round(relTime);
308 dEdx.fillCluster(qtot, qmax, cluster.row, cluster.sector, mP[2], mP[3], merger->GetConstantMem()->calibObjects, zz, pad, relTime);
312 dEdxAlt.fillCluster(qtot, qmax, cluster.row, cluster.sector, mP[2], mP[3], merger->GetConstantMem()->calibObjects, zz, pad, relTime);
319 if (retValInt || allowChangeClusters) {
321 }
else if (finalFit) {
332 if (finalOutInFit && !(merger->Param().rec.tpc.disableRefitAttachment & 4) && lastRow != 255 && lastSector != 255) {
333 StoreLoopPropagation(merger, lastSector, lastRow, iTrk, lastRow >
clusters[(iWay & 1) ? (maxN - 1) : 0].row, prop.GetAlpha());
334 CADEBUG(printf(
"\t\tSTORING %d lastRow %d row %d out %d\n", iTrk, (
int)lastRow, (
int)
clusters[(iWay & 1) ? (maxN - 1) : 0].row, lastRow >
clusters[(iWay & 1) ? (maxN - 1) : 0].row));
336 if (!(iWay & 1) && !finalFit && !track.CCE() && !track.Looper()) {
337 deltaZ = ShiftZ(
clusters, merger, maxN);
345 o2::utils::DebugStreamer::instance()->getStreamer(
"debug_accept_track",
"UPDATE") << o2::utils::DebugStreamer::instance()->getUniqueTreeName(
"debug_accept_track").data() <<
"iTrk=" << iTrk <<
"outerParam=" << track.OuterParam() <<
"track=" <<
this <<
"ihitStart=" << ihitStart <<
"\n";
351 if (
param.rec.tpc.minNClustersFinalTrack != -1 && N + NTolerated <
param.rec.tpc.minNClustersFinalTrack) {
355 if (
param.par.dodEdx &&
param.dodEdxEnabled) {
356 dEdx.computedEdx(merger->MergedTracksdEdx()[iTrk],
param);
358 dEdxAlt.computedEdx(merger->MergedTracksdEdxAlt()[iTrk],
param);
361 Alpha = prop.GetAlpha();
362 MoveToReference(prop,
param, Alpha);
363 NormalizeAlpha(Alpha);
370 static constexpr float kDeg2Rad = M_PI / 180.f;
371 static constexpr float kSectAngle = 2 * M_PI / 18.f;
373 if (
param.rec.tpc.trackReferenceX <= 500) {
375 float saveAlpha = Alpha;
376 for (int32_t attempt = 0; attempt < 3; attempt++) {
377 float dAngle = CAMath::Round(CAMath::ATan2(mP[0], mX) / kDeg2Rad / 20.f) * kSectAngle;
379 if (prop.PropagateToXAlpha(
param.rec.tpc.trackReferenceX, Alpha, 0)) {
383 if (CAMath::Abs(mP[0]) <= mX * CAMath::Tan(kSectAngle / 2.f)) {
390 if (CAMath::Abs(mP[0]) > mX * CAMath::Tan(kSectAngle / 2.f)) {
391 float dAngle = CAMath::Round(CAMath::ATan2(mP[0], mX) / kDeg2Rad / 20.f) * kSectAngle;
400 if (mirrorParameters) {
401 prop.Mirror(inFlyDirection);
404 prop.GetErr2(err2Y, err2Z,
param, toZ,
row, clusterState, sector, -1.f, 0.f, 0.f);
405 prop.Model().
Y() = mP[0] = toY;
406 prop.Model().Z() = mP[1] = toZ;
413 if (CAMath::Abs(mC[5]) < 0.1f) {
414 mC[5] = mC[5] > 0 ? 0.1f : -0.1f;
419 mC[1] = mC[4] = mC[6] = mC[8] = mC[11] = mC[13] = 0;
420 prop.SetTrack(
this, prop.GetAlpha());
425GPUd() int32_t
GPUTPCGMTrackParam::MergeDoubleRowClusters(int32_t& ihit, int32_t wayDirection,
GPUTPCGMMergedTrackHit*
GPUrestrict()
clusters, const
GPUTPCGMMerger*
GPUrestrict() merger,
GPUTPCGMPropagator&
GPUrestrict() prop,
float&
GPUrestrict() xx,
float&
GPUrestrict() yy,
float&
GPUrestrict() zz, int32_t maxN,
float clAlpha, uint8_t&
GPUrestrict() clusterState,
bool rejectChi2)
428 float maxDistY, maxDistZ;
429 prop.GetErr2(maxDistY, maxDistZ, merger->Param(), zz,
clusters[ihit].row, 0,
clusters[ihit].sector, -1.f, 0.f, 0.f);
430 maxDistY = (maxDistY + mC[0]) * 20.f;
431 maxDistZ = (maxDistZ + mC[2]) * 20.f;
432 int32_t noReject = 0;
433 if (CAMath::Abs(clAlpha - prop.GetAlpha()) > 1.e-4f) {
434 noReject = prop.RotateToAlpha(clAlpha);
436 float projY = 0, projZ = 0;
438 noReject |= prop.GetPropagatedYZ(xx, projY, projZ);
445 float clamp = cl.qTot;
447 merger->GetConstantMem()->calibObjects.fastTransformHelper->Transform(
clusters[ihit].sector,
clusters[ihit].
row, cl.getPad(), cl.
getTime(), clx, cly, clz, mTOffset);
448 float dy = cly - projY;
449 float dz = clz - projZ;
450 if (noReject == 0 && (dy * dy > maxDistY || dz * dz > maxDistZ)) {
451 CADEBUG(printf(
"\t\tRejecting double-row cluster: dy %f, dz %f, chiY %f, chiZ %f (Y: trk %f prj %f cl %f - Z: trk %f prj %f cl %f)\n", dy, dz, sqrtf(maxDistY), sqrtf(maxDistZ), mP[0], projY, cly, mP[1], projZ, clz));
456 CADEBUG(printf(
"\t\tMerging hit row %d X %f Y %f Z %f (dy %f, dz %f, chiY %f, chiZ %f)\n",
clusters[ihit].
row, clx, cly, clz, dy, dz, sqrtf(maxDistY), sqrtf(maxDistZ)));
460 clusterState |=
clusters[ihit].state;
463 if (!(ihit + wayDirection >= 0 && ihit + wayDirection < maxN &&
clusters[ihit].
row ==
clusters[ihit + wayDirection].
row &&
clusters[ihit].sector ==
clusters[ihit + wayDirection].sector)) {
466 ihit += wayDirection;
469 CADEBUG(printf(
"\t\tNo matching cluster in double-row, skipping\n"));
483 Merger->GetConstantMem()->calibObjects.fastTransformHelper->InverseTransformYZtoX(sector, iRow, mP[0], mP[1], X);
484 if (prop.GetPropagatedYZ(X, Y, Z)) {
488 return AttachClusters(Merger, sector, iRow, iTrack, goodLeg, Y, Z);
493 const auto&
param = Merger->Param();
494 if (
param.rec.tpc.disableRefitAttachment & 1) {
501 if (
row.NHits() == 0) {
505 const float zOffset =
param.par.continuousTracking ? Merger->GetConstantMem()->calibObjects.fastTransformHelper->getCorrMap()->convVertexTimeToZOffset(sector, mTOffset,
param.continuousMaxTimeBin) : 0;
506 const float y0 =
row.Grid().YMin();
507 const float stepY =
row.HstepY();
508 const float z0 =
row.Grid().ZMin() - zOffset;
509 const float stepZ =
row.HstepZ();
512 float uncorrectedY, uncorrectedZ;
513 Merger->GetConstantMem()->calibObjects.fastTransformHelper->InverseTransformYZtoNominalYZ(sector, iRow, Y, Z, uncorrectedY, uncorrectedZ);
514 if (CAMath::Abs(uncorrectedY) >
row.getTPCMaxY()) {
518 bool protect = CAMath::Abs(GetQPt() *
param.qptB5Scaler) <=
param.rec.tpc.rejectQPtB5 && goodLeg;
520 param.GetClusterErrors2(sector, iRow, Z, mP[2], mP[3], -1.f, 0.f, 0.f, err2Y, err2Z);
521 const float tubeMaxSize2 = protect ?
param.rec.tpc.tubeProtectMaxSize2 :
param.rec.tpc.tubeRemoveMaxSize2;
522 const float tubeMinSize2 = protect ?
param.rec.tpc.tubeProtectMinSize2 : 0.f;
523 float tubeSigma2 = protect ?
param.rec.tpc.tubeProtectSigma2 :
param.rec.tpc.tubeRemoveSigma2;
524 uint32_t pad = CAMath::Float2UIntRn(GPUTPCGeometry::LinearY2Pad(sector, iRow, uncorrectedY));
525 float time = Merger->GetConstantMem()->calibObjects.fastTransformHelper->getCorrMap()->InverseTransformInTimeFrame(sector, uncorrectedZ + (
param.par.continuousTracking ? Merger->GetConstantMem()->calibObjects.fastTransformHelper->getCorrMap()->convVertexTimeToZOffset(sector, mTOffset,
param.continuousMaxTimeBin) : 0),
param.continuousMaxTimeBin);
526 if (iRow <
param.rec.tpc.tubeExtraProtectMinRow ||
527 pad < param.rec.tpc.tubeExtraProtectEdgePads || pad >= (uint32_t)(GPUTPCGeometry::NPads(iRow) -
param.rec.tpc.tubeExtraProtectEdgePads) ||
528 param.GetUnscaledMult(
time) / GPUTPCGeometry::Row2X(iRow) >
param.rec.tpc.tubeExtraProtectMinOccupancy) {
529 tubeSigma2 *= protect ? 2 : 0.5;
531 const float sy2 = CAMath::Max(tubeMinSize2, CAMath::Min(tubeMaxSize2, tubeSigma2 * (err2Y + CAMath::Abs(mC[0]))));
532 const float sz2 = CAMath::Max(tubeMinSize2, CAMath::Min(tubeMaxSize2, tubeSigma2 * (err2Z + CAMath::Abs(mC[2]))));
533 const float tubeY = CAMath::Sqrt(sy2);
534 const float tubeZ = CAMath::Sqrt(sz2);
535 const float sy21 = 1.f / sy2;
536 const float sz21 = 1.f / sz2;
538 row.Grid().GetBinArea(uncorrectedY, uncorrectedZ + zOffset, tubeY, tubeZ, bin, ny, nz);
539 const int32_t nBinsY =
row.Grid().Ny();
540 const int32_t idOffset = tracker.Data().ClusterIdOffset();
541 const int32_t*
ids = &(tracker.Data().ClusterDataIndex()[
row.HitNumberOffset()]);
551 for (int32_t k = 0; k <= nz; k++) {
552 const int32_t mybin = bin + k * nBinsY;
553 const uint32_t hitFst = firsthit[mybin];
554 const uint32_t hitLst = firsthit[mybin + ny + 1];
555 for (uint32_t ih = hitFst; ih < hitLst; ih++) {
556 int32_t
id = idOffset +
ids[ih];
559 if (myWeight <= *
weight) {
563 const cahit2 hh = hits[ih];
564 const float y =
y0 + hh.
x * stepY;
565 const float z = z0 + hh.
y * stepZ;
566 const float dy =
y - uncorrectedY;
567 const float dz =
z - uncorrectedZ;
568 if (dy * dy * sy21 + dz * dz * sz21 <= CAMath::Sqrt(2.f)) {
570 CAMath::AtomicMax(
weight, myWeight);
579 static constexpr float kSectAngle = 2 * M_PI / 18.f;
580 if (Merger->Param().rec.tpc.disableRefitAttachment & 2) {
583 if (CAMath::Abs(lastRow - toRow) < 2) {
586 int32_t
step = toRow > lastRow ? 1 : -1;
587 float xx = mX - GPUTPCGeometry::Row2X(lastRow);
588 for (int32_t iRow = lastRow + step; iRow != toRow; iRow +=
step) {
589 if (CAMath::Abs(mP[2]) > maxSinPhi) {
592 if (CAMath::Abs(mP[0]) > CAMath::Abs(mX) * CAMath::Tan(kSectAngle / 2.f)) {
595 int32_t err = prop.PropagateToXAlpha(xx + GPUTPCGeometry::Row2X(iRow), prop.GetAlpha(), inFlyDirection);
599 if (dodEdx && iRow + step == toRow) {
600 float yUncorrected, zUncorrected;
601 Merger->GetConstantMem()->calibObjects.fastTransformHelper->InverseTransformYZtoNominalYZ(sector, iRow, mP[0], mP[1], yUncorrected, zUncorrected);
602 uint32_t pad = CAMath::Float2UIntRn(GPUTPCGeometry::LinearY2Pad(sector, iRow, yUncorrected));
603 if (pad >= GPUTPCGeometry::NPads(iRow) || (Merger->GetConstantMem()->calibObjects.dEdxCalibContainer && Merger->GetConstantMem()->calibObjects.dEdxCalibContainer->isDead(sector, iRow, pad))) {
607 CADEBUG(printf(
"Attaching in row %d\n", iRow));
608 AttachClusters(Merger, sector, iRow, iTrack, goodLeg, prop);
615 CADEBUG(printf(
"\t%21sStorO Alpha %8.3f , X %8.3f - Y %8.3f, Z %8.3f - QPt %7.2f, SP %5.2f --- Cov sY %8.3f sZ %8.3f sSP %8.3f sPt %8.3f\n",
"",
alpha, mX, mP[0], mP[1], mP[4], mP[2], sqrtf(mC[0]), sqrtf(mC[2]), sqrtf(mC[5]), sqrtf(mC[14])));
616 for (int32_t
i = 0;
i < 5;
i++) {
617 outerParam->P[
i] = mP[
i];
619 for (int32_t
i = 0;
i < 15;
i++) {
620 outerParam->C[
i] = mC[
i];
623 outerParam->alpha =
alpha;
634 if (CAMath::Abs(mP[2]) < 0.75) {
637 if ((mP[2] * mP[4] < 0) ^ outwards) {
641 uint32_t nLoopData = CAMath::AtomicAdd(&Merger->Memory()->nLoopData, 1u);
642 if (nLoopData >= Merger->NMaxTracks()) {
643 Merger->raiseError(GPUErrors::ERROR_MERGER_LOOPER_OVERFLOW, nLoopData, Merger->NMaxTracks());
644 CAMath::AtomicExch(&Merger->Memory()->nLoopData, Merger->NMaxTracks());
653 data.outwards = outwards;
654 Merger->LoopData()[nLoopData] =
data;
660 prop.SetMaterialTPC();
661 prop.SetPolynomialField(&Merger->Param().polynomialField);
663 prop.SetMatLUT(Merger->Param().rec.useMatLUT ? Merger->GetConstantMem()->calibObjects.matLUT : nullptr);
664 prop.SetSeedingErrors(
false);
665 prop.SetFitInProjections(
true);
666 prop.SetPropagateBzOnly(
false);
669 prop.SetTrack(&
data.param,
data.alpha);
673 data.param.AttachClustersLooperFollow(Merger, prop,
data.sector,
data.row,
data.track,
data.outwards);
680 bool inFlyDirection = (Merger->MergedTracks()[iTrack].Leg() & 1) ^ up;
682 static constexpr float kSectAngle = 2 * M_PI / 18.f;
684 bool right = (mP[2] < 0) ^ up;
686 float lrFactor =
right ^ !up ? 1.f : -1.f;
688 CADEBUG(printf(
"\nCIRCLE Track %d: Sector %d Alpha %f X %f Y %f Z %f SinPhi %f DzDs %f QPt %f - Right %d Up %d lrFactor %f\n", iTrack, sector, prop.GetAlpha(), mX, mP[0], mP[1], mP[2], mP[3], mP[4], (int32_t)
right, (int32_t)up, lrFactor));
691 if (prop.RotateToAlpha(prop.GetAlpha() + (CAMath::Pi() / 2.f) * lrFactor)) {
694 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));
695 uint32_t maxTries = 100;
697 while (CAMath::Abs(mX) <= CAMath::Abs(mP[0]) * CAMath::Tan(kSectAngle / 2.f) + 0.1f) {
698 if (maxTries-- == 0) {
701 if (CAMath::Abs(mP[2]) > 0.7f) {
704 if (up ? (-mP[0] * lrFactor > GPUTPCGeometry::Row2X(
GPUCA_ROW_COUNT - 1)) : (-mP[0] * lrFactor < GPUTPCGeometry::Row2X(0))) {
707 if (!((up ? (-mP[0] * lrFactor >= toX) : (-mP[0] * lrFactor <= toX)) || (
right ^ (mP[2] > 0)))) {
710 int32_t err = prop.PropagateToXAlpha(mX + (up ? 1.f : -1.f), prop.GetAlpha(), inFlyDirection);
712 CADEBUG(printf(
"\t\tpropagation error (%d)\n", err));
715 CADEBUG(printf(
"\tPropagated to y = %f: X %f Z %f SinPhi %f\n", mX, mP[0], mP[1], mP[2]));
717 float rowX = GPUTPCGeometry::Row2X(
j);
718 if (CAMath::Abs(rowX - (-mP[0] * lrFactor)) < 1.5f) {
719 CADEBUG(printf(
"\t\tAttempt row %d (X %f Y %f Z %f)\n",
j, rowX, mX * lrFactor, mP[1]));
720 AttachClusters(Merger, sector,
j, iTrack,
false, mX * lrFactor, mP[1]);
724 if (maxTries-- == 0) {
728 if (++sector >= sectorSide + 18) {
732 if (--sector < sectorSide) {
736 CADEBUG(printf(
"\tRotating to sector %d: %f --> %f\n", sector, prop.GetAlpha(),
param.Alpha(sector) + (CAMath::Pi() / 2.f) * lrFactor));
737 int32_t err = prop.RotateToAlpha(
param.Alpha(sector) + (CAMath::Pi() / 2.f) * lrFactor);
739 CADEBUG(printf(
"Rotation Error %d\n", err));
742 CADEBUG(printf(
"\tAfter Rotating Alpha %f Position X %f Y %f Z %f SinPhi %f\n", prop.GetAlpha(), mP[0], mX, mP[1], mP[2]));
748 static constexpr float kSectAngle = 2 * M_PI / 18.f;
750 float X = mP[2] > 0 ? mP[0] : -mP[0];
751 float Y = mP[2] > 0 ? -mX : mX;
753 float SinPhi = CAMath::Sqrt(1 - mP[2] * mP[2]) * (mP[2] > 0 ? -1 : 1);
754 float b = prop.GetBz(prop.GetAlpha(), mX, mP[0], mP[1]);
756 float dx = outwards ? 1.f : -1.f;
757 const float myRowX = GPUTPCGeometry::Row2X(iRow);
761 uint32_t maxTries = 100;
763 float ex = CAMath::Sqrt(1 - SinPhi * SinPhi);
764 float exi = 1.f / ex;
765 float dxBzQ = dx * -
b * mP[4];
766 float newSinPhi = SinPhi + dxBzQ;
771 if (mP[2] > 0 ? (newSinPhi > 0.5) : (newSinPhi < -0.5)) {
776 float h2 = dS * exi * exi;
777 float h4 = .5f * h2 * dxBzQ;
780 Y += dS * SinPhi + h4;
783 if (CAMath::Abs(X) > CAMath::Abs(Y) * CAMath::Tan(kSectAngle / 2.f)) {
789 float paramX = mP[2] > 0 ? -Y : Y;
790 int32_t
step = outwards ? 1 : -1;
793 float rowX = mX + GPUTPCGeometry::Row2X(
j) - myRowX;
794 if (CAMath::Abs(rowX - paramX) < 1.5f) {
796 AttachClusters(Merger, sector,
j, iTrack,
false, mP[2] > 0 ? X : -X, Z);
807 const auto&
GPUrestrict() cls = merger->GetConstantMem()->ioPtrs.clustersNative->clustersLinear;
809 const auto tmp = zn > z0 ?
std::
array<
float, 3>{zn, z0, GPUTPCGeometry::Row2X(
clusters[N - 1].
row)} : std::array<float, 3>{z0, zn, GPUTPCGeometry::Row2X(
clusters[0].
row)};
810 return ShiftZ(merger,
clusters[0].sector, tmp[0], tmp[1], tmp[2]);
815 if (!merger->Param().par.continuousTracking) {
819 bool beamlineReached =
false;
820 const float r1 = CAMath::Max(0.0001f, CAMath::Abs(mP[4] * merger->Param().polynomialField.GetNominalBz()));
822 const float dist2 = mX * mX + mP[0] * mP[0];
823 const float dist1r2 = dist2 * r1 * r1;
825 const float alpha = CAMath::ACos(1 - 0.5f * dist1r2);
826 const float beta = CAMath::ATan2(mP[0], mX);
827 const int32_t comp = mP[2] > CAMath::Sin(beta);
828 const float sinab = CAMath::Sin((comp ? 0.5f : -0.5f) *
alpha + beta);
829 const float res = CAMath::Abs(sinab - mP[2]);
832 const float r = 1.f / r1;
833 const float dS =
alpha *
r;
834 float z0 = dS * mP[3];
835 if (CAMath::Abs(z0) > GPUTPCGeometry::TPCLength()) {
836 z0 = z0 > 0 ? GPUTPCGeometry::TPCLength() : -
GPUTPCGeometry::TPCLength();
839 beamlineReached =
true;
846 if (!beamlineReached) {
847 float refZ = ((sector <
GPUCA_NSECTORS / 2) ? merger->Param().rec.tpc.defaultZOffsetOverR : -merger->Param().rec.tpc.defaultZOffsetOverR) * clx;
849 merger->GetConstantMem()->calibObjects.fastTransformHelper->getCorrMap()->TransformIdealZ(sector, cltmax, basez, mTOffset);
850 deltaZ = basez - refZ;
853 float deltaT = merger->GetConstantMem()->calibObjects.fastTransformHelper->getCorrMap()->convDeltaZtoDeltaTimeInTimeFrame(sector, deltaZ);
855 const float maxT = cltmin - merger->GetConstantMem()->calibObjects.fastTransformHelper->getCorrMap()->getT0();
856 const float minT = cltmax - merger->GetConstantMem()->calibObjects.fastTransformHelper->getCorrMap()->getMaxDriftTime(sector);
859 if (mTOffset < minT) {
860 deltaT = minT - mTOffset;
862 if (mTOffset + deltaT > maxT) {
863 deltaT =
maxT - mTOffset;
866 deltaZ += merger->GetConstantMem()->calibObjects.fastTransformHelper->getCorrMap()->convDeltaTimeToDeltaZinTimeFrame(sector, deltaT);
879 bool ok =
c[0] >= 0 &&
c[2] >= 0 &&
c[5] >= 0 &&
c[9] >= 0 &&
c[14] >= 0 && (
c[1] *
c[1] <=
c[2] *
c[0]) && (
c[3] *
c[3] <=
c[5] *
c[0]) && (
c[4] *
c[4] <=
c[5] *
c[2]) && (
c[6] *
c[6] <=
c[9] *
c[0]) && (
c[7] *
c[7] <=
c[9] *
c[2]) && (
c[8] *
c[8] <=
c[9] *
c[5]) &&
880 (
c[10] *
c[10] <=
c[14] *
c[0]) && (
c[11] *
c[11] <=
c[14] *
c[2]) && (
c[12] *
c[12] <=
c[14] *
c[5]) && (
c[13] *
c[13] <=
c[14] *
c[9]);
887 bool ok = CAMath::Finite(mX) && CAMath::Finite(mChi2);
890 for (int32_t
i = 0;
i < 15;
i++) {
891 ok = ok && CAMath::Finite(
c[
i]);
893 for (int32_t
i = 0;
i < 5;
i++) {
894 ok = ok && CAMath::Finite(mP[
i]);
896 if ((overrideCovYY > 0 ? overrideCovYY :
c[0]) > 4.f * 4.f ||
c[2] > 4.f * 4.f ||
c[5] > 2.f * 2.f ||
c[9] > 2.f * 2.f) {
918 int32_t nTrackHits = track.NClusters();
919 int32_t NTolerated = 0;
921 float Alpha = track.
Alpha();
922 CADEBUG(int32_t nTrackHitsOld = nTrackHits;
float ptOld = t.QPt());
923 bool ok = t.Fit(merger, iTrk, merger->Clusters() + track.FirstClusterRef(), nTrackHits, NTolerated, Alpha, attempt,
GPUCA_MAX_SIN_PHI, track);
924 CADEBUG(printf(
"Finished Fit Track %d\n", iTrk));
925 CADEBUG(printf(
"OUTPUT hits %d -> %d+%d = %d, QPt %f -> %f, SP %f, OK %d chi2 %f chi2ndf %f\n", nTrackHitsOld, nTrackHits, NTolerated, nTrackHits + NTolerated, ptOld, t.QPt(), t.SinPhi(), (int32_t)ok, t.Chi2(), t.Chi2() / CAMath::Max(1, nTrackHits)));
927 if (!ok && attempt == 0 && merger->Param().rec.tpc.retryRefit) {
928 for (uint32_t
i = 0;
i < track.NClusters();
i++) {
931 CADEBUG(printf(
"Track rejected, marking for retry\n"));
932 if (merger->Param().rec.tpc.retryRefit == 2) {
933 nTrackHits = track.NClusters();
936 Alpha = track.
Alpha();
937 ok = t.Fit(merger, iTrk, merger->Clusters() + track.FirstClusterRef(), nTrackHits, NTolerated, Alpha, 1,
GPUCA_MAX_SIN_PHI, track);
939 uint32_t nRefit = CAMath::AtomicAdd(&merger->Memory()->nRetryRefit, 1u);
940 merger->RetryRefitIds()[nRefit] = iTrk;
944 if (CAMath::Abs(t.QPt()) < 1.e-4f) {
948 CADEBUG(
if (t.GetX() > 250) { printf(
"ERROR, Track %d at impossible X %f, Pt %f, Looper %d\n", iTrk, t.GetX(), CAMath::Abs(1.f / t.QPt()), (int32_t)merger->MergedTracks()[iTrk].Looper()); });
951 track.SetNClustersFitted(nTrackHits);
953 track.
Alpha() = Alpha;
961 CAMath::SinCos(
alpha, sA, cA);
963 float sinPhi0 = mP[2], cosPhi0 = CAMath::Sqrt(1 - mP[2] * mP[2]);
964 float cosPhi = cosPhi0 * cA + sinPhi0 * sA;
965 float sinPhi = -cosPhi0 * sA + sinPhi0 * cA;
966 float j0 = cosPhi0 / cosPhi;
967 float j2 = cosPhi / cosPhi0;
968 mX =
x0 * cA + mP[0] * sA;
969 mP[0] = -
x0 * sA + mP[0] * cA;
983 SinPhi() = -SinPhi();
1000 mC[9] += errors2[3];
1001 mC[14] += errors2[4];
1006 const int32_t diagMap[5] = {0, 2, 5, 9, 14};
1007 const float oldDiag[5] = {mC[0], mC[2], mC[5], mC[9], mC[14]};
1008 for (int32_t
i = 0;
i < 5;
i++) {
1009 mC[diagMap[
i]] += errors2[
i];
1010 for (int32_t
j = 0;
j <
i;
j++) {
1011 mC[diagMap[
i - 1] +
j + 1] *= gpu::CAMath::Sqrt(mC[diagMap[
i]] * mC[diagMap[
j]] / (oldDiag[
i] * oldDiag[
j]));
Helper class to access correction maps.
#define GPUCA_DEBUG_STREAMER_CHECK(...)
#define GPUCA_RTC_CONSTEXPR
#define GPUCA_MAX_SIN_PHI_LOW
#define GPUCA_TRACKLET_SELECTOR_MIN_HITS_B5(QPTB5)
#define GPUCA_MAX_SIN_PHI
#define GPUCA_PAR_NO_ATOMIC_PRECHECK
#define GPUCA_PAR_MERGER_INTERPOLATION_ERROR_TYPE_A
#define GPUCA_GET_CONSTEXPR(obj, val)
GPUdii() void GPUTPCGMTrackParam
GPUdni() void GPUTPCGMTrackParam
#define DEBUG_SINGLE_TRACK
float int32_t const GPUParam int16_t int8_t bool int8_t sector
float int32_t const GPUParam & param
@ updateErrorClusterRejectedDistance
@ updateErrorClusterRejected
@ updateErrorClusterRejectedEdge
int32_t GPUTPCGMMergedTrackHit int32_t int32_t float & Alpha
int32_t GPUTPCGMMergedTrackHit int32_t int32_t float int32_t float GPUTPCGMMergedTrack & track
int32_t int32_t int32_t bool float Y
GLfloat GLfloat GLfloat alpha
GLsizei const GLuint const GLfloat * weights
GLuint GLuint GLfloat weight
GLboolean GLboolean GLboolean b
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
GLuint GLfloat GLfloat y0
GLdouble GLdouble GLdouble z
Global TPC definitions and constants.
GPUdi() T BetheBlochAleph(T bg
@ streamUpdateTrack
stream update track informations
Defining DataPointCompositeObject explicitly as copiable.
std::string getTime(uint64_t ts)
@ clustererAndSharedFlags
GPUCA_PAR_MERGER_INTERPOLATION_ERROR_TYPE_A errorY
InterpolationErrorHit hit[GPUCA_MERGER_MAX_TRACK_CLUSTERS]
std::vector< Cluster > clusters