@@ -1084,13 +1084,13 @@ void AODProducerWorkflowDPL::fillMCParticlesTable(o2::steer::MCKinematicsReader&
10841084 const gsl::span<const o2::dataformats::VtxTrackRef>& primVer2TRefs,
10851085 const gsl::span<const GIndex>& GIndices,
10861086 const o2::globaltracking::RecoContainer& data,
1087- const std::vector<std::vector< int > >& mcColToEvSrc)
1087+ const std::vector<MCColInfo >& mcColToEvSrc)
10881088{
10891089 int NSources = 0 ;
10901090 int NEvents = 0 ;
10911091 for (auto & p : mcColToEvSrc) {
1092- NSources = std::max (p[ 1 ] , NSources);
1093- NEvents = std::max (p[ 2 ] , NEvents);
1092+ NSources = std::max (p. sourceID , NSources);
1093+ NEvents = std::max (p. eventID , NEvents);
10941094 }
10951095 NSources++; // 0 - indexed
10961096 NEvents++;
@@ -1166,9 +1166,9 @@ void AODProducerWorkflowDPL::fillMCParticlesTable(o2::steer::MCKinematicsReader&
11661166
11671167 size_t offset = 0 ;
11681168 for (auto & colInfo : mcColToEvSrc) { // loop over "<eventID, sourceID> <-> combined MC col. ID" key pairs
1169- int event = colInfo[ 2 ] ;
1170- int source = colInfo[ 1 ] ;
1171- int mcColId = colInfo[ 0 ] ;
1169+ int event = colInfo. eventID ;
1170+ int source = colInfo. sourceID ;
1171+ int mcColId = colInfo. colIndex ;
11721172 std::vector<MCTrack> const & mcParticles = mcReader.getTracks (source, event);
11731173 LOG (debug) << " Event=" << event << " source=" << source << " collision=" << mcColId;
11741174 auto & preselect = mToStore [source][event];
@@ -2179,10 +2179,8 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc)
21792179 zdcChannelsT);
21802180 }
21812181
2182- // keep track event/source id for each mc-collision
2183- // using map and not unordered_map to ensure
2184- // correct ordering when iterating over container elements
2185- std::vector<std::vector<int >> mcColToEvSrc;
2182+ // keep track of event_id + source_id + bc for each mc-collision
2183+ std::vector<MCColInfo> mcColToEvSrc;
21862184
21872185 if (mUseMC ) {
21882186 using namespace o2 ::aodmchelpers;
@@ -2255,13 +2253,13 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc)
22552253 0 ,
22562254 sourceID);
22572255 }
2258- mcColToEvSrc.emplace_back (std::vector< int > {iCol, sourceID, eventID}); // point background and injected signal events to one collision
2256+ mcColToEvSrc.emplace_back (MCColInfo {iCol, sourceID, eventID, globalBC }); // point background and injected signal events to one collision
22592257 }
22602258 }
22612259 }
22622260
22632261 std::sort (mcColToEvSrc.begin (), mcColToEvSrc.end (),
2264- [](const std::vector< int > & left, const std::vector< int > & right) { return (left[ 0 ] < right[ 0 ] ); });
2262+ [](const MCColInfo & left, const MCColInfo & right) { return (left. colIndex < right. colIndex ); });
22652263
22662264 // vector of FDD amplitudes
22672265 int16_t aFDDAmplitudesA[8 ] = {0u }, aFDDAmplitudesC[8 ] = {0u };
@@ -2360,16 +2358,46 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc)
23602358 }
23612359
23622360 if (mUseMC ) {
2363- // filling MC collision labels
2361+ // Fill MC collision labels using information from the primary vertexer.
23642362 mcColLabelsCursor.reserve (primVerLabels.size ());
2365- for (auto & label : primVerLabels) {
2366- auto it = std::find_if (mcColToEvSrc.begin (), mcColToEvSrc.end (),
2367- [&label](const auto & mcColInfo) { return mcColInfo[1 ] == label.getSourceID () && mcColInfo[2 ] == label.getEventID (); });
2363+ for (size_t ivert = 0 ; ivert < primVerLabels.size (); ++ivert) {
2364+ const auto & label = primVerLabels[ivert];
2365+
2366+ // Collect all MC collision candidates matching this (sourceID, eventID) label.
2367+ // In the non-embedding case there is exactly one candidate. In the embedding
2368+ // case the same (sourceID, eventID) pair can appear in multiple collisions,
2369+ // so we need to disambiguate.
2370+ std::vector<std::pair<int32_t , int64_t >> candidates; // (colIndex, bc)
2371+ for (const auto & colInfo : mcColToEvSrc) {
2372+ if (colInfo.sourceID == label.getSourceID () &&
2373+ colInfo.eventID == label.getEventID ()) {
2374+ candidates.emplace_back (colInfo.colIndex , colInfo.bc );
2375+ }
2376+ }
2377+
23682378 int32_t mcCollisionID = -1 ;
2369- if (it != mcColToEvSrc.end ()) {
2370- mcCollisionID = it->at (0 );
2379+ if (candidates.size () == 1 ) {
2380+ mcCollisionID = candidates[0 ].first ;
2381+ } else if (candidates.size () > 1 ) {
2382+ // Disambiguate by BC: pick the MCCollision whose BC is closest
2383+ // to the reconstructed collision's BC.
2384+ // TODO: Consider a complementary strategy using the MC labels of tracks
2385+ // associated to the primary vertex, and/or by allowing the primary
2386+ // vertexer to return multiple MC collision labels per vertex.
2387+ const auto & timeStamp = primVertices[ivert].getTimeStamp ();
2388+ const double interactionTime = timeStamp.getTimeStamp () * 1E3 ; // us -> ns
2389+ const auto recoBC = relativeTime_to_GlobalBC (interactionTime);
2390+ int64_t bestDiff = std::numeric_limits<int64_t >::max ();
2391+ for (const auto & [colIndex, bc] : candidates) {
2392+ const auto bcDiff = std::abs (static_cast <int64_t >(bc) - static_cast <int64_t >(recoBC));
2393+ if (bcDiff < bestDiff) {
2394+ bestDiff = bcDiff;
2395+ mcCollisionID = colIndex;
2396+ }
2397+ }
23712398 }
2372- uint16_t mcMask = 0 ; // todo: set mask using normalized weights?
2399+
2400+ uint16_t mcMask = 0 ; // TODO: set mask using normalised weights
23732401 mcColLabelsCursor (mcCollisionID, mcMask);
23742402 }
23752403 }
0 commit comments