Skip to content

Commit 918b42f

Browse files
authored
[PWGLF] Add function to compute jet pt resolution (#15268)
1 parent 476b9f5 commit 918b42f

File tree

1 file changed

+160
-0
lines changed

1 file changed

+160
-0
lines changed

PWGLF/Tasks/Nuspex/antinucleiInJets.cxx

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,13 @@ struct ReducedParticle {
128128
}
129129
};
130130

131+
// Jet Matching
132+
struct JetMatching {
133+
double distance;
134+
double ptTrue;
135+
double ptDiff;
136+
};
137+
131138
struct AntinucleiInJets {
132139

133140
// Histogram registries for data, MC, quality control, multiplicity and correlations
@@ -145,6 +152,7 @@ struct AntinucleiInJets {
145152
Configurable<double> cfgAreaFrac{"cfgAreaFrac", 0.6, "fraction of jet area"};
146153
Configurable<double> cfgEtaJetMax{"cfgEtaJetMax", 0.5, "max jet eta"};
147154
Configurable<double> cfgMinPtTrack{"cfgMinPtTrack", 0.15, "minimum pt of tracks for jet reconstruction"};
155+
Configurable<double> alpha{"alpha", 0.3, "parameter to control jet matching"};
148156

149157
// Event selection criteria
150158
Configurable<bool> rejectITSROFBorder{"rejectITSROFBorder", true, "Reject events near the ITS ROF border"};
@@ -501,6 +509,11 @@ struct AntinucleiInJets {
501509
registryMC.add("antiproton_coal_ue", "antiproton_coal_ue", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}});
502510
}
503511

