From f537df4225471db065169590d1f190a66979d5a5 Mon Sep 17 00:00:00 2001 From: Alberto Caliva Date: Wed, 4 Mar 2026 21:56:16 +0100 Subject: [PATCH 1/4] Add function to compute jet pt resolution --- PWGLF/Tasks/Nuspex/antinucleiInJets.cxx | 161 ++++++++++++++++++++++++ 1 file changed, 161 insertions(+) diff --git a/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx b/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx index c055f5c2e2c..1f91e443e7c 100644 --- a/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx +++ b/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx @@ -128,6 +128,13 @@ struct ReducedParticle { } }; +// Jet Matching +struct JetMatching { + double distance; + double ptTrue; + double ptDiff; +}; + struct AntinucleiInJets { // Histogram registries for data, MC, quality control, multiplicity and correlations @@ -145,6 +152,7 @@ struct AntinucleiInJets { Configurable cfgAreaFrac{"cfgAreaFrac", 0.6, "fraction of jet area"}; Configurable cfgEtaJetMax{"cfgEtaJetMax", 0.5, "max jet eta"}; Configurable cfgMinPtTrack{"cfgMinPtTrack", 0.15, "minimum pt of tracks for jet reconstruction"}; + Configurable alpha{"alpha", 0.3, "parameter to control jet matching"}; // Event selection criteria Configurable rejectITSROFBorder{"rejectITSROFBorder", true, "Reject events near the ITS ROF border"}; @@ -501,6 +509,11 @@ struct AntinucleiInJets { registryMC.add("antiproton_coal_ue", "antiproton_coal_ue", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); } + // jet pt resolution + if (doprocessJetPtResolution) { + registryMC.add("jetPtResolution", "jet Pt Resolution", HistType::kTH2F, {{200, 0, 20, "#it{p}^{jet}_{T,true} (GeV/#it{c})"}}, {{1000, -5, 5, "#Delta #it{p}^{jet}_{T} (GeV/#it{c})"}}); + } + // Coalescence and Correlation analysis if (doprocessCoalescenceCorr) { @@ -3912,6 +3925,154 @@ struct AntinucleiInJets { } } PROCESS_SWITCH(AntinucleiInJets, processCoalescenceCorr, "process coalescence correlation", false); + + + // Jet Pt resolution + void processJetPtResolution(RecCollisionsMc const& collisions, AntiNucleiTracksMc const& mcTracks, aod::McParticles const& mcParticles) + { + // Define per-event particle containers + std::vector fjParticles; + std::vector fjTracks; + + // Jet and area definitions + fastjet::JetDefinition jetDef(fastjet::antikt_algorithm, rJet); + fastjet::AreaDefinition areaDef(fastjet::active_area, fastjet::GhostedAreaSpec(1.0)); + + // Loop over all reconstructed collisions + for (const auto& collision : collisions) { + + // Clear containers at the start of the event loop + fjParticles.clear(); + fjTracks.clear(); + + // Reject reconstructed collisions with no simulated collision + if (!collision.has_mcCollision()) + continue; + + // Apply event selection: require sel8 and vertex position to be within the allowed z range + if (!collision.sel8() || std::fabs(collision.posZ()) > zVtx) + continue; + + // Reject events near the ITS Read-Out Frame border + if (rejectITSROFBorder && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) + continue; + + // Reject events at the Time Frame border + if (rejectTFBorder && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) + continue; + + // Require at least one ITS-TPC matched track + if (requireVtxITSTPC && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) + continue; + + // Reject events with same-bunch pileup + if (rejectSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) + continue; + + // Require consistent FT0 vs PV z-vertex + if (requireIsGoodZvtxFT0VsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) + continue; + + // Require TOF match for at least one vertex track + if (requireIsVertexTOFmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) + continue; + + // Get tracks and particles in this MC collision + const auto mcTracksThisMcColl = mcTracks.sliceBy(mcTracksPerMcCollision, collision.globalIndex()); + const auto mcParticlesThisMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, collision.globalIndex()); + + // Loop over reconstructed tracks + for (auto const& track : mcTracksThisMcColl) { + + // Apply track selection for jet reconstruction + if (!passedTrackSelectionForJetReconstruction(track)) + continue; + + // 4-momentum representation of a particle + fastjet::PseudoJet fourMomentum(track.px(), track.py(), track.pz(), track.energy(MassPionCharged)); + fjTracks.emplace_back(fourMomentum); + } + + // Loop over MC particles + for (const auto& particle : mcParticlesThisMcColl) { + + // Select physical primary particles or HF decay products + if (!isPhysicalPrimaryOrFromHF(particle, mcParticles)) + continue; + + // Select particles within acceptance + if (particle.eta() < minEta || particle.eta() > maxEta || particle.pt() < cfgMinPtTrack) + continue; + + // 4-momentum representation of a particle + double energy = std::sqrt(particle.p() * particle.p() + MassPionCharged * MassPionCharged); + fastjet::PseudoJet fourMomentum(particle.px(), particle.py(), particle.pz(), energy); + fjParticles.emplace_back(fourMomentum); + } + + // Reject empty events + if (fjTracks.empty() || fjParticles.empty()) + continue; + + // Cluster particles using the anti-kt algorithm + fastjet::ClusterSequenceArea csRec(fjTracks, jetDef, areaDef); + std::vector jetsRec = fastjet::sorted_by_pt(csRec.inclusive_jets()); + + fastjet::ClusterSequenceArea csGen(fjParticles, jetDef, areaDef); + std::vector jetsGen = fastjet::sorted_by_pt(csGen.inclusive_jets()); + + // Loop over reconstructed jets + std::vector jetGenRec; + for (const auto& jetRec : jetsRec) { + + // Jet must be fully contained in the acceptance + if ((std::fabs(jetRec.eta()) + rJet) > (maxEta - deltaEtaEdge)) + continue; + + // Apply area cut if required + if (applyAreaCut && (jetRec.area() / (PI * rJet * rJet)) > maxNormalizedJetArea) + continue; + + // Clear jet-pair container + jetGenRec.clear(); + + for (const auto& jetGen : jetsGen) { + + // Jet must be fully contained in the acceptance + if ((std::fabs(jetGen.eta()) + rJet) > (maxEta - deltaEtaEdge)) + continue; + + // Apply area cut if required + if (applyAreaCut && (jetGen.area() / (PI * rJet * rJet)) > maxNormalizedJetArea) + continue; + + double deltaEta = jetGen.eta() - jetRec.eta(); + double deltaPhi = getDeltaPhi(jetGen.phi(), jetRec.phi()); + double deltaR = std::sqrt(deltaEta * deltaEta + deltaPhi * deltaPhi); + if (deltaR < rJet) + jetGenRec.emplace_back({deltaR, jetGen.pt(), jetGen.pt() - jetRec.pt()}); + } + if (jetGenRec.empty()) + continue; + + double distanceMin(1e+06); + double diffPt(0); + double ptJetTrue(0); + for (const auto& jetPair : jetGenRec) { + if (jetPair.distance < distanceMin) { + distanceMin = jetPair.distance; + diffPt = jetPair.ptDiff; + ptJetTrue = jetPair.ptTrue; + } + } + + if (distanceMin < alpha * rJet) { + registryMC.fill(HIST("jetPtResolution"), ptJetTrue, diffPt); + } + } + } + } + PROCESS_SWITCH(AntinucleiInJets, processJetPtResolution, "process jet pt resolution", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From c1cfb897fdc31bfd8b9c11229ac0375da36d7bff Mon Sep 17 00:00:00 2001 From: Alberto Caliva Date: Wed, 4 Mar 2026 21:58:24 +0100 Subject: [PATCH 2/4] fix whitespace --- PWGLF/Tasks/Nuspex/antinucleiInJets.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx b/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx index 1f91e443e7c..ff6bfd87b1c 100644 --- a/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx +++ b/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx @@ -4065,7 +4065,7 @@ struct AntinucleiInJets { ptJetTrue = jetPair.ptTrue; } } - + if (distanceMin < alpha * rJet) { registryMC.fill(HIST("jetPtResolution"), ptJetTrue, diffPt); } From df52a4ed500fd23cef22564bb0f94d10a26d2ce6 Mon Sep 17 00:00:00 2001 From: Alberto Caliva Date: Wed, 4 Mar 2026 22:00:52 +0100 Subject: [PATCH 3/4] fix trailing space --- PWGLF/Tasks/Nuspex/antinucleiInJets.cxx | 1 - 1 file changed, 1 deletion(-) diff --git a/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx b/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx index ff6bfd87b1c..fd0c103367b 100644 --- a/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx +++ b/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx @@ -3926,7 +3926,6 @@ struct AntinucleiInJets { } PROCESS_SWITCH(AntinucleiInJets, processCoalescenceCorr, "process coalescence correlation", false); - // Jet Pt resolution void processJetPtResolution(RecCollisionsMc const& collisions, AntiNucleiTracksMc const& mcTracks, aod::McParticles const& mcParticles) { From 819221c0c96f60645eab009222527288d749e137 Mon Sep 17 00:00:00 2001 From: Alberto Caliva Date: Thu, 5 Mar 2026 03:34:06 +0100 Subject: [PATCH 4/4] fix typos --- PWGLF/Tasks/Nuspex/antinucleiInJets.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx b/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx index fd0c103367b..cedb442bd4e 100644 --- a/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx +++ b/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx @@ -511,7 +511,7 @@ struct AntinucleiInJets { // jet pt resolution if (doprocessJetPtResolution) { - registryMC.add("jetPtResolution", "jet Pt Resolution", HistType::kTH2F, {{200, 0, 20, "#it{p}^{jet}_{T,true} (GeV/#it{c})"}}, {{1000, -5, 5, "#Delta #it{p}^{jet}_{T} (GeV/#it{c})"}}); + registryMC.add("jetPtResolution", "jet Pt Resolution", HistType::kTH2F, {{200, 0, 20, "#it{p}^{jet}_{T,true} (GeV/#it{c})"}, {1000, -5, 5, "#Delta #it{p}^{jet}_{T} (GeV/#it{c})"}}); } // Coalescence and Correlation analysis @@ -4049,7 +4049,7 @@ struct AntinucleiInJets { double deltaPhi = getDeltaPhi(jetGen.phi(), jetRec.phi()); double deltaR = std::sqrt(deltaEta * deltaEta + deltaPhi * deltaPhi); if (deltaR < rJet) - jetGenRec.emplace_back({deltaR, jetGen.pt(), jetGen.pt() - jetRec.pt()}); + jetGenRec.push_back({deltaR, jetGen.pt(), jetGen.pt() - jetRec.pt()}); } if (jetGenRec.empty()) continue;