From 1135b0dbb7c38a27000424615a432f54ed1faf1d Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Fri, 5 Sep 2025 13:50:29 +0200 Subject: [PATCH 1/8] add proper lifetime to THnSparse --- PWGHF/D2H/Tasks/taskLc.cxx | 42 ++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/PWGHF/D2H/Tasks/taskLc.cxx b/PWGHF/D2H/Tasks/taskLc.cxx index 85eee1bb213..748c0333815 100644 --- a/PWGHF/D2H/Tasks/taskLc.cxx +++ b/PWGHF/D2H/Tasks/taskLc.cxx @@ -66,6 +66,9 @@ struct HfTaskLc { Configurable storeOccupancy{"storeOccupancy", true, "Flag to store occupancy information"}; Configurable occEstimator{"occEstimator", 2, "Occupancy estimation (None: 0, ITS: 1, FT0C: 2)"}; + constexpr static float CtToProperLifetimePs = 1.f / o2::constants::physics::LightSpeedCm2PS; + constexpr static float NanoToPico = 1000.f; + HfHelper hfHelper; SliceCache cache; @@ -100,6 +103,7 @@ struct HfTaskLc { ConfigurableAxis thnConfigAxisGenPtB{"thnConfigAxisGenPtB", {1000, 0, 100}, "Gen Pt B"}; ConfigurableAxis thnConfigAxisNumPvContr{"thnConfigAxisNumPvContr", {200, -0.5, 199.5}, "Number of PV contributors"}; ConfigurableAxis thnConfigAxisOccupancy{"thnConfigAxisOccupancy", {14, 0, 14000}, "axis for centrality"}; + ConfigurableAxis thnConfigAxisProperLifetime{"thnConfigAxisProperLifetime", {200, 0, 2}, "Proper lifetime, ps"}; HistogramRegistry registry{ "registry", @@ -317,6 +321,7 @@ struct HfTaskLc { const AxisSpec thnAxisPtB{thnConfigAxisGenPtB, "#it{p}_{T}^{B} (GeV/#it{c})"}; const AxisSpec thnAxisTracklets{thnConfigAxisNumPvContr, "Number of PV contributors"}; const AxisSpec thnAxisOccupancy{thnConfigAxisOccupancy, "Occupancy"}; + const AxisSpec thnAxisProperLifetime{thnConfigAxisProperLifetime, "T_{proper} (ps)"}; bool isDataWithMl = doprocessDataWithMl || doprocessDataWithMlWithFT0C || doprocessDataWithMlWithFT0M; bool isMcWithMl = doprocessMcWithMl || doprocessMcWithMlWithFT0C || doprocessMcWithMlWithFT0M; @@ -332,13 +337,13 @@ struct HfTaskLc { axesStd = {thnAxisMass, thnAxisPt, thnAxisCentrality, thnAxisPtProng0, thnAxisPtProng1, thnAxisPtProng2, thnAxisChi2PCA, thnAxisDecLength, thnAxisCPA, thnAxisTracklets, thnAxisPtB, thnAxisCanType}; } if (isMcStd || isMcWithMl) { - axesGen = {thnAxisPt, thnAxisCentrality, thnAxisY, thnAxisTracklets, thnAxisPtB, thnAxisCanType}; + axesGen = {thnAxisPt, thnAxisCentrality, thnAxisY, thnAxisTracklets, thnAxisPtB, thnAxisCanType, thnAxisProperLifetime}; } if (isDataWithMl) { - axesWithBdt = {thnAxisMass, thnAxisPt, thnAxisCentrality, thnAxisBdtScoreLcBkg, thnAxisBdtScoreLcPrompt, thnAxisBdtScoreLcNonPrompt, thnAxisTracklets}; + axesWithBdt = {thnAxisMass, thnAxisPt, thnAxisCentrality, thnAxisBdtScoreLcBkg, thnAxisBdtScoreLcPrompt, thnAxisBdtScoreLcNonPrompt, thnAxisTracklets, thnAxisProperLifetime}; } if (isMcWithMl) { - axesWithBdt = {thnAxisMass, thnAxisPt, thnAxisCentrality, thnAxisBdtScoreLcBkg, thnAxisBdtScoreLcPrompt, thnAxisBdtScoreLcNonPrompt, thnAxisTracklets, thnAxisPtB, thnAxisCanType}; + axesWithBdt = {thnAxisMass, thnAxisPt, thnAxisCentrality, thnAxisBdtScoreLcBkg, thnAxisBdtScoreLcPrompt, thnAxisBdtScoreLcNonPrompt, thnAxisTracklets, thnAxisPtB, thnAxisCanType, thnAxisProperLifetime}; } if (storeOccupancy) { @@ -542,6 +547,7 @@ struct HfTaskLc { } double massLc(-1); double outputBkg(-1), outputPrompt(-1), outputFD(-1); + const float properLifetime = hfHelper.ctLc(candidate) * CtToProperLifetimePs; if ((candidate.isSelLcToPKPi() >= selectionFlagLc) && pdgCodeProng0 == kProton) { massLc = hfHelper.invMassLcToPKPi(candidate); @@ -553,9 +559,9 @@ struct HfTaskLc { } /// Fill the ML outputScores and variables of candidate if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { - registry.get(HIST("hnLcVarsWithBdt"))->Fill(massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, ptRecB, originType, occ); + registry.get(HIST("hnLcVarsWithBdt"))->Fill(massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, ptRecB, originType, properLifetime, occ); } else { - registry.get(HIST("hnLcVarsWithBdt"))->Fill(massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, ptRecB, originType); + registry.get(HIST("hnLcVarsWithBdt"))->Fill(massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, ptRecB, originType, properLifetime); } } else { @@ -580,10 +586,10 @@ struct HfTaskLc { } /// Fill the ML outputScores and variables of candidate (todo: add multiplicity) if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { - registry.get(HIST("hnLcVarsWithBdt"))->Fill(massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, ptRecB, originType, occ); + registry.get(HIST("hnLcVarsWithBdt"))->Fill(massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, ptRecB, originType, properLifetime, occ); } else { - registry.get(HIST("hnLcVarsWithBdt"))->Fill(massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, ptRecB, originType); + registry.get(HIST("hnLcVarsWithBdt"))->Fill(massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, ptRecB, originType, properLifetime); } } else { if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { @@ -624,6 +630,11 @@ struct HfTaskLc { occ = o2::hf_occupancy::getOccupancyGenColl(recoCollsPerMcColl, occEstimator); } + const auto mcDaughter0 = particle.template daughters_as>().begin(); + const float p2m = particle.p() / o2::constants::physics::MassLambdaCPlus; + const float gamma = std::sqrt(1 + p2m * p2m); // mother's particle Lorentz factor + const float properLifetime = mcDaughter0.vt() * NanoToPico / gamma; // from ns to ps * from lab time to proper time + registry.fill(HIST("MC/generated/signal/hPtGen"), ptGen); registry.fill(HIST("MC/generated/signal/hEtaGen"), particle.eta()); registry.fill(HIST("MC/generated/signal/hYGen"), yGen); @@ -635,10 +646,10 @@ struct HfTaskLc { if (particle.originMcGen() == RecoDecay::OriginType::Prompt) { if (fillTHn) { if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { - registry.get(HIST("hnLcVarsGen"))->Fill(ptGen, cent, yGen, numPvContributors, ptGenB, originType, occ); + registry.get(HIST("hnLcVarsGen"))->Fill(ptGen, cent, yGen, numPvContributors, ptGenB, originType, properLifetime, occ); } else { - registry.get(HIST("hnLcVarsGen"))->Fill(ptGen, cent, yGen, numPvContributors, ptGenB, originType); + registry.get(HIST("hnLcVarsGen"))->Fill(ptGen, cent, yGen, numPvContributors, ptGenB, originType, properLifetime); } } registry.fill(HIST("MC/generated/prompt/hPtGenPrompt"), ptGen); @@ -653,10 +664,10 @@ struct HfTaskLc { ptGenB = mcParticles.rawIteratorAt(particle.idxBhadMotherPart()).pt(); if (fillTHn) { if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { - registry.get(HIST("hnLcVarsGen"))->Fill(ptGen, cent, yGen, numPvContributors, ptGenB, originType, occ); + registry.get(HIST("hnLcVarsGen"))->Fill(ptGen, cent, yGen, numPvContributors, ptGenB, originType, properLifetime, occ); } else { - registry.get(HIST("hnLcVarsGen"))->Fill(ptGen, cent, yGen, numPvContributors, ptGenB, originType); + registry.get(HIST("hnLcVarsGen"))->Fill(ptGen, cent, yGen, numPvContributors, ptGenB, originType, properLifetime); } } registry.fill(HIST("MC/generated/nonprompt/hPtGenNonPrompt"), ptGen); @@ -748,6 +759,7 @@ struct HfTaskLc { } double massLc(-1); double outputBkg(-1), outputPrompt(-1), outputFD(-1); + const float properLifetime = hfHelper.ctLc(candidate) * CtToProperLifetimePs; if (candidate.isSelLcToPKPi() >= selectionFlagLc) { massLc = hfHelper.invMassLcToPKPi(candidate); @@ -759,10 +771,10 @@ struct HfTaskLc { } /// Fill the ML outputScores and variables of candidate if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { - registry.get(HIST("hnLcVarsWithBdt"))->Fill(massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, occ); + registry.get(HIST("hnLcVarsWithBdt"))->Fill(massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, properLifetime, occ); } else { - registry.get(HIST("hnLcVarsWithBdt"))->Fill(massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors); + registry.get(HIST("hnLcVarsWithBdt"))->Fill(massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, properLifetime); } } else { if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { @@ -785,9 +797,9 @@ struct HfTaskLc { } /// Fill the ML outputScores and variables of candidate if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { - registry.get(HIST("hnLcVarsWithBdt"))->Fill(massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, occ); + registry.get(HIST("hnLcVarsWithBdt"))->Fill(massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, properLifetime, occ); } else { - registry.get(HIST("hnLcVarsWithBdt"))->Fill(massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors); + registry.get(HIST("hnLcVarsWithBdt"))->Fill(massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, properLifetime); } } else { if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { From cc0075bce972bb485391dfad516624764b541754 Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Fri, 5 Sep 2025 19:02:49 +0200 Subject: [PATCH 2/8] bugfix: do not write KF minv into non-KF tree --- PWGHF/TableProducer/treeCreatorLcToPKPi.cxx | 28 ++++++++------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx b/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx index 90b47824835..25b76ba4f32 100644 --- a/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx @@ -565,17 +565,11 @@ struct HfTreeCreatorLcToPKPi { /// \brief function to evaluate invariant mass of the Lc candidate and KPi pair /// \param candidate candidate instance /// \param candFlag flag indicating if PKPi (0) or PiKP (1) hypothesis is used - template + template std::pair evaluateInvariantMasses(CandType const& candidate, int candFlag) { - float invMass, invMassKPi; - if constexpr (reconstructionType == aod::hf_cand::VertexerType::DCAFitter) { - invMass = candFlag == 0 ? hfHelper.invMassLcToPKPi(candidate) : hfHelper.invMassLcToPiKP(candidate); - invMassKPi = candFlag == 0 ? hfHelper.invMassKPiPairLcToPKPi(candidate) : hfHelper.invMassKPiPairLcToPiKP(candidate); - } else { - invMass = candFlag == 0 ? candidate.kfMassPKPi() : candidate.kfMassPiKP(); - invMassKPi = candFlag == 0 ? candidate.kfMassKPi() : candidate.kfMassPiK(); - } + const float invMass = candFlag == 0 ? hfHelper.invMassLcToPKPi(candidate) : hfHelper.invMassLcToPiKP(candidate); + const float invMassKPi = candFlag == 0 ? hfHelper.invMassKPiPairLcToPKPi(candidate) : hfHelper.invMassKPiPairLcToPiKP(candidate); return std::make_pair(invMass, invMassKPi); } @@ -612,10 +606,10 @@ struct HfTreeCreatorLcToPKPi { /// \param candidate candidate instance /// \param candidateMlScore instance of handler of vectors with ML scores associated with the current candidate /// \param candFlag flag indicating if PKPi (0) or PiKP (1) hypothesis is used - template + template void fillLiteTable(CandType const& candidate, aod::HfMlLcToPKPi::iterator const& candidateMlScore, int candFlag) { - auto [functionInvMass, functionInvMassKPi] = evaluateInvariantMasses(candidate, candFlag); + auto [functionInvMass, functionInvMassKPi] = evaluateInvariantMasses(candidate, candFlag); const float functionCt = hfHelper.ctLc(candidate); const float functionY = hfHelper.yLc(candidate); @@ -697,10 +691,10 @@ struct HfTreeCreatorLcToPKPi { /// \param candidate candidate instance /// \param candidateMlScore instance of handler of vectors with ML scores associated with the current candidate /// \param candFlag flag indicating if PKPi (0) or PiKP (1) hypothesis is used - template + template void fillFullTable(CandType const& candidate, aod::HfMlLcToPKPi::iterator const& candidateMlScore, int candFlag) { - auto [functionInvMass, functionInvMassKPi] = evaluateInvariantMasses(candidate, candFlag); + auto [functionInvMass, functionInvMassKPi] = evaluateInvariantMasses(candidate, candFlag); const float functionCt = hfHelper.ctLc(candidate); const float functionY = hfHelper.yLc(candidate); const float functionE = hfHelper.eLc(candidate); @@ -948,9 +942,9 @@ struct HfTreeCreatorLcToPKPi { const bool notSkippedBkg = isMcCandidateSignal || candidate.pt() > downSampleBkgPtMax || pseudoRndm < downSampleBkgFactor; if (passSelection && notSkippedBkg && (keepAll || (keepOnlySignalMc && isMcCandidateSignal) || (keepOnlyBkg && !isMcCandidateSignal) || (keepCorrBkgMC && isCorrBkg))) { if (fillCandidateLiteTable) { - fillLiteTable(candidate, candidateMlScore, candFlag); + fillLiteTable(candidate, candidateMlScore, candFlag); } else { - fillFullTable(candidate, candidateMlScore, candFlag); + fillFullTable(candidate, candidateMlScore, candFlag); } if constexpr (reconstructionType == aod::hf_cand::VertexerType::KfParticle) { @@ -1130,9 +1124,9 @@ struct HfTreeCreatorLcToPKPi { const int functionSelection = candFlag == 0 ? candidate.isSelLcToPKPi() : candidate.isSelLcToPiKP(); if (functionSelection >= selectionFlagLc && (candidate.pt() > downSampleBkgPtMax || (pseudoRndm < downSampleBkgFactor && candidate.pt() < downSampleBkgPtMax))) { if (fillCandidateLiteTable) { - fillLiteTable(candidate, candidateMlScore, candFlag); + fillLiteTable(candidate, candidateMlScore, candFlag); } else { - fillFullTable(candidate, candidateMlScore, candFlag); + fillFullTable(candidate, candidateMlScore, candFlag); } if constexpr (reconstructionType == aod::hf_cand::VertexerType::KfParticle) { From 54a5a51a7a706ca2815ed334826d4e3d42e08cf9 Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Mon, 8 Sep 2025 14:02:06 +0200 Subject: [PATCH 3/8] get rid of magic numbers in Ml classes enumeration --- PWGHF/D2H/Tasks/taskLc.cxx | 39 ++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/PWGHF/D2H/Tasks/taskLc.cxx b/PWGHF/D2H/Tasks/taskLc.cxx index 748c0333815..317ef712dd3 100644 --- a/PWGHF/D2H/Tasks/taskLc.cxx +++ b/PWGHF/D2H/Tasks/taskLc.cxx @@ -69,6 +69,13 @@ struct HfTaskLc { constexpr static float CtToProperLifetimePs = 1.f / o2::constants::physics::LightSpeedCm2PS; constexpr static float NanoToPico = 1000.f; + enum MlClasses : int { + MlClassBackground = 0, + MlClassPrompt, + MlClassNonPrompt, + NumberOfMlClasses + }; + HfHelper hfHelper; SliceCache cache; @@ -552,10 +559,10 @@ struct HfTaskLc { massLc = hfHelper.invMassLcToPKPi(candidate); if constexpr (fillMl) { - if (candidate.mlProbLcToPKPi().size() == 3) { - outputBkg = candidate.mlProbLcToPKPi()[0]; /// bkg score - outputPrompt = candidate.mlProbLcToPKPi()[1]; /// prompt score - outputFD = candidate.mlProbLcToPKPi()[2]; /// non-prompt score + if (candidate.mlProbLcToPKPi().size() == NumberOfMlClasses) { + outputBkg = candidate.mlProbLcToPKPi()[MlClassBackground]; /// bkg score + outputPrompt = candidate.mlProbLcToPKPi()[MlClassPrompt]; /// prompt score + outputFD = candidate.mlProbLcToPKPi()[MlClassNonPrompt]; /// non-prompt score } /// Fill the ML outputScores and variables of candidate if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { @@ -579,10 +586,10 @@ struct HfTaskLc { massLc = hfHelper.invMassLcToPiKP(candidate); if constexpr (fillMl) { - if (candidate.mlProbLcToPiKP().size() == 3) { - outputBkg = candidate.mlProbLcToPiKP()[0]; /// bkg score - outputPrompt = candidate.mlProbLcToPiKP()[1]; /// prompt score - outputFD = candidate.mlProbLcToPiKP()[2]; /// non-prompt score + if (candidate.mlProbLcToPiKP().size() == NumberOfMlClasses) { + outputBkg = candidate.mlProbLcToPiKP()[MlClassBackground]; /// bkg score + outputPrompt = candidate.mlProbLcToPiKP()[MlClassPrompt]; /// prompt score + outputFD = candidate.mlProbLcToPiKP()[MlClassNonPrompt]; /// non-prompt score } /// Fill the ML outputScores and variables of candidate (todo: add multiplicity) if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { @@ -764,10 +771,10 @@ struct HfTaskLc { massLc = hfHelper.invMassLcToPKPi(candidate); if constexpr (fillMl) { - if (candidate.mlProbLcToPKPi().size() == 3) { - outputBkg = candidate.mlProbLcToPKPi()[0]; /// bkg score - outputPrompt = candidate.mlProbLcToPKPi()[1]; /// prompt score - outputFD = candidate.mlProbLcToPKPi()[2]; /// non-prompt score + if (candidate.mlProbLcToPKPi().size() == NumberOfMlClasses) { + outputBkg = candidate.mlProbLcToPKPi()[MlClassBackground]; /// bkg score + outputPrompt = candidate.mlProbLcToPKPi()[MlClassPrompt]; /// prompt score + outputFD = candidate.mlProbLcToPKPi()[MlClassNonPrompt]; /// non-prompt score } /// Fill the ML outputScores and variables of candidate if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { @@ -790,10 +797,10 @@ struct HfTaskLc { massLc = hfHelper.invMassLcToPiKP(candidate); if constexpr (fillMl) { - if (candidate.mlProbLcToPiKP().size() == 3) { - outputBkg = candidate.mlProbLcToPiKP()[0]; /// bkg score - outputPrompt = candidate.mlProbLcToPiKP()[1]; /// prompt score - outputFD = candidate.mlProbLcToPiKP()[2]; /// non-prompt score + if (candidate.mlProbLcToPiKP().size() == NumberOfMlClasses) { + outputBkg = candidate.mlProbLcToPiKP()[MlClassBackground]; /// bkg score + outputPrompt = candidate.mlProbLcToPiKP()[MlClassPrompt]; /// prompt score + outputFD = candidate.mlProbLcToPiKP()[MlClassNonPrompt]; /// non-prompt score } /// Fill the ML outputScores and variables of candidate if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { From b6ded05347062b83e8db4f70c7ed1988381fbfea Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Mon, 8 Sep 2025 14:09:11 +0200 Subject: [PATCH 4/8] Revert "bugfix: do not write KF minv into non-KF tree" This reverts commit cc0075bce972bb485391dfad516624764b541754. --- PWGHF/TableProducer/treeCreatorLcToPKPi.cxx | 28 +++++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx b/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx index 25b76ba4f32..90b47824835 100644 --- a/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx @@ -565,11 +565,17 @@ struct HfTreeCreatorLcToPKPi { /// \brief function to evaluate invariant mass of the Lc candidate and KPi pair /// \param candidate candidate instance /// \param candFlag flag indicating if PKPi (0) or PiKP (1) hypothesis is used - template + template std::pair evaluateInvariantMasses(CandType const& candidate, int candFlag) { - const float invMass = candFlag == 0 ? hfHelper.invMassLcToPKPi(candidate) : hfHelper.invMassLcToPiKP(candidate); - const float invMassKPi = candFlag == 0 ? hfHelper.invMassKPiPairLcToPKPi(candidate) : hfHelper.invMassKPiPairLcToPiKP(candidate); + float invMass, invMassKPi; + if constexpr (reconstructionType == aod::hf_cand::VertexerType::DCAFitter) { + invMass = candFlag == 0 ? hfHelper.invMassLcToPKPi(candidate) : hfHelper.invMassLcToPiKP(candidate); + invMassKPi = candFlag == 0 ? hfHelper.invMassKPiPairLcToPKPi(candidate) : hfHelper.invMassKPiPairLcToPiKP(candidate); + } else { + invMass = candFlag == 0 ? candidate.kfMassPKPi() : candidate.kfMassPiKP(); + invMassKPi = candFlag == 0 ? candidate.kfMassKPi() : candidate.kfMassPiK(); + } return std::make_pair(invMass, invMassKPi); } @@ -606,10 +612,10 @@ struct HfTreeCreatorLcToPKPi { /// \param candidate candidate instance /// \param candidateMlScore instance of handler of vectors with ML scores associated with the current candidate /// \param candFlag flag indicating if PKPi (0) or PiKP (1) hypothesis is used - template + template void fillLiteTable(CandType const& candidate, aod::HfMlLcToPKPi::iterator const& candidateMlScore, int candFlag) { - auto [functionInvMass, functionInvMassKPi] = evaluateInvariantMasses(candidate, candFlag); + auto [functionInvMass, functionInvMassKPi] = evaluateInvariantMasses(candidate, candFlag); const float functionCt = hfHelper.ctLc(candidate); const float functionY = hfHelper.yLc(candidate); @@ -691,10 +697,10 @@ struct HfTreeCreatorLcToPKPi { /// \param candidate candidate instance /// \param candidateMlScore instance of handler of vectors with ML scores associated with the current candidate /// \param candFlag flag indicating if PKPi (0) or PiKP (1) hypothesis is used - template + template void fillFullTable(CandType const& candidate, aod::HfMlLcToPKPi::iterator const& candidateMlScore, int candFlag) { - auto [functionInvMass, functionInvMassKPi] = evaluateInvariantMasses(candidate, candFlag); + auto [functionInvMass, functionInvMassKPi] = evaluateInvariantMasses(candidate, candFlag); const float functionCt = hfHelper.ctLc(candidate); const float functionY = hfHelper.yLc(candidate); const float functionE = hfHelper.eLc(candidate); @@ -942,9 +948,9 @@ struct HfTreeCreatorLcToPKPi { const bool notSkippedBkg = isMcCandidateSignal || candidate.pt() > downSampleBkgPtMax || pseudoRndm < downSampleBkgFactor; if (passSelection && notSkippedBkg && (keepAll || (keepOnlySignalMc && isMcCandidateSignal) || (keepOnlyBkg && !isMcCandidateSignal) || (keepCorrBkgMC && isCorrBkg))) { if (fillCandidateLiteTable) { - fillLiteTable(candidate, candidateMlScore, candFlag); + fillLiteTable(candidate, candidateMlScore, candFlag); } else { - fillFullTable(candidate, candidateMlScore, candFlag); + fillFullTable(candidate, candidateMlScore, candFlag); } if constexpr (reconstructionType == aod::hf_cand::VertexerType::KfParticle) { @@ -1124,9 +1130,9 @@ struct HfTreeCreatorLcToPKPi { const int functionSelection = candFlag == 0 ? candidate.isSelLcToPKPi() : candidate.isSelLcToPiKP(); if (functionSelection >= selectionFlagLc && (candidate.pt() > downSampleBkgPtMax || (pseudoRndm < downSampleBkgFactor && candidate.pt() < downSampleBkgPtMax))) { if (fillCandidateLiteTable) { - fillLiteTable(candidate, candidateMlScore, candFlag); + fillLiteTable(candidate, candidateMlScore, candFlag); } else { - fillFullTable(candidate, candidateMlScore, candFlag); + fillFullTable(candidate, candidateMlScore, candFlag); } if constexpr (reconstructionType == aod::hf_cand::VertexerType::KfParticle) { From 8c3b8ad75503c195a4650770577a120408589a5f Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Mon, 8 Sep 2025 17:02:52 +0200 Subject: [PATCH 5/8] make thnAxisProperLifetime optional --- PWGHF/D2H/Tasks/taskLc.cxx | 114 +++++++++++++++++++++---------------- 1 file changed, 65 insertions(+), 49 deletions(-) diff --git a/PWGHF/D2H/Tasks/taskLc.cxx b/PWGHF/D2H/Tasks/taskLc.cxx index 317ef712dd3..13b11e30dbc 100644 --- a/PWGHF/D2H/Tasks/taskLc.cxx +++ b/PWGHF/D2H/Tasks/taskLc.cxx @@ -65,6 +65,7 @@ struct HfTaskLc { Configurable fillTHn{"fillTHn", false, "fill THn"}; Configurable storeOccupancy{"storeOccupancy", true, "Flag to store occupancy information"}; Configurable occEstimator{"occEstimator", 2, "Occupancy estimation (None: 0, ITS: 1, FT0C: 2)"}; + Configurable storeProperLifetime{"storeProperLifetime", false, "Flag to store proper lifetime"}; constexpr static float CtToProperLifetimePs = 1.f / o2::constants::physics::LightSpeedCm2PS; constexpr static float NanoToPico = 1000.f; @@ -344,22 +345,29 @@ struct HfTaskLc { axesStd = {thnAxisMass, thnAxisPt, thnAxisCentrality, thnAxisPtProng0, thnAxisPtProng1, thnAxisPtProng2, thnAxisChi2PCA, thnAxisDecLength, thnAxisCPA, thnAxisTracklets, thnAxisPtB, thnAxisCanType}; } if (isMcStd || isMcWithMl) { - axesGen = {thnAxisPt, thnAxisCentrality, thnAxisY, thnAxisTracklets, thnAxisPtB, thnAxisCanType, thnAxisProperLifetime}; + axesGen = {thnAxisPt, thnAxisCentrality, thnAxisY, thnAxisTracklets, thnAxisPtB, thnAxisCanType}; } if (isDataWithMl) { - axesWithBdt = {thnAxisMass, thnAxisPt, thnAxisCentrality, thnAxisBdtScoreLcBkg, thnAxisBdtScoreLcPrompt, thnAxisBdtScoreLcNonPrompt, thnAxisTracklets, thnAxisProperLifetime}; + axesWithBdt = {thnAxisMass, thnAxisPt, thnAxisCentrality, thnAxisBdtScoreLcBkg, thnAxisBdtScoreLcPrompt, thnAxisBdtScoreLcNonPrompt, thnAxisTracklets}; } if (isMcWithMl) { - axesWithBdt = {thnAxisMass, thnAxisPt, thnAxisCentrality, thnAxisBdtScoreLcBkg, thnAxisBdtScoreLcPrompt, thnAxisBdtScoreLcNonPrompt, thnAxisTracklets, thnAxisPtB, thnAxisCanType, thnAxisProperLifetime}; + axesWithBdt = {thnAxisMass, thnAxisPt, thnAxisCentrality, thnAxisBdtScoreLcBkg, thnAxisBdtScoreLcPrompt, thnAxisBdtScoreLcNonPrompt, thnAxisTracklets, thnAxisPtB, thnAxisCanType}; + } + + if (storeProperLifetime) { + for (const auto& axes : std::array*, 2>{&axesGen, &axesWithBdt}) { + if (!axes->empty()) { + axes->push_back(thnAxisProperLifetime); + } + } } if (storeOccupancy) { - if (!axesWithBdt.empty()) - axesWithBdt.push_back(thnAxisOccupancy); - if (!axesStd.empty()) - axesStd.push_back(thnAxisOccupancy); - if (!axesGen.empty()) - axesGen.push_back(thnAxisOccupancy); + for (const auto& axes : std::array*, 3>{&axesWithBdt, &axesStd, &axesGen}) { + if (!axes->empty()) { + axes->push_back(thnAxisOccupancy); + } + } } if (isDataWithMl) { @@ -565,21 +573,20 @@ struct HfTaskLc { outputFD = candidate.mlProbLcToPKPi()[MlClassNonPrompt]; /// non-prompt score } /// Fill the ML outputScores and variables of candidate + std::vector valuesToFill{massLc, pt, cent, outputBkg, outputPrompt, outputFD, static_cast(numPvContributors), ptRecB, static_cast(originType)}; + if (storeProperLifetime) { + valuesToFill.push_back(properLifetime); + } if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { - registry.get(HIST("hnLcVarsWithBdt"))->Fill(massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, ptRecB, originType, properLifetime, occ); - } else { - registry.get(HIST("hnLcVarsWithBdt"))->Fill(massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, ptRecB, originType, properLifetime); + valuesToFill.push_back(occ); } - + registry.get(HIST("hnLcVarsWithBdt"))->Fill(valuesToFill.data()); } else { - + std::vector valuesToFill{massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, static_cast(numPvContributors), ptRecB, static_cast(originType)}; if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { - registry.get(HIST("hnLcVars"))->Fill(massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, numPvContributors, ptRecB, originType, occ); - - } else { - - registry.get(HIST("hnLcVars"))->Fill(massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, numPvContributors, ptRecB, originType); + valuesToFill.push_back(occ); } + registry.get(HIST("hnLcVars"))->Fill(valuesToFill.data()); } } if ((candidate.isSelLcToPiKP() >= selectionFlagLc) && pdgCodeProng0 == kPiPlus) { @@ -592,18 +599,20 @@ struct HfTaskLc { outputFD = candidate.mlProbLcToPiKP()[MlClassNonPrompt]; /// non-prompt score } /// Fill the ML outputScores and variables of candidate (todo: add multiplicity) + std::vector valuesToFill{massLc, pt, cent, outputBkg, outputPrompt, outputFD, static_cast(numPvContributors), ptRecB, static_cast(originType)}; + if (storeProperLifetime) { + valuesToFill.push_back(properLifetime); + } if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { - registry.get(HIST("hnLcVarsWithBdt"))->Fill(massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, ptRecB, originType, properLifetime, occ); - - } else { - registry.get(HIST("hnLcVarsWithBdt"))->Fill(massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, ptRecB, originType, properLifetime); + valuesToFill.push_back(occ); } + registry.get(HIST("hnLcVarsWithBdt"))->Fill(valuesToFill.data()); } else { + std::vector valuesToFill{massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, static_cast(numPvContributors), ptRecB, static_cast(originType)}; if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { - registry.get(HIST("hnLcVars"))->Fill(massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, numPvContributors, ptRecB, originType, occ); - } else { - registry.get(HIST("hnLcVars"))->Fill(massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, numPvContributors, ptRecB, originType); + valuesToFill.push_back(occ); } + registry.get(HIST("hnLcVars"))->Fill(valuesToFill.data()); } } } @@ -652,12 +661,14 @@ struct HfTaskLc { if (particle.originMcGen() == RecoDecay::OriginType::Prompt) { if (fillTHn) { + std::vector valuesToFill{ptGen, cent, yGen, static_cast(numPvContributors), ptGenB, static_cast(originType)}; + if (storeProperLifetime) { + valuesToFill.push_back(properLifetime); + } if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { - registry.get(HIST("hnLcVarsGen"))->Fill(ptGen, cent, yGen, numPvContributors, ptGenB, originType, properLifetime, occ); - - } else { - registry.get(HIST("hnLcVarsGen"))->Fill(ptGen, cent, yGen, numPvContributors, ptGenB, originType, properLifetime); + valuesToFill.push_back(occ); } + registry.get(HIST("hnLcVarsGen"))->Fill(valuesToFill.data()); } registry.fill(HIST("MC/generated/prompt/hPtGenPrompt"), ptGen); registry.fill(HIST("MC/generated/prompt/hEtaGenPrompt"), particle.eta()); @@ -670,12 +681,14 @@ struct HfTaskLc { if (particle.originMcGen() == RecoDecay::OriginType::NonPrompt) { ptGenB = mcParticles.rawIteratorAt(particle.idxBhadMotherPart()).pt(); if (fillTHn) { + std::vector valuesToFill{ptGen, cent, yGen, static_cast(numPvContributors), ptGenB, static_cast(originType)}; + if (storeProperLifetime) { + valuesToFill.push_back(properLifetime); + } if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { - registry.get(HIST("hnLcVarsGen"))->Fill(ptGen, cent, yGen, numPvContributors, ptGenB, originType, properLifetime, occ); - - } else { - registry.get(HIST("hnLcVarsGen"))->Fill(ptGen, cent, yGen, numPvContributors, ptGenB, originType, properLifetime); + valuesToFill.push_back(occ); } + registry.get(HIST("hnLcVarsGen"))->Fill(valuesToFill.data()); } registry.fill(HIST("MC/generated/nonprompt/hPtGenNonPrompt"), ptGen); registry.fill(HIST("MC/generated/nonprompt/hEtaGenNonPrompt"), particle.eta()); @@ -777,20 +790,20 @@ struct HfTaskLc { outputFD = candidate.mlProbLcToPKPi()[MlClassNonPrompt]; /// non-prompt score } /// Fill the ML outputScores and variables of candidate + std::vector valuesToFill{massLc, pt, cent, outputBkg, outputPrompt, outputFD, static_cast(numPvContributors)}; + if (storeProperLifetime) { + valuesToFill.push_back(properLifetime); + } if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { - registry.get(HIST("hnLcVarsWithBdt"))->Fill(massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, properLifetime, occ); - - } else { - registry.get(HIST("hnLcVarsWithBdt"))->Fill(massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, properLifetime); + valuesToFill.push_back(occ); } + registry.get(HIST("hnLcVarsWithBdt"))->Fill(valuesToFill.data()); } else { + std::vector valuesToFill{massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, static_cast(numPvContributors)}; if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { - - registry.get(HIST("hnLcVars"))->Fill(massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, numPvContributors, occ); - } else { - - registry.get(HIST("hnLcVars"))->Fill(massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, numPvContributors); + valuesToFill.push_back(occ); } + registry.get(HIST("hnLcVars"))->Fill(valuesToFill.data()); } } if (candidate.isSelLcToPiKP() >= selectionFlagLc) { @@ -803,17 +816,20 @@ struct HfTaskLc { outputFD = candidate.mlProbLcToPiKP()[MlClassNonPrompt]; /// non-prompt score } /// Fill the ML outputScores and variables of candidate + std::vector valuesToFill{massLc, pt, cent, outputBkg, outputPrompt, outputFD, static_cast(numPvContributors)}; + if (storeProperLifetime) { + valuesToFill.push_back(properLifetime); + } if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { - registry.get(HIST("hnLcVarsWithBdt"))->Fill(massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, properLifetime, occ); - } else { - registry.get(HIST("hnLcVarsWithBdt"))->Fill(massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, properLifetime); + valuesToFill.push_back(occ); } + registry.get(HIST("hnLcVarsWithBdt"))->Fill(valuesToFill.data()); } else { + std::vector valuesToFill{massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, static_cast(numPvContributors)}; if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { - registry.get(HIST("hnLcVars"))->Fill(massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, numPvContributors, occ); - } else { - registry.get(HIST("hnLcVars"))->Fill(massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, numPvContributors); + valuesToFill.push_back(occ); } + registry.get(HIST("hnLcVars"))->Fill(valuesToFill.data()); } } } From 8d6e98c7f381171f404d8c81fb721b0167d72b31 Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Mon, 8 Sep 2025 17:17:26 +0200 Subject: [PATCH 6/8] linter: Double_t -> double --- PWGHF/D2H/Tasks/taskLc.cxx | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/PWGHF/D2H/Tasks/taskLc.cxx b/PWGHF/D2H/Tasks/taskLc.cxx index 13b11e30dbc..cf4d7028e26 100644 --- a/PWGHF/D2H/Tasks/taskLc.cxx +++ b/PWGHF/D2H/Tasks/taskLc.cxx @@ -573,7 +573,7 @@ struct HfTaskLc { outputFD = candidate.mlProbLcToPKPi()[MlClassNonPrompt]; /// non-prompt score } /// Fill the ML outputScores and variables of candidate - std::vector valuesToFill{massLc, pt, cent, outputBkg, outputPrompt, outputFD, static_cast(numPvContributors), ptRecB, static_cast(originType)}; + std::vector valuesToFill{massLc, pt, cent, outputBkg, outputPrompt, outputFD, static_cast(numPvContributors), ptRecB, static_cast(originType)}; if (storeProperLifetime) { valuesToFill.push_back(properLifetime); } @@ -582,7 +582,7 @@ struct HfTaskLc { } registry.get(HIST("hnLcVarsWithBdt"))->Fill(valuesToFill.data()); } else { - std::vector valuesToFill{massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, static_cast(numPvContributors), ptRecB, static_cast(originType)}; + std::vector valuesToFill{massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, static_cast(numPvContributors), ptRecB, static_cast(originType)}; if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { valuesToFill.push_back(occ); } @@ -599,7 +599,7 @@ struct HfTaskLc { outputFD = candidate.mlProbLcToPiKP()[MlClassNonPrompt]; /// non-prompt score } /// Fill the ML outputScores and variables of candidate (todo: add multiplicity) - std::vector valuesToFill{massLc, pt, cent, outputBkg, outputPrompt, outputFD, static_cast(numPvContributors), ptRecB, static_cast(originType)}; + std::vector valuesToFill{massLc, pt, cent, outputBkg, outputPrompt, outputFD, static_cast(numPvContributors), ptRecB, static_cast(originType)}; if (storeProperLifetime) { valuesToFill.push_back(properLifetime); } @@ -608,7 +608,7 @@ struct HfTaskLc { } registry.get(HIST("hnLcVarsWithBdt"))->Fill(valuesToFill.data()); } else { - std::vector valuesToFill{massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, static_cast(numPvContributors), ptRecB, static_cast(originType)}; + std::vector valuesToFill{massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, static_cast(numPvContributors), ptRecB, static_cast(originType)}; if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { valuesToFill.push_back(occ); } @@ -661,7 +661,7 @@ struct HfTaskLc { if (particle.originMcGen() == RecoDecay::OriginType::Prompt) { if (fillTHn) { - std::vector valuesToFill{ptGen, cent, yGen, static_cast(numPvContributors), ptGenB, static_cast(originType)}; + std::vector valuesToFill{ptGen, cent, yGen, static_cast(numPvContributors), ptGenB, static_cast(originType)}; if (storeProperLifetime) { valuesToFill.push_back(properLifetime); } @@ -681,7 +681,7 @@ struct HfTaskLc { if (particle.originMcGen() == RecoDecay::OriginType::NonPrompt) { ptGenB = mcParticles.rawIteratorAt(particle.idxBhadMotherPart()).pt(); if (fillTHn) { - std::vector valuesToFill{ptGen, cent, yGen, static_cast(numPvContributors), ptGenB, static_cast(originType)}; + std::vector valuesToFill{ptGen, cent, yGen, static_cast(numPvContributors), ptGenB, static_cast(originType)}; if (storeProperLifetime) { valuesToFill.push_back(properLifetime); } @@ -790,7 +790,7 @@ struct HfTaskLc { outputFD = candidate.mlProbLcToPKPi()[MlClassNonPrompt]; /// non-prompt score } /// Fill the ML outputScores and variables of candidate - std::vector valuesToFill{massLc, pt, cent, outputBkg, outputPrompt, outputFD, static_cast(numPvContributors)}; + std::vector valuesToFill{massLc, pt, cent, outputBkg, outputPrompt, outputFD, static_cast(numPvContributors)}; if (storeProperLifetime) { valuesToFill.push_back(properLifetime); } @@ -799,7 +799,7 @@ struct HfTaskLc { } registry.get(HIST("hnLcVarsWithBdt"))->Fill(valuesToFill.data()); } else { - std::vector valuesToFill{massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, static_cast(numPvContributors)}; + std::vector valuesToFill{massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, static_cast(numPvContributors)}; if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { valuesToFill.push_back(occ); } @@ -816,7 +816,7 @@ struct HfTaskLc { outputFD = candidate.mlProbLcToPiKP()[MlClassNonPrompt]; /// non-prompt score } /// Fill the ML outputScores and variables of candidate - std::vector valuesToFill{massLc, pt, cent, outputBkg, outputPrompt, outputFD, static_cast(numPvContributors)}; + std::vector valuesToFill{massLc, pt, cent, outputBkg, outputPrompt, outputFD, static_cast(numPvContributors)}; if (storeProperLifetime) { valuesToFill.push_back(properLifetime); } @@ -825,7 +825,7 @@ struct HfTaskLc { } registry.get(HIST("hnLcVarsWithBdt"))->Fill(valuesToFill.data()); } else { - std::vector valuesToFill{massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, static_cast(numPvContributors)}; + std::vector valuesToFill{massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, static_cast(numPvContributors)}; if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { valuesToFill.push_back(occ); } From bb3a0a5fee4e3526847763f13f37993a8f23cc35 Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Mon, 8 Sep 2025 17:28:15 +0200 Subject: [PATCH 7/8] swap occupancy and lifetime axes for backward compatibility --- PWGHF/D2H/Tasks/taskLc.cxx | 49 +++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/PWGHF/D2H/Tasks/taskLc.cxx b/PWGHF/D2H/Tasks/taskLc.cxx index cf4d7028e26..5e8b0318035 100644 --- a/PWGHF/D2H/Tasks/taskLc.cxx +++ b/PWGHF/D2H/Tasks/taskLc.cxx @@ -354,18 +354,17 @@ struct HfTaskLc { axesWithBdt = {thnAxisMass, thnAxisPt, thnAxisCentrality, thnAxisBdtScoreLcBkg, thnAxisBdtScoreLcPrompt, thnAxisBdtScoreLcNonPrompt, thnAxisTracklets, thnAxisPtB, thnAxisCanType}; } - if (storeProperLifetime) { - for (const auto& axes : std::array*, 2>{&axesGen, &axesWithBdt}) { + if (storeOccupancy) { + for (const auto& axes : std::array*, 3>{&axesWithBdt, &axesStd, &axesGen}) { if (!axes->empty()) { - axes->push_back(thnAxisProperLifetime); + axes->push_back(thnAxisOccupancy); } } } - - if (storeOccupancy) { - for (const auto& axes : std::array*, 3>{&axesWithBdt, &axesStd, &axesGen}) { + if (storeProperLifetime) { + for (const auto& axes : std::array*, 2>{&axesGen, &axesWithBdt}) { if (!axes->empty()) { - axes->push_back(thnAxisOccupancy); + axes->push_back(thnAxisProperLifetime); } } } @@ -574,12 +573,12 @@ struct HfTaskLc { } /// Fill the ML outputScores and variables of candidate std::vector valuesToFill{massLc, pt, cent, outputBkg, outputPrompt, outputFD, static_cast(numPvContributors), ptRecB, static_cast(originType)}; - if (storeProperLifetime) { - valuesToFill.push_back(properLifetime); - } if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { valuesToFill.push_back(occ); } + if (storeProperLifetime) { + valuesToFill.push_back(properLifetime); + } registry.get(HIST("hnLcVarsWithBdt"))->Fill(valuesToFill.data()); } else { std::vector valuesToFill{massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, static_cast(numPvContributors), ptRecB, static_cast(originType)}; @@ -600,12 +599,12 @@ struct HfTaskLc { } /// Fill the ML outputScores and variables of candidate (todo: add multiplicity) std::vector valuesToFill{massLc, pt, cent, outputBkg, outputPrompt, outputFD, static_cast(numPvContributors), ptRecB, static_cast(originType)}; - if (storeProperLifetime) { - valuesToFill.push_back(properLifetime); - } if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { valuesToFill.push_back(occ); } + if (storeProperLifetime) { + valuesToFill.push_back(properLifetime); + } registry.get(HIST("hnLcVarsWithBdt"))->Fill(valuesToFill.data()); } else { std::vector valuesToFill{massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, static_cast(numPvContributors), ptRecB, static_cast(originType)}; @@ -662,12 +661,12 @@ struct HfTaskLc { if (particle.originMcGen() == RecoDecay::OriginType::Prompt) { if (fillTHn) { std::vector valuesToFill{ptGen, cent, yGen, static_cast(numPvContributors), ptGenB, static_cast(originType)}; - if (storeProperLifetime) { - valuesToFill.push_back(properLifetime); - } if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { valuesToFill.push_back(occ); } + if (storeProperLifetime) { + valuesToFill.push_back(properLifetime); + } registry.get(HIST("hnLcVarsGen"))->Fill(valuesToFill.data()); } registry.fill(HIST("MC/generated/prompt/hPtGenPrompt"), ptGen); @@ -682,12 +681,12 @@ struct HfTaskLc { ptGenB = mcParticles.rawIteratorAt(particle.idxBhadMotherPart()).pt(); if (fillTHn) { std::vector valuesToFill{ptGen, cent, yGen, static_cast(numPvContributors), ptGenB, static_cast(originType)}; - if (storeProperLifetime) { - valuesToFill.push_back(properLifetime); - } if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { valuesToFill.push_back(occ); } + if (storeProperLifetime) { + valuesToFill.push_back(properLifetime); + } registry.get(HIST("hnLcVarsGen"))->Fill(valuesToFill.data()); } registry.fill(HIST("MC/generated/nonprompt/hPtGenNonPrompt"), ptGen); @@ -791,12 +790,12 @@ struct HfTaskLc { } /// Fill the ML outputScores and variables of candidate std::vector valuesToFill{massLc, pt, cent, outputBkg, outputPrompt, outputFD, static_cast(numPvContributors)}; - if (storeProperLifetime) { - valuesToFill.push_back(properLifetime); - } if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { valuesToFill.push_back(occ); } + if (storeProperLifetime) { + valuesToFill.push_back(properLifetime); + } registry.get(HIST("hnLcVarsWithBdt"))->Fill(valuesToFill.data()); } else { std::vector valuesToFill{massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, static_cast(numPvContributors)}; @@ -817,12 +816,12 @@ struct HfTaskLc { } /// Fill the ML outputScores and variables of candidate std::vector valuesToFill{massLc, pt, cent, outputBkg, outputPrompt, outputFD, static_cast(numPvContributors)}; - if (storeProperLifetime) { - valuesToFill.push_back(properLifetime); - } if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { valuesToFill.push_back(occ); } + if (storeProperLifetime) { + valuesToFill.push_back(properLifetime); + } registry.get(HIST("hnLcVarsWithBdt"))->Fill(valuesToFill.data()); } else { std::vector valuesToFill{massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, static_cast(numPvContributors)}; From 270def9d7446738eafdc0f9db2f476e59363f106 Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Mon, 8 Sep 2025 17:59:18 +0200 Subject: [PATCH 8/8] add proper lifetime also to axesStd --- PWGHF/D2H/Tasks/taskLc.cxx | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/PWGHF/D2H/Tasks/taskLc.cxx b/PWGHF/D2H/Tasks/taskLc.cxx index 5e8b0318035..f1fdc7ef961 100644 --- a/PWGHF/D2H/Tasks/taskLc.cxx +++ b/PWGHF/D2H/Tasks/taskLc.cxx @@ -362,7 +362,7 @@ struct HfTaskLc { } } if (storeProperLifetime) { - for (const auto& axes : std::array*, 2>{&axesGen, &axesWithBdt}) { + for (const auto& axes : std::array*, 3>{&axesWithBdt, &axesStd, &axesGen}) { if (!axes->empty()) { axes->push_back(thnAxisProperLifetime); } @@ -585,6 +585,9 @@ struct HfTaskLc { if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { valuesToFill.push_back(occ); } + if (storeProperLifetime) { + valuesToFill.push_back(properLifetime); + } registry.get(HIST("hnLcVars"))->Fill(valuesToFill.data()); } } @@ -611,6 +614,9 @@ struct HfTaskLc { if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { valuesToFill.push_back(occ); } + if (storeProperLifetime) { + valuesToFill.push_back(properLifetime); + } registry.get(HIST("hnLcVars"))->Fill(valuesToFill.data()); } } @@ -802,6 +808,9 @@ struct HfTaskLc { if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { valuesToFill.push_back(occ); } + if (storeProperLifetime) { + valuesToFill.push_back(properLifetime); + } registry.get(HIST("hnLcVars"))->Fill(valuesToFill.data()); } } @@ -828,6 +837,9 @@ struct HfTaskLc { if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) { valuesToFill.push_back(occ); } + if (storeProperLifetime) { + valuesToFill.push_back(properLifetime); + } registry.get(HIST("hnLcVars"))->Fill(valuesToFill.data()); } }