@@ -258,6 +258,8 @@ struct nucleiInJets {
258258 using JetMCPartTable = soa::Filtered<soa::Join<aod::ChargedMCParticleLevelJets, aod::ChargedMCParticleLevelJetConstituents, aod::ChargedMCParticleLevelJetsMatchedToChargedMCDetectorLevelJets>>;
259259 using JetMCDetTable = soa::Filtered<soa::Join<aod::ChargedMCDetectorLevelJets, aod::ChargedMCDetectorLevelJetConstituents, aod::ChargedMCDetectorLevelJetsMatchedToChargedMCParticleLevelJets>>;
260260
261+ Preslice<soa::Join<aod::ChargedMCDetectorLevelJets, aod::ChargedMCDetectorLevelJetConstituents, aod::ChargedMCDetectorLevelJetsMatchedToChargedMCParticleLevelJets>> detectorJetsPerCollision = aod::jet::collisionId;
262+
261263 SliceCache cache;
262264 HistogramRegistry jetHist{" jetHist" , {}, OutputObjHandlingPolicy::AnalysisObject};
263265
@@ -817,15 +819,23 @@ struct nucleiInJets {
817819 jetHist.add <TH2 >(" eff/recmatched/mcCSpectra/gen/perpCone/pt/PtParticleType" , " Pt (gen, mcCSpectra, perp cone) vs particletype" , HistType::kTH2D , {{PtAxis}, {14 , -7 , 7 }});
818820
819821 jetHist.add <TH1 >(" jetSelCorr/genSel/hLeadingJetPt" , " particle-level leading jet selected for jet-selection correction; #it{p}_{T,lead}^{gen} (GeV/#it{c}); Entries" , HistType::kTH1F , {{100 , 0 ., 100 .}});
820- jetHist.add <TH1 >(" jetSelCorr/recoSel/hLeadingJetPtBkgSub" , " matched detector-level leading jet selected for jet-selection correction; #it{p}_{T,lead}^{reco,corr} (GeV/#it{c}); Entries" , HistType::kTH1F , {{120 , -20 ., 100 .}});
822+ jetHist.add <TH1 >(" jetSelCorr/recoSel/hLeadingJetPtBkgSub" , " detector-level leading jet selected for jet-selection correction; #it{p}_{T,lead}^{reco,corr} (GeV/#it{c}); Entries" , HistType::kTH1F , {{120 , -20 ., 100 .}});
821823 jetHist.add <TH2 >(" jetSelCorr/recoSel/hMatchedLeadingJetPt" , " selected matched leading jet; #it{p}_{T,lead}^{reco,corr} (GeV/#it{c}); #it{p}_{T,lead}^{gen} (GeV/#it{c})" , HistType::kTH2F , {{120 , -20 ., 100 .}, {100 , 0 ., 100 .}});
822824 jetHist.add <TH1 >(" jetSelCorr/eventNorm/hEventCounts" , " event count for leading-jet event-normalization correction; event selection; Entries" , HistType::kTH1D , {{2 , 0 ., 2 .}});
823825 jetHist.get <TH1 >(HIST (" jetSelCorr/eventNorm/hEventCounts" ))->GetXaxis ()->SetBinLabel (1 , " gen lead #it{p}_{T} > cut" );
824826 jetHist.get <TH1 >(HIST (" jetSelCorr/eventNorm/hEventCounts" ))->GetXaxis ()->SetBinLabel (2 , " reco lead #it{p}_{T}^{corr} > cut" );
827+ jetHist.add <TH1 >(" jetSelCorr/recoSel/hMatchStatus" , " selected detector leading-jet matching; status; reconstructed collisions" , HistType::kTH1D , {{3 , 0 ., 3 .}});
828+ jetHist.get <TH1 >(HIST (" jetSelCorr/recoSel/hMatchStatus" ))->GetXaxis ()->SetBinLabel (1 , " no truth match in MC collision" );
829+ jetHist.get <TH1 >(HIST (" jetSelCorr/recoSel/hMatchStatus" ))->GetXaxis ()->SetBinLabel (2 , " truth axis outside acceptance" );
830+ jetHist.get <TH1 >(HIST (" jetSelCorr/recoSel/hMatchStatus" ))->GetXaxis ()->SetBinLabel (3 , " accepted truth axis" );
831+ jetHist.add <TH1 >(" jetSelCorr/eventNorm/hSelectedRecoCollisions" , " selected reconstructed collisions per MC collision; selected reconstructed collisions; MC collisions" , HistType::kTH1D , {{11 , -0.5 , 10.5 }});
832+ jetHist.add <TH1 >(" jetSelCorr/matchedTruthAxis/hEventCount" , " selected reconstructed collisions with accepted matched truth axis; selection; reconstructed collisions" , HistType::kTH1D , {{1 , 0 ., 1 .}});
833+ jetHist.add <TH2 >(" jetSelCorr/matchedTruthAxis/jetCone/pt/PtParticleType" , " generated primaries around the matched truth axis; #it{p}_{T}^{gen} (GeV/#it{c}); particle type" , HistType::kTH2D , {{PtAxis}, {14 , -7 , 7 }});
834+ jetHist.add <TH2 >(" jetSelCorr/matchedTruthAxis/perpCone/pt/PtParticleType" , " generated primaries in perpendicular cones of the matched truth jet; #it{p}_{T}^{gen} (GeV/#it{c}); particle type" , HistType::kTH2D , {{PtAxis}, {14 , -7 , 7 }});
825835 jetHist.add <TH2 >(" jetSelCorr/genSel/jetCone/pt/PtParticleType" , " generated primaries in particle-level leading-jet cone; #it{p}_{T}^{gen} (GeV/#it{c}); particle type" , HistType::kTH2D , {{PtAxis}, {14 , -7 , 7 }});
826836 jetHist.add <TH2 >(" jetSelCorr/genSel/perpCone/pt/PtParticleType" , " generated primaries in particle-level perpendicular cone; #it{p}_{T}^{gen} (GeV/#it{c}); particle type" , HistType::kTH2D , {{PtAxis}, {14 , -7 , 7 }});
827- jetHist.add <TH2 >(" jetSelCorr/recoSel/jetCone/pt/PtParticleType" , " generated primaries in matched reco- selected leading-jet cone ; #it{p}_{T}^{gen} (GeV/#it{c}); particle type" , HistType::kTH2D , {{PtAxis}, {14 , -7 , 7 }});
828- jetHist.add <TH2 >(" jetSelCorr/recoSel/perpCone/pt/PtParticleType" , " generated primaries in matched reco- selected perpendicular cone ; #it{p}_{T}^{gen} (GeV/#it{c}); particle type" , HistType::kTH2D , {{PtAxis}, {14 , -7 , 7 }});
837+ jetHist.add <TH2 >(" jetSelCorr/recoSel/jetCone/pt/PtParticleType" , " generated primaries around the selected detector leading-jet axis ; #it{p}_{T}^{gen} (GeV/#it{c}); particle type" , HistType::kTH2D , {{PtAxis}, {14 , -7 , 7 }});
838+ jetHist.add <TH2 >(" jetSelCorr/recoSel/perpCone/pt/PtParticleType" , " generated primaries in perpendicular cones of the selected detector leading jet ; #it{p}_{T}^{gen} (GeV/#it{c}); particle type" , HistType::kTH2D , {{PtAxis}, {14 , -7 , 7 }});
829839
830840 jetHist.add <TH2 >(" feeddown/antiProton/jetCone/PtOrigin" , " reconstructed #bar{p} origin in jet cone; #it{p}_{T}^{rec} (GeV/#it{c}); origin" , HistType::kTH2D , {{PtAxis}, {ParticleOriginAxis}});
831841 jetHist.add <TH2 >(" feeddown/antiProton/jetCone/PtOriginTPC" , " reconstructed #bar{p} origin in jet cone, TPC PID; #it{p}_{T}^{rec} (GeV/#it{c}); origin" , HistType::kTH2D , {{PtAxis}, {ParticleOriginAxis}});
@@ -2406,7 +2416,7 @@ struct nucleiInJets {
24062416 return true ;
24072417 }
24082418
2409- template <bool RecoSelected, typename ParticlesType>
2419+ template <bool RecoSelected, bool MatchedTruthAxis = false , typename ParticlesType>
24102420 void fillJetSelectionCorrectionParticles (const ParticlesType& mcParticles, double jetEta, double jetPhi)
24112421 {
24122422 const auto perpConePhiJet = getPerpendicuarPhi (jetPhi);
@@ -2430,7 +2440,9 @@ struct nucleiInJets {
24302440 const double delPhi = TVector2::Phi_mpi_pi (jetPhi - mcParticle.phi ());
24312441 const double rJet = RecoDecay::sqrtSumOfSquares (delEta, delPhi);
24322442 if (rJet < cfgjetR) {
2433- if constexpr (RecoSelected) {
2443+ if constexpr (MatchedTruthAxis) {
2444+ jetHist.fill (HIST (" jetSelCorr/matchedTruthAxis/jetCone/pt/PtParticleType" ), mcParticle.pt (), particleType);
2445+ } else if constexpr (RecoSelected) {
24342446 jetHist.fill (HIST (" jetSelCorr/recoSel/jetCone/pt/PtParticleType" ), mcParticle.pt (), particleType);
24352447 } else {
24362448 jetHist.fill (HIST (" jetSelCorr/genSel/jetCone/pt/PtParticleType" ), mcParticle.pt (), particleType);
@@ -2442,7 +2454,9 @@ struct nucleiInJets {
24422454 const double rPerpCone1 = RecoDecay::sqrtSumOfSquares (delEta, delPhiPerpCone1);
24432455 const double rPerpCone2 = RecoDecay::sqrtSumOfSquares (delEta, delPhiPerpCone2);
24442456 if (rPerpCone1 < cfgjetR || rPerpCone2 < cfgjetR) {
2445- if constexpr (RecoSelected) {
2457+ if constexpr (MatchedTruthAxis) {
2458+ jetHist.fill (HIST (" jetSelCorr/matchedTruthAxis/perpCone/pt/PtParticleType" ), mcParticle.pt (), particleType);
2459+ } else if constexpr (RecoSelected) {
24462460 jetHist.fill (HIST (" jetSelCorr/recoSel/perpCone/pt/PtParticleType" ), mcParticle.pt (), particleType);
24472461 } else {
24482462 jetHist.fill (HIST (" jetSelCorr/genSel/perpCone/pt/PtParticleType" ), mcParticle.pt (), particleType);
@@ -2818,7 +2832,7 @@ struct nucleiInJets {
28182832 int nprocessSimJEEvents = 0 ;
28192833 void processJetSelectionCorrection (aod::JetMcCollision const & collision,
28202834 soa::SmallGroups<soa::Join<aod::JetCollisionsMCD, aod::BkgChargedRhos>> const & recocolls,
2821- JetMCDetTable const &, JetMCPartTable const & mcpjets, aod::JetParticles const & mcParticles)
2835+ JetMCDetTable const & mcdjets , JetMCPartTable const & mcpjets, aod::JetParticles const & mcParticles)
28222836 {
28232837 if (std::abs (collision.posZ ()) > cfgMaxZVertex) {
28242838 return ;
@@ -2847,61 +2861,80 @@ struct nucleiInJets {
28472861 fillJetSelectionCorrectionParticles<false >(mcParticles, genLeadingJetEta, genLeadingJetPhi);
28482862 }
28492863
2850- bool hasRecoSelectedLeadingJet = false ;
2851- double recoSelectedLeadingJetPt = -999 .;
2852- double recoSelectedMatchedGenJetPt = -999 .;
2853- double recoSelectedMatchedGenJetEta = -999 .;
2854- double recoSelectedMatchedGenJetPhi = -999 .;
2855-
2856- for (const auto & mcpjet : mcpjets) {
2857- if (!mcpjet.has_matchedJetGeo ()) {
2864+ // Count each reconstructed collision, as in data. The generated selection
2865+ // above is independent: neither branch requires the other to pass the cut.
2866+ int nSelectedRecoCollisions = 0 ;
2867+ const double jetArea = M_PI * cfgjetR * cfgjetR;
2868+ for (const auto & recocoll : recocolls) {
2869+ if (!isRecoCollisionSelectedForJetSelectionCorrection (recocoll)) {
28582870 continue ;
28592871 }
2860- if (! isConeAxisAccepted (mcpjet. eta () )) {
2872+ if (usebkgSubractionMC && !(recocoll. rho () > 0 . )) {
28612873 continue ;
28622874 }
2863- for (const auto & mcdjet : mcpjet.template matchedJetGeo_as <JetMCDetTable>()) {
2864- if (!isConeAxisAccepted (mcdjet.eta ())) {
2865- continue ;
2866- }
2867- double selectedRecoCollisionRho = -1 .;
2868- bool hasSelectedRecoCollision = false ;
2869- for (const auto & recocoll : recocolls) {
2870- if (mcdjet.collisionId () != recocoll.globalIndex ()) {
2871- continue ;
2872- }
2873- if (!isRecoCollisionSelectedForJetSelectionCorrection (recocoll)) {
2874- continue ;
2875- }
2876- selectedRecoCollisionRho = recocoll.rho ();
2877- hasSelectedRecoCollision = true ;
2878- break ;
2879- }
2880- if (!hasSelectedRecoCollision) {
2881- continue ;
2882- }
28832875
2884- const double jetArea = M_PI * cfgjetR * cfgjetR;
2885- const double mcdJetPtBkgSub = usebkgSubractionMC ? mcdjet.pt () - selectedRecoCollisionRho * jetArea : mcdjet.pt ();
2886- if (mcdJetPtBkgSub <= cfgjetPtBkgSubMinMC) {
2876+ const auto jetsInCollision = mcdjets.sliceBy (detectorJetsPerCollision, recocoll.globalIndex ());
2877+ auto leadingJet = jetsInCollision.begin ();
2878+ bool hasLeadingJet = false ;
2879+ double leadingJetPt = cfgjetPtBkgSubMinMC;
2880+ for (auto jet = jetsInCollision.begin (); jet != jetsInCollision.end (); ++jet) {
2881+ if (!isConeAxisAccepted (jet.eta ())) {
28872882 continue ;
28882883 }
2889- if (mcdJetPtBkgSub > recoSelectedLeadingJetPt) {
2890- hasRecoSelectedLeadingJet = true ;
2891- recoSelectedLeadingJetPt = mcdJetPtBkgSub;
2892- recoSelectedMatchedGenJetPt = mcpjet.pt ();
2893- recoSelectedMatchedGenJetEta = mcpjet.eta ();
2894- recoSelectedMatchedGenJetPhi = mcpjet.phi ();
2884+ const double correctedPt = usebkgSubractionMC ? jet.pt () - recocoll.rho () * jetArea : jet.pt ();
2885+ if (correctedPt > leadingJetPt) {
2886+ leadingJet = jet;
2887+ leadingJetPt = correctedPt;
2888+ hasLeadingJet = true ;
28952889 }
28962890 }
2897- }
2891+ if (!hasLeadingJet) {
2892+ continue ;
2893+ }
28982894
2899- if (hasRecoSelectedLeadingJet) {
2895+ ++nSelectedRecoCollisions;
29002896 jetHist.fill (HIST (" jetSelCorr/eventNorm/hEventCounts" ), 1.5 );
2901- jetHist.fill (HIST (" jetSelCorr/recoSel/hLeadingJetPtBkgSub" ), recoSelectedLeadingJetPt);
2902- jetHist.fill (HIST (" jetSelCorr/recoSel/hMatchedLeadingJetPt" ), recoSelectedLeadingJetPt, recoSelectedMatchedGenJetPt);
2903- fillJetSelectionCorrectionParticles<true >(mcParticles, recoSelectedMatchedGenJetEta, recoSelectedMatchedGenJetPhi);
2897+ jetHist.fill (HIST (" jetSelCorr/recoSel/hLeadingJetPtBkgSub" ), leadingJetPt);
2898+ // All selected detector jets, including unmatched jets, use detector axes
2899+ // Never substitute a matched subleading jet or mix truth and detector axes
2900+ fillJetSelectionCorrectionParticles<true >(mcParticles, leadingJet.eta (), leadingJet.phi ());
2901+
2902+ // Preserve a separate matched-truth-axis sample for efficiency comparisons
2903+ // Resolve multiple geometrical matches by the smallest angular distance
2904+ bool hasTruthMatch = false ;
2905+ double closestDistance = 1 .e9 ;
2906+ double truthPt = 0 .;
2907+ double truthEta = 0 .;
2908+ double truthPhi = 0 .;
2909+ if (leadingJet.has_matchedJetGeo ()) {
2910+ for (const auto & truthJet : leadingJet.template matchedJetGeo_as <JetMCPartTable>()) {
2911+ if (truthJet.mcCollisionId () != collision.globalIndex ()) {
2912+ continue ;
2913+ }
2914+ const double distance = RecoDecay::sqrtSumOfSquares (leadingJet.eta () - truthJet.eta (), TVector2::Phi_mpi_pi (leadingJet.phi () - truthJet.phi ()));
2915+ if (distance < closestDistance) {
2916+ closestDistance = distance;
2917+ hasTruthMatch = true ;
2918+ truthPt = truthJet.pt ();
2919+ truthEta = truthJet.eta ();
2920+ truthPhi = truthJet.phi ();
2921+ }
2922+ }
2923+ }
2924+ if (!hasTruthMatch) {
2925+ jetHist.fill (HIST (" jetSelCorr/recoSel/hMatchStatus" ), 0.5 );
2926+ continue ;
2927+ }
2928+ jetHist.fill (HIST (" jetSelCorr/recoSel/hMatchedLeadingJetPt" ), leadingJetPt, truthPt);
2929+ if (!isConeAxisAccepted (truthEta)) {
2930+ jetHist.fill (HIST (" jetSelCorr/recoSel/hMatchStatus" ), 1.5 );
2931+ continue ;
2932+ }
2933+ jetHist.fill (HIST (" jetSelCorr/recoSel/hMatchStatus" ), 2.5 );
2934+ jetHist.fill (HIST (" jetSelCorr/matchedTruthAxis/hEventCount" ), 0.5 );
2935+ fillJetSelectionCorrectionParticles<true , true >(mcParticles, truthEta, truthPhi);
29042936 }
2937+ jetHist.fill (HIST (" jetSelCorr/eventNorm/hSelectedRecoCollisions" ), nSelectedRecoCollisions);
29052938 }
29062939
29072940 void processGenMatched (aod::JetMcCollision const & collision,
0 commit comments