From d368c23e1b9c6e7c7168f5117f5686778592f62d Mon Sep 17 00:00:00 2001 From: ariffero Date: Thu, 19 Mar 2026 16:05:03 +0100 Subject: [PATCH 1/3] Fix ambiguous-track BC handling in UPCCandProducer Validate bcIds() before resolving ambiguous-track BCs, skip empty or out-of-range entries, and ignore tracks that have neither a valid ambiguous BC nor a valid collision association. This avoids crashes from invalid BC slices and from dereferencing missing collision links in forward-track processing. --- PWGUD/TableProducer/UPCCandidateProducer.cxx | 50 +++++++++++++++----- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/PWGUD/TableProducer/UPCCandidateProducer.cxx b/PWGUD/TableProducer/UPCCandidateProducer.cxx index 2208060bd59..4780ab5bdc0 100644 --- a/PWGUD/TableProducer/UPCCandidateProducer.cxx +++ b/PWGUD/TableProducer/UPCCandidateProducer.cxx @@ -603,17 +603,25 @@ struct UpcCandProducer { // "uncorrected" bcs template void collectAmbTrackBCs(std::unordered_map& ambTrIds, + TBCs const& bcs, TAmbTracks ambTracks) { for (const auto& ambTrk : ambTracks) { auto trkId = getAmbTrackId(ambTrk); - const auto& bcSlice = ambTrk.template bc_as(); - uint64_t trackBC = -1; - if (bcSlice.size() != 0) { - auto first = bcSlice.begin(); - trackBC = first.globalBC(); + + const auto& bcIds = ambTrk.bcIds(); + if (bcIds.size() == 0) + continue; + + const auto firstBcId = static_cast(*bcIds.begin()); + if (firstBcId < 0 || firstBcId >= static_cast(bcs.size())) { + LOGP(debug, + "Skipping ambiguous track {}: invalid first bcId {} (nBCs = {})", + trkId, firstBcId, bcs.size()); + continue; } - ambTrIds[trkId] = trackBC; + + ambTrIds[trkId] = bcs.iteratorAt(firstBcId).globalBC(); } } @@ -649,16 +657,22 @@ struct UpcCandProducer { continue; int64_t trkId = trk.globalIndex(); int32_t nContrib = -1; + bool hasTrackBC = false; uint64_t trackBC = 0; if (trk.has_collision()) { const auto& col = trk.collision(); nContrib = col.numContrib(); trackBC = col.bc_as().globalBC(); + hasTrackBC = true; } else { auto ambIter = ambBarrelTrBCs.find(trkId); - if (ambIter != ambBarrelTrBCs.end()) + if (ambIter != ambBarrelTrBCs.end()) { trackBC = ambIter->second; + hasTrackBC = true; + } } + if (!hasTrackBC) + continue; int64_t tint = TMath::FloorNint(trk.trackTime() / o2::constants::lhc::LHCBunchSpacingNS + static_cast(fBarrelTrackTShift)); uint64_t bc = trackBC + tint; if (nContrib > upcCuts.getMaxNContrib()) @@ -683,15 +697,22 @@ struct UpcCandProducer { continue; int64_t trkId = trk.globalIndex(); int32_t nContrib = -1; + bool hasTrackBC = false; uint64_t trackBC = 0; auto ambIter = ambFwdTrBCs.find(trkId); if (ambIter == ambFwdTrBCs.end()) { + if (!trk.has_collision()) + continue; const auto& col = trk.collision(); nContrib = col.numContrib(); trackBC = col.bc_as().globalBC(); + hasTrackBC = true; } else { trackBC = ambIter->second; + hasTrackBC = true; } + if (!hasTrackBC) + continue; int64_t tint = TMath::FloorNint(trk.trackTime() / o2::constants::lhc::LHCBunchSpacingNS + static_cast(fMuonTrackTShift)); uint64_t bc = trackBC + tint; if (nContrib > upcCuts.getMaxNContrib()) @@ -716,9 +737,12 @@ struct UpcCandProducer { continue; int64_t trkId = trk.globalIndex(); int32_t nContrib = -1; + bool hasTrackBC = false; uint64_t trackBC = 0; auto ambIter = ambFwdTrBCs.find(trkId); if (ambIter == ambFwdTrBCs.end()) { + if (!trk.has_collision()) + continue; const auto& col = trk.collision(); nContrib = col.numContrib(); trackBC = col.bc_as().globalBC(); @@ -732,6 +756,8 @@ struct UpcCandProducer { } else { trackBC = ambIter->second; } + if (!hasTrackBC) + continue; int64_t tint = TMath::FloorNint(trk.trackTime() / o2::constants::lhc::LHCBunchSpacingNS + static_cast(fMuonTrackTShift)); uint64_t bc = trackBC + tint; if (nContrib > upcCuts.getMaxNContrib()) @@ -800,7 +826,7 @@ struct UpcCandProducer { // trackID -> index in amb. track table std::unordered_map ambBarrelTrBCs; if (upcCuts.getAmbigSwitch() != 1) - collectAmbTrackBCs<0, BCsWithBcSels>(ambBarrelTrBCs, ambBarrelTracks); + collectAmbTrackBCs<0, BCsWithBcSels>(ambBarrelTrBCs, bcs, ambBarrelTracks); collectBarrelTracks(bcsMatchedTrIdsTOF, 0, @@ -1101,10 +1127,10 @@ struct UpcCandProducer { // trackID -> index in amb. track table std::unordered_map ambBarrelTrBCs; - collectAmbTrackBCs<0, BCsWithBcSels>(ambBarrelTrBCs, ambBarrelTracks); + collectAmbTrackBCs<0, BCsWithBcSels>(ambBarrelTrBCs, bcs, ambBarrelTracks); std::unordered_map ambFwdTrBCs; - collectAmbTrackBCs<1, BCsWithBcSels>(ambFwdTrBCs, ambFwdTracks); + collectAmbTrackBCs<1, BCsWithBcSels>(ambFwdTrBCs, bcs, ambFwdTracks); collectForwardTracks(bcsMatchedTrIdsMID, o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack, @@ -1301,7 +1327,7 @@ struct UpcCandProducer { // trackID -> index in amb. track table std::unordered_map ambFwdTrBCs; - collectAmbTrackBCs<1, BCsWithBcSels>(ambFwdTrBCs, ambFwdTracks); + collectAmbTrackBCs<1, BCsWithBcSels>(ambFwdTrBCs, bcs, ambFwdTracks); collectForwardTracks(bcsMatchedTrIdsMID, o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack, @@ -1556,7 +1582,7 @@ struct UpcCandProducer { // trackID -> index in amb. track table std::unordered_map ambFwdTrBCs; - collectAmbTrackBCs<1, BCsWithBcSels>(ambFwdTrBCs, ambFwdTracks); + collectAmbTrackBCs<1, BCsWithBcSels>(ambFwdTrBCs, bcs,ambFwdTracks); collectForwardTracks(bcsMatchedTrIdsMID, o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack, From 2d2557b6e39e7f9312d5853c699dea4d4228c6bb Mon Sep 17 00:00:00 2001 From: ariffero Date: Thu, 19 Mar 2026 17:30:40 +0100 Subject: [PATCH 2/3] Add Andrea Riffero as author of UPCCandidateProducer --- PWGUD/TableProducer/UPCCandidateProducer.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/PWGUD/TableProducer/UPCCandidateProducer.cxx b/PWGUD/TableProducer/UPCCandidateProducer.cxx index 4780ab5bdc0..5253fae5b1c 100644 --- a/PWGUD/TableProducer/UPCCandidateProducer.cxx +++ b/PWGUD/TableProducer/UPCCandidateProducer.cxx @@ -11,6 +11,8 @@ /// \author Nazar Burmasov, nazar.burmasov@cern.ch /// \author Diana Krupova, diana.krupova@cern.ch /// \since 04.06.2024 +/// \author Andrea Riffero, andrea.giovanni.riffero@cern.ch +/// \since 19.03.2026 #include "PWGUD/Core/UPCCutparHolder.h" #include "PWGUD/Core/UPCHelpers.h" From be24acbe04ff80c616c452dd8fb7c11b5e98a296 Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Fri, 20 Mar 2026 09:03:12 +0000 Subject: [PATCH 3/3] Please consider the following formatting changes --- PWGUD/TableProducer/UPCCandidateProducer.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/PWGUD/TableProducer/UPCCandidateProducer.cxx b/PWGUD/TableProducer/UPCCandidateProducer.cxx index 5253fae5b1c..4e9ea87dccb 100644 --- a/PWGUD/TableProducer/UPCCandidateProducer.cxx +++ b/PWGUD/TableProducer/UPCCandidateProducer.cxx @@ -614,7 +614,7 @@ struct UpcCandProducer { const auto& bcIds = ambTrk.bcIds(); if (bcIds.size() == 0) continue; - + const auto firstBcId = static_cast(*bcIds.begin()); if (firstBcId < 0 || firstBcId >= static_cast(bcs.size())) { LOGP(debug, @@ -713,7 +713,7 @@ struct UpcCandProducer { trackBC = ambIter->second; hasTrackBC = true; } - if (!hasTrackBC) + if (!hasTrackBC) continue; int64_t tint = TMath::FloorNint(trk.trackTime() / o2::constants::lhc::LHCBunchSpacingNS + static_cast(fMuonTrackTShift)); uint64_t bc = trackBC + tint; @@ -758,7 +758,7 @@ struct UpcCandProducer { } else { trackBC = ambIter->second; } - if (!hasTrackBC) + if (!hasTrackBC) continue; int64_t tint = TMath::FloorNint(trk.trackTime() / o2::constants::lhc::LHCBunchSpacingNS + static_cast(fMuonTrackTShift)); uint64_t bc = trackBC + tint; @@ -1584,7 +1584,7 @@ struct UpcCandProducer { // trackID -> index in amb. track table std::unordered_map ambFwdTrBCs; - collectAmbTrackBCs<1, BCsWithBcSels>(ambFwdTrBCs, bcs,ambFwdTracks); + collectAmbTrackBCs<1, BCsWithBcSels>(ambFwdTrBCs, bcs, ambFwdTracks); collectForwardTracks(bcsMatchedTrIdsMID, o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack,