@@ -266,6 +266,9 @@ struct HfCorrelatorD0Hadrons {
266266 ConfigurableAxis binsPosZ{" binsPosZ" , {100 , -10 ., 10 .}, " primary vertex z coordinate" };
267267 ConfigurableAxis binsPoolBin{" binsPoolBin" , {9 , 0 ., 9 .}, " PoolBin" };
268268 ConfigurableAxis binsCentFt0m{" binsCentFt0m" , {100 , 0 ., 100 .}, " Centrality percentile (FT0M)" };
269+ ConfigurableAxis binsBdtScoreBkg{" binsBdtScoreBkg" , {500 , 0 ., 1 .}, " Bdt score background" };
270+ ConfigurableAxis binsBdtScorePrompt{" binsBdtScorePrompt" , {200 , 0 ., 1 .}, " Bdt score prompt" };
271+ ConfigurableAxis binsBdtScoreNonPrompt{" binsBdtScoreNonPrompt" , {200 , 0 ., 1 .}, " Bdt score non-prompt" };
269272
270273 HistogramRegistry registry{" registry" , {}, OutputObjHandlingPolicy::AnalysisObject};
271274
@@ -285,9 +288,9 @@ struct HfCorrelatorD0Hadrons {
285288 AxisSpec const axisSignalStatus = {200 , 0 ., 200 ., " Signal status" };
286289 AxisSpec axisEvtCount = {1 , -0.5 , 0.5 };
287290 AxisSpec const axisTrkCount = {5 , 0 ., 5 .};
288- AxisSpec axisBdtScoreBkg = {500 , 0 ., 1 . , " Bdt score background" };
289- AxisSpec axisBdtScorePrompt = {200 , 0 ., 1 . , " Bdt score prompt" };
290- AxisSpec axisBdtScoreNonPrompt = {200 , 0 ., 1 . , " Bdt score Nonprompt" };
291+ AxisSpec axisBdtScoreBkg = {binsBdtScoreBkg , " Bdt score background" };
292+ AxisSpec axisBdtScorePrompt = {binsBdtScorePrompt , " Bdt score prompt" };
293+ AxisSpec axisBdtScoreNonPrompt = {binsBdtScoreNonPrompt , " Bdt score Nonprompt" };
291294 AxisSpec axisOrigin = {10 , 0 ., 10 ., " Candidate origin" };
292295 AxisSpec axisCent = {binsCentFt0m, " Centrality" };
293296
@@ -322,9 +325,11 @@ struct HfCorrelatorD0Hadrons {
322325 registry.add (" hYRec" , " D0,D0bar candidates - MC reco" , {HistType::kTH1F , {axisRapidity}});
323326 registry.add (" hMassD0RecSig" , " D0 signal candidates massVsPt - MC reco" , {HistType::kTH2F , {{axisMassD}, {axisPtD}}});
324327 registry.add (" hMassD0RecRef" , " D0 reflection candidates massVsPt - MC reco" , {HistType::kTH2F , {{axisMassD}, {axisPtD}}});
328+ registry.add (" hMassD0RecRefAfterRejectBoth" , " D0 reflection candidates after rejecting D0 and D0bar candidates massVsPt - MC reco" , {HistType::kTH2F , {{axisMassD}, {axisPtD}}});
325329 registry.add (" hMassD0RecBg" , " D0 background candidates massVsPt - MC reco" , {HistType::kTH2F , {{axisMassD}, {axisPtD}}});
326330 registry.add (" hMassD0barRecSig" , " D0bar signal candidates massVsPt - MC reco" , {HistType::kTH2F , {{axisMassD}, {axisPtD}}});
327331 registry.add (" hMassD0barRecRef" , " D0bar reflection candidates massVsPt - MC reco" , {HistType::kTH2F , {{axisMassD}, {axisPtD}}});
332+ registry.add (" hMassD0barRecRefAfterRejectBoth" , " D0bar reflection candidates after rejecting D0 and D0bar candidates massVsPt - MC reco" , {HistType::kTH2F , {{axisMassD}, {axisPtD}}});
328333 registry.add (" hMassD0barRecBg" , " D0bar background candidates massVsPt - MC reco" , {HistType::kTH2F , {{axisMassD}, {axisPtD}}});
329334 registry.add (" hPtCandRecSigPrompt" , " D0,Hadron candidates Prompt - MC Reco" , {HistType::kTH1F , {axisPtD}});
330335 registry.add (" hPtVsMLScoresVsEtaRecSigPrompt" , " Prompt D0-D0bar signal candidates MLVsPtVsEta - MC reco" , {HistType::kTHnSparseD , {{axisBdtScoreBkg}, {axisBdtScorePrompt}, {axisBdtScoreNonPrompt}, {axisPtD}, {axisEta}}});
@@ -583,9 +588,15 @@ struct HfCorrelatorD0Hadrons {
583588 void processMcRec (SelectedCollisions::iterator const & collision,
584589 SelectedTracksMcRec const & tracks,
585590 SelectedCandidatesMcRecMl const & candidates,
586- aod::McParticles const & mcParticles)
591+ aod::McParticles const & mcParticles,
592+ aod::BCsWithTimestamps const &)
587593 {
588594 BinningType const corrBinning{{zPoolBins, multPoolBins}, true };
595+
596+ auto bc = collision.bc_as <aod::BCsWithTimestamps>();
597+ int gCollisionId = collision.globalIndex ();
598+ int64_t timeStamp = bc.timestamp ();
599+
589600 // find leading particle
590601 if (correlateD0WithLeadingParticle) {
591602 leadingIndex = findLeadingParticle (tracks, etaTrackMax.value );
@@ -625,6 +636,30 @@ struct HfCorrelatorD0Hadrons {
625636 std::vector<float > outputMlD0 = {-1 ., -1 ., -1 .};
626637 std::vector<float > outputMlD0bar = {-1 ., -1 ., -1 .};
627638
639+ std::vector<int64_t > softPionTrackIdsForOfflineMixing;
640+ std::vector<int > softPionStatusesForOfflineMixing;
641+ bool hasAcceptedD0ForOfflineMixing = false ;
642+
643+ auto addSoftPionTrackForOfflineMixing = [&softPionTrackIdsForOfflineMixing, &softPionStatusesForOfflineMixing](int64_t trackId, int softPiStatus) {
644+ for (auto iTrack = 0u ; iTrack < softPionTrackIdsForOfflineMixing.size (); ++iTrack) {
645+ if (softPionTrackIdsForOfflineMixing[iTrack] == trackId) {
646+ softPionStatusesForOfflineMixing[iTrack] |= softPiStatus;
647+ return ;
648+ }
649+ }
650+ softPionTrackIdsForOfflineMixing.push_back (trackId);
651+ softPionStatusesForOfflineMixing.push_back (softPiStatus);
652+ };
653+
654+ auto getSoftPionStatusForOfflineMixing = [&softPionTrackIdsForOfflineMixing, &softPionStatusesForOfflineMixing](int64_t trackId) {
655+ for (auto iTrack = 0u ; iTrack < softPionTrackIdsForOfflineMixing.size (); ++iTrack) {
656+ if (softPionTrackIdsForOfflineMixing[iTrack] == trackId) {
657+ return softPionStatusesForOfflineMixing[iTrack];
658+ }
659+ }
660+ return static_cast <int >(aod::hf_d0_assoc_tracks::NotSoftPi);
661+ };
662+
628663 for (const auto & candidate : candidates) {
629664 bool isD0Prompt = candidate.originMcRec () == RecoDecay::OriginType::Prompt;
630665 bool isD0NonPrompt = candidate.originMcRec () == RecoDecay::OriginType::NonPrompt;
@@ -646,6 +681,10 @@ struct HfCorrelatorD0Hadrons {
646681 const auto invMassD0 = HfHelper::invMassD0ToPiK (candidate);
647682 const auto invMassD0bar = HfHelper::invMassD0barToKPi (candidate);
648683
684+ if (candidate.isSelD0 () >= selectionFlagD0 || candidate.isSelD0bar () >= selectionFlagD0bar) {
685+ hasAcceptedD0ForOfflineMixing = true ;
686+ }
687+
649688 if (std::abs (candidate.flagMcMatchRec ()) == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) {
650689 // fill per-candidate distributions from D0/D0bar true candidates
651690 registry.fill (HIST (" hPtCandRec" ), candidate.pt ());
@@ -671,13 +710,17 @@ struct HfCorrelatorD0Hadrons {
671710 }
672711 } else if (candidate.flagMcMatchRec () == -o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) {
673712 registry.fill (HIST (" hMassD0RecRef" ), invMassD0, candidate.pt (), efficiencyWeight);
713+ if (candidate.isSelD0bar () < selectionFlagD0bar) {
714+ registry.fill (HIST (" hMassD0RecRefAfterRejectBoth" ), invMassD0, candidate.pt (), efficiencyWeight);
715+ }
674716 } else {
675717 registry.fill (HIST (" hMassD0RecBg" ), invMassD0, candidate.pt (), efficiencyWeight);
676718 }
677719 for (unsigned int iclass = 0 ; iclass < classMl->size (); iclass++) {
678720 outputMlD0[iclass] = candidate.mlProbD0 ()[classMl->at (iclass)];
679721 }
680722 registry.fill (HIST (" hMLScoresVsMassVsPtVsEtaVsOriginVsCent" ), outputMlD0[0 ], outputMlD0[1 ], outputMlD0[2 ], invMassD0, candidate.pt (), candidate.eta (), isD0Prompt, cent, efficiencyWeight);
723+ entryD0 (candidate.phi (), candidate.eta (), candidate.pt (), invMassD0, poolBin, gCollisionId , timeStamp, (candidate.isSelD0bar () != 0 ) ? o2::aod::hf_correlation_d0_hadron::D0D0barBoth : o2::aod::hf_correlation_d0_hadron::D0Only);
681724 }
682725 if (candidate.isSelD0bar () >= selectionFlagD0bar) { // only reco as D0bar
683726 if (candidate.flagMcMatchRec () == -o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { // also matched as D0bar
@@ -693,13 +736,17 @@ struct HfCorrelatorD0Hadrons {
693736 }
694737 } else if (candidate.flagMcMatchRec () == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) {
695738 registry.fill (HIST (" hMassD0barRecRef" ), invMassD0bar, candidate.pt (), efficiencyWeight);
739+ if (candidate.isSelD0 () < selectionFlagD0) {
740+ registry.fill (HIST (" hMassD0barRecRefAfterRejectBoth" ), invMassD0bar, candidate.pt (), efficiencyWeight);
741+ }
696742 } else {
697743 registry.fill (HIST (" hMassD0barRecBg" ), invMassD0bar, candidate.pt (), efficiencyWeight);
698744 }
699745 for (unsigned int iclass = 0 ; iclass < classMl->size (); iclass++) {
700746 outputMlD0bar[iclass] = candidate.mlProbD0bar ()[classMl->at (iclass)];
701747 }
702748 registry.fill (HIST (" hMLScoresVsMassVsPtVsEtaVsOriginVsCent" ), outputMlD0bar[0 ], outputMlD0bar[1 ], outputMlD0bar[2 ], invMassD0bar, candidate.pt (), candidate.eta (), isD0Prompt, cent, efficiencyWeight);
749+ entryD0 (candidate.phi (), candidate.eta (), candidate.pt (), invMassD0bar, poolBin, gCollisionId , timeStamp, (candidate.isSelD0 () != 0 ) ? o2::aod::hf_correlation_d0_hadron::D0D0barBoth : o2::aod::hf_correlation_d0_hadron::D0barOnly);
703750 }
704751 entryD0CandRecoInfo (invMassD0, invMassD0bar, candidate.pt (), outputMlD0[0 ], outputMlD0[2 ], outputMlD0bar[0 ], outputMlD0bar[2 ]);
705752 entryD0CandGenInfo (isD0Prompt);
@@ -740,12 +787,14 @@ struct HfCorrelatorD0Hadrons {
740787
741788 if (candidate.isSelD0 () >= selectionFlagD0) {
742789 if ((std::abs (invMassDstar1 - invMassD0) - softPiMass) < ptSoftPionMax) {
790+ addSoftPionTrackForOfflineMixing (track.globalIndex (), aod::hf_d0_assoc_tracks::SoftPiD0);
743791 continue ;
744792 }
745793 }
746794
747795 if (candidate.isSelD0bar () >= selectionFlagD0bar) {
748796 if ((std::abs (invMassDstar2 - invMassD0bar) - softPiMass) < ptSoftPionMax) {
797+ addSoftPionTrackForOfflineMixing (track.globalIndex (), aod::hf_d0_assoc_tracks::SoftPiD0bar);
749798 continue ;
750799 }
751800 }
@@ -806,6 +855,20 @@ struct HfCorrelatorD0Hadrons {
806855 entryTrackRecoInfo (track.dcaXY (), track.dcaZ (), track.tpcNClsCrossedRows ());
807856 } // end inner loop (Tracks)
808857 } // end of outer loop (D0)
858+
859+ // loop to save tables for offline event mixing
860+ if (hasAcceptedD0ForOfflineMixing) {
861+ for (const auto & track : tracks) {
862+ const auto softPiStatus = getSoftPionStatusForOfflineMixing (track.globalIndex ());
863+
864+ registry.fill (HIST (" hTracksBeforeSoftMix" ), track.pt ());
865+ if (softPiStatus == aod::hf_d0_assoc_tracks::NotSoftPi) {
866+ registry.fill (HIST (" hTracksAfterSoftMix" ), track.pt ());
867+ }
868+
869+ entryD0Hadron (track.phi (), track.eta (), track.pt (), poolBin, gCollisionId , timeStamp, softPiStatus);
870+ }
871+ }
809872 }
810873
811874 PROCESS_SWITCH (HfCorrelatorD0Hadrons, processMcRec, " Process MC Reco mode" , true );
@@ -817,6 +880,8 @@ struct HfCorrelatorD0Hadrons {
817880 {
818881 BinningTypeMcGen const corrBinningMcGen{{zPoolBins, multPoolBinsMcGen}, true };
819882 int poolBin = corrBinningMcGen.getBin (std::make_tuple (mcCollision.posZ (), mcCollision.multMCFT0A ()));
883+ int gCollisionId = mcCollision.globalIndex ();
884+ int64_t timeStamp = 0 ;
820885 registry.fill (HIST (" hCollisionPoolBin" ), poolBin);
821886 registry.fill (HIST (" hEvtCountGen" ), 0 );
822887 // MC gen level
@@ -828,6 +893,29 @@ struct HfCorrelatorD0Hadrons {
828893 bool isD0NonPrompt = false ;
829894 int trackOrigin = -1 ;
830895 float cent = 100 .; // Centrality Placeholder: will be updated later
896+ std::vector<int64_t > softPionTrackIdsForOfflineMixing;
897+ std::vector<int > softPionStatusesForOfflineMixing;
898+ bool hasAcceptedD0ForOfflineMixing = false ;
899+
900+ auto addSoftPionTrackForOfflineMixing = [&softPionTrackIdsForOfflineMixing, &softPionStatusesForOfflineMixing](int64_t trackId, int softPiStatus) {
901+ for (auto iTrack = 0u ; iTrack < softPionTrackIdsForOfflineMixing.size (); ++iTrack) {
902+ if (softPionTrackIdsForOfflineMixing[iTrack] == trackId) {
903+ softPionStatusesForOfflineMixing[iTrack] |= softPiStatus;
904+ return ;
905+ }
906+ }
907+ softPionTrackIdsForOfflineMixing.push_back (trackId);
908+ softPionStatusesForOfflineMixing.push_back (softPiStatus);
909+ };
910+
911+ auto getSoftPionStatusForOfflineMixing = [&softPionTrackIdsForOfflineMixing, &softPionStatusesForOfflineMixing](int64_t trackId) {
912+ for (auto iTrack = 0u ; iTrack < softPionTrackIdsForOfflineMixing.size (); ++iTrack) {
913+ if (softPionTrackIdsForOfflineMixing[iTrack] == trackId) {
914+ return softPionStatusesForOfflineMixing[iTrack];
915+ }
916+ }
917+ return static_cast <int >(aod::hf_d0_assoc_tracks::NotSoftPi);
918+ };
831919
832920 for (const auto & particleTrigg : mcParticles) {
833921 if (std::abs (particleTrigg.pdgCode ()) != Pdg::kD0 ) {
@@ -841,6 +929,7 @@ struct HfCorrelatorD0Hadrons {
841929 if (ptCandMin >= 0 . && particleTrigg.pt () < ptCandMin) {
842930 continue ;
843931 }
932+ hasAcceptedD0ForOfflineMixing = true ;
844933
845934 registry.fill (HIST (" hD0PoolBin" ), poolBin);
846935 registry.fill (HIST (" hPtCandGen" ), particleTrigg.pt ());
@@ -860,6 +949,7 @@ struct HfCorrelatorD0Hadrons {
860949 registry.fill (HIST (" hPtCandGenNonPrompt" ), particleTrigg.pt ());
861950 registry.fill (HIST (" hPtVsEtaCandGenSigNonPrompt" ), particleTrigg.pt (), particleTrigg.eta ());
862951 }
952+ entryD0 (particleTrigg.phi (), particleTrigg.eta (), particleTrigg.pt (), MassD0, poolBin, gCollisionId , timeStamp, (particleTrigg.pdgCode () == Pdg::kD0 ) ? o2::aod::hf_correlation_d0_hadron::D0Only : o2::aod::hf_correlation_d0_hadron::D0barOnly);
863953
864954 // =============== D-h correlation dedicated section =====================
865955 for (const auto & particleAssoc : mcParticles) {
@@ -884,6 +974,7 @@ struct HfCorrelatorD0Hadrons {
884974 auto indexMotherD0 = RecoDecay::getMother (mcParticles, particleTrigg, Pdg::kDStar , true , nullptr , 1 );
885975 bool correlationStatus = false ;
886976 if (std::abs (particleAssoc.pdgCode ()) == kPiPlus && indexMotherPi >= 0 && indexMotherD0 >= 0 && indexMotherPi == indexMotherD0) {
977+ addSoftPionTrackForOfflineMixing (particleAssoc.globalIndex (), (particleTrigg.pdgCode () == Pdg::kD0 ) ? aod::hf_d0_assoc_tracks::SoftPiD0 : aod::hf_d0_assoc_tracks::SoftPiD0bar);
887978 if (!storeAutoCorrelationFlag) {
888979 continue ;
889980 }
@@ -911,6 +1002,31 @@ struct HfCorrelatorD0Hadrons {
9111002 } // end inner loop (Tracks)
9121003 }
9131004 } // end outer loop (D0)
1005+
1006+ if (hasAcceptedD0ForOfflineMixing) {
1007+ for (const auto & particleAssoc : mcParticles) {
1008+ if (std::abs (particleAssoc.eta ()) > etaTrackMax) {
1009+ continue ;
1010+ }
1011+ if (particleAssoc.pt () < ptTrackMin) {
1012+ continue ;
1013+ }
1014+ if ((std::abs (particleAssoc.pdgCode ()) != kElectron ) && (std::abs (particleAssoc.pdgCode ()) != kMuonMinus ) && (std::abs (particleAssoc.pdgCode ()) != kPiPlus ) && (std::abs (particleAssoc.pdgCode ()) != kKPlus ) && (std::abs (particleAssoc.pdgCode ()) != kProton )) {
1015+ continue ;
1016+ }
1017+ if (!particleAssoc.isPhysicalPrimary ()) {
1018+ continue ;
1019+ }
1020+ const auto softPiStatus = getSoftPionStatusForOfflineMixing (particleAssoc.globalIndex ());
1021+
1022+ registry.fill (HIST (" hTracksBeforeSoftMix" ), particleAssoc.pt ());
1023+ if (softPiStatus == aod::hf_d0_assoc_tracks::NotSoftPi) {
1024+ registry.fill (HIST (" hTracksAfterSoftMix" ), particleAssoc.pt ());
1025+ }
1026+
1027+ entryD0Hadron (particleAssoc.phi (), particleAssoc.eta (), particleAssoc.pt (), poolBin, gCollisionId , timeStamp, softPiStatus);
1028+ }
1029+ }
9141030 }
9151031
9161032 PROCESS_SWITCH (HfCorrelatorD0Hadrons, processMcGen, " Process MC Gen mode" , false );
0 commit comments