512+
// jet pt resolution
513+
if (doprocessJetPtResolution) {
514+
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})"}});
515+
}
516+
504517
// Coalescence and Correlation analysis
505518
if (doprocessCoalescenceCorr) {
506519

@@ -3912,6 +3925,153 @@ struct AntinucleiInJets {
39123925
}
39133926
}
39143927
PROCESS_SWITCH(AntinucleiInJets, processCoalescenceCorr, "process coalescence correlation", false);
3928+
3929+
// Jet Pt resolution
3930+
void processJetPtResolution(RecCollisionsMc const& collisions, AntiNucleiTracksMc const& mcTracks, aod::McParticles const& mcParticles)
3931+
{
3932+
// Define per-event particle containers
3933+
std::vector<fastjet::PseudoJet> fjParticles;
3934+
std::vector<fastjet::PseudoJet> fjTracks;
3935+
3936+
// Jet and area definitions
3937+
fastjet::JetDefinition jetDef(fastjet::antikt_algorithm, rJet);
3938+
fastjet::AreaDefinition areaDef(fastjet::active_area, fastjet::GhostedAreaSpec(1.0));
3939+
3940+
// Loop over all reconstructed collisions
3941+
for (const auto& collision : collisions) {
3942+
3943+
// Clear containers at the start of the event loop
3944+
fjParticles.clear();
3945+
fjTracks.clear();
3946+
3947+
// Reject reconstructed collisions with no simulated collision
3948+
if (!collision.has_mcCollision())
3949+
continue;
3950+
3951+
// Apply event selection: require sel8 and vertex position to be within the allowed z range
3952+
if (!collision.sel8() || std::fabs(collision.posZ()) > zVtx)
3953+
continue;
3954+
3955+
// Reject events near the ITS Read-Out Frame border
3956+
if (rejectITSROFBorder && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder))
3957+
continue;
3958+
3959+
// Reject events at the Time Frame border
3960+
if (rejectTFBorder && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder))
3961+
continue;
3962+
3963+
// Require at least one ITS-TPC matched track
3964+
if (requireVtxITSTPC && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC))
3965+
continue;
3966+
3967+
// Reject events with same-bunch pileup
3968+
if (rejectSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup))
3969+
continue;
3970+
3971+
// Require consistent FT0 vs PV z-vertex
3972+
if (requireIsGoodZvtxFT0VsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV))
3973+
continue;
3974+
3975+
// Require TOF match for at least one vertex track
3976+
if (requireIsVertexTOFmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched))
3977+
continue;
3978+
3979+
// Get tracks and particles in this MC collision
3980+
const auto mcTracksThisMcColl = mcTracks.sliceBy(mcTracksPerMcCollision, collision.globalIndex());
3981+
const auto mcParticlesThisMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, collision.globalIndex());
3982+
3983+
// Loop over reconstructed tracks
3984+
for (auto const& track : mcTracksThisMcColl) {
3985+
3986+
// Apply track selection for jet reconstruction
3987+
if (!passedTrackSelectionForJetReconstruction(track))
3988+
continue;
3989+
3990+
// 4-momentum representation of a particle
3991+
fastjet::PseudoJet fourMomentum(track.px(), track.py(), track.pz(), track.energy(MassPionCharged));
3992+
fjTracks.emplace_back(fourMomentum);
3993+
}
3994+
3995+
// Loop over MC particles
3996+
for (const auto& particle : mcParticlesThisMcColl) {
3997+
3998+
// Select physical primary particles or HF decay products
3999+
if (!isPhysicalPrimaryOrFromHF(particle, mcParticles))
4000+
continue;
4001+
4002+
// Select particles within acceptance
4003+
if (particle.eta() < minEta || particle.eta() > maxEta || particle.pt() < cfgMinPtTrack)
4004+
continue;
4005+
4006+
// 4-momentum representation of a particle
4007+
double energy = std::sqrt(particle.p() * particle.p() + MassPionCharged * MassPionCharged);
4008+
fastjet::PseudoJet fourMomentum(particle.px(), particle.py(), particle.pz(), energy);
4009+
fjParticles.emplace_back(fourMomentum);
4010+
}
4011+
4012+
// Reject empty events
4013+
if (fjTracks.empty() || fjParticles.empty())
4014+
continue;
4015+
4016+
// Cluster particles using the anti-kt algorithm
4017+
fastjet::ClusterSequenceArea csRec(fjTracks, jetDef, areaDef);
4018+
std::vector<fastjet::PseudoJet> jetsRec = fastjet::sorted_by_pt(csRec.inclusive_jets());
4019+
4020+
fastjet::ClusterSequenceArea csGen(fjParticles, jetDef, areaDef);
4021+
std::vector<fastjet::PseudoJet> jetsGen = fastjet::sorted_by_pt(csGen.inclusive_jets());
4022+
4023+
// Loop over reconstructed jets
4024+
std::vector<JetMatching> jetGenRec;
4025+
for (const auto& jetRec : jetsRec) {
4026+
4027+
// Jet must be fully contained in the acceptance
4028+
if ((std::fabs(jetRec.eta()) + rJet) > (maxEta - deltaEtaEdge))
4029+
continue;
4030+
4031+
// Apply area cut if required
4032+
if (applyAreaCut && (jetRec.area() / (PI * rJet * rJet)) > maxNormalizedJetArea)
4033+
continue;
4034+
4035+
// Clear jet-pair container
4036+
jetGenRec.clear();
4037+
4038+
for (const auto& jetGen : jetsGen) {
4039+
4040+
// Jet must be fully contained in the acceptance
4041+
if ((std::fabs(jetGen.eta()) + rJet) > (maxEta - deltaEtaEdge))
4042+
continue;
4043+
4044+
// Apply area cut if required
4045+
if (applyAreaCut && (jetGen.area() / (PI * rJet * rJet)) > maxNormalizedJetArea)
4046+
continue;
4047+
4048+
double deltaEta = jetGen.eta() - jetRec.eta();
4049+
double deltaPhi = getDeltaPhi(jetGen.phi(), jetRec.phi());
4050+
double deltaR = std::sqrt(deltaEta * deltaEta + deltaPhi * deltaPhi);
4051+
if (deltaR < rJet)
4052+
jetGenRec.push_back({deltaR, jetGen.pt(), jetGen.pt() - jetRec.pt()});
4053+
}
4054+
if (jetGenRec.empty())
4055+
continue;
4056+
4057+
double distanceMin(1e+06);
4058+
double diffPt(0);
4059+
double ptJetTrue(0);
4060+
for (const auto& jetPair : jetGenRec) {
4061+
if (jetPair.distance < distanceMin) {
4062+
distanceMin = jetPair.distance;
4063+
diffPt = jetPair.ptDiff;
4064+
ptJetTrue = jetPair.ptTrue;
4065+
}
4066+
}
4067+
4068+
if (distanceMin < alpha * rJet) {
4069+
registryMC.fill(HIST("jetPtResolution"), ptJetTrue, diffPt);
4070+
}
4071+
}
4072+
}
4073+
}
4074+
PROCESS_SWITCH(AntinucleiInJets, processJetPtResolution, "process jet pt resolution", false);
39154075
};
39164076

39174077
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)

0 commit comments

Comments
 (0)