From ca902eaf3c5f2a0f4c6de90f236465c72070f394 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Mon, 19 Jan 2026 16:06:22 +0100 Subject: [PATCH 1/4] Update alice3HfTask3Prong.cxx --- ALICE3/Tasks/alice3HfTask3Prong.cxx | 80 +++++++++++++++++++++-------- 1 file changed, 58 insertions(+), 22 deletions(-) diff --git a/ALICE3/Tasks/alice3HfTask3Prong.cxx b/ALICE3/Tasks/alice3HfTask3Prong.cxx index 6d0ec84f215..a5cdae3b36e 100644 --- a/ALICE3/Tasks/alice3HfTask3Prong.cxx +++ b/ALICE3/Tasks/alice3HfTask3Prong.cxx @@ -87,14 +87,15 @@ struct Alice3HfTask3Prong { HistogramRegistry registry{"registry", {}}; // Names of folders and suffixes for MC signal histograms - constexpr static std::string_view SignalFolders[] = {"signal", "prompt", "nonprompt"}; - constexpr static std::string_view SignalSuffixes[] = {"", "Prompt", "NonPrompt"}; - enum SignalClasses : int { Signal = 0, Prompt, - NonPrompt + NonPrompt, + Bkg, + NSignalClasses }; + constexpr static std::string_view SignalFolders[SignalClasses::NSignalClasses] = {"signal", "prompt", "nonprompt", "background"}; + constexpr static std::string_view SignalSuffixes[SignalClasses::NSignalClasses] = {"", "Prompt", "NonPrompt", "Bkg"}; void init(InitContext&) { @@ -109,9 +110,11 @@ struct Alice3HfTask3Prong { } auto addHistogramsRec = [&](const std::string& histoName, const std::string& xAxisTitle, const std::string& yAxisTitle, const HistogramConfigSpec& configSpec) { - registry.add(("MC/rec/signal/" + histoName + "RecSig").c_str(), ("3-prong cands (matched);" + xAxisTitle + ";" + yAxisTitle).c_str(), configSpec); - registry.add(("MC/rec/prompt/" + histoName + "RecSigPrompt").c_str(), ("3-prong cands (matched, prompt);" + xAxisTitle + ";" + yAxisTitle).c_str(), configSpec); - registry.add(("MC/rec/nonprompt/" + histoName + "RecSigNonPrompt").c_str(), ("3-prong cands (matched, non-prompt);" + xAxisTitle + ";" + yAxisTitle).c_str(), configSpec); + const char* basePath = "MC/rec"; + registry.add(Form("%s/signal/%sRecSig%s",basePath, histoName.c_str(), SignalSuffixes[SignalClasses::Signal].data()), ("3-prong cands (matched);" + xAxisTitle + ";" + yAxisTitle).c_str(), configSpec); + registry.add(Form("%s/prompt/%sRecSig%s", basePath, histoName.c_str(), SignalSuffixes[SignalClasses::Prompt].data()), ("3-prong cands (matched, prompt);" + xAxisTitle + ";" + yAxisTitle).c_str(), configSpec); + registry.add(Form("%s/nonprompt/%sRecSig%s", basePath, histoName.c_str(), SignalSuffixes[SignalClasses::NonPrompt].data()), ("3-prong cands (matched, non-prompt);" + xAxisTitle + ";" + yAxisTitle).c_str(), configSpec); + registry.add(Form("%s/background/%sRecSig%s", basePath, histoName.c_str(), SignalSuffixes[SignalClasses::Bkg].data()), ("3-prong cands (unmatched);" + xAxisTitle + ";" + yAxisTitle).c_str(), configSpec); }; auto addHistogramsGen = [&](const std::string& histoName, const std::string& xAxisTitle, const std::string& yAxisTitle, const HistogramConfigSpec& configSpec) { @@ -174,9 +177,16 @@ struct Alice3HfTask3Prong { auto h2 = registry.add("hSelectionStatus", "3-prong cands;selection status;entries", {HistType::kTH2F, {{5, -0.5, 4.5}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); h2->GetXaxis()->SetBinLabel(1, "mass hypo 0"); h2->GetXaxis()->SetBinLabel(2, "mass hypo 1"); - auto h = registry.add("MC/rec/hCandidateCounter", "Candidate counter;entries", {HistType::kTH1D, {{2, -0.5, 1.5}}}); + auto h = registry.add("MC/rec/hCandidateCounter", "Candidate counter;entries", {HistType::kTH1D, {{4, -0.5, 3.5}}}); h->GetXaxis()->SetBinLabel(1, "Calls"); h->GetXaxis()->SetBinLabel(2, "Candidates"); + h->GetXaxis()->SetBinLabel(3, "Passed Y cut"); + h->GetXaxis()->SetBinLabel(4, "Has MC match"); + + registry.add("MC/rec/hPtDeltaProng0", ";prong 0 (#it{p}_{T}-#it{p}_{T, gen}) (GeV/#it{c});entries", {HistType::kTH1F, {{100, -5, 5.}}}); + registry.add("MC/rec/hPtDeltaProng1", ";prong 1 (#it{p}_{T}-#it{p}_{T, gen}) (GeV/#it{c});entries", {HistType::kTH1F, {{100, -5, 5.}}}); + registry.add("MC/rec/hPtDeltaProng2", ";prong 2 (#it{p}_{T}-#it{p}_{T, gen}) (GeV/#it{c});entries", {HistType::kTH1F, {{100, -5, 5.}}}); + // Number of events processed h = registry.add("hNEventsProcessed", "number of events processed;entries;", {HistType::kTH1F, {{2, 0.5, 2.5}}}); h->GetXaxis()->SetBinLabel(1, "Generated"); @@ -207,7 +217,7 @@ struct Alice3HfTask3Prong { /// Helper function for filling MC reconstructed histograms for prompt, nonpromt and common (signal) /// \param candidate is a reconstructed candidate /// \tparam SignalType is an enum defining which histogram in which folder (signal, prompt or nonpromt) to fill - template + template void fillHistogramsRecSig(CandidateType const& candidate, float mass, bool isSwapped = false) { static constexpr auto histoPrefix = HIST("MC/rec/") + HIST(SignalFolders[SignalType]) + HIST("/"); @@ -268,21 +278,38 @@ struct Alice3HfTask3Prong { if (yCandRecoMax >= 0. && std::abs(hfHelper.getCandY(candidate)) > yCandRecoMax) { continue; } - auto mcParticle = allParticles.iteratorAt(candidate.particleMcRec()); - if (candidate.particleMcRec() > 0) { + registry.fill(HIST("MC/rec/hCandidateCounter"), 2.); + if (candidate.particleMcRec() >= 0) { + registry.fill(HIST("MC/rec/hCandidateCounter"), 3.); + auto mcParticle = allParticles.iteratorAt(candidate.particleMcRec()); if (mcParticle.has_daughters()) { auto daughters = mcParticle.daughtersIds(); - LOG(info) << "Reco candidate matched to MC particle with PDG " << mcParticle.pdgCode() << " daughters: " << daughters.size(); - for (auto dauId : daughters) { + LOG(debug) << "Reco candidate matched to MC particle with PDG " << mcParticle.pdgCode() << " daughters: " << daughters.size(); + int prongIdx = 0; + for (int dauId = daughters[0]; dauId <= daughters[1]; dauId++) { auto dau = allParticles.iteratorAt(dauId); - LOG(info) << " dauId: " << dauId << " PDG: " << dau.pdgCode(); + LOG(debug) << " dauId: " << dauId << " PDG: " << dau.pdgCode() << " with pT: " << dau.pt(); + switch (prongIdx) { + case 0: + registry.fill(HIST("MC/rec/hPtDeltaProng0"), candidate.ptProng0() - dau.pt()); + break; + case 1: + registry.fill(HIST("MC/rec/hPtDeltaProng1"), candidate.ptProng1() - dau.pt()); + break; + case 2: + registry.fill(HIST("MC/rec/hPtDeltaProng2"), candidate.ptProng2() - dau.pt()); + break; + default: + break; + } + prongIdx++; } } } - if (candidate.flagMcRec() != 0) { - // Get the corresponding MC particle. + if (candidate.flagMcRec() != 0) { // Particle is matched to MC truth + // Get the corresponding MC particle. const auto pt = candidate.pt(); const auto originType = candidate.originMcRec(); @@ -290,11 +317,11 @@ struct Alice3HfTask3Prong { registry.fill(HIST("hSelectionStatus"), 0., pt); double mass = hfHelper.getCandMass(candidate); /// Fill histograms - fillHistogramsRecSig(candidate, mass, false); + fillHistogramsRecSig(candidate, mass, false); if (originType == RecoDecay::OriginType::Prompt) { - fillHistogramsRecSig(candidate, mass, false); + fillHistogramsRecSig(candidate, mass, false); } else if (originType == RecoDecay::OriginType::NonPrompt) { - fillHistogramsRecSig(candidate, mass, false); + fillHistogramsRecSig(candidate, mass, false); } if (fillThn) { std::vector valuesToFill{mass, pt}; @@ -312,11 +339,11 @@ struct Alice3HfTask3Prong { registry.fill(HIST("hSelectionStatus"), 1., pt); double mass = hfHelper.getCandMass(candidate); /// Fill histograms - fillHistogramsRecSig(candidate, mass, true); + fillHistogramsRecSig(candidate, mass, true); if (originType == RecoDecay::OriginType::Prompt) { - fillHistogramsRecSig(candidate, mass, true); + fillHistogramsRecSig(candidate, mass, true); } else if (originType == RecoDecay::OriginType::NonPrompt) { - fillHistogramsRecSig(candidate, mass, true); + fillHistogramsRecSig(candidate, mass, true); } if (fillThn) { std::vector valuesToFill{mass, pt}; @@ -330,6 +357,15 @@ struct Alice3HfTask3Prong { registry.get(HIST("hSparseRec"))->Fill(valuesToFill.data()); } } + } else { // Background + if (candidate.isSelMassHypo0()) { + double mass = hfHelper.getCandMass(candidate); + fillHistogramsRecSig(candidate, mass, false); + } + if (candidate.isSelMassHypo1()) { + double mass = hfHelper.getCandMass(candidate); + fillHistogramsRecSig(candidate, mass, true); + } } } } From 73b0df91d61380838875917fa81588717f711ad1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Mon, 19 Jan 2026 16:07:03 +0100 Subject: [PATCH 2/4] Refactor selection flags and improve variable usage --- .../TableProducer/alice3HfSelector3Prong.cxx | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/ALICE3/TableProducer/alice3HfSelector3Prong.cxx b/ALICE3/TableProducer/alice3HfSelector3Prong.cxx index 68ef8fb8c0a..5a9c517c3b6 100644 --- a/ALICE3/TableProducer/alice3HfSelector3Prong.cxx +++ b/ALICE3/TableProducer/alice3HfSelector3Prong.cxx @@ -313,21 +313,19 @@ struct Alice3HfSelector3Prong { template void runSelect3Prong(CandType const& cands) { - bool isSelMassHypo0{false}; - bool isSelMassHypo1{false}; std::vector outputMl{-1.f, -1.f, -1.f}; uint32_t pidMask = 0; - + // looping over 3-prong cands for (const auto& cand : cands) { registry.fill(HIST("hSelections"), 1, cand.pt()); outputMl = {-1.f, -1.f, -1.f}; pidMask = 0; - auto ptCand = cand.pt(); - int const ptBin = findBin(binsPt, ptCand); + const float ptCand = cand.pt(); + const int ptBin = findBin(binsPt, ptCand); if (ptBin == -1) { - candSelFlags(isSelMassHypo0, isSelMassHypo1, pidMask); + candSelFlags(false, false, pidMask); if (applyMl) { candMlScores(outputMl[0], outputMl[1], outputMl[2]); } @@ -335,10 +333,10 @@ struct Alice3HfSelector3Prong { } // Here all cands pass the cut on the mass selection - bool const selMassHypo0 = selectionCandidateMass(ptBin, cand); - bool const selMassHypo1 = selectionCandidateMass(ptBin, cand); + const bool selMassHypo0 = selectionCandidateMass(ptBin, cand); + const bool selMassHypo1 = selectionCandidateMass(ptBin, cand); if (!selMassHypo0 && !selMassHypo1) { - candSelFlags(isSelMassHypo0, isSelMassHypo1, pidMask); + candSelFlags(false, false, pidMask); if (applyMl) { candMlScores(outputMl[0], outputMl[1], outputMl[2]); } @@ -348,7 +346,7 @@ struct Alice3HfSelector3Prong { // Topological selection (TODO: track quality selection) if (!selectionTopol(cand, ptCand)) { - candSelFlags(isSelMassHypo0, isSelMassHypo1, pidMask); + candSelFlags(false, false, pidMask); if (applyMl) { candMlScores(outputMl[0], outputMl[1], outputMl[2]); } @@ -359,7 +357,7 @@ struct Alice3HfSelector3Prong { // PID selection configurePidMask(cand, pidMask); if (pidMask == 0) { - candSelFlags(isSelMassHypo0, isSelMassHypo1, pidMask); + candSelFlags(false, false, pidMask); if (applyMl) { candMlScores(outputMl[0], outputMl[1], outputMl[2]); } @@ -375,7 +373,7 @@ struct Alice3HfSelector3Prong { isSelectedMl = mlResponse.isSelectedMl(inputFeaturesMassHypo0, ptCand, outputMl); candMlScores(outputMl[0], outputMl[1], outputMl[2]); if (!isSelectedMl) { - candSelFlags(isSelMassHypo0, isSelMassHypo1, pidMask); + candSelFlags(false, false, pidMask); continue; } From b92f7b0e20a7faefb153438d55360a713de4599d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Mon, 19 Jan 2026 16:07:32 +0100 Subject: [PATCH 3/4] Refactor mcGenFlags and update track logging --- ALICE3/TableProducer/alice3-decayfinder.cxx | 22 ++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/ALICE3/TableProducer/alice3-decayfinder.cxx b/ALICE3/TableProducer/alice3-decayfinder.cxx index 17e900ad692..a78a2ce252c 100644 --- a/ALICE3/TableProducer/alice3-decayfinder.cxx +++ b/ALICE3/TableProducer/alice3-decayfinder.cxx @@ -661,7 +661,7 @@ struct alice3decayFinder { if (doprocessFindLc) { for (auto const& mcParticle : mcParticles) { if (std::abs(mcParticle.pdgCode()) != motherPdgCode) { - mcGenFlags(-1, -1, -1); + mcGenFlags(-1, 0, 0); continue; } std::vector idxBhadMothers{}; @@ -671,7 +671,7 @@ struct alice3decayFinder { auto bHadMother = mcParticles.rawIteratorAt(idxBhadMothers[0]); ptBMotherGen = bHadMother.pt(); } - mcGenFlags(origin, ptBMotherGen, mcParticle.pdgCode() ? charmHadFlag : -charmHadFlag); + mcGenFlags(origin, ptBMotherGen, mcParticle.pdgCode() > 0 ? charmHadFlag : -charmHadFlag); if (mcParticle.pdgCode() > 0) { histos.fill(HIST("h2dGen3Prong"), mcParticle.pt(), mcParticle.eta()); } else { @@ -1040,9 +1040,9 @@ struct alice3decayFinder { mCandidate3Prong.eta, mCandidate3Prong.phi, mCandidate3Prong.pt, - mCandidate3Prong.Pdaug2[0], mCandidate3Prong.Pdaug2[1], mCandidate3Prong.Pdaug2[2], - mCandidate3Prong.Pdaug1[0], mCandidate3Prong.Pdaug1[1], mCandidate3Prong.Pdaug1[2], mCandidate3Prong.Pdaug0[0], mCandidate3Prong.Pdaug0[1], mCandidate3Prong.Pdaug0[2], + mCandidate3Prong.Pdaug1[0], mCandidate3Prong.Pdaug1[1], mCandidate3Prong.Pdaug1[2], + mCandidate3Prong.Pdaug2[0], mCandidate3Prong.Pdaug2[1], mCandidate3Prong.Pdaug2[2], mCandidate3Prong.impactParameterY0, mCandidate3Prong.impactParameterY1, mCandidate3Prong.impactParameterY2, std::sqrt(mCandidate3Prong.errorImpactParameterY0), std::sqrt(mCandidate3Prong.errorImpactParameterY1), @@ -1066,15 +1066,27 @@ struct alice3decayFinder { void processFindLc(aod::Collision const& collision, aod::McParticles const& mcParticles, - Alice3TracksWPid const&) + Alice3TracksWPid const& tracks) { + LOG(debug) << "Processing Lc candidates for collision " << collision.globalIndex() << " with " << tracks.size() << " tracks"; + for (auto const& track : tracks) { + if (track.has_mcParticle()) { + LOG(debug) << " - track index: " << track.globalIndex() << ", pT: " << track.pt() << " (MC pt " << track.mcParticle().pt() << "), PID: " << track.mcParticle().pdgCode(); + } + } auto tracksPiPlus = tracksPiPlusFromLc->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + LOG(debug) << " - found " << tracksPiPlus.size() << " pi+ from Lc"; auto tracksKaPlus = tracksKaPlusFromLc->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + LOG(debug) << " - found " << tracksKaPlus.size() << " K+ from Lc"; auto tracksPrPlus = tracksPrPlusFromLc->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + LOG(debug) << " - found " << tracksPrPlus.size() << " p+ from Lc"; auto tracksPiMinus = tracksPiMinusFromLc->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + LOG(debug) << " - found " << tracksPiMinus.size() << " pi- from Lc"; auto tracksKaMinus = tracksKaMinusFromLc->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + LOG(debug) << " - found " << tracksKaMinus.size() << " K- from Lc"; auto tracksPrMinus = tracksPrMinusFromLc->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + LOG(debug) << " - found " << tracksPrMinus.size() << " p- from Lc"; if (doDCAplots3Prong) { for (auto const& track : tracksPiPlus) From 3e856a3ff90a37db74f1412acb4f538322c9e2a1 Mon Sep 17 00:00:00 2001 From: ALICE Builder Date: Mon, 19 Jan 2026 16:07:56 +0100 Subject: [PATCH 4/4] Please consider the following formatting changes to #14548 (#14549) --- ALICE3/TableProducer/alice3HfSelector3Prong.cxx | 2 +- ALICE3/Tasks/alice3HfTask3Prong.cxx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ALICE3/TableProducer/alice3HfSelector3Prong.cxx b/ALICE3/TableProducer/alice3HfSelector3Prong.cxx index 5a9c517c3b6..d075b56b0c9 100644 --- a/ALICE3/TableProducer/alice3HfSelector3Prong.cxx +++ b/ALICE3/TableProducer/alice3HfSelector3Prong.cxx @@ -315,7 +315,7 @@ struct Alice3HfSelector3Prong { { std::vector outputMl{-1.f, -1.f, -1.f}; uint32_t pidMask = 0; - + // looping over 3-prong cands for (const auto& cand : cands) { registry.fill(HIST("hSelections"), 1, cand.pt()); diff --git a/ALICE3/Tasks/alice3HfTask3Prong.cxx b/ALICE3/Tasks/alice3HfTask3Prong.cxx index a5cdae3b36e..388faa68d18 100644 --- a/ALICE3/Tasks/alice3HfTask3Prong.cxx +++ b/ALICE3/Tasks/alice3HfTask3Prong.cxx @@ -111,7 +111,7 @@ struct Alice3HfTask3Prong { auto addHistogramsRec = [&](const std::string& histoName, const std::string& xAxisTitle, const std::string& yAxisTitle, const HistogramConfigSpec& configSpec) { const char* basePath = "MC/rec"; - registry.add(Form("%s/signal/%sRecSig%s",basePath, histoName.c_str(), SignalSuffixes[SignalClasses::Signal].data()), ("3-prong cands (matched);" + xAxisTitle + ";" + yAxisTitle).c_str(), configSpec); + registry.add(Form("%s/signal/%sRecSig%s", basePath, histoName.c_str(), SignalSuffixes[SignalClasses::Signal].data()), ("3-prong cands (matched);" + xAxisTitle + ";" + yAxisTitle).c_str(), configSpec); registry.add(Form("%s/prompt/%sRecSig%s", basePath, histoName.c_str(), SignalSuffixes[SignalClasses::Prompt].data()), ("3-prong cands (matched, prompt);" + xAxisTitle + ";" + yAxisTitle).c_str(), configSpec); registry.add(Form("%s/nonprompt/%sRecSig%s", basePath, histoName.c_str(), SignalSuffixes[SignalClasses::NonPrompt].data()), ("3-prong cands (matched, non-prompt);" + xAxisTitle + ";" + yAxisTitle).c_str(), configSpec); registry.add(Form("%s/background/%sRecSig%s", basePath, histoName.c_str(), SignalSuffixes[SignalClasses::Bkg].data()), ("3-prong cands (unmatched);" + xAxisTitle + ";" + yAxisTitle).c_str(), configSpec);