From 8ace56123219cb87b5ce5bbd85db3cb974a91efb Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Fri, 25 Sep 2026 10:17:28 +0200 Subject: [PATCH 1/2] Reset the TPC hit grouping at the end of each event This fixes TPC hits in parallel o2-sim depending on which events a worker simulated before. - The hit-grouping state in tpc::Detector::ProcessHits was kept in function-local statics and carried over into the next event. - In parallel mode the next event is any chunk, so the number of empty hit groups varied from run to run. - The state is now a set of detector members that EndOfEvent resets. Co-Authored-By: Claude Opus 5.5 --- .../include/TPCSimulation/Detector.h | 4 ++ Detectors/TPC/simulation/src/Detector.cxx | 37 ++++++++++--------- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/Detectors/TPC/simulation/include/TPCSimulation/Detector.h b/Detectors/TPC/simulation/include/TPCSimulation/Detector.h index 10ff59360374c..d8e341f9c30c5 100644 --- a/Detectors/TPC/simulation/include/TPCSimulation/Detector.h +++ b/Detectors/TPC/simulation/include/TPCSimulation/Detector.h @@ -156,6 +156,10 @@ class Detector : public o2::base::DetImpl int mElectronCounter = 0; int mStepCounter = 0; ElementalHit mHitLast{}; ///TrackTime() * 1.0e9; const int trackID = fMC->GetStack()->GetCurrentTrackNumber(); - const int detID = vol->getMCid(); o2::data::Stack* stack = (o2::data::Stack*)fMC->GetStack(); if (fMC->IsTrackEntering() || fMC->IsTrackExiting()) { stack->addTrackReference(o2::TrackReference(position.X(), position.Y(), position.Z(), momentum.X(), momentum.Y(), @@ -258,37 +257,38 @@ Bool_t Detector::ProcessHits(FairVolume* vol) } // ADD HIT - static thread_local int oldTrackId = trackID; - static thread_local int oldDetId = detID; - static thread_local int groupCounter = 0; - static thread_local int oldSectorId = sectorID; + // the first hit of an event starts the grouping afresh + if (!mCurrentGroup) { + mOldTrackId = trackID; + mOldSectorId = sectorID; + mGroupCounter = 0; + } // a new group is starting -> put it into the container - static thread_local HitGroup* currentgroup = nullptr; - if (groupCounter == 0) { + if (mGroupCounter == 0) { mHitsPerSectorCollection[sectorID]->emplace_back(trackID); - currentgroup = &(mHitsPerSectorCollection[sectorID]->back()); + mCurrentGroup = &(mHitsPerSectorCollection[sectorID]->back()); } - if (trackID == oldTrackId && oldSectorId == sectorID) { - groupCounter++; + if (trackID == mOldTrackId && mOldSectorId == sectorID) { + mGroupCounter++; mHitCounter++; mElectronCounter += numberOfElectrons; - currentgroup->addHit(position.X(), position.Y(), position.Z(), time, numberOfElectrons); + mCurrentGroup->addHit(position.X(), position.Y(), position.Z(), time, numberOfElectrons); - // add last buffered hit, which was not yet added to the currentgroup + // add last buffered hit, which was not yet added to the current group if (mHitLast.GetEnergyLoss() >= 0) { - currentgroup->addHit(mHitLast.GetX(), mHitLast.GetY(), mHitLast.GetZ(), mHitLast.GetTime(), mHitLast.GetEnergyLoss()); + mCurrentGroup->addHit(mHitLast.GetX(), mHitLast.GetY(), mHitLast.GetZ(), mHitLast.GetTime(), mHitLast.GetEnergyLoss()); mHitLast.mELoss = -1; - groupCounter++; + mGroupCounter++; mHitCounter++; mElectronCounter += mHitLast.GetEnergyLoss(); } } // finish group else { - oldTrackId = trackID; - oldSectorId = sectorID; - groupCounter = 0; + mOldTrackId = trackID; + mOldSectorId = sectorID; + mGroupCounter = 0; // buffer this hit, otherwise it wouldnt be stored in the HitGroup mHitLast = ElementalHit(position.X(), position.Y(), position.Z(), time, numberOfElectrons); @@ -310,6 +310,9 @@ Bool_t Detector::ProcessHits(FairVolume* vol) void Detector::EndOfEvent() { + // the hit grouping must not carry over into the next event + mCurrentGroup = nullptr; + mHitLast.mELoss = -1; if (!o2::utils::ShmManager::Instance().isOperational()) { for (int i = 0; i < Sector::MAXSECTOR; ++i) { mHitsPerSectorCollection[i]->clear(); From 641b8907a3051db2a98d707c3a44546ea10d55a9 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Fri, 25 Sep 2026 11:11:11 +0200 Subject: [PATCH 2/2] Count the charge of the buffered TPC hit in the electron counter This fixes the electron count that the TPC detector prints at the end of a run. - The charge of the buffered hit was read after it had been reset to -1. - It is now added before the reset. Co-Authored-By: Claude Opus 5.5 --- Detectors/TPC/simulation/src/Detector.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/TPC/simulation/src/Detector.cxx b/Detectors/TPC/simulation/src/Detector.cxx index 6a97a9b37fc96..da75d8f81f466 100644 --- a/Detectors/TPC/simulation/src/Detector.cxx +++ b/Detectors/TPC/simulation/src/Detector.cxx @@ -278,10 +278,10 @@ Bool_t Detector::ProcessHits(FairVolume* vol) // add last buffered hit, which was not yet added to the current group if (mHitLast.GetEnergyLoss() >= 0) { mCurrentGroup->addHit(mHitLast.GetX(), mHitLast.GetY(), mHitLast.GetZ(), mHitLast.GetTime(), mHitLast.GetEnergyLoss()); - mHitLast.mELoss = -1; mGroupCounter++; mHitCounter++; mElectronCounter += mHitLast.GetEnergyLoss(); + mHitLast.mELoss = -1; } } // finish group