@@ -85,6 +85,10 @@ using GenCollisionsMc = aod::McCollisions;
8585using AntiNucleiTracks = soa::Join<aod::Tracks, aod::TracksExtra, aod::TrackSelection, aod::TrackSelectionExtension, aod::TracksDCA, aod::pidTPCFullPr, aod::pidTPCFullDe, aod::pidTPCFullHe, aod::pidTOFFullPr, aod::pidTOFFullDe, aod::pidTOFFullHe>;
8686using AntiNucleiTracksMc = soa::Join<AntiNucleiTracks, aod::McTrackLabels>;
8787
88+ // Define preslices to group MC tracks and MC particles by their associated MC collision
89+ Preslice<AntiNucleiTracksMc> mcTracksPerMcCollision = o2::aod::track::collisionId;
90+ Preslice<aod::McParticles> mcParticlesPerMcCollision = o2::aod::mcparticle::mcCollisionId;
91+
8892struct AntinucleiInJets {
8993
9094 // Histogram registries for data, MC, quality control, multiplicity and correlations
@@ -1433,53 +1437,20 @@ struct AntinucleiInJets {
14331437 PROCESS_SWITCH (AntinucleiInJets, processQC, " Process QC" , false );
14341438
14351439 // Antinuclei reconstruction efficiency
1436- void processAntinucleiEfficiency (RecCollisionsMc const & collisions , AntiNucleiTracksMc const & mcTracks, aod::McParticles const & mcParticles)
1440+ void processAntinucleiEfficiency (GenCollisionsMc const & genCollisions, RecCollisionsMc const & recCollisions , AntiNucleiTracksMc const & mcTracks, aod::McParticles const & mcParticles)
14371441 {
1438- // Loop over all simulated collision events
1439- for (const auto & collision : collisions) {
1440-
1441- // Count all generated events before applying any event selection criteria
1442- registryMC.fill (HIST (" number_of_events_mc_nuclei_efficiency" ), 0.5 );
1443-
1444- // Apply event selection: require sel8 and vertex position within the allowed z range
1445- if (!collision.sel8 () || std::fabs (collision.posZ ()) > zVtx)
1446- continue ;
1447-
1448- // Count events that pass the selection criteria
1449- registryMC.fill (HIST (" number_of_events_mc_nuclei_efficiency" ), 1.5 );
1450-
1451- // Reject events near the ITS Read-Out Frame border
1452- if (rejectITSROFBorder && !collision.selection_bit (o2::aod::evsel::kNoITSROFrameBorder ))
1453- continue ;
1454- registryMC.fill (HIST (" number_of_events_mc_nuclei_efficiency" ), 2.5 );
1455-
1456- // Reject events at the Time Frame border
1457- if (rejectTFBorder && !collision.selection_bit (o2::aod::evsel::kNoTimeFrameBorder ))
1458- continue ;
1459- registryMC.fill (HIST (" number_of_events_mc_nuclei_efficiency" ), 3.5 );
1460-
1461- // Require at least one ITS-TPC matched track
1462- if (requireVtxITSTPC && !collision.selection_bit (o2::aod::evsel::kIsVertexITSTPC ))
1463- continue ;
1464- registryMC.fill (HIST (" number_of_events_mc_nuclei_efficiency" ), 4.5 );
1465-
1466- // Reject events with same-bunch pileup
1467- if (rejectSameBunchPileup && !collision.selection_bit (o2::aod::evsel::kNoSameBunchPileup ))
1468- continue ;
1469- registryMC.fill (HIST (" number_of_events_mc_nuclei_efficiency" ), 5.5 );
1442+ // Loop over generated collisions
1443+ for (const auto & collision : genCollisions) {
14701444
1471- // Require consistent FT0 vs PV z-vertex
1472- if (requireIsGoodZvtxFT0VsPV && ! collision.selection_bit (o2::aod::evsel:: kIsGoodZvtxFT0vsPV ) )
1445+ // Apply event selection: require vertex position to be within the allowed z range
1446+ if (std::fabs ( collision.posZ ()) > zVtx )
14731447 continue ;
1474- registryMC.fill (HIST (" number_of_events_mc_nuclei_efficiency" ), 6.5 );
14751448
1476- // Require TOF match for at least one vertex track
1477- if (requireIsVertexTOFmatched && !collision.selection_bit (o2::aod::evsel::kIsVertexTOFmatched ))
1478- continue ;
1479- registryMC.fill (HIST (" number_of_events_mc_nuclei_efficiency" ), 7.5 );
1449+ // Get particles in this MC collision
1450+ const auto mcParticlesThisMcColl = mcParticles.sliceBy (mcParticlesPerMcCollision, collision.globalIndex ());
14801451
14811452 // Loop over all generated Monte Carlo particles for the selected event
1482- for (const auto & particle : mcParticles ) {
1453+ for (const auto & particle : mcParticlesThisMcColl ) {
14831454
14841455 // Select primary particles
14851456 if (!particle.isPhysicalPrimary ())
@@ -1527,9 +1498,56 @@ struct AntinucleiInJets {
15271498 break ;
15281499 }
15291500 }
1501+ }
1502+
1503+ // Loop over all reconstructed collisions
1504+ for (const auto & collision : recCollisions) {
1505+
1506+ // Count all generated events before applying any event selection criteria
1507+ registryMC.fill (HIST (" number_of_events_mc_nuclei_efficiency" ), 0.5 );
1508+
1509+ // Apply event selection: require sel8 and vertex position within the allowed z range
1510+ if (!collision.sel8 () || std::fabs (collision.posZ ()) > zVtx)
1511+ continue ;
1512+
1513+ // Count events that pass the selection criteria
1514+ registryMC.fill (HIST (" number_of_events_mc_nuclei_efficiency" ), 1.5 );
1515+
1516+ // Reject events near the ITS Read-Out Frame border
1517+ if (rejectITSROFBorder && !collision.selection_bit (o2::aod::evsel::kNoITSROFrameBorder ))
1518+ continue ;
1519+ registryMC.fill (HIST (" number_of_events_mc_nuclei_efficiency" ), 2.5 );
1520+
1521+ // Reject events at the Time Frame border
1522+ if (rejectTFBorder && !collision.selection_bit (o2::aod::evsel::kNoTimeFrameBorder ))
1523+ continue ;
1524+ registryMC.fill (HIST (" number_of_events_mc_nuclei_efficiency" ), 3.5 );
1525+
1526+ // Require at least one ITS-TPC matched track
1527+ if (requireVtxITSTPC && !collision.selection_bit (o2::aod::evsel::kIsVertexITSTPC ))
1528+ continue ;
1529+ registryMC.fill (HIST (" number_of_events_mc_nuclei_efficiency" ), 4.5 );
1530+
1531+ // Reject events with same-bunch pileup
1532+ if (rejectSameBunchPileup && !collision.selection_bit (o2::aod::evsel::kNoSameBunchPileup ))
1533+ continue ;
1534+ registryMC.fill (HIST (" number_of_events_mc_nuclei_efficiency" ), 5.5 );
1535+
1536+ // Require consistent FT0 vs PV z-vertex
1537+ if (requireIsGoodZvtxFT0VsPV && !collision.selection_bit (o2::aod::evsel::kIsGoodZvtxFT0vsPV ))
1538+ continue ;
1539+ registryMC.fill (HIST (" number_of_events_mc_nuclei_efficiency" ), 6.5 );
1540+
1541+ // Require TOF match for at least one vertex track
1542+ if (requireIsVertexTOFmatched && !collision.selection_bit (o2::aod::evsel::kIsVertexTOFmatched ))
1543+ continue ;
1544+ registryMC.fill (HIST (" number_of_events_mc_nuclei_efficiency" ), 7.5 );
1545+
1546+ // Get tracks in this MC collision
1547+ const auto mcTracksThisMcColl = mcTracks.sliceBy (mcTracksPerMcCollision, collision.globalIndex ());
15301548
15311549 // Loop over all reconstructed MC tracks
1532- for (auto const & track : mcTracks ) {
1550+ for (auto const & track : mcTracksThisMcColl ) {
15331551
15341552 // Apply standard track selection criteria
15351553 if (!passedTrackSelection (track))
@@ -1762,8 +1780,11 @@ struct AntinucleiInJets {
17621780 // Event counter: after event selection
17631781 registryMC.fill (HIST (" genEvents" ), 1.5 );
17641782
1783+ // Get particles in this MC collision
1784+ const auto mcParticlesThisMcColl = mcParticles.sliceBy (mcParticlesPerMcCollision, collision.globalIndex ());
1785+
17651786 // Loop over MC particles
1766- for (const auto & particle : mcParticles ) {
1787+ for (const auto & particle : mcParticlesThisMcColl ) {
17671788
17681789 // Select physical primary particles or HF decay products
17691790 if (!isPhysicalPrimaryOrFromHF (particle, mcParticles))
@@ -1974,9 +1995,12 @@ struct AntinucleiInJets {
19741995 continue ;
19751996 registryMC.fill (HIST (" recEvents" ), 7.5 );
19761997
1998+ // Get tracks in this MC collision
1999+ const auto mcTracksThisMcColl = mcTracks.sliceBy (mcTracksPerMcCollision, collision.globalIndex ());
2000+
19772001 // Loop over reconstructed tracks
19782002 int id (-1 );
1979- for (auto const & track : mcTracks ) {
2003+ for (auto const & track : mcTracksThisMcColl ) {
19802004 id++;
19812005
19822006 // Get corresponding MC particle
@@ -2048,7 +2072,7 @@ struct AntinucleiInJets {
20482072 for (const auto & particle : jetConstituents) {
20492073
20502074 // Get corresponding track and apply track selection criteria
2051- auto const & track = mcTracks .iteratorAt (particle.user_index ());
2075+ auto const & track = mcTracksThisMcColl .iteratorAt (particle.user_index ());
20522076 if (!passedTrackSelection (track))
20532077 continue ;
20542078
@@ -2129,7 +2153,7 @@ struct AntinucleiInJets {
21292153 for (auto const & index : antiprotonTrackIndex) {
21302154
21312155 // retrieve track associated to index
2132- auto const & track = mcTracks .iteratorAt (index);
2156+ auto const & track = mcTracksThisMcColl .iteratorAt (index);
21332157
21342158 // Get corresponding MC particle
21352159 if (!track.has_mcParticle ())
@@ -2436,8 +2460,11 @@ struct AntinucleiInJets {
24362460 if (std::fabs (collision.posZ ()) > zVtx)
24372461 continue ;
24382462
2463+ // Get particles in this MC collision
2464+ const auto mcParticlesThisMcColl = mcParticles.sliceBy (mcParticlesPerMcCollision, collision.globalIndex ());
2465+
24392466 // Loop over all generated Monte Carlo particles for the selected event
2440- for (const auto & particle : mcParticles ) {
2467+ for (const auto & particle : mcParticlesThisMcColl ) {
24412468
24422469 // Select primary particles
24432470 if (!particle.isPhysicalPrimary ())
@@ -2493,8 +2520,11 @@ struct AntinucleiInJets {
24932520 if (requireIsVertexTOFmatched && !collision.selection_bit (o2::aod::evsel::kIsVertexTOFmatched ))
24942521 continue ;
24952522
2523+ // Get tracks in this MC collision
2524+ const auto mcTracksThisMcColl = mcTracks.sliceBy (mcTracksPerMcCollision, collision.globalIndex ());
2525+
24962526 // Loop over reconstructed tracks
2497- for (auto const & track : mcTracks ) {
2527+ for (auto const & track : mcTracksThisMcColl ) {
24982528
24992529 // Select only antimatter
25002530 if (track.sign () > 0 )
0 commit comments