From f488c19c3d205888387b6d7928051acf35c3de99 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Sat, 1 Nov 2025 21:50:44 +0100 Subject: [PATCH 1/2] GPU TPC: Add attachProtect flag, and mark all clusters also in the history of protected tracks such --- .../DataCompression/GPUTPCClusterRejection.h | 19 +++++++++++++------ .../GPUTPCCompressionKernels.cxx | 7 ++++++- GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx | 13 +++++++++++-- GPU/GPUTracking/Merger/GPUTPCGMMergerTypes.h | 3 ++- GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx | 6 ++++++ 5 files changed, 38 insertions(+), 10 deletions(-) diff --git a/GPU/GPUTracking/DataCompression/GPUTPCClusterRejection.h b/GPU/GPUTracking/DataCompression/GPUTPCClusterRejection.h index f39994f2d1045..ae3ffb29926a7 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCClusterRejection.h +++ b/GPU/GPUTracking/DataCompression/GPUTPCClusterRejection.h @@ -25,18 +25,19 @@ struct GPUTPCClusterRejection { { (void)counts; // FIXME: Avoid incorrect -Wunused-but-set-parameter warning (void)mev200; + bool retVal = false; if (attach == 0) { - return false; + retVal = false; } else if ((attach & gputpcgmmergertypes::attachGoodLeg) == 0) { if constexpr (C) { counts->nLoopers++; } - return true; + retVal = true; } else if (attach & gputpcgmmergertypes::attachHighIncl) { if constexpr (C) { counts->nHighIncl++; } - return true; + retVal = true; } else if (attach & gputpcgmmergertypes::attachTube) { protect = true; if constexpr (C) { @@ -46,17 +47,23 @@ struct GPUTPCClusterRejection { counts->nTube++; } } - return false; + retVal = false; } else if ((attach & gputpcgmmergertypes::attachGood) == 0) { protect = true; if constexpr (C) { counts->nRejected++; } - return false; + retVal = false; } else { physics = true; - return false; + retVal = false; } + + if (attach & gputpcgmmergertypes::attachProtect) { + protect = true; + retVal = false; + } + return retVal; } static constexpr inline bool GetIsRejected(int32_t attach) diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx index d5567bb5148d9..911af719dd3d4 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx @@ -56,10 +56,12 @@ GPUdii() void GPUTPCCompressionKernels::Thread= GPUSettings::RejectionStrategyA && (rejectTrk || GPUTPCClusterRejection::GetIsRejected(attach)); + bool rejectCluster = processors.param.rec.tpc.rejectionStrategy >= GPUSettings::RejectionStrategyA && !(attach & gputpcgmmergertypes::attachProtect) && (rejectTrk || GPUTPCClusterRejection::GetIsRejected(attach)); if (rejectCluster) { compressor.mClusterStatus[hitId] = 1; // Cluster rejected, do not store continue; + } else if (processors.param.rec.tpc.rejectionStrategy >= GPUSettings::RejectionStrategyA && rejectTrk) { + continue; } if (!(param.rec.tpc.compressionTypeMask & GPUSettings::CompressionTrackModel)) { @@ -199,6 +201,9 @@ GPUd() bool GPUTPCCompression::rejectCluster(int32_t idx, GPUParam& GPUrestrict( if (GPUTPCClusterRejection::GetIsRejected(attach)) { return true; } + if (attach & gputpcgmmergertypes::attachProtect) { + return false; + } int32_t id = attach & gputpcgmmergertypes::attachTrackMask; auto& trk = ioPtrs.mergedTracks[id]; if (CAMath::Abs(trk.GetParam().GetQPt() * param.qptB5Scaler) > param.rec.tpc.rejectQPtB5 || trk.MergedLooper()) { diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx index 212850f107098..8793f3bb399c8 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx @@ -1848,7 +1848,11 @@ GPUd() void GPUTPCGMMerger::PrepareForFit1(int32_t nBlocks, int32_t nThreads, in GPUTPCGMMergedTrack& trk = mMergedTracks[i]; if (trk.OK()) { for (uint32_t j = 0; j < trk.NClusters(); j++) { - mClusterAttachment[mClusters[trk.FirstClusterRef() + j].num] = attachAttached | attachGood; + uint32_t weight = attachAttached | attachGood; + if (CAMath::Abs(trk.GetParam().GetQPt() * Param().qptB5Scaler) <= Param().rec.tpc.rejectQPtB5 && !trk.MergedLooper() && trk.Leg() == 0) { + weight |= attachProtect; + } + mClusterAttachment[mClusters[trk.FirstClusterRef() + j].num] = weight; CAMath::AtomicAdd(&mSharedCount[mClusters[trk.FirstClusterRef() + j].num], 1u); } if (!trk.CCE() && !trk.MergedLooper()) { @@ -1896,7 +1900,9 @@ GPUd() void GPUTPCGMMerger::Finalize0(int32_t nBlocks, int32_t nThreads, int32_t mTrackSort[mTrackOrderAttach[i]] = i; } for (uint32_t i = iBlock * nThreads + iThread; i < mMemory->nMergedTrackClusters; i += nThreads * nBlocks) { - mClusterAttachment[mClusters[i].num] = 0; // Reset adjacent attachment for attached clusters, set correctly below + if (!(mClusterAttachment[mClusters[i].num] & attachProtect)) { + mClusterAttachment[mClusters[i].num] = 0; // Reset adjacent attachment for attached clusters, set correctly below + } } } @@ -1919,6 +1925,9 @@ GPUd() void GPUTPCGMMerger::Finalize1(int32_t nBlocks, int32_t nThreads, int32_t if (trk.Leg() == 0) { weight |= attachGoodLeg; } + if (CAMath::Abs(trk.GetParam().GetQPt() * Param().qptB5Scaler) <= Param().rec.tpc.rejectQPtB5 && !trk.MergedLooper() && trk.Leg() == 0) { + weight |= attachProtect; + } CAMath::AtomicMax(&mClusterAttachment[id], weight); } } diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMergerTypes.h b/GPU/GPUTracking/Merger/GPUTPCGMMergerTypes.h index ba251ce34a3eb..731439aab0be2 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMergerTypes.h +++ b/GPU/GPUTracking/Merger/GPUTPCGMMergerTypes.h @@ -21,7 +21,8 @@ namespace o2::gpu::gputpcgmmergertypes { -enum attachTypes { attachAttached = 0x40000000, +enum attachTypes { attachProtect = 0x80000000, + attachAttached = 0x40000000, attachGood = 0x20000000, attachGoodLeg = 0x10000000, attachTube = 0x08000000, diff --git a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx index 2b7f23aba0557..0e9cbdacee24e 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx @@ -514,6 +514,8 @@ GPUd() float GPUTPCGMTrackParam::AttachClusters(const GPUTPCGMMerger* GPUrestric const float stepZ = row.HstepZ(); int32_t bin, ny, nz; + bool protect = CAMath::Abs(GetQPt() * Merger->Param().qptB5Scaler) <= Merger->Param().rec.tpc.rejectQPtB5 && goodLeg; + float err2Y, err2Z; Merger->Param().GetClusterErrors2(sector, iRow, Z, mP[2], mP[3], -1.f, 0.f, 0.f, err2Y, err2Z); // TODO: Use correct time/avgCharge const float sy2 = CAMath::Min(Merger->Param().rec.tpc.tubeMaxSize2, Merger->Param().rec.tpc.tubeChi2 * (err2Y + CAMath::Abs(mC[0]))); // Cov can be bogus when following circle @@ -538,6 +540,10 @@ GPUd() float GPUTPCGMTrackParam::AttachClusters(const GPUTPCGMMerger* GPUrestric if (goodLeg) { myWeight |= gputpcgmmergertypes::attachGoodLeg; } + if (protect) { + myWeight |= gputpcgmmergertypes::attachProtect; + } + for (int32_t k = 0; k <= nz; k++) { const int32_t mybin = bin + k * nBinsY; const uint32_t hitFst = firsthit[mybin]; From ff512c2b708d110a067a1fc0948ac4e3b8c837b3 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Sat, 1 Nov 2025 21:58:04 +0100 Subject: [PATCH 2/2] GPU TPC: Add tubeProtectSigma2 tubeProtectMaxSize2 tubeRemoveSigma2 tubeRemoveMaxSize2 options --- GPU/GPUTracking/Definitions/GPUSettingsList.h | 7 +++++-- GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/GPU/GPUTracking/Definitions/GPUSettingsList.h b/GPU/GPUTracking/Definitions/GPUSettingsList.h index be9127a0c5070..091eeccfd0246 100644 --- a/GPU/GPUTracking/Definitions/GPUSettingsList.h +++ b/GPU/GPUTracking/Definitions/GPUSettingsList.h @@ -68,8 +68,11 @@ AddOptionRTC(minNClustersFinalTrack, int32_t, -1, "", 0, "required min number of AddOptionRTC(searchWindowDZDR, float, 2.5f, "", 0, "Use DZDR window for seeding instead of neighboursSearchArea") AddOptionRTC(trackReferenceX, float, 1000.f, "", 0, "Transport all tracks to this X after tracking (disabled if > 500, auto = 1000)") AddOptionRTC(zsThreshold, float, 2.0f, "", 0, "Zero-Suppression threshold") -AddOptionRTC(tubeChi2, float, 5.f * 5.f, "", 0, "Max chi2 to mark cluster adjacent to track") -AddOptionRTC(tubeMaxSize2, float, 2.5f * 2.5f, "", 0, "Square of max tube size (normally derrived from tpcTubeChi2)") +AddOptionRTC(tubeProtectSigma2, float, 5.f * 5.f, "", 0, "Max sigma2 to mark adjacent cluster for protection") +AddOptionRTC(tubeProtectMaxSize2, float, 3.5f * 3.5f, "", 0, "Square of max tube size (if smaller than tubeProtectChi2)") +AddOptionRTC(tubeProtectMinSize2, float, 1.0f * 1.0f, "", 0, "Square of min tube size (if larger than tubeProtectChi2)") +AddOptionRTC(tubeRemoveSigma2, float, 1.f * 1.f, "", 0, "Max sigma2 to mark adjacent cluster for removal") +AddOptionRTC(tubeRemoveMaxSize2, float, 1.5f * 1.5f, "", 0, "Square of max tube size (if smaller than tubeRejectChi2)") AddOptionRTC(clustersShiftTimebins, float, 0, "", 0, "Shift of TPC clusters (applied during CTF cluster decoding)") AddOptionRTC(clustersShiftTimebinsClusterizer, float, 0, "", 0, "Shift of TPC clusters (applied during CTF clusterization)") AddOptionRTC(clustersEdgeFixDistance, float, 0.f, "", 0, "If >0, revert cluster.flag edge bit distance to edge exceeds this parameter (fixed during CTF decoding)") diff --git a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx index 0e9cbdacee24e..0adfae0aa1fbd 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx @@ -518,8 +518,11 @@ GPUd() float GPUTPCGMTrackParam::AttachClusters(const GPUTPCGMMerger* GPUrestric float err2Y, err2Z; Merger->Param().GetClusterErrors2(sector, iRow, Z, mP[2], mP[3], -1.f, 0.f, 0.f, err2Y, err2Z); // TODO: Use correct time/avgCharge - const float sy2 = CAMath::Min(Merger->Param().rec.tpc.tubeMaxSize2, Merger->Param().rec.tpc.tubeChi2 * (err2Y + CAMath::Abs(mC[0]))); // Cov can be bogus when following circle - const float sz2 = CAMath::Min(Merger->Param().rec.tpc.tubeMaxSize2, Merger->Param().rec.tpc.tubeChi2 * (err2Z + CAMath::Abs(mC[2]))); // In that case we should provide the track error externally + const float tubeMaxSize2 = protect ? Merger->Param().rec.tpc.tubeProtectMaxSize2 : Merger->Param().rec.tpc.tubeRemoveMaxSize2; + const float tubeMinSize2 = protect ? Merger->Param().rec.tpc.tubeProtectMinSize2 : 0.f; + const float tubeSigma2 = protect ? Merger->Param().rec.tpc.tubeProtectSigma2 : Merger->Param().rec.tpc.tubeRemoveSigma2; + const float sy2 = CAMath::Max(tubeMinSize2, CAMath::Min(tubeMaxSize2, tubeSigma2 * (err2Y + CAMath::Abs(mC[0])))); // Cov can be bogus when following circle + const float sz2 = CAMath::Max(tubeMinSize2, CAMath::Min(tubeMaxSize2, tubeSigma2 * (err2Z + CAMath::Abs(mC[2])))); // In that case we should provide the track error externally const float tubeY = CAMath::Sqrt(sy2); const float tubeZ = CAMath::Sqrt(sz2); const float sy21 = 1.f / sy2;