@@ -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,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
39174077WorkflowSpec defineDataProcessing (ConfigContext const & cfgc)
0 commit comments