From 67ba4eb9fb942c2c0d27d228071c0f90004bb415 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrea=20Tavira=20Garc=C3=ADa?= <118979672+atavirag@users.noreply.github.com> Date: Wed, 14 Oct 2026 13:32:52 +0000 Subject: [PATCH 01/15] Move kinematic selections to a separate function --- .../TableProducer/correlatorDMesonPairs.cxx | 182 +++++++----------- 1 file changed, 71 insertions(+), 111 deletions(-) diff --git a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx index 76c9767de64..77482a36524 100644 --- a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx @@ -157,6 +157,7 @@ struct HfCorrelatorDMesonPairs { Configurable massCut{"massCut", 0.05, "Maximum deviation from PDG peak allowed for signal region"}; Configurable removeAmbiguous{"removeAmbiguous", false, "Flag to remove ambiguous candidates"}; Configurable ptMaxRemoveAmbiguous{"ptMaxRemoveAmbiguous", 5.0, "Max. pT to remove the ambiguous candidates"}; + Configurable useD0SelectorMlInfo{"useD0SelectorMlInfo", false, "Flag for applying ML info in D0 selection"}; // Event mixing configurables Configurable applyMixedEvent{"applyMixedEvent", false, "Flag to make the event mixing"}; @@ -429,6 +430,28 @@ struct HfCorrelatorDMesonPairs { } } + + template + bool passKinematicSelections(const T& candidate, bool isDCand, bool isDbarCand) + { + if (std::abs(HfHelper::yD0(candidate)) > yCandMax) { + return false; + } + if (ptCandMin >= 0. && candidate.pt() < ptCandMin) { + return false; + } + bool const isSignalD0Cand = std::abs(HfHelper::invMassD0ToPiK(candidate) - MassD0) < massCut; + bool const isSignalD0barCand = std::abs(HfHelper::invMassD0barToKPi(candidate) - MassD0Bar) < massCut; + if (selectSignalRegionOnly && !(isSignalD0Cand || isSignalD0barCand)) { + return false; + } + // Remove ambiguous D0 candidates if flag is true + if (removeAmbiguous && (isDCand && isDbarCand) && candidate.pt() < ptMaxRemoveAmbiguous) { + return false; + } + return true; + } + /// Sets bits to select candidate type for D0 /// SelectedD and SelectedDbar bits look at whether the candidate passed the selection flags. /// \param candidate is candidate @@ -725,44 +748,32 @@ struct HfCorrelatorDMesonPairs { } auto selectedD0CandidatesGrouped = selectedD0Candidates->sliceByCached(aod::hf_cand::collisionId, gCollisionId, cache); getCountersPerEvent(selectedD0CandidatesGrouped); - // protection against empty tables to be sliced - if (selectedD0Candidates.size() <= 1) { - return; - } for (const auto& candidate1 : selectedD0CandidatesGrouped) { outputMlD0Cand1.clear(); outputMlD0barCand1.clear(); - if (std::abs(HfHelper::yD0(candidate1)) > yCandMax) { - continue; - } - if (ptCandMin >= 0. && candidate1.pt() < ptCandMin) { - continue; - } auto prong0Cand1 = candidate1.template prong0_as(); auto prong1Cand1 = candidate1.template prong1_as(); - bool const isSignalD0Cand1 = std::abs(HfHelper::invMassD0ToPiK(candidate1) - MassD0) < massCut; - bool const isSignalD0barCand1 = std::abs(HfHelper::invMassD0barToKPi(candidate1) - MassD0Bar) < massCut; - if (selectSignalRegionOnly && !(isSignalD0Cand1 || isSignalD0barCand1)) { - continue; - } - auto candidateType1 = assignCandidateTypeD0(candidate1); // Candidate type attribution bool const isDCand1 = isD(candidateType1); bool const isDbarCand1 = isDbar(candidateType1); + if (!passKinematicSelections(candidate1, isDCand1, isDbarCand1)) { + continue; + } + bool isSelectedMlD0Cand1 = false; bool isSelectedMlD0barCand1 = false; if (applyMl) { if (isDCand1) { - std::vector inputFeaturesD0 = hfMlResponse.getInputFeatures(candidate1, o2::constants::physics::kD0); + std::vector inputFeaturesD0 = hfMlResponse.getInputFeatures(candidate1, o2::constants::physics::kD0); isSelectedMlD0Cand1 = hfMlResponse.isSelectedMl(inputFeaturesD0, candidate1.pt(), outputMlD0Cand1); } if (isDbarCand1) { - std::vector inputFeaturesD0bar = hfMlResponse.getInputFeatures(candidate1, o2::constants::physics::kD0Bar); + std::vector inputFeaturesD0bar = hfMlResponse.getInputFeatures(candidate1, o2::constants::physics::kD0Bar); isSelectedMlD0barCand1 = hfMlResponse.isSelectedMl(inputFeaturesD0bar, candidate1.pt(), outputMlD0barCand1); } @@ -772,11 +783,6 @@ struct HfCorrelatorDMesonPairs { } } - // Remove ambiguous D0 candidates if flag is true - if (removeAmbiguous && (isDCand1 && isDbarCand1) && candidate1.pt() < ptMaxRemoveAmbiguous) { - continue; - } - registry.fill(HIST("hPtProng0"), candidate1.ptProng0()); registry.fill(HIST("hPtProng1"), candidate1.ptProng1()); registry.fill(HIST("hEta"), candidate1.eta()); @@ -855,38 +861,30 @@ struct HfCorrelatorDMesonPairs { outputMlD0Cand2.clear(); outputMlD0barCand2.clear(); - if (std::abs(HfHelper::yD0(candidate2)) > yCandMax) { - continue; - } - if (ptCandMin >= 0. && candidate2.pt() < ptCandMin) { - continue; - } auto prong0Cand2 = candidate2.template prong0_as(); auto prong1Cand2 = candidate2.template prong1_as(); if ((prong0Cand1 == prong0Cand2) || (prong1Cand1 == prong1Cand2) || (prong0Cand1 == prong1Cand2) || (prong1Cand1 == prong0Cand2)) { continue; } - bool const isSignalD0Cand2 = std::abs(HfHelper::invMassD0ToPiK(candidate2) - MassD0) < massCut; - bool const isSignalD0barCand2 = std::abs(HfHelper::invMassD0barToKPi(candidate2) - MassD0Bar) < massCut; - if (selectSignalRegionOnly && !(isSignalD0Cand2 || isSignalD0barCand2)) { - continue; - } auto candidateType2 = assignCandidateTypeD0(candidate2); // Candidate type attribution - bool const isDCand2 = isD(candidateType2); bool const isDbarCand2 = isDbar(candidateType2); + if (!passKinematicSelections(candidate2, isDCand2, isDbarCand2)) { + continue; + } + bool isSelectedMlD0Cand2 = false; bool isSelectedMlD0barCand2 = false; if (applyMl) { if (isDCand2) { - std::vector inputFeaturesD0 = hfMlResponse.getInputFeatures(candidate2, o2::constants::physics::kD0); + std::vector inputFeaturesD0 = hfMlResponse.getInputFeatures(candidate2, o2::constants::physics::kD0); isSelectedMlD0Cand2 = hfMlResponse.isSelectedMl(inputFeaturesD0, candidate2.pt(), outputMlD0Cand2); } if (isDbarCand2) { - std::vector inputFeaturesD0bar = hfMlResponse.getInputFeatures(candidate2, o2::constants::physics::kD0Bar); + std::vector inputFeaturesD0bar = hfMlResponse.getInputFeatures(candidate2, o2::constants::physics::kD0Bar); isSelectedMlD0barCand2 = hfMlResponse.isSelectedMl(inputFeaturesD0bar, candidate2.pt(), outputMlD0barCand2); } @@ -894,34 +892,25 @@ struct HfCorrelatorDMesonPairs { if (!isSelectedMlD0Cand2 && !isSelectedMlD0barCand2) { continue; } + } - // Remove ambiguous D0 candidates if flag is true - if (removeAmbiguous && (isDCand2 && isDbarCand2) && candidate2.pt() < ptMaxRemoveAmbiguous) { - continue; + if (applyMixedEvent) { + if (isDCand2) { + entryDMesonInfoCand2(candidate2.pt(), candidate2.eta(), candidate2.phi(), HfHelper::invMassD0barToKPi(candidate2), candidateType2, poolBin, gCollisionId, timeStamp); } - - if (applyMixedEvent) { - if (isDCand2) { - entryDMesonInfoCand2(candidate2.pt(), candidate2.eta(), candidate2.phi(), HfHelper::invMassD0barToKPi(candidate2), candidateType2, poolBin, gCollisionId, timeStamp); - } - if (isDbarCand2) { - entryDMesonInfoCand2(candidate2.pt(), candidate2.eta(), candidate2.phi(), HfHelper::invMassD0barToKPi(candidate2), candidateType2, poolBin, gCollisionId, timeStamp); - } - registry.fill(HIST("hD0Cand2Bin"), poolBin); + if (isDbarCand2) { + entryDMesonInfoCand2(candidate2.pt(), candidate2.eta(), candidate2.phi(), HfHelper::invMassD0barToKPi(candidate2), candidateType2, poolBin, gCollisionId, timeStamp); } + registry.fill(HIST("hD0Cand2Bin"), poolBin); + } - fillEntry(isDCand1, isDbarCand1, isDCand2, isDbarCand2, candidateType1, candidateType2, HfHelper::yD0(candidate1), HfHelper::yD0(candidate2), + // Fill entries for D0-D0(bar) pairs and plot histos + fillEntry(isDCand1, isDbarCand1, isDCand2, isDbarCand2, candidateType1, candidateType2, HfHelper::yD0(candidate1), HfHelper::yD0(candidate2), candidate1.eta(), candidate2.eta(), candidate1.phi(), candidate2.phi(), candidate1.pt(), candidate2.pt(), HfHelper::invMassD0ToPiK(candidate1), HfHelper::invMassD0barToKPi(candidate1), HfHelper::invMassD0ToPiK(candidate2), HfHelper::invMassD0barToKPi(candidate2)); - + if (applyMl) { entryD0PairMl(outputMlD0Cand1, outputMlD0barCand1, outputMlD0Cand2, outputMlD0barCand2); - } else { - // Fill entries - fillEntry(isDCand1, isDbarCand1, isDCand2, isDbarCand2, candidateType1, candidateType2, HfHelper::yD0(candidate1), HfHelper::yD0(candidate2), - candidate1.eta(), candidate2.eta(), candidate1.phi(), candidate2.phi(), - candidate1.pt(), candidate2.pt(), HfHelper::invMassD0ToPiK(candidate1), HfHelper::invMassD0barToKPi(candidate1), - HfHelper::invMassD0ToPiK(candidate2), HfHelper::invMassD0barToKPi(candidate2)); } } // end inner loop (Cand2) } // end outer loop (Cand1) @@ -955,17 +944,6 @@ struct HfCorrelatorDMesonPairs { auto prong0Cand1 = candidate1.template prong0_as(); auto prong1Cand1 = candidate1.template prong1_as(); - if (std::abs(HfHelper::yD0(candidate1)) > yCandMax) { - continue; - } - if (ptCandMin >= 0. && candidate1.pt() < ptCandMin) { - continue; - } - bool const isSignalD0Cand1 = std::abs(massD0Cand1 - MassD0) < massCut; - bool const isSignalD0barCand1 = std::abs(massD0barCand1 - MassD0Bar) < massCut; - if (selectSignalRegionOnly && !(isSignalD0Cand1 || isSignalD0barCand1)) { - continue; - } if (candidate1.isSelD0() < selectionFlagD0 && candidate1.isSelD0bar() < selectionFlagD0bar) { continue; } @@ -983,13 +961,17 @@ struct HfCorrelatorDMesonPairs { bool isSelectedMlD0Cand1 = false; bool isSelectedMlD0barCand1 = false; + if (!passKinematicSelections(candidate1, isDCand1, isDbarCand1)) { + continue; + } + if (applyMl) { if (isDCand1) { - std::vector inputFeaturesD0 = hfMlResponse.getInputFeatures(candidate1, o2::constants::physics::kD0); + std::vector inputFeaturesD0 = hfMlResponse.getInputFeatures(candidate1, o2::constants::physics::kD0); isSelectedMlD0Cand1 = hfMlResponse.isSelectedMl(inputFeaturesD0, candidate1.pt(), outputMlD0Cand1); } if (isDbarCand1) { - std::vector inputFeaturesD0bar = hfMlResponse.getInputFeatures(candidate1, o2::constants::physics::kD0Bar); + std::vector inputFeaturesD0bar = hfMlResponse.getInputFeatures(candidate1, o2::constants::physics::kD0Bar); isSelectedMlD0barCand1 = hfMlResponse.isSelectedMl(inputFeaturesD0bar, candidate1.pt(), outputMlD0barCand1); } // Remove non-ML selected D0 candidates @@ -998,11 +980,6 @@ struct HfCorrelatorDMesonPairs { } } - // Remove ambiguous D0 candidates if flag is true - if (removeAmbiguous && (isDCand1 && isDbarCand1) && candidate1.pt() < ptMaxRemoveAmbiguous) { - continue; - } - if (isTrueDCand1) { registry.fill(HIST("hStatusSinglePart"), 5); } else if (isTrueDbarCand1) { @@ -1071,17 +1048,6 @@ struct HfCorrelatorDMesonPairs { auto prong0Cand2 = candidate2.template prong0_as(); auto prong1Cand2 = candidate2.template prong1_as(); - if (std::abs(HfHelper::yD0(candidate2)) > yCandMax) { - continue; - } - if (ptCandMin >= 0. && candidate2.pt() < ptCandMin) { - continue; - } - bool const isSignalD0Cand2 = std::abs(massD0Cand2 - MassD0) < massCut; - bool const isSignalD0barCand2 = std::abs(massD0barCand2 - MassD0Bar) < massCut; - if (selectSignalRegionOnly && !(isSignalD0Cand2 || isSignalD0barCand2)) { - continue; - } if (candidate2.isSelD0() < selectionFlagD0 && candidate2.isSelD0bar() < selectionFlagD0bar) { continue; } @@ -1098,16 +1064,20 @@ struct HfCorrelatorDMesonPairs { int8_t matchedRec2 = candidate2.flagMcMatchRec(); int8_t originRec2 = candidate2.originMcRec(); + if (!passKinematicSelections(candidate2, isDCand2, isDbarCand2)) { + continue; + } + bool isSelectedMlD0Cand2 = false; bool isSelectedMlD0barCand2 = false; if (applyMl) { if (isDCand2) { - std::vector inputFeaturesD0 = hfMlResponse.getInputFeatures(candidate2, o2::constants::physics::kD0); + std::vector inputFeaturesD0 = hfMlResponse.getInputFeatures(candidate2, o2::constants::physics::kD0); isSelectedMlD0Cand2 = hfMlResponse.isSelectedMl(inputFeaturesD0, candidate2.pt(), outputMlD0Cand2); } if (isDbarCand2) { - std::vector inputFeaturesD0bar = hfMlResponse.getInputFeatures(candidate2, o2::constants::physics::kD0Bar); + std::vector inputFeaturesD0bar = hfMlResponse.getInputFeatures(candidate2, o2::constants::physics::kD0Bar); isSelectedMlD0barCand2 = hfMlResponse.isSelectedMl(inputFeaturesD0bar, candidate2.pt(), outputMlD0barCand2); } @@ -1115,25 +1085,15 @@ struct HfCorrelatorDMesonPairs { if (!isSelectedMlD0Cand2 && !isSelectedMlD0barCand2) { continue; } + } - // Remove ambiguous D0 candidates if flag is true - if (removeAmbiguous && (isDCand2 && isDbarCand2) && candidate2.pt() < ptMaxRemoveAmbiguous) { - continue; - } - - // Fill tables - fillEntry(isDCand1, isDbarCand1, isDCand2, isDbarCand2, candidateType1, candidateType2, yCandidate1, yCandidate2, etaCandidate1, etaCandidate2, phiCandidate1, phiCandidate2, - ptCandidate1, ptCandidate2, massD0Cand1, massD0barCand1, massD0Cand2, massD0barCand2); - fillMcHistos(matchedRec1, matchedRec2, static_cast(isTrueDCand1), static_cast(isTrueDbarCand1), static_cast(isTrueDCand2), static_cast(isTrueDbarCand2)); - entryD0PairMcInfo(originRec1, originRec2, matchedRec1, matchedRec2); + // Fill entries for D0-D0(bar) pairs and plot histos + fillEntry(isDCand1, isDbarCand1, isDCand2, isDbarCand2, candidateType1, candidateType2, yCandidate1, yCandidate2, etaCandidate1, etaCandidate2, phiCandidate1, phiCandidate2, + ptCandidate1, ptCandidate2, massD0Cand1, massD0barCand1, massD0Cand2, massD0barCand2); + fillMcHistos(matchedRec1, matchedRec2, static_cast(isTrueDCand1), static_cast(isTrueDbarCand1), static_cast(isTrueDCand2), static_cast(isTrueDbarCand2)); + entryD0PairMcInfo(originRec1, originRec2, matchedRec1, matchedRec2); + if (applyMl) { entryD0PairMl(outputMlD0Cand1, outputMlD0barCand1, outputMlD0Cand2, outputMlD0barCand2); - - } else { - // Fill tables - fillEntry(isDCand1, isDbarCand1, isDCand2, isDbarCand2, candidateType1, candidateType2, yCandidate1, yCandidate2, etaCandidate1, etaCandidate2, phiCandidate1, phiCandidate2, - ptCandidate1, ptCandidate2, massD0Cand1, massD0barCand1, massD0Cand2, massD0barCand2); - fillMcHistos(matchedRec1, matchedRec2, static_cast(isTrueDCand1), static_cast(isTrueDbarCand1), static_cast(isTrueDCand2), static_cast(isTrueDbarCand2)); - entryD0PairMcInfo(originRec1, originRec2, matchedRec1, matchedRec2); } } // end inner loop (Cand2) } // end outer loop (Cand1) @@ -1154,8 +1114,8 @@ struct HfCorrelatorDMesonPairs { // Get counters per event int nDevent = 0, nDbarevent = 0, nDDbarevent = 0, nDorDbarevent = 0; for (const auto& particle : mcParticles) { - // check if the particle is D0 or D0bar - if (std::abs(particle.pdgCode()) != Pdg::kD0) { + // check if the particle is D0 or D0bar decaying to k pi + if (!(std::abs(particle.flagMcMatchGen()) == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK)) { continue; } if (std::abs(particle.y()) > yCandMax) { @@ -1194,8 +1154,8 @@ struct HfCorrelatorDMesonPairs { } for (const auto& particle1 : mcParticles) { - // check if the particle is D0 or D0bar - if (std::abs(particle1.pdgCode()) != Pdg::kD0) { + // check if the particle is D0 or D0bar decaying to k pi + if (!(std::abs(particle1.flagMcMatchGen()) == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK)) { continue; } registry.fill(HIST("hPtCandMcGen"), particle1.pt()); @@ -1241,8 +1201,8 @@ struct HfCorrelatorDMesonPairs { registry.fill(HIST("hNContribMcGen"), numPvContributorsGen); for (auto particle2 = particle1 + 1; particle2 != mcParticles.end(); ++particle2) { - // check if the particle is D0 or D0bar - if (std::abs(particle2.pdgCode()) != Pdg::kD0) { + // check if the particle is D0 or D0bar decaying to k pi + if (!(std::abs(particle2.flagMcMatchGen()) == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK)) { continue; } if (std::abs(particle2.y()) > yCandMax) { From 78363f4a8a06019ba0e1ea61139d0f9b1b8176e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrea=20Tavira=20Garc=C3=ADa?= <118979672+atavirag@users.noreply.github.com> Date: Wed, 14 Oct 2026 13:40:15 +0000 Subject: [PATCH 02/15] unify flagD0(bar) selections for MC and data partitions --- PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx index 77482a36524..040305ca33d 100644 --- a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx @@ -189,7 +189,7 @@ struct HfCorrelatorDMesonPairs { SliceCache cache; using SelCollisionsWithD0 = soa::Filtered>; - using CandidatesD0Data = soa::Join; + using CandidatesD0Data = soa::Join; using FilteredD0Candidates = soa::Filtered; using TracksData = soa::Filtered>; // trackFilter applied @@ -213,8 +213,8 @@ struct HfCorrelatorDMesonPairs { // using TracksWPid = soa::Join; - Partition> selectedD0Candidates = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; - Partition> selectedD0CandidatesMc = aod::hf_sel_candidate_d0::isRecoHfFlag >= selectionFlagHf; + Partition> selectedD0Candidates = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; + Partition> selectedD0CandidatesMc = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; // ThnSparse for ML outputScores and Vars ConfigurableAxis thnConfigAxisBkgScore{"thnConfigAxisBkgScore", {100, 0, 1}, "Bkg score bins"}; @@ -923,7 +923,7 @@ struct HfCorrelatorDMesonPairs { PROCESS_SWITCH(HfCorrelatorDMesonPairs, processData, "Process data mode", true); - void processMcRec(aod::Collision const& collision, soa::Join const& candidates, aod::Tracks const&) + void processMcRec(aod::Collision const& collision, soa::Join const& candidates, aod::Tracks const&) { for (const auto& candidate : candidates) { analysePid(candidate); @@ -944,10 +944,6 @@ struct HfCorrelatorDMesonPairs { auto prong0Cand1 = candidate1.template prong0_as(); auto prong1Cand1 = candidate1.template prong1_as(); - if (candidate1.isSelD0() < selectionFlagD0 && candidate1.isSelD0bar() < selectionFlagD0bar) { - continue; - } - auto candidateType1 = assignCandidateTypeD0(candidate1); // Candidate type attribution bool const isDCand1 = isD(candidateType1); @@ -1048,9 +1044,6 @@ struct HfCorrelatorDMesonPairs { auto prong0Cand2 = candidate2.template prong0_as(); auto prong1Cand2 = candidate2.template prong1_as(); - if (candidate2.isSelD0() < selectionFlagD0 && candidate2.isSelD0bar() < selectionFlagD0bar) { - continue; - } if ((prong0Cand1 == prong0Cand2) || (prong1Cand1 == prong1Cand2) || (prong0Cand1 == prong1Cand2) || (prong1Cand1 == prong0Cand2)) { continue; } From 91240e7533dc1f9af6fce0510eda513c8cda0d8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrea=20Tavira=20Garc=C3=ADa?= <118979672+atavirag@users.noreply.github.com> Date: Wed, 14 Oct 2026 15:07:35 +0000 Subject: [PATCH 03/15] Remove candidate groups (grouping should be done by default with selCollisionsWithD0) --- .../TableProducer/correlatorDMesonPairs.cxx | 41 +++++++------------ 1 file changed, 14 insertions(+), 27 deletions(-) diff --git a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx index 040305ca33d..b13c1b224a2 100644 --- a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx @@ -149,7 +149,6 @@ struct HfCorrelatorDMesonPairs { Configurable selectionFlagD0{"selectionFlagD0", 1, "Selection Flag for D0"}; Configurable selectionFlagD0bar{"selectionFlagD0bar", 1, "Selection Flag for D0bar"}; - Configurable selectionFlagHf{"selectionFlagHf", 1, "Selection Flag for HF flagged candidates"}; Configurable yCandMax{"yCandMax", 0.8, "maximum |y| of D0 candidates"}; Configurable ptCandMin{"ptCandMin", -1., "minimum pT of D0 candidates"}; Configurable> binsPt{"binsPt", std::vector{o2::analysis::hf_cuts_d0_to_pi_k::vecBinsPt}, "pT bin limits for candidate mass plots"}; @@ -186,10 +185,9 @@ struct HfCorrelatorDMesonPairs { Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB"}; Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; - SliceCache cache; - using SelCollisionsWithD0 = soa::Filtered>; using CandidatesD0Data = soa::Join; + using CandidatesD0McRec = soa::Join; using FilteredD0Candidates = soa::Filtered; using TracksData = soa::Filtered>; // trackFilter applied @@ -213,9 +211,6 @@ struct HfCorrelatorDMesonPairs { // using TracksWPid = soa::Join; - Partition> selectedD0Candidates = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; - Partition> selectedD0CandidatesMc = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; - // ThnSparse for ML outputScores and Vars ConfigurableAxis thnConfigAxisBkgScore{"thnConfigAxisBkgScore", {100, 0, 1}, "Bkg score bins"}; ConfigurableAxis thnConfigAxisSignalScore{"thnConfigAxisSignalScore", {100, 0, 1}, "Signal score bins"}; @@ -556,22 +551,14 @@ struct HfCorrelatorDMesonPairs { int nDevent = 0, nDbarevent = 0, nDDbarevent = 0, nDorDbarevent = 0; for (const auto& candidate : d0Candidates) { // Get counters per event - bool const isSignalD0 = std::abs(HfHelper::invMassD0ToPiK(candidate) - MassD0) < massCut; - bool const isSignalD0bar = std::abs(HfHelper::invMassD0barToKPi(candidate) - MassD0Bar) < massCut; - if (selectSignalRegionOnly && !(isSignalD0 || isSignalD0bar)) { - continue; - } auto candidateType1 = assignCandidateTypeD0(candidate); // Candidate type attribution - registry.fill(HIST("hPtCand"), candidate.pt()); - if (std::abs(HfHelper::yD0(candidate)) > yCandMax) { - continue; - } - if (ptCandMin >= 0. && candidate.pt() < ptCandMin) { + bool const isDCand1 = isD(candidateType1); + bool const isDbarCand1 = isDbar(candidateType1); + + if (!passKinematicSelections(candidate, isDCand1, isDbarCand1)) { continue; } - bool const isDCand1 = isD(candidateType1); - bool const isDbarCand1 = isDbar(candidateType1); if (isDCand1) { nDevent++; } @@ -746,9 +733,9 @@ struct HfCorrelatorDMesonPairs { for (const auto& candidate : candidates) { analysePid(candidate); } - auto selectedD0CandidatesGrouped = selectedD0Candidates->sliceByCached(aod::hf_cand::collisionId, gCollisionId, cache); - getCountersPerEvent(selectedD0CandidatesGrouped); - for (const auto& candidate1 : selectedD0CandidatesGrouped) { + + getCountersPerEvent(candidates); + for (const auto& candidate1 : candidates) { outputMlD0Cand1.clear(); outputMlD0barCand1.clear(); @@ -856,7 +843,7 @@ struct HfCorrelatorDMesonPairs { } // Loop on the second D0 candidate - for (auto candidate2 = candidate1 + 1; candidate2 != selectedD0CandidatesGrouped.end(); ++candidate2) { + for (auto candidate2 = candidate1 + 1; candidate2 != candidates.end(); ++candidate2) { outputMlD0Cand2.clear(); outputMlD0barCand2.clear(); @@ -923,14 +910,14 @@ struct HfCorrelatorDMesonPairs { PROCESS_SWITCH(HfCorrelatorDMesonPairs, processData, "Process data mode", true); - void processMcRec(aod::Collision const& collision, soa::Join const& candidates, aod::Tracks const&) + void processMcRec(SelCollisionsWithD0::iterator const& collision, CandidatesD0McRec const& candidates, aod::Tracks const&) { for (const auto& candidate : candidates) { analysePid(candidate); } - auto selectedD0CandidatesGroupedMc = selectedD0CandidatesMc->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); - getCountersPerEvent(selectedD0CandidatesGroupedMc); - for (const auto& candidate1 : selectedD0CandidatesGroupedMc) { + + getCountersPerEvent(candidates); + for (const auto& candidate1 : candidates) { outputMlD0Cand1.clear(); outputMlD0barCand1.clear(); @@ -1030,7 +1017,7 @@ struct HfCorrelatorDMesonPairs { } } - for (auto candidate2 = candidate1 + 1; candidate2 != selectedD0CandidatesGroupedMc.end(); ++candidate2) { + for (auto candidate2 = candidate1 + 1; candidate2 != candidates.end(); ++candidate2) { outputMlD0Cand2.clear(); outputMlD0barCand2.clear(); From dd550311e91addd9a3a886ae6136bfd4b03bae8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrea=20Tavira=20Garc=C3=ADa?= <118979672+atavirag@users.noreply.github.com> Date: Wed, 14 Oct 2026 15:22:23 +0000 Subject: [PATCH 04/15] Move analysePid to the main loop --- PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx index b13c1b224a2..0983101cac0 100644 --- a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx @@ -730,12 +730,9 @@ struct HfCorrelatorDMesonPairs { int cntD0 = 0; - for (const auto& candidate : candidates) { - analysePid(candidate); - } - getCountersPerEvent(candidates); for (const auto& candidate1 : candidates) { + analysePid(candidate1); outputMlD0Cand1.clear(); outputMlD0barCand1.clear(); @@ -912,12 +909,10 @@ struct HfCorrelatorDMesonPairs { void processMcRec(SelCollisionsWithD0::iterator const& collision, CandidatesD0McRec const& candidates, aod::Tracks const&) { - for (const auto& candidate : candidates) { - analysePid(candidate); - } getCountersPerEvent(candidates); for (const auto& candidate1 : candidates) { + analysePid(candidate1); outputMlD0Cand1.clear(); outputMlD0barCand1.clear(); From b713bd8c1ae4eb2440d1eaea8c5353145a8e47be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrea=20Tavira=20Garc=C3=ADa?= <118979672+atavirag@users.noreply.github.com> Date: Wed, 14 Oct 2026 15:44:29 +0000 Subject: [PATCH 05/15] Reorganise functions to do one thing at a time - Removed fillEntry and fillEntryMc - New function: setPairType - New function: fillSelectionStatusHisto - New function: fillMatchingHisto - Restored selectionFlags (it didn't get the expected results) --- .../TableProducer/correlatorDMesonPairs.cxx | 128 ++++++++++-------- 1 file changed, 72 insertions(+), 56 deletions(-) diff --git a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx index 0983101cac0..f76396cc256 100644 --- a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx @@ -196,6 +196,8 @@ struct HfCorrelatorDMesonPairs { Filter d0Filter = (o2::aod::hf_track_index::hfflag & static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK))) != static_cast(0); Filter trackFilter = (nabs(aod::track::eta) < etaTrackMax) && (nabs(aod::track::pt) > ptTrackMin) && (nabs(aod::track::dcaXY) < dcaXYTrackMax) && (nabs(aod::track::dcaZ) < dcaZTrackMax); + SliceCache cache; + Preslice perCol2Prong = aod::hf_cand::collisionId; Preslice candsD0PerCollision = aod::hf_cand::collisionId; Preslice trackIndicesPerCollision = aod::track::collisionId; @@ -210,6 +212,8 @@ struct HfCorrelatorDMesonPairs { std::vector outputMlD0barCand2; // using TracksWPid = soa::Join; + Partition> selectedD0Candidates = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; + Partition> selectedD0CandidatesMc = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; // ThnSparse for ML outputScores and Vars ConfigurableAxis thnConfigAxisBkgScore{"thnConfigAxisBkgScore", {100, 0, 1}, "Bkg score bins"}; @@ -596,11 +600,12 @@ struct HfCorrelatorDMesonPairs { } } - /// Fill selection status histogram - void fillEntry(const bool& isDCand1, const bool& isDbarCand1, const bool& isDCand2, const bool& isDbarCand2, - const uint8_t candidateType1, const uint8_t candidateType2, float yCand1, float yCand2, float etaCand1, float etaCand2, float phiCand1, float phiCand2, - double ptCand1, double ptCand2, float massDCand1, float massDbarCand1, float massDCand2, float massDbarCand2) + void fillSelectionStatusHisto(const uint8_t candidateType1, const uint8_t candidateType2) { + bool const isDCand1 = isD(candidateType1), isDCand2 = isD(candidateType2); + bool const isDbarCand1 = isDbar(candidateType1), isDbarCand2 = isDbar(candidateType2); + bool const isTrueDCand1 = isTrueD(candidateType1), isTrueDCand2 = isTrueD(candidateType2); + bool const isTrueDbarCand1 = isTrueDbar(candidateType1), isTrueDbarCand2 = isTrueDbar(candidateType2); /// Fill information on the D candidates registry.fill(HIST("hSelectionStatus"), 2); @@ -622,41 +627,75 @@ struct HfCorrelatorDMesonPairs { } /// Collect information on the D pairs - uint8_t pairType(0); registry.fill(HIST("hSelectionStatus"), 1); if (isDCand1 && isDCand2) { - SETBIT(pairType, DD); registry.fill(HIST("hSelectionStatus"), 14); if ((!isDbarCand1) && (!isDbarCand2)) { registry.fill(HIST("hSelectionStatus"), 18); } } if (isDbarCand1 && isDbarCand2) { - SETBIT(pairType, DbarDbar); registry.fill(HIST("hSelectionStatus"), 15); if ((!isDCand1) && (!isDCand2)) { registry.fill(HIST("hSelectionStatus"), 19); } } if (isDCand1 && isDbarCand2) { - SETBIT(pairType, DDbar); registry.fill(HIST("hSelectionStatus"), 16); if ((!isDbarCand1) && (!isDCand2)) { registry.fill(HIST("hSelectionStatus"), 20); } } if (isDbarCand1 && isDCand2) { - SETBIT(pairType, DbarD); registry.fill(HIST("hSelectionStatus"), 17); if ((!isDCand1) && (!isDbarCand2)) { registry.fill(HIST("hSelectionStatus"), 21); } } + // Fill True info + if (isTrueDCand1 != 0) { + registry.fill(HIST("hSelectionStatus"), 6); + } else if (isTrueDbarCand1 != 0) { + registry.fill(HIST("hSelectionStatus"), 7); + } + if (isTrueDCand2 != 0) { + registry.fill(HIST("hSelectionStatus"), 12); + } else if (isTrueDbarCand2 != 0) { + registry.fill(HIST("hSelectionStatus"), 13); + } + if ((isTrueDCand1 != 0) && (isTrueDCand2 != 0)) { + registry.fill(HIST("hSelectionStatus"), 22); + } else if ((isTrueDbarCand1 != 0) && (isTrueDbarCand2 != 0)) { + registry.fill(HIST("hSelectionStatus"), 23); + } else if ((isTrueDCand1 != 0) && (isTrueDbarCand2 != 0)) { + registry.fill(HIST("hSelectionStatus"), 24); + } else if ((isTrueDbarCand1 != 0) && (isTrueDCand2 != 0)) { + registry.fill(HIST("hSelectionStatus"), 25); + } + } + + uint8_t setPairType(const uint8_t candidateType1, const uint8_t candidateType2) + { + uint8_t pairType(0); + bool const isDCand1 = isD(candidateType1), isDCand2 = isD(candidateType2); + bool const isDbarCand1 = isDbar(candidateType1), isDbarCand2 = isDbar(candidateType2); - entryD0Pair(ptCand1, ptCand2, yCand1, yCand2, etaCand1, etaCand2, phiCand1, phiCand2, massDCand1, massDbarCand1, massDCand2, massDbarCand2, pairType, candidateType1, candidateType2); + if (isDCand1 && isDCand2) { + SETBIT(pairType, DD); + } + if (isDbarCand1 && isDbarCand2) { + SETBIT(pairType, DbarDbar); + } + if (isDCand1 && isDbarCand2) { + SETBIT(pairType, DDbar); + } + if (isDbarCand1 && isDCand2) { + SETBIT(pairType, DbarD); + } + return pairType; } - void fillMcHistos(int8_t matchedRec1, int8_t matchedRec2, int8_t isTrueDCand1, int8_t isTrueDbarCand1, int8_t isTrueDCand2, int8_t isTrueDbarCand2) + void fillMatchingHisto(int8_t matchedRec1, int8_t matchedRec2) { // Fill hMatchingMcRec - Cand 1 registry.fill(HIST("hMatchingMcRec"), 1); @@ -676,26 +715,6 @@ struct HfCorrelatorDMesonPairs { } else if (matchedRec2 == 0) { registry.fill(HIST("hMatchingMcRec"), 8); } - // Fill True info - if (isTrueDCand1 != 0) { - registry.fill(HIST("hSelectionStatus"), 6); - } else if (isTrueDbarCand1 != 0) { - registry.fill(HIST("hSelectionStatus"), 7); - } - if (isTrueDCand2 != 0) { - registry.fill(HIST("hSelectionStatus"), 12); - } else if (isTrueDbarCand2 != 0) { - registry.fill(HIST("hSelectionStatus"), 13); - } - if ((isTrueDCand1 != 0) && (isTrueDCand2 != 0)) { - registry.fill(HIST("hSelectionStatus"), 22); - } else if ((isTrueDbarCand1 != 0) && (isTrueDbarCand2 != 0)) { - registry.fill(HIST("hSelectionStatus"), 23); - } else if ((isTrueDCand1 != 0) && (isTrueDbarCand2 != 0)) { - registry.fill(HIST("hSelectionStatus"), 24); - } else if ((isTrueDbarCand1 != 0) && (isTrueDCand2 != 0)) { - registry.fill(HIST("hSelectionStatus"), 25); - } } /// D0(bar)-D0(bar) correlation pair builder - for real data and data-like analysis (i.e. reco-level w/o matching request via MC truth) @@ -731,7 +750,10 @@ struct HfCorrelatorDMesonPairs { int cntD0 = 0; getCountersPerEvent(candidates); - for (const auto& candidate1 : candidates) { + + auto selectedD0CandidatesGrouped = selectedD0Candidates->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); + + for (const auto& candidate1 : selectedD0CandidatesGrouped) { analysePid(candidate1); outputMlD0Cand1.clear(); @@ -840,7 +862,7 @@ struct HfCorrelatorDMesonPairs { } // Loop on the second D0 candidate - for (auto candidate2 = candidate1 + 1; candidate2 != candidates.end(); ++candidate2) { + for (auto candidate2 = candidate1 + 1; candidate2 != selectedD0CandidatesGrouped.end(); ++candidate2) { outputMlD0Cand2.clear(); outputMlD0barCand2.clear(); @@ -888,11 +910,13 @@ struct HfCorrelatorDMesonPairs { registry.fill(HIST("hD0Cand2Bin"), poolBin); } + uint8_t pairType = setPairType(candidateType1, candidateType2); + // Fill entries for D0-D0(bar) pairs and plot histos - fillEntry(isDCand1, isDbarCand1, isDCand2, isDbarCand2, candidateType1, candidateType2, HfHelper::yD0(candidate1), HfHelper::yD0(candidate2), - candidate1.eta(), candidate2.eta(), candidate1.phi(), candidate2.phi(), - candidate1.pt(), candidate2.pt(), HfHelper::invMassD0ToPiK(candidate1), HfHelper::invMassD0barToKPi(candidate1), - HfHelper::invMassD0ToPiK(candidate2), HfHelper::invMassD0barToKPi(candidate2)); + fillSelectionStatusHisto(candidateType1, candidateType2); + entryD0Pair(candidate1.pt(), candidate2.pt(), HfHelper::yD0(candidate1), HfHelper::yD0(candidate2), candidate1.eta(), candidate2.eta(), + candidate1.phi(), candidate2.phi(), HfHelper::invMassD0ToPiK(candidate1), HfHelper::invMassD0barToKPi(candidate1), + HfHelper::invMassD0ToPiK(candidate2), HfHelper::invMassD0barToKPi(candidate2), pairType, candidateType1, candidateType2); if (applyMl) { entryD0PairMl(outputMlD0Cand1, outputMlD0barCand1, outputMlD0Cand2, outputMlD0barCand2); } @@ -911,18 +935,13 @@ struct HfCorrelatorDMesonPairs { { getCountersPerEvent(candidates); - for (const auto& candidate1 : candidates) { + auto selectedD0CandidatesGroupedMc = selectedD0CandidatesMc->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); + for (const auto& candidate1 : selectedD0CandidatesGroupedMc) { analysePid(candidate1); outputMlD0Cand1.clear(); outputMlD0barCand1.clear(); - auto ptCandidate1 = candidate1.pt(); - auto yCandidate1 = HfHelper::yD0(candidate1); - auto phiCandidate1 = candidate1.phi(); - auto etaCandidate1 = candidate1.eta(); - float const massD0Cand1 = HfHelper::invMassD0ToPiK(candidate1); - float const massD0barCand1 = HfHelper::invMassD0barToKPi(candidate1); auto prong0Cand1 = candidate1.template prong0_as(); auto prong1Cand1 = candidate1.template prong1_as(); @@ -1012,17 +1031,11 @@ struct HfCorrelatorDMesonPairs { } } - for (auto candidate2 = candidate1 + 1; candidate2 != candidates.end(); ++candidate2) { + for (auto candidate2 = candidate1 + 1; candidate2 != selectedD0CandidatesGroupedMc.end(); ++candidate2) { outputMlD0Cand2.clear(); outputMlD0barCand2.clear(); - auto ptCandidate2 = candidate2.pt(); - auto yCandidate2 = HfHelper::yD0(candidate2); - auto phiCandidate2 = candidate2.phi(); - auto etaCandidate2 = candidate2.eta(); - float const massD0Cand2 = HfHelper::invMassD0ToPiK(candidate2); - float const massD0barCand2 = HfHelper::invMassD0barToKPi(candidate2); auto prong0Cand2 = candidate2.template prong0_as(); auto prong1Cand2 = candidate2.template prong1_as(); @@ -1033,8 +1046,6 @@ struct HfCorrelatorDMesonPairs { bool const isDCand2 = isD(candidateType2); bool const isDbarCand2 = isDbar(candidateType2); - bool const isTrueDCand2 = isTrueD(candidateType2); - bool const isTrueDbarCand2 = isTrueDbar(candidateType2); int8_t matchedRec2 = candidate2.flagMcMatchRec(); int8_t originRec2 = candidate2.originMcRec(); @@ -1062,10 +1073,15 @@ struct HfCorrelatorDMesonPairs { } } + uint8_t pairType = setPairType(candidateType1, candidateType2); + // Fill entries for D0-D0(bar) pairs and plot histos - fillEntry(isDCand1, isDbarCand1, isDCand2, isDbarCand2, candidateType1, candidateType2, yCandidate1, yCandidate2, etaCandidate1, etaCandidate2, phiCandidate1, phiCandidate2, - ptCandidate1, ptCandidate2, massD0Cand1, massD0barCand1, massD0Cand2, massD0barCand2); - fillMcHistos(matchedRec1, matchedRec2, static_cast(isTrueDCand1), static_cast(isTrueDbarCand1), static_cast(isTrueDCand2), static_cast(isTrueDbarCand2)); + fillSelectionStatusHisto(candidateType1, candidateType2); + fillMatchingHisto(matchedRec1, matchedRec2); + + entryD0Pair(candidate1.pt(), candidate2.pt(), HfHelper::yD0(candidate1), HfHelper::yD0(candidate2), candidate1.eta(), candidate2.eta(), + candidate1.phi(), candidate2.phi(), HfHelper::invMassD0ToPiK(candidate1), HfHelper::invMassD0barToKPi(candidate1), + HfHelper::invMassD0ToPiK(candidate2), HfHelper::invMassD0barToKPi(candidate2), pairType, candidateType1, candidateType2); entryD0PairMcInfo(originRec1, originRec2, matchedRec1, matchedRec2); if (applyMl) { entryD0PairMl(outputMlD0Cand1, outputMlD0barCand1, outputMlD0Cand2, outputMlD0barCand2); From 3ffab5890f3c2eac046fda389726d29d2cf7a92e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrea=20Tavira=20Garc=C3=ADa?= <118979672+atavirag@users.noreply.github.com> Date: Wed, 14 Oct 2026 16:11:06 +0000 Subject: [PATCH 06/15] New function: passMlSelections --- .../TableProducer/correlatorDMesonPairs.cxx | 101 ++++++------------ 1 file changed, 32 insertions(+), 69 deletions(-) diff --git a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx index f76396cc256..6524c9a4d1e 100644 --- a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx @@ -212,8 +212,8 @@ struct HfCorrelatorDMesonPairs { std::vector outputMlD0barCand2; // using TracksWPid = soa::Join; - Partition> selectedD0Candidates = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; - Partition> selectedD0CandidatesMc = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; + Partition selectedD0Candidates = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; + Partition selectedD0CandidatesMc = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; // ThnSparse for ML outputScores and Vars ConfigurableAxis thnConfigAxisBkgScore{"thnConfigAxisBkgScore", {100, 0, 1}, "Bkg score bins"}; @@ -524,6 +524,28 @@ struct HfCorrelatorDMesonPairs { return (TESTBIT(candidateType, TrueDbar)); } + template + bool passMlSelections(const T& candidate, bool isDCand, bool isDbarCand, std::vector& outputMlD0Cand, std::vector& outputMlD0barCand) + { + bool isSelectedMlD0Cand = false; + bool isSelectedMlD0barCand = false; + + if (isDCand) { + std::vector inputFeaturesD0 = hfMlResponse.getInputFeatures(candidate, o2::constants::physics::kD0); + isSelectedMlD0Cand = hfMlResponse.isSelectedMl(inputFeaturesD0, candidate.pt(), outputMlD0Cand); + } + if (isDbarCand) { + std::vector inputFeaturesD0bar = hfMlResponse.getInputFeatures(candidate, o2::constants::physics::kD0Bar); + isSelectedMlD0barCand = hfMlResponse.isSelectedMl(inputFeaturesD0bar, candidate.pt(), outputMlD0barCand); + } + + // Remove non-ML selected D0 candidates + if (!isSelectedMlD0Cand && !isSelectedMlD0barCand) { + return false; + } + return true; + } + /// Fill PID related plots for D0 and D0bar /// \param candidate is candidate template @@ -770,23 +792,8 @@ struct HfCorrelatorDMesonPairs { continue; } - bool isSelectedMlD0Cand1 = false; - bool isSelectedMlD0barCand1 = false; - - if (applyMl) { - if (isDCand1) { - std::vector inputFeaturesD0 = hfMlResponse.getInputFeatures(candidate1, o2::constants::physics::kD0); - isSelectedMlD0Cand1 = hfMlResponse.isSelectedMl(inputFeaturesD0, candidate1.pt(), outputMlD0Cand1); - } - if (isDbarCand1) { - std::vector inputFeaturesD0bar = hfMlResponse.getInputFeatures(candidate1, o2::constants::physics::kD0Bar); - isSelectedMlD0barCand1 = hfMlResponse.isSelectedMl(inputFeaturesD0bar, candidate1.pt(), outputMlD0barCand1); - } - - // Remove non-ML selected D0 candidates - if (!isSelectedMlD0Cand1 && !isSelectedMlD0barCand1) { - continue; - } + if (applyMl && !passMlSelections(candidate1, isDCand1, isDbarCand1, outputMlD0Cand1, outputMlD0barCand1)) { + continue; } registry.fill(HIST("hPtProng0"), candidate1.ptProng0()); @@ -881,23 +888,8 @@ struct HfCorrelatorDMesonPairs { continue; } - bool isSelectedMlD0Cand2 = false; - bool isSelectedMlD0barCand2 = false; - - if (applyMl) { - if (isDCand2) { - std::vector inputFeaturesD0 = hfMlResponse.getInputFeatures(candidate2, o2::constants::physics::kD0); - isSelectedMlD0Cand2 = hfMlResponse.isSelectedMl(inputFeaturesD0, candidate2.pt(), outputMlD0Cand2); - } - if (isDbarCand2) { - std::vector inputFeaturesD0bar = hfMlResponse.getInputFeatures(candidate2, o2::constants::physics::kD0Bar); - isSelectedMlD0barCand2 = hfMlResponse.isSelectedMl(inputFeaturesD0bar, candidate2.pt(), outputMlD0barCand2); - } - - // Remove non-ML selected D0 candidates - if (!isSelectedMlD0Cand2 && !isSelectedMlD0barCand2) { - continue; - } + if (applyMl && !passMlSelections(candidate2, isDCand2, isDbarCand2, outputMlD0Cand2, outputMlD0barCand2)) { + continue; } if (applyMixedEvent) { @@ -955,26 +947,12 @@ struct HfCorrelatorDMesonPairs { int8_t matchedRec1 = candidate1.flagMcMatchRec(); int8_t originRec1 = candidate1.originMcRec(); - bool isSelectedMlD0Cand1 = false; - bool isSelectedMlD0barCand1 = false; - if (!passKinematicSelections(candidate1, isDCand1, isDbarCand1)) { continue; } - if (applyMl) { - if (isDCand1) { - std::vector inputFeaturesD0 = hfMlResponse.getInputFeatures(candidate1, o2::constants::physics::kD0); - isSelectedMlD0Cand1 = hfMlResponse.isSelectedMl(inputFeaturesD0, candidate1.pt(), outputMlD0Cand1); - } - if (isDbarCand1) { - std::vector inputFeaturesD0bar = hfMlResponse.getInputFeatures(candidate1, o2::constants::physics::kD0Bar); - isSelectedMlD0barCand1 = hfMlResponse.isSelectedMl(inputFeaturesD0bar, candidate1.pt(), outputMlD0barCand1); - } - // Remove non-ML selected D0 candidates - if (!isSelectedMlD0Cand1 && !isSelectedMlD0barCand1) { - continue; - } + if (applyMl && !passMlSelections(candidate1, isDCand1, isDbarCand1, outputMlD0Cand1, outputMlD0barCand1)) { + continue; } if (isTrueDCand1) { @@ -1054,23 +1032,8 @@ struct HfCorrelatorDMesonPairs { continue; } - bool isSelectedMlD0Cand2 = false; - bool isSelectedMlD0barCand2 = false; - - if (applyMl) { - if (isDCand2) { - std::vector inputFeaturesD0 = hfMlResponse.getInputFeatures(candidate2, o2::constants::physics::kD0); - isSelectedMlD0Cand2 = hfMlResponse.isSelectedMl(inputFeaturesD0, candidate2.pt(), outputMlD0Cand2); - } - if (isDbarCand2) { - std::vector inputFeaturesD0bar = hfMlResponse.getInputFeatures(candidate2, o2::constants::physics::kD0Bar); - isSelectedMlD0barCand2 = hfMlResponse.isSelectedMl(inputFeaturesD0bar, candidate2.pt(), outputMlD0barCand2); - } - - // Remove non-ML selected D0 candidates - if (!isSelectedMlD0Cand2 && !isSelectedMlD0barCand2) { - continue; - } + if (applyMl && !passMlSelections(candidate2, isDCand2, isDbarCand2, outputMlD0Cand2, outputMlD0barCand2)) { + continue; } uint8_t pairType = setPairType(candidateType1, candidateType2); From 3dd8570f1932a5fc4adc6823636d5ebf948f9bf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrea=20Tavira=20Garc=C3=ADa?= <118979672+atavirag@users.noreply.github.com> Date: Wed, 14 Oct 2026 18:49:07 +0000 Subject: [PATCH 07/15] Join McRec and Data processes --> processImpl --- .../TableProducer/correlatorDMesonPairs.cxx | 256 +++++++----------- 1 file changed, 99 insertions(+), 157 deletions(-) diff --git a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx index 6524c9a4d1e..8d48e4347e3 100644 --- a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx @@ -382,6 +382,7 @@ struct HfCorrelatorDMesonPairs { registry.add("hInputCheckD0OrD0barMcGen", "Check on input D0 | D0bar meson candidates/event MC Gen", {HistType::kTH1F, {axisInputD0}}); registry.add("hMass", "D Meson pair candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{120, 1.5848, 2.1848}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hMassSig", "MC-matched D Meson pair candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{120, 1.5848, 2.1848}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); registry.add("hMassMcRecPrompt", "D Meson pair candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{120, 1.5848, 2.1848}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); registry.add("hMassMcRecNonPrompt", "D Meson pair candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{120, 1.5848, 2.1848}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); registry.add("hMassMcRecReflections", "D Meson pair candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{120, 1.5848, 2.1848}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); @@ -571,42 +572,50 @@ struct HfCorrelatorDMesonPairs { /// Fill counters for D0 and D0bar /// \param d0Candidates contains all D0 candidates - template + template void getCountersPerEvent(const T& d0Candidates) { int nDevent = 0, nDbarevent = 0, nDDbarevent = 0, nDorDbarevent = 0; for (const auto& candidate : d0Candidates) { // Get counters per event - auto candidateType1 = assignCandidateTypeD0(candidate); // Candidate type attribution - bool const isDCand1 = isD(candidateType1); - bool const isDbarCand1 = isDbar(candidateType1); + auto candidateType = assignCandidateTypeD0(candidate); // Candidate type attribution + bool const isDCand = isD(candidateType); + bool const isDbarCand = isDbar(candidateType); + bool const isTrueDCand = isTrueD(candidateType); + bool const isTrueDbarCand = isTrueDbar(candidateType); - if (!passKinematicSelections(candidate, isDCand1, isDbarCand1)) { + if (!passKinematicSelections(candidate, isDCand, isDbarCand)) { continue; } - if (isDCand1) { + if (isDCand) { nDevent++; } - if (isDbarCand1) { + if (isDbarCand) { nDbarevent++; } - if (isDCand1 && isDbarCand1) { + if (isDCand && isDbarCand) { nDDbarevent++; } - if (isDCand1 || isDbarCand1) { + if (isDCand || isDbarCand) { nDorDbarevent++; } // Fill selection status single particle registry.fill(HIST("hStatusSinglePart"), 1); - if (isDCand1 && !isDbarCand1) { + if (isDCand && !isDbarCand) { registry.fill(HIST("hStatusSinglePart"), 2); - } else if (isDbarCand1 && !isDCand1) { + } else if (isDbarCand && !isDCand) { registry.fill(HIST("hStatusSinglePart"), 3); - } else if (isDCand1 && isDbarCand1) { + } else if (isDCand && isDbarCand) { registry.fill(HIST("hStatusSinglePart"), 4); } + // fill true info (available only in MC) + if (isTrueDCand) { + registry.fill(HIST("hStatusSinglePart"), 5); + } else if (isTrueDbarCand) { + registry.fill(HIST("hStatusSinglePart"), 6); + } } if (nDevent > 0) { registry.fill(HIST("hInputCheckD0"), nDevent); @@ -739,15 +748,13 @@ struct HfCorrelatorDMesonPairs { } } - /// D0(bar)-D0(bar) correlation pair builder - for real data and data-like analysis (i.e. reco-level w/o matching request via MC truth) - void processData(SelCollisionsWithD0::iterator const& collision, - CandidatesD0Data const& candidates, TracksData const& tracks, aod::BCsWithTimestamps const&) + template + void processImpl(TCollision const& collision, + TCandidates const& selectedD0CandidatesGrouped, // per-collision slice of the partition + TTracks const& tracks, + const int64_t timeStamp) { - - auto bc = collision.bc_as(); int gCollisionId = collision.globalIndex(); - int64_t timeStamp = bc.timestamp(); - int poolBin = corrBinning->getBin(std::make_tuple(collision.posZ(), collision.multFT0M())); int nTracks = 0; @@ -771,9 +778,7 @@ struct HfCorrelatorDMesonPairs { int cntD0 = 0; - getCountersPerEvent(candidates); - - auto selectedD0CandidatesGrouped = selectedD0Candidates->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); + getCountersPerEvent(selectedD0CandidatesGrouped); for (const auto& candidate1 : selectedD0CandidatesGrouped) { analysePid(candidate1); @@ -784,9 +789,21 @@ struct HfCorrelatorDMesonPairs { auto prong0Cand1 = candidate1.template prong0_as(); auto prong1Cand1 = candidate1.template prong1_as(); - auto candidateType1 = assignCandidateTypeD0(candidate1); // Candidate type attribution + int8_t matchedRec1 = 0; + int8_t originRec1 = 0; + + if constexpr (IsMcRec) { + matchedRec1 = candidate1.flagMcMatchRec(); + originRec1 = candidate1.originMcRec(); + } + + auto candidateType1 = assignCandidateTypeD0(candidate1); // Candidate type attribution bool const isDCand1 = isD(candidateType1); bool const isDbarCand1 = isDbar(candidateType1); + bool const isTrueDCand1 = isTrueD(candidateType1); + bool const isTrueDbarCand1 = isTrueDbar(candidateType1); + + registry.fill(HIST("hPtCand"), candidate1.pt()); if (!passKinematicSelections(candidate1, isDCand1, isDbarCand1)) { continue; @@ -809,10 +826,26 @@ struct HfCorrelatorDMesonPairs { if (isDCand1) { registry.fill(HIST("hMass"), HfHelper::invMassD0ToPiK(candidate1), candidate1.pt()); + // Fill THnSparse for D0 candidates if (applyMl) { - registry.fill(HIST("hnDMesonMl"), outputMlD0Cand1[0], outputMlD0Cand1[1], HfHelper::invMassD0ToPiK(candidate1), candidate1.pt(), candidate1.y(MassD0), collision.numContrib(), 0, candidateType1); + registry.fill(HIST("hnDMesonMl"), outputMlD0Cand1[0], outputMlD0Cand1[1], HfHelper::invMassD0ToPiK(candidate1), candidate1.pt(), candidate1.y(MassD0), collision.numContrib(), originRec1, candidateType1); } else { - registry.fill(HIST("hnDMeson"), HfHelper::invMassD0ToPiK(candidate1), candidate1.pt(), candidate1.y(MassD0), collision.numContrib(), 0, candidateType1); + registry.fill(HIST("hnDMeson"), HfHelper::invMassD0ToPiK(candidate1), candidate1.pt(), candidate1.y(MassD0), collision.numContrib(), originRec1, candidateType1); + } + // Fill MC-matched histograms for D0 candidates + if (isTrueDCand1) { + registry.fill(HIST("hMassSig"), HfHelper::invMassD0ToPiK(candidate1), candidate1.pt()); + registry.fill(HIST("hPtVsYVsNContribMcRec"), candidate1.pt(), HfHelper::yD0(candidate1), collision.numContrib()); + registry.fill(HIST("hNContribMcRec"), collision.numContrib()); + if (originRec1 == RecoDecay::Prompt) { + registry.fill(HIST("hMassMcRecPrompt"), HfHelper::invMassD0ToPiK(candidate1), candidate1.pt()); + registry.fill(HIST("hPtVsYVsNContribMcRecPrompt"), candidate1.pt(), HfHelper::yD0(candidate1), collision.numContrib()); + } else if (originRec1 == RecoDecay::NonPrompt) { + registry.fill(HIST("hMassMcRecNonPrompt"), HfHelper::invMassD0ToPiK(candidate1), candidate1.pt()); + registry.fill(HIST("hPtVsYVsNContribMcRecNonPrompt"), candidate1.pt(), HfHelper::yD0(candidate1), collision.numContrib()); + } + } else if (isTrueDbarCand1) { + registry.fill(HIST("hMassMcRecReflections"), HfHelper::invMassD0ToPiK(candidate1), candidate1.pt()); } // Fill D0 table for offline event mixing if (applyMixedEvent) { @@ -820,11 +853,25 @@ struct HfCorrelatorDMesonPairs { } } if (isDbarCand1) { + // Fill THnSparse for D0bar candidates registry.fill(HIST("hMass"), HfHelper::invMassD0barToKPi(candidate1), candidate1.pt()); if (applyMl) { - registry.fill(HIST("hnDMesonMl"), outputMlD0barCand1[0], outputMlD0barCand1[1], HfHelper::invMassD0barToKPi(candidate1), candidate1.pt(), candidate1.y(MassD0), collision.numContrib(), 0, candidateType1); + registry.fill(HIST("hnDMesonMl"), outputMlD0barCand1[0], outputMlD0barCand1[1], HfHelper::invMassD0barToKPi(candidate1), candidate1.pt(), candidate1.y(MassD0), collision.numContrib(), originRec1, candidateType1); } else { - registry.fill(HIST("hnDMeson"), HfHelper::invMassD0barToKPi(candidate1), candidate1.pt(), candidate1.y(MassD0), collision.numContrib(), 0, candidateType1); + registry.fill(HIST("hnDMeson"), HfHelper::invMassD0barToKPi(candidate1), candidate1.pt(), candidate1.y(MassD0), collision.numContrib(), originRec1, candidateType1); + } + // Fill MC-matched histograms for D0bar candidates + if (isTrueDbarCand1) { + registry.fill(HIST("hMassSig"), HfHelper::invMassD0barToKPi(candidate1), candidate1.pt()); + registry.fill(HIST("hPtVsYVsNContribMcRec"), candidate1.pt(), HfHelper::yD0(candidate1), collision.numContrib()); + registry.fill(HIST("hNContribMcRec"), collision.numContrib()); + if (originRec1 == RecoDecay::Prompt) { + registry.fill(HIST("hMassMcRecPrompt"), HfHelper::invMassD0barToKPi(candidate1), candidate1.pt()); + } else if (originRec1 == RecoDecay::NonPrompt) { + registry.fill(HIST("hMassMcRecNonPrompt"), HfHelper::invMassD0barToKPi(candidate1), candidate1.pt()); + } + } else if (isTrueDCand1) { + registry.fill(HIST("hMassMcRecReflections"), HfHelper::invMassD0barToKPi(candidate1), candidate1.pt()); } // Fill D0 table for offline event mixing if (applyMixedEvent) { @@ -880,10 +927,18 @@ struct HfCorrelatorDMesonPairs { continue; } - auto candidateType2 = assignCandidateTypeD0(candidate2); // Candidate type attribution + auto candidateType2 = assignCandidateTypeD0(candidate2); // Candidate type attribution bool const isDCand2 = isD(candidateType2); bool const isDbarCand2 = isDbar(candidateType2); + int8_t matchedRec2 = 0; + int8_t originRec2 = 0; + + if constexpr (IsMcRec) { + matchedRec2 = candidate2.flagMcMatchRec(); + originRec2 = candidate2.originMcRec(); + } + if (!passKinematicSelections(candidate2, isDCand2, isDbarCand2)) { continue; } @@ -912,6 +967,10 @@ struct HfCorrelatorDMesonPairs { if (applyMl) { entryD0PairMl(outputMlD0Cand1, outputMlD0barCand1, outputMlD0Cand2, outputMlD0barCand2); } + if constexpr (IsMcRec) { + fillMatchingHisto(matchedRec1, matchedRec2); + entryD0PairMcInfo(originRec1, originRec2, matchedRec1, matchedRec2); + } } // end inner loop (Cand2) } // end outer loop (Cand1) @@ -921,139 +980,22 @@ struct HfCorrelatorDMesonPairs { } } + void processData(SelCollisionsWithD0::iterator const& collision, + CandidatesD0Data const&, TracksData const& tracks, aod::BCsWithTimestamps const&) + { + const auto timeStamp = collision.bc_as().timestamp(); + auto grouped = selectedD0Candidates->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); + processImpl(collision, grouped, tracks, timeStamp); + } PROCESS_SWITCH(HfCorrelatorDMesonPairs, processData, "Process data mode", true); - void processMcRec(SelCollisionsWithD0::iterator const& collision, CandidatesD0McRec const& candidates, aod::Tracks const&) + void processMcRec(SelCollisionsWithD0::iterator const& collision, CandidatesD0McRec const&, TracksData const& tracks) { - - getCountersPerEvent(candidates); - auto selectedD0CandidatesGroupedMc = selectedD0CandidatesMc->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); - for (const auto& candidate1 : selectedD0CandidatesGroupedMc) { - analysePid(candidate1); - - outputMlD0Cand1.clear(); - outputMlD0barCand1.clear(); - - auto prong0Cand1 = candidate1.template prong0_as(); - auto prong1Cand1 = candidate1.template prong1_as(); - - auto candidateType1 = assignCandidateTypeD0(candidate1); // Candidate type attribution - - bool const isDCand1 = isD(candidateType1); - bool const isDbarCand1 = isDbar(candidateType1); - bool const isTrueDCand1 = isTrueD(candidateType1); - bool const isTrueDbarCand1 = isTrueDbar(candidateType1); - - int8_t matchedRec1 = candidate1.flagMcMatchRec(); - int8_t originRec1 = candidate1.originMcRec(); - - if (!passKinematicSelections(candidate1, isDCand1, isDbarCand1)) { - continue; - } - - if (applyMl && !passMlSelections(candidate1, isDCand1, isDbarCand1, outputMlD0Cand1, outputMlD0barCand1)) { - continue; - } - - if (isTrueDCand1) { - registry.fill(HIST("hStatusSinglePart"), 5); - } else if (isTrueDbarCand1) { - registry.fill(HIST("hStatusSinglePart"), 6); - } - - registry.fill(HIST("hPtProng0"), candidate1.ptProng0()); - registry.fill(HIST("hPtProng1"), candidate1.ptProng1()); - registry.fill(HIST("hEta"), candidate1.eta()); - registry.fill(HIST("hPhi"), candidate1.phi()); - registry.fill(HIST("hY"), candidate1.y(MassD0)); - registry.fill(HIST("hPtCandAfterCut"), candidate1.pt()); - - if (isDCand1) { - if (applyMl) { - registry.fill(HIST("hnDMesonMl"), outputMlD0Cand1[0], outputMlD0Cand1[1], HfHelper::invMassD0ToPiK(candidate1), candidate1.pt(), candidate1.y(MassD0), collision.numContrib(), originRec1, candidateType1); - } else { - registry.fill(HIST("hnDMeson"), HfHelper::invMassD0ToPiK(candidate1), candidate1.pt(), candidate1.y(MassD0), collision.numContrib(), originRec1, candidateType1); - } - if (isTrueDCand1) { - registry.fill(HIST("hMass"), HfHelper::invMassD0ToPiK(candidate1), candidate1.pt()); - registry.fill(HIST("hPtVsYVsNContribMcRec"), candidate1.pt(), HfHelper::yD0(candidate1), collision.numContrib()); - registry.fill(HIST("hNContribMcRec"), collision.numContrib()); - if (originRec1 == RecoDecay::Prompt) { - registry.fill(HIST("hMassMcRecPrompt"), HfHelper::invMassD0ToPiK(candidate1), candidate1.pt()); - registry.fill(HIST("hPtVsYVsNContribMcRecPrompt"), candidate1.pt(), HfHelper::yD0(candidate1), collision.numContrib()); - } else if (originRec1 == RecoDecay::NonPrompt) { - registry.fill(HIST("hMassMcRecNonPrompt"), HfHelper::invMassD0ToPiK(candidate1), candidate1.pt()); - registry.fill(HIST("hPtVsYVsNContribMcRecNonPrompt"), candidate1.pt(), HfHelper::yD0(candidate1), collision.numContrib()); - } - } else if (isTrueDbarCand1) { - registry.fill(HIST("hMassMcRecReflections"), HfHelper::invMassD0ToPiK(candidate1), candidate1.pt()); - } - } - if (isDbarCand1) { - if (applyMl) { - registry.fill(HIST("hnDMesonMl"), outputMlD0barCand1[0], outputMlD0barCand1[1], HfHelper::invMassD0barToKPi(candidate1), candidate1.pt(), candidate1.y(MassD0), collision.numContrib(), originRec1, candidateType1); - } else { - registry.fill(HIST("hnDMeson"), HfHelper::invMassD0barToKPi(candidate1), candidate1.pt(), candidate1.y(MassD0), collision.numContrib(), originRec1, candidateType1); - } - if (isTrueDbarCand1) { - registry.fill(HIST("hMass"), HfHelper::invMassD0barToKPi(candidate1), candidate1.pt()); - registry.fill(HIST("hPtVsYVsNContribMcRec"), candidate1.pt(), HfHelper::yD0(candidate1), collision.numContrib()); - registry.fill(HIST("hNContribMcRec"), collision.numContrib()); - if (originRec1 == RecoDecay::Prompt) { - registry.fill(HIST("hMassMcRecPrompt"), HfHelper::invMassD0barToKPi(candidate1), candidate1.pt()); - } else if (originRec1 == RecoDecay::NonPrompt) { - registry.fill(HIST("hMassMcRecNonPrompt"), HfHelper::invMassD0barToKPi(candidate1), candidate1.pt()); - } - } else if (isTrueDCand1) { - registry.fill(HIST("hMassMcRecReflections"), HfHelper::invMassD0barToKPi(candidate1), candidate1.pt()); - } - } - - for (auto candidate2 = candidate1 + 1; candidate2 != selectedD0CandidatesGroupedMc.end(); ++candidate2) { - - outputMlD0Cand2.clear(); - outputMlD0barCand2.clear(); - - auto prong0Cand2 = candidate2.template prong0_as(); - auto prong1Cand2 = candidate2.template prong1_as(); - - if ((prong0Cand1 == prong0Cand2) || (prong1Cand1 == prong1Cand2) || (prong0Cand1 == prong1Cand2) || (prong1Cand1 == prong0Cand2)) { - continue; - } - auto candidateType2 = assignCandidateTypeD0(candidate2); // Candidate type attribution - - bool const isDCand2 = isD(candidateType2); - bool const isDbarCand2 = isDbar(candidateType2); - - int8_t matchedRec2 = candidate2.flagMcMatchRec(); - int8_t originRec2 = candidate2.originMcRec(); - - if (!passKinematicSelections(candidate2, isDCand2, isDbarCand2)) { - continue; - } - - if (applyMl && !passMlSelections(candidate2, isDCand2, isDbarCand2, outputMlD0Cand2, outputMlD0barCand2)) { - continue; - } - - uint8_t pairType = setPairType(candidateType1, candidateType2); - - // Fill entries for D0-D0(bar) pairs and plot histos - fillSelectionStatusHisto(candidateType1, candidateType2); - fillMatchingHisto(matchedRec1, matchedRec2); - - entryD0Pair(candidate1.pt(), candidate2.pt(), HfHelper::yD0(candidate1), HfHelper::yD0(candidate2), candidate1.eta(), candidate2.eta(), - candidate1.phi(), candidate2.phi(), HfHelper::invMassD0ToPiK(candidate1), HfHelper::invMassD0barToKPi(candidate1), - HfHelper::invMassD0ToPiK(candidate2), HfHelper::invMassD0barToKPi(candidate2), pairType, candidateType1, candidateType2); - entryD0PairMcInfo(originRec1, originRec2, matchedRec1, matchedRec2); - if (applyMl) { - entryD0PairMl(outputMlD0Cand1, outputMlD0barCand1, outputMlD0Cand2, outputMlD0barCand2); - } - } // end inner loop (Cand2) - } // end outer loop (Cand1) + const auto timeStamp = collision.bc_as().timestamp(); + auto grouped = selectedD0CandidatesMc->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); + processImpl(collision, grouped, tracks, timeStamp); } - - PROCESS_SWITCH(HfCorrelatorDMesonPairs, processMcRec, "Process Mc reco mode", false); + PROCESS_SWITCH(HfCorrelatorDMesonPairs, processMcRec, "Process MC reco mode", false); void processMcGen(aod::McCollision const&, soa::SmallGroups> const& collisions, McParticlesPlus2Prong const& mcParticles) { From f4d5593822b2bb16582304d0dd347530d5015917 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrea=20Tavira=20Garc=C3=ADa?= <118979672+atavirag@users.noreply.github.com> Date: Wed, 14 Oct 2026 19:42:47 +0000 Subject: [PATCH 08/15] Add possibility to swap D Dbar candidates --- .../TableProducer/correlatorDMesonPairs.cxx | 35 +++++++++++++++---- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx index 8d48e4347e3..c2ee86869c0 100644 --- a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx @@ -51,6 +51,7 @@ #include +#include #include #include #include @@ -525,6 +526,18 @@ struct HfCorrelatorDMesonPairs { return (TESTBIT(candidateType, TrueDbar)); } + /// Canonical pair ordering: + /// D0 before D0bar; for equal flavours, higher pT first. + /// \return true if candidate 1 and candidate 2 should be exchanged + template + static bool shouldSwapOrder(const bool isD1, const bool isDbar1, const bool isD2, const bool isDbar2, const T& candidate1, const T& candidate2) + { + if (isD1 != isD2 || isDbar1 != isDbar2) { // different flavour content + return !isD1 && isD2; // Dbar(-only) first, D second -> swap + } + return candidate1.pt() < candidate2.pt(); + } + template bool passMlSelections(const T& candidate, bool isDCand, bool isDbarCand, std::vector& outputMlD0Cand, std::vector& outputMlD0barCand) { @@ -798,10 +811,10 @@ struct HfCorrelatorDMesonPairs { } auto candidateType1 = assignCandidateTypeD0(candidate1); // Candidate type attribution - bool const isDCand1 = isD(candidateType1); - bool const isDbarCand1 = isDbar(candidateType1); - bool const isTrueDCand1 = isTrueD(candidateType1); - bool const isTrueDbarCand1 = isTrueDbar(candidateType1); + bool isDCand1 = isD(candidateType1); + bool isDbarCand1 = isDbar(candidateType1); + bool isTrueDCand1 = isTrueD(candidateType1); + bool isTrueDbarCand1 = isTrueDbar(candidateType1); registry.fill(HIST("hPtCand"), candidate1.pt()); @@ -928,8 +941,10 @@ struct HfCorrelatorDMesonPairs { } auto candidateType2 = assignCandidateTypeD0(candidate2); // Candidate type attribution - bool const isDCand2 = isD(candidateType2); - bool const isDbarCand2 = isDbar(candidateType2); + bool isDCand2 = isD(candidateType2); + bool isDbarCand2 = isDbar(candidateType2); + bool isTrueDCand2 = isTrueD(candidateType2); + bool isTrueDbarCand2 = isTrueDbar(candidateType2); int8_t matchedRec2 = 0; int8_t originRec2 = 0; @@ -958,6 +973,12 @@ struct HfCorrelatorDMesonPairs { } uint8_t pairType = setPairType(candidateType1, candidateType2); + if (shouldSwapOrder(isDCand1, isDbarCand1, isDCand2, isDbarCand2, candidate1, candidate2)) { + std::swap(isDCand1, isDCand2); + std::swap(isDbarCand1, isDbarCand2); + std::swap(isTrueDCand1, isTrueDCand2); + std::swap(isTrueDbarCand1, isTrueDbarCand2); + } // Fill entries for D0-D0(bar) pairs and plot histos fillSelectionStatusHisto(candidateType1, candidateType2); @@ -989,7 +1010,7 @@ struct HfCorrelatorDMesonPairs { } PROCESS_SWITCH(HfCorrelatorDMesonPairs, processData, "Process data mode", true); - void processMcRec(SelCollisionsWithD0::iterator const& collision, CandidatesD0McRec const&, TracksData const& tracks) + void processMcRec(SelCollisionsWithD0::iterator const& collision, CandidatesD0McRec const&, TracksData const& tracks, aod::BCsWithTimestamps const&) { const auto timeStamp = collision.bc_as().timestamp(); auto grouped = selectedD0CandidatesMc->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); From 70bb9be7dc28bada00b19c9b959cc964bfb5b5ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrea=20Tavira=20Garc=C3=ADa?= <118979672+atavirag@users.noreply.github.com> Date: Thu, 15 Oct 2026 09:05:02 +0000 Subject: [PATCH 09/15] Optimise MC gen function --- .../TableProducer/correlatorDMesonPairs.cxx | 515 +++++++----------- 1 file changed, 192 insertions(+), 323 deletions(-) diff --git a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx index c2ee86869c0..5257afd930e 100644 --- a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx @@ -21,7 +21,6 @@ #include "PWGHF/DataModel/AliasTables.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/DataModel/TrackIndexSkimmingTables.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" #include "PWGHF/HFC/DataModel/DMesonPairsTables.h" @@ -41,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -51,12 +51,13 @@ #include -#include #include #include #include #include #include +#include +#include #include using namespace o2; @@ -67,6 +68,8 @@ using namespace o2::framework::expressions; namespace { +using DecayChannel = o2::hf_decay::hf_cand_2prong::DecayChannelMain; + enum CandidateType { SelectedD = 0, // This particle is selected as a D SelectedDbar, // This particle is selected as a Dbar @@ -103,25 +106,21 @@ struct HfCorrelatorD0HadronsSelection { using CandidatesD0Data = soa::Join; Partition selectedD0Candidates = - aod::hf_sel_candidate_d0::isSelD0 >= 1 || - aod::hf_sel_candidate_d0::isSelD0bar >= 1; + aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || + aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; // Process function to select collisions with at least one D0 candidate passing the selection criteria void processD0SelectionData(SelCollisions::iterator const& collision, CandidatesD0Data const&) { - bool isSel8 = !useSel8 || collision.sel8(); - bool isNoSameBunchPileUp = !selNoSameBunchPileUpColl || - collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup); + bool const isSel8 = !useSel8 || collision.sel8(); + bool const isNoSameBunchPileUp = !selNoSameBunchPileUpColl || + collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup); bool isD0Found = !doSelD0Collision; if (doSelD0Collision) { auto grouped = selectedD0Candidates.sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); for (const auto& candidate : grouped) { - - if (candidate.isSelD0() < selectionFlagD0 && candidate.isSelD0bar() < selectionFlagD0bar) { - continue; - } if (std::abs(HfHelper::yD0(candidate)) > yCandMax || candidate.pt() < ptCandMin) { continue; } @@ -157,7 +156,6 @@ struct HfCorrelatorDMesonPairs { Configurable massCut{"massCut", 0.05, "Maximum deviation from PDG peak allowed for signal region"}; Configurable removeAmbiguous{"removeAmbiguous", false, "Flag to remove ambiguous candidates"}; Configurable ptMaxRemoveAmbiguous{"ptMaxRemoveAmbiguous", 5.0, "Max. pT to remove the ambiguous candidates"}; - Configurable useD0SelectorMlInfo{"useD0SelectorMlInfo", false, "Flag for applying ML info in D0 selection"}; // Event mixing configurables Configurable applyMixedEvent{"applyMixedEvent", false, "Flag to make the event mixing"}; @@ -167,9 +165,8 @@ struct HfCorrelatorDMesonPairs { Configurable dcaXYTrackMax{"dcaXYTrackMax", 1., "max. DCA_xy of tracks"}; Configurable dcaZTrackMax{"dcaZTrackMax", 1., "max. DCA_z of tracks"}; Configurable ptTrackMin{"ptTrackMin", 0.3, "min. track pT"}; - Configurable ptTrackMax{"ptTrackMax", 100., "max. track pT"}; - Configurable multMin{"multMin", 0., "minimum multiplicity accepted"}; - Configurable multMax{"multMax", 10000., "maximum multiplicity accepted"}; + Configurable multMin{"multMin", 0, "minimum multiplicity accepted"}; + Configurable multMax{"multMax", 10000, "maximum multiplicity accepted"}; // ML inference Configurable applyMl{"applyMl", false, "Flag to apply ML selections"}; @@ -186,22 +183,20 @@ struct HfCorrelatorDMesonPairs { Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB"}; Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + // Table aliases. The partitions below must have exactly the same type as the + // candidate table taken by the process functions, otherwise they are never bound. using SelCollisionsWithD0 = soa::Filtered>; using CandidatesD0Data = soa::Join; using CandidatesD0McRec = soa::Join; - - using FilteredD0Candidates = soa::Filtered; - using TracksData = soa::Filtered>; // trackFilter applied + using TracksData = soa::Filtered>; Filter collisionFilter = aod::hf_selection_dmeson_collision::dmesonSel == true; - Filter d0Filter = (o2::aod::hf_track_index::hfflag & static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK))) != static_cast(0); - Filter trackFilter = (nabs(aod::track::eta) < etaTrackMax) && (nabs(aod::track::pt) > ptTrackMin) && (nabs(aod::track::dcaXY) < dcaXYTrackMax) && (nabs(aod::track::dcaZ) < dcaZTrackMax); + Filter trackFilter = (nabs(aod::track::eta) < etaTrackMax) && (aod::track::pt > ptTrackMin) && (nabs(aod::track::dcaXY) < dcaXYTrackMax) && (nabs(aod::track::dcaZ) < dcaZTrackMax); SliceCache cache; - Preslice perCol2Prong = aod::hf_cand::collisionId; - Preslice candsD0PerCollision = aod::hf_cand::collisionId; - Preslice trackIndicesPerCollision = aod::track::collisionId; + Partition selectedD0Candidates = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; + Partition selectedD0CandidatesMc = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; o2::analysis::HfMlResponseD0ToKPi hfMlResponse; o2::ccdb::CcdbApi ccdbApi; @@ -212,10 +207,6 @@ struct HfCorrelatorDMesonPairs { std::vector outputMlD0Cand2; std::vector outputMlD0barCand2; - // using TracksWPid = soa::Join; - Partition selectedD0Candidates = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; - Partition selectedD0CandidatesMc = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; - // ThnSparse for ML outputScores and Vars ConfigurableAxis thnConfigAxisBkgScore{"thnConfigAxisBkgScore", {100, 0, 1}, "Bkg score bins"}; ConfigurableAxis thnConfigAxisSignalScore{"thnConfigAxisSignalScore", {100, 0, 1}, "Signal score bins"}; @@ -236,8 +227,6 @@ struct HfCorrelatorDMesonPairs { ConfigurableAxis binsMultiplicity{"binsMultiplicity", {VARIABLE_WIDTH, 0.0f, 2000.0f, 6000.0f, 100000.0f}, "Mixing bins - multiplicity"}; ConfigurableAxis binsZVtx{"binsZVtx", {VARIABLE_WIDTH, -10.0f, -2.5f, 2.5f, 10.0f}, "Mixing bins - z-vertex"}; ConfigurableAxis binsPoolBin{"binsPoolBin", {9, 0., 9.}, "PoolBin"}; - ConfigurableAxis binsMultFT0M{"binsMultFT0M", {600, 0., 6000.}, "Multiplicity as FT0M signal amplitude"}; - ConfigurableAxis binsDcaXY{"binsDcaXY", {128, -0.2, 0.2}, "DCA xy"}; std::unique_ptr corrBinning; HistogramRegistry registry{ @@ -257,7 +246,7 @@ struct HfCorrelatorDMesonPairs { {"hPhiMcGen", "D meson candidates MC Gen;candidate #it{#varphi};entries", hTH1Phi}, {"hPtVsYVsNContribMcGen", "D meson candidates MC Gen;candidate #it{p}_{T} (GeV/#it{c});#it{y};Number of contributors", hTH3PtVsYVsNContrib}, {"hPtVsYVsNContribMcGenPrompt", "D meson candidates MC Gen Prompt;candidate #it{p}_{T} (GeV/#it{c});#it{y};Number of contributors", hTH3PtVsYVsNContrib}, - {"hPtVsYVsNContribMcGenNonPrompt", "D meson candidates MC Gen Prompt;candidate #it{p}_{T} (GeV/#it{c});#it{y};Number of contributors", hTH3PtVsYVsNContrib}, + {"hPtVsYVsNContribMcGenNonPrompt", "D meson candidates MC Gen Non-prompt;candidate #it{p}_{T} (GeV/#it{c});#it{y};Number of contributors", hTH3PtVsYVsNContrib}, {"hNContribMcGen", "D meson candidates MC Gen;Number of PV contributors", hTH1NContrib}, // MC Rec plots {"hPtVsYVsNContribMcRec", "D meson candidates MC Rec;candidate #it{p}_{T} (GeV/#it{c});#it{y};Number of contributors", hTH3PtVsYVsNContrib}, @@ -274,7 +263,6 @@ struct HfCorrelatorDMesonPairs { void init(InitContext&) { - if (applyMl) { hfMlResponse.configure(binsPtMl, cutsMl, cutDirMl, nClassesMl); if (loadModelsFromCCDB) { @@ -411,32 +399,24 @@ struct HfCorrelatorDMesonPairs { } // Event mixing - AxisSpec axisPtHadron = {(std::vector)binsPtHadron, "#it{p}_{T} Hadron (GeV/#it{c})"}; - AxisSpec const axisMultiplicity = {binsMultiplicity, "Multiplicity"}; - AxisSpec axisMultFT0M = {binsMultFT0M, "MultiplicityFT0M"}; - AxisSpec const axisPosZ = {binsZVtx, "PosZ"}; AxisSpec const axisPoolBin = {binsPoolBin, "PoolBin"}; - AxisSpec const axisDcaXY = {binsDcaXY, "DCA xy"}; corrBinning = std::make_unique(BinningType{{binsZVtx, binsMultiplicity}}); if (applyMixedEvent) { - registry.add("hMultiplicityPreSelection", "multiplicity prior to selection;multiplicity;entries", {HistType::kTH1F, {{10000, 0., 10000.}}}); - registry.add("hMultiplicity", "multiplicity;multiplicity;entries", {HistType::kTH1F, {{10000, 0., 10000.}}}); registry.add("hMultFT0M", "multiplicity;multiplicity;entries", {HistType::kTH1F, {{10000, 0., 10000.}}}); registry.add("hZvtx", "z vertex;z vertex;entries", {HistType::kTH1F, {{200, -20., 20.}}}); registry.add("hD0Bin", "D0 selected in pool Bin;pool Bin;entries", {HistType::kTH1F, {{axisPoolBin}}}); registry.add("hD0Cand2Bin", "D0 selected in pool Bin;pool Bin;entries", {HistType::kTH1F, {{axisPoolBin}}}); - registry.add("hTracksBin", "Tracks selected in pool Bin;pool Bin;entries", {HistType::kTH1F, {{axisPoolBin}}}); - registry.add("hDcaXYVsPt", "DCA xy vs pt", {HistType::kTH2F, {{axisDcaXY}, {axisPtHadron}}}); } } - + /// Kinematic, signal-region and ambiguity selections of a candidate + /// \return true if the candidate passes the selections template - bool passKinematicSelections(const T& candidate, bool isDCand, bool isDbarCand) + bool passKinematicSelections(const T& candidate, const bool isDCand, const bool isDbarCand) { if (std::abs(HfHelper::yD0(candidate)) > yCandMax) { - return false; + return false; } if (ptCandMin >= 0. && candidate.pt() < ptCandMin) { return false; @@ -468,10 +448,10 @@ struct HfCorrelatorDMesonPairs { SETBIT(candidateType, SelectedDbar); } if constexpr (IsMcRec) { - if (candidate.flagMcMatchRec() == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { // matched as D0 + if (candidate.flagMcMatchRec() == DecayChannel::D0ToPiK) { // matched as D0 SETBIT(candidateType, TrueD); } - if (candidate.flagMcMatchRec() == -o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { // matched as D0bar + if (candidate.flagMcMatchRec() == -DecayChannel::D0ToPiK) { // matched as D0bar SETBIT(candidateType, TrueDbar); } } @@ -495,39 +475,37 @@ struct HfCorrelatorDMesonPairs { } /// Check if the candidate is a D - /// \param candidate is candidate - /// \return true if is a D bool isD(const uint8_t candidateType) { return (TESTBIT(candidateType, SelectedD)); } /// Check if the candidate is a Dbar - /// \param candidate is candidate - /// \return true if is a Dbar bool isDbar(const uint8_t candidateType) { return (TESTBIT(candidateType, SelectedDbar)); } /// Check if the candidate is a true D - /// \param candidate is candidate - /// \return true if is a true D bool isTrueD(const uint8_t candidateType) { return (TESTBIT(candidateType, TrueD)); } /// Check if the candidate is a true Dbar - /// \param candidate is candidate - /// \return true if is a true Dbar bool isTrueDbar(const uint8_t candidateType) { return (TESTBIT(candidateType, TrueDbar)); } - /// Canonical pair ordering: - /// D0 before D0bar; for equal flavours, higher pT first. + /// Rapidity and pT selections of gen-level particles + template + bool passGenSelections(const T& particle) + { + return std::abs(particle.y()) <= yCandMax && (ptCandMin < 0. || particle.pt() >= ptCandMin); + } + + /// Canonical pair ordering: D0 before D0bar; for equal flavours, higher pT first. /// \return true if candidate 1 and candidate 2 should be exchanged template static bool shouldSwapOrder(const bool isD1, const bool isDbar1, const bool isD2, const bool isDbar2, const T& candidate1, const T& candidate2) @@ -538,8 +516,10 @@ struct HfCorrelatorDMesonPairs { return candidate1.pt() < candidate2.pt(); } + /// ML selections of a candidate + /// \return true if the candidate is selected by the ML model (as D0 and/or D0bar) template - bool passMlSelections(const T& candidate, bool isDCand, bool isDbarCand, std::vector& outputMlD0Cand, std::vector& outputMlD0barCand) + bool passMlSelections(const T& candidate, const bool isDCand, const bool isDbarCand, std::vector& outputMlD0Cand, std::vector& outputMlD0barCand) { bool isSelectedMlD0Cand = false; bool isSelectedMlD0barCand = false; @@ -553,11 +533,7 @@ struct HfCorrelatorDMesonPairs { isSelectedMlD0barCand = hfMlResponse.isSelectedMl(inputFeaturesD0bar, candidate.pt(), outputMlD0barCand); } - // Remove non-ML selected D0 candidates - if (!isSelectedMlD0Cand && !isSelectedMlD0barCand) { - return false; - } - return true; + return isSelectedMlD0Cand || isSelectedMlD0barCand; } /// Fill PID related plots for D0 and D0bar @@ -584,14 +560,14 @@ struct HfCorrelatorDMesonPairs { } /// Fill counters for D0 and D0bar - /// \param d0Candidates contains all D0 candidates + /// \param d0Candidates contains the D0 candidates of the collision template void getCountersPerEvent(const T& d0Candidates) { int nDevent = 0, nDbarevent = 0, nDDbarevent = 0, nDorDbarevent = 0; for (const auto& candidate : d0Candidates) { // Get counters per event - auto candidateType = assignCandidateTypeD0(candidate); // Candidate type attribution + auto const candidateType = assignCandidateTypeD0(candidate); // Candidate type attribution bool const isDCand = isD(candidateType); bool const isDbarCand = isDbar(candidateType); bool const isTrueDCand = isTrueD(candidateType); @@ -697,23 +673,23 @@ struct HfCorrelatorDMesonPairs { } } // Fill True info - if (isTrueDCand1 != 0) { + if (isTrueDCand1) { registry.fill(HIST("hSelectionStatus"), 6); - } else if (isTrueDbarCand1 != 0) { + } else if (isTrueDbarCand1) { registry.fill(HIST("hSelectionStatus"), 7); } - if (isTrueDCand2 != 0) { + if (isTrueDCand2) { registry.fill(HIST("hSelectionStatus"), 12); - } else if (isTrueDbarCand2 != 0) { + } else if (isTrueDbarCand2) { registry.fill(HIST("hSelectionStatus"), 13); } - if ((isTrueDCand1 != 0) && (isTrueDCand2 != 0)) { + if (isTrueDCand1 && isTrueDCand2) { registry.fill(HIST("hSelectionStatus"), 22); - } else if ((isTrueDbarCand1 != 0) && (isTrueDbarCand2 != 0)) { + } else if (isTrueDbarCand1 && isTrueDbarCand2) { registry.fill(HIST("hSelectionStatus"), 23); - } else if ((isTrueDCand1 != 0) && (isTrueDbarCand2 != 0)) { + } else if (isTrueDCand1 && isTrueDbarCand2) { registry.fill(HIST("hSelectionStatus"), 24); - } else if ((isTrueDbarCand1 != 0) && (isTrueDCand2 != 0)) { + } else if (isTrueDbarCand1 && isTrueDCand2) { registry.fill(HIST("hSelectionStatus"), 25); } } @@ -739,57 +715,40 @@ struct HfCorrelatorDMesonPairs { return pairType; } - void fillMatchingHisto(int8_t matchedRec1, int8_t matchedRec2) + template + void fillMatchingHisto(const int8_t matched1, const int8_t matched2) { - // Fill hMatchingMcRec - Cand 1 - registry.fill(HIST("hMatchingMcRec"), 1); - if (matchedRec1 == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { - registry.fill(HIST("hMatchingMcRec"), 2); - } else if (matchedRec1 == -o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { - registry.fill(HIST("hMatchingMcRec"), 3); - } else if (matchedRec1 == 0) { - registry.fill(HIST("hMatchingMcRec"), 4); + auto hist = IsGen ? registry.get(HIST("hMatchingMcGen")) : registry.get(HIST("hMatchingMcRec")); + hist->Fill(1); + if (matched1 == DecayChannel::D0ToPiK) { + hist->Fill(2); + } else if (matched1 == -DecayChannel::D0ToPiK) { + hist->Fill(3); + } else if (matched1 == 0) { + hist->Fill(4); } - // Fill hMatchingMcRec - Cand 2 - registry.fill(HIST("hMatchingMcRec"), 5); - if (matchedRec2 == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { - registry.fill(HIST("hMatchingMcRec"), 6); - } else if (matchedRec2 == -o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { - registry.fill(HIST("hMatchingMcRec"), 7); - } else if (matchedRec2 == 0) { - registry.fill(HIST("hMatchingMcRec"), 8); + hist->Fill(5); + if (matched2 == DecayChannel::D0ToPiK) { + hist->Fill(6); + } else if (matched2 == -DecayChannel::D0ToPiK) { + hist->Fill(7); + } else if (matched2 == 0) { + hist->Fill(8); } } - template + /// D0(bar)-D0(bar) correlation pair builder, shared by the data and MC-reco modes + /// \param collision is the collision + /// \param selectedD0CandidatesGrouped is the per-collision slice of the selected D0 candidates + /// \param tracks are the (already filtered) tracks of the collision + /// \param timeStamp is the BC timestamp of the collision + template void processImpl(TCollision const& collision, - TCandidates const& selectedD0CandidatesGrouped, // per-collision slice of the partition - TTracks const& tracks, + TCandidates const& selectedD0CandidatesGrouped, const int64_t timeStamp) { - int gCollisionId = collision.globalIndex(); - int poolBin = corrBinning->getBin(std::make_tuple(collision.posZ(), collision.multFT0M())); - - int nTracks = 0; - if (collision.numContrib() > 1) { - for (const auto& track : tracks) { - if (std::abs(track.eta()) >= etaTrackMax || std::abs(track.dcaXY()) >= dcaXYTrackMax || std::abs(track.dcaZ()) >= dcaZTrackMax) { - continue; - } - nTracks++; - } - } - if (applyMixedEvent) { - registry.fill(HIST("hMultiplicityPreSelection"), nTracks); - } - if (nTracks < multMin || nTracks > multMax) { - return; - } - if (applyMixedEvent) { - registry.fill(HIST("hMultiplicity"), nTracks); - } - - int cntD0 = 0; + int const gCollisionId = collision.globalIndex(); + int const poolBin = corrBinning->getBin(std::make_tuple(collision.posZ(), collision.multFT0M())); getCountersPerEvent(selectedD0CandidatesGrouped); @@ -799,22 +758,21 @@ struct HfCorrelatorDMesonPairs { outputMlD0Cand1.clear(); outputMlD0barCand1.clear(); - auto prong0Cand1 = candidate1.template prong0_as(); - auto prong1Cand1 = candidate1.template prong1_as(); - - int8_t matchedRec1 = 0; - int8_t originRec1 = 0; + auto const prong0Cand1 = candidate1.prong0Id(); + auto const prong1Cand1 = candidate1.prong1Id(); + [[maybe_unused]] int8_t matchedRec1 = 0; + [[maybe_unused]] int8_t originRec1 = 0; if constexpr (IsMcRec) { matchedRec1 = candidate1.flagMcMatchRec(); originRec1 = candidate1.originMcRec(); } - auto candidateType1 = assignCandidateTypeD0(candidate1); // Candidate type attribution - bool isDCand1 = isD(candidateType1); - bool isDbarCand1 = isDbar(candidateType1); - bool isTrueDCand1 = isTrueD(candidateType1); - bool isTrueDbarCand1 = isTrueDbar(candidateType1); + auto const candidateType1 = assignCandidateTypeD0(candidate1); // Candidate type attribution + bool const isDCand1 = isD(candidateType1); + bool const isDbarCand1 = isDbar(candidateType1); + bool const isTrueDCand1 = isTrueD(candidateType1); + bool const isTrueDbarCand1 = isTrueDbar(candidateType1); registry.fill(HIST("hPtCand"), candidate1.pt()); @@ -866,8 +824,8 @@ struct HfCorrelatorDMesonPairs { } } if (isDbarCand1) { - // Fill THnSparse for D0bar candidates registry.fill(HIST("hMass"), HfHelper::invMassD0barToKPi(candidate1), candidate1.pt()); + // Fill THnSparse for D0bar candidates if (applyMl) { registry.fill(HIST("hnDMesonMl"), outputMlD0barCand1[0], outputMlD0barCand1[1], HfHelper::invMassD0barToKPi(candidate1), candidate1.pt(), candidate1.y(MassD0), collision.numContrib(), originRec1, candidateType1); } else { @@ -880,75 +838,38 @@ struct HfCorrelatorDMesonPairs { registry.fill(HIST("hNContribMcRec"), collision.numContrib()); if (originRec1 == RecoDecay::Prompt) { registry.fill(HIST("hMassMcRecPrompt"), HfHelper::invMassD0barToKPi(candidate1), candidate1.pt()); + registry.fill(HIST("hPtVsYVsNContribMcRecPrompt"), candidate1.pt(), HfHelper::yD0(candidate1), collision.numContrib()); } else if (originRec1 == RecoDecay::NonPrompt) { registry.fill(HIST("hMassMcRecNonPrompt"), HfHelper::invMassD0barToKPi(candidate1), candidate1.pt()); + registry.fill(HIST("hPtVsYVsNContribMcRecNonPrompt"), candidate1.pt(), HfHelper::yD0(candidate1), collision.numContrib()); } } else if (isTrueDCand1) { registry.fill(HIST("hMassMcRecReflections"), HfHelper::invMassD0barToKPi(candidate1), candidate1.pt()); } - // Fill D0 table for offline event mixing + // Fill D0bar table for offline event mixing if (applyMixedEvent) { - entryDMesonInfoCand1(candidate1.pt(), candidate1.eta(), candidate1.phi(), HfHelper::invMassD0ToPiK(candidate1), candidateType1, poolBin, gCollisionId, timeStamp); + entryDMesonInfoCand1(candidate1.pt(), candidate1.eta(), candidate1.phi(), HfHelper::invMassD0barToKPi(candidate1), candidateType1, poolBin, gCollisionId, timeStamp); } } - if (applyMixedEvent) { - // Loop on the associated tracks for offline event mixing - for (const auto& track : tracks) { - // apply track selection - if (track.collisionId() != gCollisionId) { - continue; - } - - // Manual trackFilter check - if (std::abs(track.eta()) >= etaTrackMax) { - continue; - } - if (track.pt() <= ptTrackMin) { - continue; - } - if (std::abs(track.dcaXY()) >= dcaXYTrackMax) { - continue; - } - if (std::abs(track.dcaZ()) >= dcaZTrackMax) { - continue; - } - // Removing D0 daughters by checking track indices - if (daughterTracksCutFlag) { - if ((candidate1.prong0Id() == track.globalIndex()) || (candidate1.prong1Id() == track.globalIndex())) { - continue; - } - } - if (cntD0 == 0) { - entryAssocHad(track.pt(), track.eta(), track.phi(), poolBin, gCollisionId, timeStamp); - registry.fill(HIST("hTracksBin"), poolBin); - registry.fill(HIST("hDcaXYVsPt"), track.dcaXY(), track.pt()); - } - } // Hadron Tracks loop - cntD0++; - } - // Loop on the second D0 candidate for (auto candidate2 = candidate1 + 1; candidate2 != selectedD0CandidatesGrouped.end(); ++candidate2) { outputMlD0Cand2.clear(); outputMlD0barCand2.clear(); - auto prong0Cand2 = candidate2.template prong0_as(); - auto prong1Cand2 = candidate2.template prong1_as(); + auto const prong0Cand2 = candidate2.prong0Id(); + auto const prong1Cand2 = candidate2.prong1Id(); if ((prong0Cand1 == prong0Cand2) || (prong1Cand1 == prong1Cand2) || (prong0Cand1 == prong1Cand2) || (prong1Cand1 == prong0Cand2)) { continue; } - auto candidateType2 = assignCandidateTypeD0(candidate2); // Candidate type attribution - bool isDCand2 = isD(candidateType2); - bool isDbarCand2 = isDbar(candidateType2); - bool isTrueDCand2 = isTrueD(candidateType2); - bool isTrueDbarCand2 = isTrueDbar(candidateType2); + auto const candidateType2 = assignCandidateTypeD0(candidate2); // Candidate type attribution + bool const isDCand2 = isD(candidateType2); + bool const isDbarCand2 = isDbar(candidateType2); int8_t matchedRec2 = 0; int8_t originRec2 = 0; - if constexpr (IsMcRec) { matchedRec2 = candidate2.flagMcMatchRec(); originRec2 = candidate2.originMcRec(); @@ -964,7 +885,7 @@ struct HfCorrelatorDMesonPairs { if (applyMixedEvent) { if (isDCand2) { - entryDMesonInfoCand2(candidate2.pt(), candidate2.eta(), candidate2.phi(), HfHelper::invMassD0barToKPi(candidate2), candidateType2, poolBin, gCollisionId, timeStamp); + entryDMesonInfoCand2(candidate2.pt(), candidate2.eta(), candidate2.phi(), HfHelper::invMassD0ToPiK(candidate2), candidateType2, poolBin, gCollisionId, timeStamp); } if (isDbarCand2) { entryDMesonInfoCand2(candidate2.pt(), candidate2.eta(), candidate2.phi(), HfHelper::invMassD0barToKPi(candidate2), candidateType2, poolBin, gCollisionId, timeStamp); @@ -972,25 +893,27 @@ struct HfCorrelatorDMesonPairs { registry.fill(HIST("hD0Cand2Bin"), poolBin); } - uint8_t pairType = setPairType(candidateType1, candidateType2); - if (shouldSwapOrder(isDCand1, isDbarCand1, isDCand2, isDbarCand2, candidate1, candidate2)) { - std::swap(isDCand1, isDCand2); - std::swap(isDbarCand1, isDbarCand2); - std::swap(isTrueDCand1, isTrueDCand2); - std::swap(isTrueDbarCand1, isTrueDbarCand2); - } + // Canonical ordering of the pair: D0 first (higher pT first for equal flavours) + bool const swapOrder = shouldSwapOrder(isDCand1, isDbarCand1, isDCand2, isDbarCand2, candidate1, candidate2); + uint8_t const type1 = swapOrder ? candidateType2 : candidateType1; + uint8_t const type2 = swapOrder ? candidateType1 : candidateType2; + auto const& first = swapOrder ? candidate2 : candidate1; + auto const& second = swapOrder ? candidate1 : candidate2; + uint8_t const pairType = setPairType(type1, type2); // Fill entries for D0-D0(bar) pairs and plot histos - fillSelectionStatusHisto(candidateType1, candidateType2); - entryD0Pair(candidate1.pt(), candidate2.pt(), HfHelper::yD0(candidate1), HfHelper::yD0(candidate2), candidate1.eta(), candidate2.eta(), - candidate1.phi(), candidate2.phi(), HfHelper::invMassD0ToPiK(candidate1), HfHelper::invMassD0barToKPi(candidate1), - HfHelper::invMassD0ToPiK(candidate2), HfHelper::invMassD0barToKPi(candidate2), pairType, candidateType1, candidateType2); + fillSelectionStatusHisto(type1, type2); + entryD0Pair(first.pt(), second.pt(), HfHelper::yD0(first), HfHelper::yD0(second), first.eta(), second.eta(), + first.phi(), second.phi(), HfHelper::invMassD0ToPiK(first), HfHelper::invMassD0barToKPi(first), + HfHelper::invMassD0ToPiK(second), HfHelper::invMassD0barToKPi(second), pairType, type1, type2); if (applyMl) { - entryD0PairMl(outputMlD0Cand1, outputMlD0barCand1, outputMlD0Cand2, outputMlD0barCand2); + entryD0PairMl(swapOrder ? outputMlD0Cand2 : outputMlD0Cand1, swapOrder ? outputMlD0barCand2 : outputMlD0barCand1, + swapOrder ? outputMlD0Cand1 : outputMlD0Cand2, swapOrder ? outputMlD0barCand1 : outputMlD0barCand2); } if constexpr (IsMcRec) { - fillMatchingHisto(matchedRec1, matchedRec2); - entryD0PairMcInfo(originRec1, originRec2, matchedRec1, matchedRec2); + fillMatchingHisto(swapOrder ? matchedRec2 : matchedRec1, swapOrder ? matchedRec1 : matchedRec2); + entryD0PairMcInfo(swapOrder ? originRec2 : originRec1, swapOrder ? originRec1 : originRec2, + swapOrder ? matchedRec2 : matchedRec1, swapOrder ? matchedRec1 : matchedRec2); } } // end inner loop (Cand2) } // end outer loop (Cand1) @@ -1001,61 +924,84 @@ struct HfCorrelatorDMesonPairs { } } + /// D0(bar)-D0(bar) correlation pair builder - for real data and data-like analysis (i.e. reco-level w/o matching request via MC truth) void processData(SelCollisionsWithD0::iterator const& collision, - CandidatesD0Data const&, TracksData const& tracks, aod::BCsWithTimestamps const&) + CandidatesD0Data const&, aod::Tracks const&, aod::BCsWithTimestamps const&) { - const auto timeStamp = collision.bc_as().timestamp(); + auto const timeStamp = collision.bc_as().timestamp(); auto grouped = selectedD0Candidates->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); - processImpl(collision, grouped, tracks, timeStamp); + processImpl(collision, grouped, timeStamp); } PROCESS_SWITCH(HfCorrelatorDMesonPairs, processData, "Process data mode", true); - void processMcRec(SelCollisionsWithD0::iterator const& collision, CandidatesD0McRec const&, TracksData const& tracks, aod::BCsWithTimestamps const&) + /// D0(bar)-D0(bar) correlation pair builder - MC reco level (candidates matched to MC truth) + void processMcRec(SelCollisionsWithD0::iterator const& collision, + CandidatesD0McRec const&, aod::Tracks const&, aod::BCsWithTimestamps const&) { - const auto timeStamp = collision.bc_as().timestamp(); + auto const timeStamp = collision.bc_as().timestamp(); auto grouped = selectedD0CandidatesMc->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); - processImpl(collision, grouped, tracks, timeStamp); + processImpl(collision, grouped, timeStamp); } PROCESS_SWITCH(HfCorrelatorDMesonPairs, processMcRec, "Process MC reco mode", false); - void processMcGen(aod::McCollision const&, soa::SmallGroups> const& collisions, McParticlesPlus2Prong const& mcParticles) + /// D0(bar)-D0(bar) correlation pair builder - MC generator level (particles flagged as D0 -> pi K) + void processMcGen(aod::McCollision const&, soa::SmallGroups> const& collisions, McParticlesPlus2Prong const& mcParticles) { + // Take the associated reconstructed collision with the highest number of PV contributors int numPvContributorsGen{0}; - for (const auto& collision : collisions) { // loop over reco collisions associated to this gen collision + for (const auto& collision : collisions) { int const numPvContributors = collision.numContrib(); - - if (numPvContributors > numPvContributorsGen) { // we take the associated reconstructed collision with higher number of PV contributors + if (numPvContributors > numPvContributorsGen) { numPvContributorsGen = numPvContributors; } } - // Get counters per event - int nDevent = 0, nDbarevent = 0, nDDbarevent = 0, nDorDbarevent = 0; + + // Select the D0(bar) -> K pi particles + std::vector selectedParticles; for (const auto& particle : mcParticles) { - // check if the particle is D0 or D0bar decaying to k pi - if (!(std::abs(particle.flagMcMatchGen()) == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK)) { - continue; - } - if (std::abs(particle.y()) > yCandMax) { + if (std::abs(particle.flagMcMatchGen()) != DecayChannel::D0ToPiK) { continue; } - if (ptCandMin >= 0. && particle.pt() < ptCandMin) { + registry.fill(HIST("hPtCandMcGen"), particle.pt()); + if (!passGenSelections(particle)) { continue; } - auto particleType = assignParticleTypeD0Gen(particle); // Candidate type attribution + selectedParticles.push_back(particle); + } + + // Single-particle histograms and per-event counters + int nDevent = 0, nDbarevent = 0, nDDbarevent = 0, nDorDbarevent = 0; + for (const auto& particle : selectedParticles) { + auto const particleType = assignParticleTypeD0Gen(particle); bool const isDParticle = isTrueD(particleType); bool const isDbarParticle = isTrueDbar(particleType); - if (isDParticle) { - nDevent++; - } - if (isDbarParticle) { - nDbarevent++; - } - if (isDParticle && isDbarParticle) { - nDDbarevent++; + nDevent += isDParticle; + nDbarevent += isDbarParticle; + nDDbarevent += (isDParticle && isDbarParticle); + nDorDbarevent += (isDParticle || isDbarParticle); + + registry.fill(HIST("hEtaMcGen"), particle.eta()); + registry.fill(HIST("hPhiMcGen"), particle.phi()); + registry.fill(HIST("hPtCandAfterCutMcGen"), particle.pt()); + + registry.fill(HIST("hStatusSinglePartMcGen"), 1); + if (isDParticle && !isDbarParticle) { + registry.fill(HIST("hStatusSinglePartMcGen"), 2); + registry.fill(HIST("hStatusSinglePartMcGen"), 5); + } else if (isDbarParticle && !isDParticle) { + registry.fill(HIST("hStatusSinglePartMcGen"), 3); + registry.fill(HIST("hStatusSinglePartMcGen"), 6); + } else if (isDParticle && isDbarParticle) { + registry.fill(HIST("hStatusSinglePartMcGen"), 4); } - if (isDParticle || isDbarParticle) { - nDorDbarevent++; + + registry.fill(HIST("hPtVsYVsNContribMcGen"), particle.pt(), particle.y(), numPvContributorsGen); + if (particle.originMcGen() == RecoDecay::Prompt) { + registry.fill(HIST("hPtVsYVsNContribMcGenPrompt"), particle.pt(), particle.y(), numPvContributorsGen); + } else if (particle.originMcGen() == RecoDecay::NonPrompt) { + registry.fill(HIST("hPtVsYVsNContribMcGenNonPrompt"), particle.pt(), particle.y(), numPvContributorsGen); } + registry.fill(HIST("hNContribMcGen"), numPvContributorsGen); } if (nDevent > 0) { registry.fill(HIST("hInputCheckD0McGen"), nDevent); @@ -1070,138 +1016,61 @@ struct HfCorrelatorDMesonPairs { registry.fill(HIST("hInputCheckD0OrD0barMcGen"), nDorDbarevent); } - for (const auto& particle1 : mcParticles) { - // check if the particle is D0 or D0bar decaying to k pi - if (!(std::abs(particle1.flagMcMatchGen()) == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK)) { - continue; - } - registry.fill(HIST("hPtCandMcGen"), particle1.pt()); + // Pairs of selected particles + for (size_t i = 0; i < selectedParticles.size(); ++i) { + for (size_t j = i + 1; j < selectedParticles.size(); ++j) { + auto const& particle1 = selectedParticles[i]; + auto const& particle2 = selectedParticles[j]; - if (std::abs(particle1.y()) > yCandMax) { - continue; - } - if (ptCandMin >= 0. && particle1.pt() < ptCandMin) { - continue; - } - registry.fill(HIST("hEtaMcGen"), particle1.eta()); - registry.fill(HIST("hPhiMcGen"), particle1.phi()); - registry.fill(HIST("hPtCandAfterCutMcGen"), particle1.pt()); + auto const type1 = assignParticleTypeD0Gen(particle1); + auto const type2 = assignParticleTypeD0Gen(particle2); - auto particleType1 = assignParticleTypeD0Gen(particle1); // Candidate sign attribution - bool const isDParticle1 = isTrueD(particleType1); - bool const isDbarParticle1 = isTrueDbar(particleType1); + // Canonical ordering (same as reco): D0 first, higher pT first for equal flavours + bool const swapOrder = shouldSwapOrder(isTrueD(type1), isTrueDbar(type1), isTrueD(type2), isTrueDbar(type2), particle1, particle2); + auto const& first = swapOrder ? particle2 : particle1; + auto const& second = swapOrder ? particle1 : particle2; + auto const typeFirst = swapOrder ? type2 : type1; + auto const typeSecond = swapOrder ? type1 : type2; + bool const isDFirst = isTrueD(typeFirst), isDbarFirst = isTrueDbar(typeFirst); + bool const isDSecond = isTrueD(typeSecond), isDbarSecond = isTrueDbar(typeSecond); - // check if it's MC matched - int8_t matchedGen1 = particle1.flagMcMatchGen(); - // check origin - int8_t originGen1 = particle1.originMcGen(); + fillMatchingHisto(first.flagMcMatchGen(), second.flagMcMatchGen()); - // Fill selection status single particle - registry.fill(HIST("hStatusSinglePartMcGen"), 1); - if (isDParticle1 && !isDbarParticle1) { - registry.fill(HIST("hStatusSinglePartMcGen"), 2); - registry.fill(HIST("hStatusSinglePartMcGen"), 5); - } else if (isDbarParticle1 && !isDParticle1) { - registry.fill(HIST("hStatusSinglePartMcGen"), 3); - registry.fill(HIST("hStatusSinglePartMcGen"), 6); - } else if (isDParticle1 && isDbarParticle1) { - registry.fill(HIST("hStatusSinglePartMcGen"), 4); - } - - registry.fill(HIST("hPtVsYVsNContribMcGen"), particle1.pt(), particle1.y(), numPvContributorsGen); - if (originGen1 == RecoDecay::Prompt) { - registry.fill(HIST("hPtVsYVsNContribMcGenPrompt"), particle1.pt(), particle1.y(), numPvContributorsGen); - } - if (originGen1 == RecoDecay::NonPrompt) { - registry.fill(HIST("hPtVsYVsNContribMcGenNonPrompt"), particle1.pt(), particle1.y(), numPvContributorsGen); - } - registry.fill(HIST("hNContribMcGen"), numPvContributorsGen); - - for (auto particle2 = particle1 + 1; particle2 != mcParticles.end(); ++particle2) { - // check if the particle is D0 or D0bar decaying to k pi - if (!(std::abs(particle2.flagMcMatchGen()) == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK)) { - continue; - } - if (std::abs(particle2.y()) > yCandMax) { - continue; - } - if (ptCandMin >= 0. && particle2.pt() < ptCandMin) { - continue; - } - // Candidate sign attribution. - auto particleType2 = assignParticleTypeD0Gen(particle2); - bool const isDParticle2 = isTrueD(particleType2); - bool const isDbarParticle2 = isTrueDbar(particleType2); - - // check if it's MC matched - int8_t matchedGen2 = particle2.flagMcMatchGen(); - // check origin - int8_t originGen2 = particle2.originMcGen(); - - // Fill hMatchingMcGen - Cand 1 - registry.fill(HIST("hMatchingMcGen"), 1); - if (matchedGen1 == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { - registry.fill(HIST("hMatchingMcGen"), 2); - } else if (matchedGen1 == -o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { - registry.fill(HIST("hMatchingMcGen"), 3); - } else if (matchedGen1 == 0) { - registry.fill(HIST("hMatchingMcGen"), 4); - } - // Fill hMatchingMcRec - Cand 2 - registry.fill(HIST("hMatchingMcGen"), 5); - if (matchedGen2 == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { - registry.fill(HIST("hMatchingMcGen"), 6); - } else if (matchedGen2 == -o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { - registry.fill(HIST("hMatchingMcGen"), 7); - } else if (matchedGen2 == 0) { - registry.fill(HIST("hMatchingMcGen"), 8); - } - - // Fill particle1's Selection Status + // Selection status registry.fill(HIST("hSelectionStatusMcGen"), 2); - if (isDParticle1 && !isDbarParticle1) { + if (isDFirst && !isDbarFirst) { registry.fill(HIST("hSelectionStatusMcGen"), 6); - } else if (isDbarParticle1 && !isDParticle1) { + } else if (isDbarFirst && !isDFirst) { registry.fill(HIST("hSelectionStatusMcGen"), 7); } - - // Fill particle2's Selection Status registry.fill(HIST("hSelectionStatusMcGen"), 8); - if (isDParticle2 && !isDbarParticle2) { + if (isDSecond && !isDbarSecond) { registry.fill(HIST("hSelectionStatusMcGen"), 12); - } else if (isDbarParticle2 && !isDParticle2) { + } else if (isDbarSecond && !isDSecond) { registry.fill(HIST("hSelectionStatusMcGen"), 13); } - // Fill pair Selection Status - uint8_t pairType(0); registry.fill(HIST("hSelectionStatusMcGen"), 1); - - if (isDParticle1 && isDParticle2) { - SETBIT(pairType, DD); + if (isDFirst && isDSecond) { registry.fill(HIST("hSelectionStatusMcGen"), 22); } - if (isDbarParticle1 && isDbarParticle2) { - SETBIT(pairType, DbarDbar); + if (isDbarFirst && isDbarSecond) { registry.fill(HIST("hSelectionStatusMcGen"), 23); } - if (isDParticle1 && isDbarParticle2) { - SETBIT(pairType, DDbar); + if (isDFirst && isDbarSecond) { registry.fill(HIST("hSelectionStatusMcGen"), 24); } - if (isDbarParticle1 && isDParticle2) { - SETBIT(pairType, DbarD); + if (isDbarFirst && isDSecond) { registry.fill(HIST("hSelectionStatusMcGen"), 25); } - // Fill pair Selection Status - entryD0PairMcGen(particle1.pt(), particle2.pt(), particle1.y(), particle2.y(), particle1.eta(), particle2.eta(), particle1.phi(), particle2.phi(), MassD0, MassD0Bar, MassD0, MassD0Bar, pairType, particleType1, particleType2); - entryD0PairMcGenInfo(originGen1, originGen2, matchedGen1, matchedGen2); - - } // end inner loop - } // end outer loop + uint8_t const pairType = setPairType(typeFirst, typeSecond); + entryD0PairMcGen(first.pt(), second.pt(), first.y(), second.y(), first.eta(), second.eta(), first.phi(), second.phi(), + MassD0, MassD0Bar, MassD0, MassD0Bar, pairType, typeFirst, typeSecond); + entryD0PairMcGenInfo(first.originMcGen(), second.originMcGen(), first.flagMcMatchGen(), second.flagMcMatchGen()); + } + } } - PROCESS_SWITCH(HfCorrelatorDMesonPairs, processMcGen, "Process D0 Mc Gen mode", false); }; From 4cd0eb648ffc070755e5e723a1eb566558fefbfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrea=20Tavira=20Garc=C3=ADa?= <118979672+atavirag@users.noreply.github.com> Date: Thu, 15 Oct 2026 09:09:50 +0000 Subject: [PATCH 10/15] reorder functions to improve readability --- .../TableProducer/correlatorDMesonPairs.cxx | 101 +++++++++--------- 1 file changed, 53 insertions(+), 48 deletions(-) diff --git a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx index 5257afd930e..47a7663dd83 100644 --- a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx @@ -410,6 +410,8 @@ struct HfCorrelatorDMesonPairs { } } + /// ------- FUNCTION DEFINITIONS ------- + /// Kinematic, signal-region and ambiguity selections of a candidate /// \return true if the candidate passes the selections template @@ -433,6 +435,57 @@ struct HfCorrelatorDMesonPairs { return true; } + /// ML selections of a candidate + /// \return true if the candidate is selected by the ML model (as D0 and/or D0bar) + template + bool passMlSelections(const T& candidate, const bool isDCand, const bool isDbarCand, std::vector& outputMlD0Cand, std::vector& outputMlD0barCand) + { + bool isSelectedMlD0Cand = false; + bool isSelectedMlD0barCand = false; + + if (isDCand) { + std::vector inputFeaturesD0 = hfMlResponse.getInputFeatures(candidate, o2::constants::physics::kD0); + isSelectedMlD0Cand = hfMlResponse.isSelectedMl(inputFeaturesD0, candidate.pt(), outputMlD0Cand); + } + if (isDbarCand) { + std::vector inputFeaturesD0bar = hfMlResponse.getInputFeatures(candidate, o2::constants::physics::kD0Bar); + isSelectedMlD0barCand = hfMlResponse.isSelectedMl(inputFeaturesD0bar, candidate.pt(), outputMlD0barCand); + } + + return isSelectedMlD0Cand || isSelectedMlD0barCand; + } + + /// Rapidity and pT selections of gen-level particles + template + bool passGenSelections(const T& particle) + { + return std::abs(particle.y()) <= yCandMax && (ptCandMin < 0. || particle.pt() >= ptCandMin); + } + + /// Sets bits to select pair types. + /// \param candidate is candidate + /// \return bitmap with type of pair (DD, DbarDbar, DDbar, DbarD) + uint8_t setPairType(const uint8_t candidateType1, const uint8_t candidateType2) + { + uint8_t pairType(0); + bool const isDCand1 = isD(candidateType1), isDCand2 = isD(candidateType2); + bool const isDbarCand1 = isDbar(candidateType1), isDbarCand2 = isDbar(candidateType2); + + if (isDCand1 && isDCand2) { + SETBIT(pairType, DD); + } + if (isDbarCand1 && isDbarCand2) { + SETBIT(pairType, DbarDbar); + } + if (isDCand1 && isDbarCand2) { + SETBIT(pairType, DDbar); + } + if (isDbarCand1 && isDCand2) { + SETBIT(pairType, DbarD); + } + return pairType; + } + /// Sets bits to select candidate type for D0 /// SelectedD and SelectedDbar bits look at whether the candidate passed the selection flags. /// \param candidate is candidate @@ -498,13 +551,6 @@ struct HfCorrelatorDMesonPairs { return (TESTBIT(candidateType, TrueDbar)); } - /// Rapidity and pT selections of gen-level particles - template - bool passGenSelections(const T& particle) - { - return std::abs(particle.y()) <= yCandMax && (ptCandMin < 0. || particle.pt() >= ptCandMin); - } - /// Canonical pair ordering: D0 before D0bar; for equal flavours, higher pT first. /// \return true if candidate 1 and candidate 2 should be exchanged template @@ -516,26 +562,6 @@ struct HfCorrelatorDMesonPairs { return candidate1.pt() < candidate2.pt(); } - /// ML selections of a candidate - /// \return true if the candidate is selected by the ML model (as D0 and/or D0bar) - template - bool passMlSelections(const T& candidate, const bool isDCand, const bool isDbarCand, std::vector& outputMlD0Cand, std::vector& outputMlD0barCand) - { - bool isSelectedMlD0Cand = false; - bool isSelectedMlD0barCand = false; - - if (isDCand) { - std::vector inputFeaturesD0 = hfMlResponse.getInputFeatures(candidate, o2::constants::physics::kD0); - isSelectedMlD0Cand = hfMlResponse.isSelectedMl(inputFeaturesD0, candidate.pt(), outputMlD0Cand); - } - if (isDbarCand) { - std::vector inputFeaturesD0bar = hfMlResponse.getInputFeatures(candidate, o2::constants::physics::kD0Bar); - isSelectedMlD0barCand = hfMlResponse.isSelectedMl(inputFeaturesD0bar, candidate.pt(), outputMlD0barCand); - } - - return isSelectedMlD0Cand || isSelectedMlD0barCand; - } - /// Fill PID related plots for D0 and D0bar /// \param candidate is candidate template @@ -694,27 +720,6 @@ struct HfCorrelatorDMesonPairs { } } - uint8_t setPairType(const uint8_t candidateType1, const uint8_t candidateType2) - { - uint8_t pairType(0); - bool const isDCand1 = isD(candidateType1), isDCand2 = isD(candidateType2); - bool const isDbarCand1 = isDbar(candidateType1), isDbarCand2 = isDbar(candidateType2); - - if (isDCand1 && isDCand2) { - SETBIT(pairType, DD); - } - if (isDbarCand1 && isDbarCand2) { - SETBIT(pairType, DbarDbar); - } - if (isDCand1 && isDbarCand2) { - SETBIT(pairType, DDbar); - } - if (isDbarCand1 && isDCand2) { - SETBIT(pairType, DbarD); - } - return pairType; - } - template void fillMatchingHisto(const int8_t matched1, const int8_t matched2) { From 914a23c77ac17a03dec4372e5905d55ab74f7ef8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrea=20Tavira=20Garc=C3=ADa?= <118979672+atavirag@users.noreply.github.com> Date: Thu, 15 Oct 2026 09:14:46 +0000 Subject: [PATCH 11/15] fix O2 linter --- PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx index 47a7663dd83..98f161c8149 100644 --- a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx @@ -145,7 +145,6 @@ struct HfCorrelatorDMesonPairs { // Tables for event mixing Produces entryDMesonInfoCand1; Produces entryDMesonInfoCand2; - Produces entryAssocHad; Configurable selectionFlagD0{"selectionFlagD0", 1, "Selection Flag for D0"}; Configurable selectionFlagD0bar{"selectionFlagD0bar", 1, "Selection Flag for D0bar"}; @@ -183,6 +182,8 @@ struct HfCorrelatorDMesonPairs { Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB"}; Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + SliceCache cache; + // Table aliases. The partitions below must have exactly the same type as the // candidate table taken by the process functions, otherwise they are never bound. using SelCollisionsWithD0 = soa::Filtered>; @@ -193,8 +194,6 @@ struct HfCorrelatorDMesonPairs { Filter collisionFilter = aod::hf_selection_dmeson_collision::dmesonSel == true; Filter trackFilter = (nabs(aod::track::eta) < etaTrackMax) && (aod::track::pt > ptTrackMin) && (nabs(aod::track::dcaXY) < dcaXYTrackMax) && (nabs(aod::track::dcaZ) < dcaZTrackMax); - SliceCache cache; - Partition selectedD0Candidates = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; Partition selectedD0CandidatesMc = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; From be10cc51f1fa7d70e770b26d217951c7626c99ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrea=20Tavira=20Garc=C3=ADa?= <118979672+atavirag@users.noreply.github.com> Date: Thu, 15 Oct 2026 09:46:31 +0000 Subject: [PATCH 12/15] remove unused configurables --- PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx index 98f161c8149..0daab813ee0 100644 --- a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx @@ -155,17 +155,7 @@ struct HfCorrelatorDMesonPairs { Configurable massCut{"massCut", 0.05, "Maximum deviation from PDG peak allowed for signal region"}; Configurable removeAmbiguous{"removeAmbiguous", false, "Flag to remove ambiguous candidates"}; Configurable ptMaxRemoveAmbiguous{"ptMaxRemoveAmbiguous", 5.0, "Max. pT to remove the ambiguous candidates"}; - - // Event mixing configurables Configurable applyMixedEvent{"applyMixedEvent", false, "Flag to make the event mixing"}; - Configurable daughterTracksCutFlag{"daughterTracksCutFlag", false, "Flag to add cut on daughter tracks"}; - Configurable> binsPtHadron{"binsPtHadron", std::vector{0.3, 2., 4., 8., 12., 50.}, "pT bin limits for assoc particle"}; - Configurable etaTrackMax{"etaTrackMax", 0.8, "max. eta of tracks"}; - Configurable dcaXYTrackMax{"dcaXYTrackMax", 1., "max. DCA_xy of tracks"}; - Configurable dcaZTrackMax{"dcaZTrackMax", 1., "max. DCA_z of tracks"}; - Configurable ptTrackMin{"ptTrackMin", 0.3, "min. track pT"}; - Configurable multMin{"multMin", 0, "minimum multiplicity accepted"}; - Configurable multMax{"multMax", 10000, "maximum multiplicity accepted"}; // ML inference Configurable applyMl{"applyMl", false, "Flag to apply ML selections"}; @@ -189,10 +179,8 @@ struct HfCorrelatorDMesonPairs { using SelCollisionsWithD0 = soa::Filtered>; using CandidatesD0Data = soa::Join; using CandidatesD0McRec = soa::Join; - using TracksData = soa::Filtered>; Filter collisionFilter = aod::hf_selection_dmeson_collision::dmesonSel == true; - Filter trackFilter = (nabs(aod::track::eta) < etaTrackMax) && (aod::track::pt > ptTrackMin) && (nabs(aod::track::dcaXY) < dcaXYTrackMax) && (nabs(aod::track::dcaZ) < dcaZTrackMax); Partition selectedD0Candidates = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; Partition selectedD0CandidatesMc = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; From cec7a01beaf5db8c9ad48769b6f380513021782e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrea=20Tavira=20Garc=C3=ADa?= <118979672+atavirag@users.noreply.github.com> Date: Thu, 15 Oct 2026 12:50:20 +0000 Subject: [PATCH 13/15] Cleanup DmesonPairsTables.h --- PWGHF/HFC/DataModel/DMesonPairsTables.h | 37 +++++++------------------ 1 file changed, 10 insertions(+), 27 deletions(-) diff --git a/PWGHF/HFC/DataModel/DMesonPairsTables.h b/PWGHF/HFC/DataModel/DMesonPairsTables.h index 65f76dc586e..dfc21ee0b6a 100644 --- a/PWGHF/HFC/DataModel/DMesonPairsTables.h +++ b/PWGHF/HFC/DataModel/DMesonPairsTables.h @@ -113,40 +113,23 @@ DECLARE_SOA_COLUMN(PoolBinD, poolBinD, int); //! Pool bin of the D meson DECLARE_SOA_COLUMN(GIndexColD, gIndexColD, int); //! G-index column of the D meson DECLARE_SOA_COLUMN(TimestampD, timestampD, int64_t); //! Timestamp of the D meson -// Associated hadron -DECLARE_SOA_COLUMN(PtHad, ptHad, float); //! Transverse momentum of the associated hadron -DECLARE_SOA_COLUMN(YHad, yHad, float); //! Rapidity of the associated hadron -DECLARE_SOA_COLUMN(EtaHad, etaHad, float); //! Pseudorapidity of the associated hadron -DECLARE_SOA_COLUMN(PhiHad, phiHad, float); //! Azimuthal angle of the associated hadron -DECLARE_SOA_COLUMN(PoolBinHad, poolBinHad, int); //! Pool bin of the associated hadron -DECLARE_SOA_COLUMN(GIndexColHad, gIndexColHad, int); //! G-index column of the associated hadron -DECLARE_SOA_COLUMN(TimestampHad, timestampHad, int64_t); //! Timestamp of the associated hadron - } // namespace hf_correlation_d_meson_had // Definition of the D meson table for D-had correlations. Contains the info needed at Data level. -#define DECLARE_DMESON_ME_TABLE(_cand_number_, _marker_value_, _description_) \ - DECLARE_SOA_TABLE(_cand_number_, "AOD", _description_, o2::soa::Marker<_marker_value_>, \ - hf_correlation_d_meson_had::PtD, \ - hf_correlation_d_meson_had::EtaD, \ - hf_correlation_d_meson_had::PhiD, \ - hf_correlation_d_meson_had::MD, \ - hf_correlation_d_meson_had::DType, \ - hf_correlation_d_meson_had::PoolBinD, \ - hf_correlation_d_meson_had::GIndexColD, \ - hf_correlation_d_meson_had::TimestampD); +#define DECLARE_DMESON_ME_TABLE(_cand_number_, _marker_value_, _description_) \ + DECLARE_SOA_TABLE(_cand_number_, "AOD", _description_, o2::soa::Marker<_marker_value_>, \ + hf_correlation_d_meson_had::PtD, \ + hf_correlation_d_meson_had::EtaD, \ + hf_correlation_d_meson_had::PhiD, \ + hf_correlation_d_meson_had::MD, \ + hf_correlation_d_meson_had::DType, \ + hf_correlation_d_meson_had::PoolBinD, \ + hf_correlation_d_meson_had::GIndexColD, \ + hf_correlation_d_meson_had::TimestampD); DECLARE_DMESON_ME_TABLE(DMesonInfoCand1, 1, "DMESCAND1"); //! D0 cand 1 info for event mixing DECLARE_DMESON_ME_TABLE(DMesonInfoCand2, 2, "DMESCAND2"); //! D0 cand 2 info for event mixing -DECLARE_SOA_TABLE(AssocHadInfo, "AOD", "ASSOCHADINFO", - hf_correlation_d_meson_had::PtHad, - hf_correlation_d_meson_had::EtaHad, - hf_correlation_d_meson_had::PhiHad, - hf_correlation_d_meson_had::PoolBinHad, - hf_correlation_d_meson_had::GIndexColHad, - hf_correlation_d_meson_had::TimestampHad); - } // namespace o2::aod #endif // PWGHF_HFC_DATAMODEL_DMESONPAIRSTABLES_H_ From 30831b8597491f8cfe0cdc713ac7bfe9a5a8a7c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrea=20Tavira=20Garc=C3=ADa?= <118979672+atavirag@users.noreply.github.com> Date: Thu, 15 Oct 2026 12:57:33 +0000 Subject: [PATCH 14/15] small fix --- PWGHF/HFC/DataModel/DMesonPairsTables.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/PWGHF/HFC/DataModel/DMesonPairsTables.h b/PWGHF/HFC/DataModel/DMesonPairsTables.h index dfc21ee0b6a..f1c8539274c 100644 --- a/PWGHF/HFC/DataModel/DMesonPairsTables.h +++ b/PWGHF/HFC/DataModel/DMesonPairsTables.h @@ -116,15 +116,15 @@ DECLARE_SOA_COLUMN(TimestampD, timestampD, int64_t); //! Timestamp of the D meso } // namespace hf_correlation_d_meson_had // Definition of the D meson table for D-had correlations. Contains the info needed at Data level. -#define DECLARE_DMESON_ME_TABLE(_cand_number_, _marker_value_, _description_) \ - DECLARE_SOA_TABLE(_cand_number_, "AOD", _description_, o2::soa::Marker<_marker_value_>, \ - hf_correlation_d_meson_had::PtD, \ - hf_correlation_d_meson_had::EtaD, \ - hf_correlation_d_meson_had::PhiD, \ - hf_correlation_d_meson_had::MD, \ - hf_correlation_d_meson_had::DType, \ - hf_correlation_d_meson_had::PoolBinD, \ - hf_correlation_d_meson_had::GIndexColD, \ +#define DECLARE_DMESON_ME_TABLE(_cand_number_, _marker_value_, _description_) \ + DECLARE_SOA_TABLE(_cand_number_, "AOD", _description_, o2::soa::Marker<_marker_value_>, \ + hf_correlation_d_meson_had::PtD, \ + hf_correlation_d_meson_had::EtaD, \ + hf_correlation_d_meson_had::PhiD, \ + hf_correlation_d_meson_had::MD, \ + hf_correlation_d_meson_had::DType, \ + hf_correlation_d_meson_had::PoolBinD, \ + hf_correlation_d_meson_had::GIndexColD, \ hf_correlation_d_meson_had::TimestampD); DECLARE_DMESON_ME_TABLE(DMesonInfoCand1, 1, "DMESCAND1"); //! D0 cand 1 info for event mixing From 99496c6520a5ad555f4af7e3a0d593bf71a0a978 Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Thu, 15 Oct 2026 12:59:26 +0000 Subject: [PATCH 15/15] Please consider the following formatting changes --- PWGHF/HFC/DataModel/DMesonPairsTables.h | 16 ++++++++-------- .../HFC/TableProducer/correlatorDMesonPairs.cxx | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/PWGHF/HFC/DataModel/DMesonPairsTables.h b/PWGHF/HFC/DataModel/DMesonPairsTables.h index f1c8539274c..a5dccbaf0aa 100644 --- a/PWGHF/HFC/DataModel/DMesonPairsTables.h +++ b/PWGHF/HFC/DataModel/DMesonPairsTables.h @@ -118,14 +118,14 @@ DECLARE_SOA_COLUMN(TimestampD, timestampD, int64_t); //! Timestamp of the D meso // Definition of the D meson table for D-had correlations. Contains the info needed at Data level. #define DECLARE_DMESON_ME_TABLE(_cand_number_, _marker_value_, _description_) \ DECLARE_SOA_TABLE(_cand_number_, "AOD", _description_, o2::soa::Marker<_marker_value_>, \ - hf_correlation_d_meson_had::PtD, \ - hf_correlation_d_meson_had::EtaD, \ - hf_correlation_d_meson_had::PhiD, \ - hf_correlation_d_meson_had::MD, \ - hf_correlation_d_meson_had::DType, \ - hf_correlation_d_meson_had::PoolBinD, \ - hf_correlation_d_meson_had::GIndexColD, \ - hf_correlation_d_meson_had::TimestampD); + hf_correlation_d_meson_had::PtD, \ + hf_correlation_d_meson_had::EtaD, \ + hf_correlation_d_meson_had::PhiD, \ + hf_correlation_d_meson_had::MD, \ + hf_correlation_d_meson_had::DType, \ + hf_correlation_d_meson_had::PoolBinD, \ + hf_correlation_d_meson_had::GIndexColD, \ + hf_correlation_d_meson_had::TimestampD); DECLARE_DMESON_ME_TABLE(DMesonInfoCand1, 1, "DMESCAND1"); //! D0 cand 1 info for event mixing DECLARE_DMESON_ME_TABLE(DMesonInfoCand2, 2, "DMESCAND2"); //! D0 cand 2 info for event mixing diff --git a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx index 0daab813ee0..b6d40c9e764 100644 --- a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx @@ -544,7 +544,7 @@ struct HfCorrelatorDMesonPairs { static bool shouldSwapOrder(const bool isD1, const bool isDbar1, const bool isD2, const bool isDbar2, const T& candidate1, const T& candidate2) { if (isD1 != isD2 || isDbar1 != isDbar2) { // different flavour content - return !isD1 && isD2; // Dbar(-only) first, D second -> swap + return !isD1 && isD2; // Dbar(-only) first, D second -> swap } return candidate1.pt() < candidate2.pt(); } @@ -937,7 +937,7 @@ struct HfCorrelatorDMesonPairs { PROCESS_SWITCH(HfCorrelatorDMesonPairs, processMcRec, "Process MC reco mode", false); /// D0(bar)-D0(bar) correlation pair builder - MC generator level (particles flagged as D0 -> pi K) - void processMcGen(aod::McCollision const&, soa::SmallGroups> const& collisions, McParticlesPlus2Prong const& mcParticles) + void processMcGen(aod::McCollision const&, soa::SmallGroups> const& collisions, McParticlesPlus2Prong const& mcParticles) { // Take the associated reconstructed collision with the highest number of PV contributors int numPvContributorsGen{0};