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