From 5335d9efa7f63ba1fd5230cb506d640179910299 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 | 52 +++++++++++++++----- 1 file changed, 40 insertions(+), 12 deletions(-) diff --git a/PWGUD/TableProducer/UPCCandidateProducer.cxx b/PWGUD/TableProducer/UPCCandidateProducer.cxx index 2208060bd59..6f75831f426 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(); @@ -729,9 +753,13 @@ struct UpcCandProducer { if (fRequireNoITSROFrameBorder && !bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { continue; // skip this track if the kNoITSROFrameBorder bit is required but not set } + 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()) @@ -800,7 +828,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 +1129,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 +1329,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 +1584,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 a61a9835db525c5fca89eea64778236ecdd29b47 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 6f75831f426..e2eff8bbb85 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 b6f0aa4f4e0134e966bce37d7e1584ad08399611 Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Fri, 27 Mar 2026 11:31:59 +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 e2eff8bbb85..10ad832634a 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; @@ -760,7 +760,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; @@ -1586,7 +1586,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,