From 2a07238c161a43fb2892dd5830cbd9614ed60853 Mon Sep 17 00:00:00 2001 From: Emil Gorm Nielsen Date: Mon, 10 Aug 2026 10:32:43 +0200 Subject: [PATCH 1/4] Less strict daughter track selection and configurable PID rejection criteria in flowGenericFramework.cxx --- .../Tasks/flowGenericFramework.cxx | 69 +++++++++---------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx b/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx index e7e888b3cdf..d84d8d89767 100644 --- a/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx +++ b/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx @@ -207,6 +207,7 @@ struct FlowGenericFramework { struct : ConfigurableGroup { O2_DEFINE_CONFIGURABLE(cfgUseLsPhi, bool, true, "Use LikeSign for Phi v2") O2_DEFINE_CONFIGURABLE(cfgUseOnlyTPC, bool, true, "Use only TPC PID for daughter selection") + O2_DEFINE_CONFIGURABLE(cfgDaughterPIDRejection, bool, true, "Reject daughters if not consistent with expected K0/Lambda decay products") O2_DEFINE_CONFIGURABLE(cfgFakeKaonCut, float, 0.1f, "Maximum difference in measured momentum and TPC inner ring momentum of particle") O2_DEFINE_CONFIGURABLE(cfgUseAsymmetricPID, bool, false, "Use asymmetric PID cuts") O2_DEFINE_CONFIGURABLE(cfgTPCNsigmaCut, float, 3.0f, "TPC N-sigma cut for pions, kaons, protons") @@ -393,9 +394,9 @@ struct FlowGenericFramework { V0EfficiencyCommonPrimaryMother, V0EfficiencyMotherSpecies, V0EfficiencyMotherRapidity, + V0EfficiencySelection, V0EfficiencyGeneratedDaughterEta, V0EfficiencyRecoDaughterEta, - V0EfficiencySelection, V0EfficiencyFilled, V0EfficiencyStageCount }; @@ -465,6 +466,7 @@ struct FlowGenericFramework { FillProperLifetime, FillArmPodCut, FillCompetingMass, + FillDaughterTrackSelected, FillV02DaughterTrackSelection, FillV0DaughterTrackSelection }; @@ -735,7 +737,7 @@ struct FlowGenericFramework { registryQA.add("K0/hK0s", "", {HistType::kTH1D, {singleCount}}); registryQA.add("K0/hK0s_corrected", "", {HistType::kTH1D, {singleCount}}); } - registryQA.add("K0/hK0Count", "Number of K0;; Count", {HistType::kTH1D, {{13, 0.5, 13.5}}}); + registryQA.add("K0/hK0Count", "Number of K0;; Count", {HistType::kTH1D, {{14, 0.5, 14.5}}}); registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(FillCandidate, "K0 candidates"); registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(FillDaughterPt, "Daughter pt"); registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(FillMassCut, "Mass cut"); @@ -747,8 +749,9 @@ struct FlowGenericFramework { registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(FillProperLifetime, "Proper lifetime"); registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(FillArmPodCut, "Armenteros-Podolanski cut"); registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(FillCompetingMass, "Competing mass rejection"); - registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(FillV02DaughterTrackSelection, "v02 Daughter track selection"); - registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(FillV0DaughterTrackSelection, "v0 Daughter track selection"); + registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(FillDaughterTrackSelected, "Daughter track selected"); + registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(FillV02DaughterTrackSelection, "v02 Daughter eta selection"); + registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(FillV0DaughterTrackSelection, "v0 Daughter eta selection"); } if (resoSwitchVals[UseParticle][Lambda] != 0) { @@ -772,7 +775,7 @@ struct FlowGenericFramework { registryQA.add("Lambda/hLambdas", "", {HistType::kTH1D, {singleCount}}); registryQA.add("Lambda/hLambdas_corrected", "", {HistType::kTH1D, {singleCount}}); } - registryQA.add("Lambda/hLambdaCount", "Number of Lambda;; Count", {HistType::kTH1D, {{13, 0.5, 13.5}}}); + registryQA.add("Lambda/hLambdaCount", "Number of Lambda;; Count", {HistType::kTH1D, {{14, 0.5, 14.5}}}); registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(FillCandidate, "Lambda candidates"); registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(FillDaughterPt, "Daughter pt"); registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(FillMassCut, "Mass cut"); @@ -784,6 +787,7 @@ struct FlowGenericFramework { registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(FillProperLifetime, "Proper lifetime"); registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(FillArmPodCut, "Armenteros-Podolanski cut"); registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(FillCompetingMass, "Competing mass rejection"); + registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(FillDaughterTrackSelected, "Daughter track selected"); registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(FillV02DaughterTrackSelection, "v02 Daughter track selection"); registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(FillV0DaughterTrackSelection, "v0 Daughter track selection"); } @@ -2118,11 +2122,11 @@ struct FlowGenericFramework { if (!selectionV0DaughterEta(postrack, fractionSetup) || !selectionV0DaughterEta(negtrack, fractionSetup)) { continue; } + registryQA.fill(HIST("K0/hK0Count"), (fractionSetup == FractionV02) ? FillV02DaughterTrackSelection : FillV0DaughterTrackSelection); if (cfgFill.cfgFillV0QA && fractionSetup == FractionV02) { fillV0QA(k0Selection, v0, postrack, negtrack, centrality, weff); } - registryQA.fill(HIST("K0/hK0Count"), (fractionSetup == FractionV02) ? FillV02DaughterTrackSelection : FillV0DaughterTrackSelection); if (v0.mK0Short() > cfgPIDCuts.cfgK0SideBand1Min && v0.mK0Short() < cfgPIDCuts.cfgK0SideBand1Max) { histosResoNpt[fractionSetup][K0Sideband1]->Fill(v0.pt(), (cfgUseNchCorrection) ? weff : 1.0); @@ -2235,34 +2239,28 @@ struct FlowGenericFramework { template bool selectionV0Daughter(const TTrack& track, int pid) { - if (!(track.itsNCls() > cfgTrackCuts.cfgMinNITSCls)) { - return 0; - } - if (!track.hasTPC()) { + if (track.tpcNClsCrossedRows() < cfgTrackCuts.cfgNTPCXrows) { return false; } - if (track.tpcNClsFound() < cfgTrackCuts.cfgNTPCCls) { - return false; - } - if (!(track.tpcNClsCrossedRows() > cfgTrackCuts.cfgNTPCXrows)) { - return 0; - } - - if (cfgPIDCuts.cfgUseOnlyTPC) { - if (pid == Pions && std::abs(track.tpcNSigmaPi()) > cfgPIDCuts.cfgTPCNsigmaCut) { - return false; - } - if (pid == Kaons && std::abs(track.tpcNSigmaKa()) > cfgPIDCuts.cfgTPCNsigmaCut) { - return false; - } - if (pid == Protons && std::abs(track.tpcNSigmaPr()) > cfgPIDCuts.cfgTPCNsigmaCut) { - return false; - } - } else { - int partIndex = cfgPIDCuts.cfgUseAsymmetricPID ? getNsigmaPIDAssymmetric(track) : getNsigmaPID(track); - int pidIndex = partIndex - 1; // 0 = pion, 1 = kaon, 2 = proton - if (pidIndex != pid) { - return false; + // Only accept daughters consistent with the expected identities of K0 or Lambda decay. + if (cfgPIDCuts.cfgDaughterPIDRejection) { + if (cfgPIDCuts.cfgUseOnlyTPC) { + if (pid == Pions && std::abs(track.tpcNSigmaPi()) > cfgPIDCuts.cfgTPCNsigmaCut) { + return false; + } else if (pid == Protons && std::abs(track.tpcNSigmaPr()) > cfgPIDCuts.cfgTPCNsigmaCut) { + return false; + } else if (pid != Pions && pid != Protons) { + return false; + } + } else { + int partIndex = cfgPIDCuts.cfgUseAsymmetricPID ? getNsigmaPIDAssymmetric(track) : getNsigmaPID(track); + int pidIndex = partIndex - 1; // 0 = pion, 1 = kaon, 2 = proton + if (pid != Pions && pid != Protons) { + return false; + } + if (pidIndex != pid) { + return false; + } } } @@ -2366,7 +2364,7 @@ struct FlowGenericFramework { if (!selectionV0Daughter(postrack, Pions) || !selectionV0Daughter(negtrack, Pions)) { return selection; } - + registryQA.fill(HIST("K0/hK0Count"), FillDaughterTrackSelected); selection.selected = true; selection.isK0 = true; registryQA.fill(HIST("K0/hK0AP"), v0.alpha(), v0.qtarm()); @@ -2453,16 +2451,17 @@ struct FlowGenericFramework { registryQA.fill(HIST("Lambda/hLambdaCount"), FillCompetingMass); if (selection.isL) { if (!selectionV0Daughter(postrack, Protons) || !selectionV0Daughter(negtrack, Pions)) { - registryQA.fill(HIST("Lambda/hLambdaAP"), v0.alpha(), v0.qtarm()); return selection; } + registryQA.fill(HIST("Lambda/hLambdaAP"), v0.alpha(), v0.qtarm()); } if (selection.isAL) { if (!selectionV0Daughter(postrack, Pions) || !selectionV0Daughter(negtrack, Protons)) { - registryQA.fill(HIST("Lambda/hAntiLambdaAP"), v0.alpha(), v0.qtarm()); return selection; } + registryQA.fill(HIST("Lambda/hAntiLambdaAP"), v0.alpha(), v0.qtarm()); } + registryQA.fill(HIST("Lambda/hLambdaCount"), FillDaughterTrackSelected); selection.selected = true; return selection; From 99644d1122c6bd42b166f91970d0a1bea21b6b24 Mon Sep 17 00:00:00 2001 From: Emil Gorm Nielsen Date: Mon, 10 Aug 2026 11:19:51 +0200 Subject: [PATCH 2/4] add eta-y plot for K0s and Lambda --- .../Tasks/flowGenericFramework.cxx | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx b/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx index d84d8d89767..91a616bc295 100644 --- a/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx +++ b/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx @@ -246,9 +246,9 @@ struct FlowGenericFramework { float ptrefup = 3.0; float ptlow = 0.2; float ptup = 10.0; - int etabins = 16; - float etalow = -0.8; - float etaup = 0.8; + int etabins = 100; + float etalow = -1; + float etaup = 1; int vtxZbins = 40; float vtxZlow = -10.0; float vtxZup = 10.0; @@ -722,7 +722,7 @@ struct FlowGenericFramework { AxisSpec axisK0Mass = {resoSwitchVals[MassBins][K0], resoCutVals[MassMin][K0], resoCutVals[MassMax][K0]}; AxisSpec axisLambdaMass = {resoSwitchVals[MassBins][Lambda], resoCutVals[MassMin][Lambda], resoCutVals[MassMax][Lambda]}; - + AxisSpec yAxis = {100, -1, 1}; // QA histograms for V0s if (resoSwitchVals[UseParticle][K0] != 0) { if (cfgFill.cfgFillV0QA) { @@ -731,7 +731,7 @@ struct FlowGenericFramework { registryQA.add("K0/PiPlusTOF_K0", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTOF}}}); registryQA.add("K0/PiMinusTOF_K0", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTOF}}}); registryQA.add("K0/hK0Phi", "", {HistType::kTH1D, {phiAxis}}); - registryQA.add("K0/hK0Eta", "", {HistType::kTH1D, {etaAxis}}); + registryQA.add("K0/hK0EtaY", "", {HistType::kTH2D, {etaAxis, yAxis}}); registryQA.add("K0/hK0AP", "", {HistType::kTH2D, {{100, -1, 1}, {500, 0, 1.}}}); registryQA.add("K0/hK0Mass_sparse", "", {HistType::kTHnSparseF, {{axisK0Mass, ptAxis, nchAxis}}}); registryQA.add("K0/hK0s", "", {HistType::kTH1D, {singleCount}}); @@ -761,7 +761,7 @@ struct FlowGenericFramework { registryQA.add("Lambda/PrPlusTOF_L", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTOF}}}); registryQA.add("Lambda/PiMinusTOF_L", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTOF}}}); registryQA.add("Lambda/hLambdaPhi", "", {HistType::kTH1D, {phiAxis}}); - registryQA.add("Lambda/hLambdaEta", "", {HistType::kTH1D, {etaAxis}}); + registryQA.add("Lambda/hLambdaEtaY", "", {HistType::kTH2D, {etaAxis, yAxis}}); registryQA.add("Lambda/hLambdaAP", "", {HistType::kTH2D, {{100, -1, 1}, {100, 0, 5.}}}); registryQA.add("Lambda/hLambdaMass_sparse", "", {HistType::kTHnSparseF, {{axisLambdaMass, ptAxis, nchAxis}}}); registryQA.add("Lambda/PiPlusTPC_AL", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTPC}}}); @@ -769,7 +769,7 @@ struct FlowGenericFramework { registryQA.add("Lambda/PiPlusTOF_AL", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTOF}}}); registryQA.add("Lambda/PrMinusTOF_AL", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTOF}}}); registryQA.add("Lambda/hAntiLambdaPhi", "", {HistType::kTH1D, {phiAxis}}); - registryQA.add("Lambda/hAntiLambdaEta", "", {HistType::kTH1D, {etaAxis}}); + registryQA.add("Lambda/hAntiLambdaEtaY", "", {HistType::kTH2D, {etaAxis, yAxis}}); registryQA.add("Lambda/hAntiLambdaAP", "", {HistType::kTH2D, {{100, -1, 1}, {100, 0, 5.}}}); registryQA.add("Lambda/hAntiLambdaMass_sparse", "", {HistType::kTHnSparseF, {{axisLambdaMass, ptAxis, nchAxis}}}); registryQA.add("Lambda/hLambdas", "", {HistType::kTH1D, {singleCount}}); @@ -2603,7 +2603,7 @@ struct FlowGenericFramework { if (selection.isK0) { registryQA.fill(HIST("K0/hK0Mass_sparse"), v0.mK0Short(), v0.pt(), centrality); registryQA.fill(HIST("K0/hK0Phi"), v0.phi()); - registryQA.fill(HIST("K0/hK0Eta"), v0.eta()); + registryQA.fill(HIST("K0/hK0EtaY"), v0.eta(), v0.yK0Short()); registryQA.fill(HIST("K0/PiPlusTPC_K0"), postrack.pt(), postrack.tpcNSigmaKa()); registryQA.fill(HIST("K0/PiPlusTOF_K0"), postrack.pt(), postrack.tofNSigmaKa()); registryQA.fill(HIST("K0/PiMinusTPC_K0"), negtrack.pt(), negtrack.tpcNSigmaKa()); @@ -2617,7 +2617,7 @@ struct FlowGenericFramework { if (selection.isL) { registryQA.fill(HIST("Lambda/hLambdaMass_sparse"), v0.mLambda(), v0.pt(), centrality); registryQA.fill(HIST("Lambda/hLambdaPhi"), v0.phi()); - registryQA.fill(HIST("Lambda/hLambdaEta"), v0.eta()); + registryQA.fill(HIST("Lambda/hLambdaEtaY"), v0.eta(), v0.yLambda()); registryQA.fill(HIST("Lambda/PrPlusTPC_L"), postrack.pt(), postrack.tpcNSigmaKa()); registryQA.fill(HIST("Lambda/PrPlusTOF_L"), postrack.pt(), postrack.tofNSigmaKa()); registryQA.fill(HIST("Lambda/PiMinusTPC_L"), negtrack.pt(), negtrack.tpcNSigmaKa()); @@ -2626,7 +2626,7 @@ struct FlowGenericFramework { if (selection.isAL) { registryQA.fill(HIST("Lambda/hAntiLambdaMass_sparse"), v0.mAntiLambda(), v0.pt(), centrality); registryQA.fill(HIST("Lambda/hAntiLambdaPhi"), v0.phi()); - registryQA.fill(HIST("Lambda/hAntiLambdaEta"), v0.eta()); + registryQA.fill(HIST("Lambda/hAntiLambdaEtaY"), v0.eta(), v0.yLambda()); registryQA.fill(HIST("Lambda/PiPlusTPC_AL"), postrack.pt(), postrack.tpcNSigmaKa()); registryQA.fill(HIST("Lambda/PiPlusTOF_AL"), postrack.pt(), postrack.tofNSigmaKa()); registryQA.fill(HIST("Lambda/PrMinusTPC_AL"), negtrack.pt(), negtrack.tpcNSigmaKa()); From 510c7a50a98331c1ba33352ac2028cdb1777e316 Mon Sep 17 00:00:00 2001 From: Emil Gorm Nielsen Date: Mon, 10 Aug 2026 13:10:18 +0200 Subject: [PATCH 3/4] Add feeddown matrix to processEfficiency --- .../Tasks/flowGenericFramework.cxx | 152 ++++++++++++++++-- 1 file changed, 137 insertions(+), 15 deletions(-) diff --git a/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx b/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx index 91a616bc295..10149c3c272 100644 --- a/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx +++ b/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx @@ -237,6 +237,7 @@ struct FlowGenericFramework { ConfigurableAxis axisNsigmaTPC{"axisNsigmaTPC", {80, -5, 5}, "nsigmaTPC axis"}; ConfigurableAxis axisNsigmaTOF{"axisNsigmaTOF", {80, -5, 5}, "nsigmaTOF axis"}; + ConfigurableAxis axisFeeddownXiPt{"axisFeeddownXiPt", {VARIABLE_WIDTH, 0, 0.1, 0.5, 0.9, 1.1, 1.3, 1.5, 1.7, 1.9, 2.1, 2.3, 2.5, 2.7, 2.9, 3.9, 4.9, 5.9, 9.9, 16.0}, "Xi pt axis for Lambda feeddown correction"}; struct GFWMemberCache { std::vector ptbinning = {0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2, 2.2, 2.4, 2.6, 2.8, 3, 3.5, 4, 5, 6, 8, 10}; @@ -411,6 +412,11 @@ struct FlowGenericFramework { V0EfficiencyDaughterKaon, V0EfficiencyDaughterPdgCategoryCount }; + enum LambdaFeeddownSpecies { + FeeddownLambdaFromXiMinus = 0, + FeeddownAntiLambdaFromXiPlus, + LambdaFeeddownSpeciesCount + }; enum ResoIDs { K0Sideband1 = 0, K0Signal, @@ -634,6 +640,7 @@ struct FlowGenericFramework { AxisSpec v0EfficiencyStageAxis = {V0EfficiencyStageCount, -0.5, static_cast(V0EfficiencyStageCount) - 0.5, "stage"}; AxisSpec v0EfficiencyDebugEtaAxis = {160, -4.f, 4.f, "#eta"}; AxisSpec v0EfficiencyDaughterPdgAxis = {V0EfficiencyDaughterPdgCategoryCount, -0.5, static_cast(V0EfficiencyDaughterPdgCategoryCount) - 0.5, "daughter PDG category"}; + AxisSpec lambdaFeeddownSpeciesAxis = {LambdaFeeddownSpeciesCount, -0.5, static_cast(LambdaFeeddownSpeciesCount) - 0.5, "species"}; ccdb->setURL("http://alice-ccdb.cern.ch"); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); @@ -659,6 +666,8 @@ struct FlowGenericFramework { registry.add("Efficiency/v0RecoDebug", "; #it{p}_{T}; Centrality (%)", {HistType::kTHnSparseF, {{ptAxis, centAxis, efficiencyParticleAxis, v0EfficiencyStageAxis}}}); registry.add("Efficiency/v0RecoDaughterEtaDebug", "; Centrality (%); particle; #eta^{MC}_{pos}; #eta^{MC}_{neg}; #eta^{reco}_{pos}; #eta^{reco}_{neg}", {HistType::kTHnSparseF, {{centAxis, efficiencyParticleAxis, v0EfficiencyDebugEtaAxis, v0EfficiencyDebugEtaAxis, v0EfficiencyDebugEtaAxis, v0EfficiencyDebugEtaAxis}}}); registry.add("Efficiency/v0RecoDaughterPdgDebug", "; Centrality (%); particle; PDG^{MC}_{pos}; PDG^{MC}_{neg}", {HistType::kTHnSparseF, {{centAxis, efficiencyParticleAxis, v0EfficiencyDaughterPdgAxis, v0EfficiencyDaughterPdgAxis}}}); + registry.add("Efficiency/lambdaFeeddownRecoXi", "; #it{p}_{T}^{#Lambda, reco}; #it{p}_{T}^{#Xi, gen}; Centrality (%)", {HistType::kTHnSparseF, {{ptAxis, axisFeeddownXiPt, centAxis, lambdaFeeddownSpeciesAxis}}}); + registry.add("Efficiency/lambdaFeeddownGeneratedXi", "; #it{p}_{T}^{#Xi, gen}; Centrality (%)", {HistType::kTHnSparseF, {{axisFeeddownXiPt, centAxis, lambdaFeeddownSpeciesAxis}}}); } if (doprocessMCReco || doprocessData || doprocessRun2 || doprocessEfficiency) { if (cfgFill.cfgFillQA) { @@ -2372,7 +2381,7 @@ struct FlowGenericFramework { } template - V0Selection selectLambda(const TCollision& collision, const TV0& v0, const TTracks&) + V0Selection selectLambda(const TCollision& collision, const TV0& v0, const TTracks&, bool fillSelectionQA = true) { using V0TrackTable = std::decay_t; V0Selection selection; @@ -2384,12 +2393,16 @@ struct FlowGenericFramework { auto postrack = v0.template posTrack_as(); auto negtrack = v0.template negTrack_as(); - registryQA.fill(HIST("Lambda/hLambdaCount"), FillCandidate); + if (fillSelectionQA) { + registryQA.fill(HIST("Lambda/hLambdaCount"), FillCandidate); + } if (postrack.pt() < resoCutVals[PosTrackPt][Lambda] || negtrack.pt() < resoCutVals[NegTrackPt][Lambda]) { return selection; } - registryQA.fill(HIST("Lambda/hLambdaCount"), FillDaughterPt); + if (fillSelectionQA) { + registryQA.fill(HIST("Lambda/hLambdaCount"), FillDaughterPt); + } if (mlambda > resoCutVals[MassMin][Lambda] && mlambda < resoCutVals[MassMax][Lambda]) { selection.isL = true; } @@ -2400,13 +2413,17 @@ struct FlowGenericFramework { if (!selection.isL && !selection.isAL) { return selection; } - registryQA.fill(HIST("Lambda/hLambdaCount"), FillMassCut); + if (fillSelectionQA) { + registryQA.fill(HIST("Lambda/hLambdaCount"), FillMassCut); + } // Rapidity correction if (std::abs(v0.yLambda()) > resoCutVals[Rapidity][Lambda]) { return selection; } - registryQA.fill(HIST("Lambda/hLambdaCount"), FillRapidityCut); + if (fillSelectionQA) { + registryQA.fill(HIST("Lambda/hLambdaCount"), FillRapidityCut); + } // DCA cuts for lambda and antilambda if (selection.isL) { if (std::abs(v0.dcapostopv()) < resoCutVals[DCAPosToPVMin][Lambda] || std::abs(v0.dcanegtopv()) < resoCutVals[DCANegToPVMin][Lambda]) { @@ -2418,50 +2435,70 @@ struct FlowGenericFramework { return selection; } } - registryQA.fill(HIST("Lambda/hLambdaCount"), FillDCAtoPV); + if (fillSelectionQA) { + registryQA.fill(HIST("Lambda/hLambdaCount"), FillDCAtoPV); + } if (resoSwitchVals[UseDCAxDaughters][Lambda] != 0 && std::abs(v0.dcaV0daughters()) > resoCutVals[DCAxDaughters][Lambda]) { return selection; } - registryQA.fill(HIST("Lambda/hLambdaCount"), FillDCAxDaughters); + if (fillSelectionQA) { + registryQA.fill(HIST("Lambda/hLambdaCount"), FillDCAxDaughters); + } // v0 radius cuts if (resoSwitchVals[UseV0Radius][Lambda] != 0 && (v0.v0radius() < resoCutVals[RadiusMin][Lambda] || v0.v0radius() > resoCutVals[RadiusMax][Lambda])) { return selection; } - registryQA.fill(HIST("Lambda/hLambdaCount"), FillV0Radius); + if (fillSelectionQA) { + registryQA.fill(HIST("Lambda/hLambdaCount"), FillV0Radius); + } // cosine pointing angle cuts if (v0.v0cosPA() < resoCutVals[CosPA][Lambda]) { return selection; } - registryQA.fill(HIST("Lambda/hLambdaCount"), FillCosPA); + if (fillSelectionQA) { + registryQA.fill(HIST("Lambda/hLambdaCount"), FillCosPA); + } // Proper lifetime if (resoSwitchVals[UseProperLifetime][Lambda] != 0 && v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massLambda > resoCutVals[LifeTime][Lambda]) { return selection; } - registryQA.fill(HIST("Lambda/hLambdaCount"), FillProperLifetime); + if (fillSelectionQA) { + registryQA.fill(HIST("Lambda/hLambdaCount"), FillProperLifetime); + } // ArmenterosPodolanskiCut if (resoSwitchVals[UseArmPodCut][Lambda] != 0 && (v0.qtarm() / std::abs(v0.alpha())) < resoCutVals[ArmPodMin][Lambda]) { return selection; } - registryQA.fill(HIST("Lambda/hLambdaCount"), FillArmPodCut); + if (fillSelectionQA) { + registryQA.fill(HIST("Lambda/hLambdaCount"), FillArmPodCut); + } if (resoSwitchVals[UseCompetingMassRejection][Lambda] != 0) { if (std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short) < resoCutVals[MassRejection][Lambda]) { return selection; } } - registryQA.fill(HIST("Lambda/hLambdaCount"), FillCompetingMass); + if (fillSelectionQA) { + registryQA.fill(HIST("Lambda/hLambdaCount"), FillCompetingMass); + } if (selection.isL) { if (!selectionV0Daughter(postrack, Protons) || !selectionV0Daughter(negtrack, Pions)) { return selection; } - registryQA.fill(HIST("Lambda/hLambdaAP"), v0.alpha(), v0.qtarm()); + if (fillSelectionQA) { + registryQA.fill(HIST("Lambda/hLambdaAP"), v0.alpha(), v0.qtarm()); + } } if (selection.isAL) { if (!selectionV0Daughter(postrack, Pions) || !selectionV0Daughter(negtrack, Protons)) { return selection; } - registryQA.fill(HIST("Lambda/hAntiLambdaAP"), v0.alpha(), v0.qtarm()); + if (fillSelectionQA) { + registryQA.fill(HIST("Lambda/hAntiLambdaAP"), v0.alpha(), v0.qtarm()); + } + } + if (fillSelectionQA) { + registryQA.fill(HIST("Lambda/hLambdaCount"), FillDaughterTrackSelected); } - registryQA.fill(HIST("Lambda/hLambdaCount"), FillDaughterTrackSelected); selection.selected = true; return selection; @@ -2904,6 +2941,30 @@ struct FlowGenericFramework { registry.fill(HIST("Efficiency/efficiencyHist"), particle.pt(), centrality, particleIndex, EfficiencyGenerated); } + template + bool isGeneratedFeeddownXi(const TParticle& particle) + { + return particle.isPhysicalPrimary() && std::abs(particle.pdgCode()) == PDG_t::kXiMinus && std::abs(particle.y()) < resoCutVals[Rapidity][Lambda]; + } + + template + int getLambdaFeeddownSpeciesFromXi(const TParticle& xiParticle) + { + return xiParticle.pdgCode() == PDG_t::kXiMinus ? FeeddownLambdaFromXiMinus : FeeddownAntiLambdaFromXiPlus; + } + + template + void fillGeneratedLambdaFeeddownXi(const TParticle& particle, float centrality) + { + if (resoSwitchVals[UseParticle][Lambda] == 0) { + return; + } + if (!isGeneratedFeeddownXi(particle)) { + return; + } + registry.fill(HIST("Efficiency/lambdaFeeddownGeneratedXi"), particle.pt(), centrality, getLambdaFeeddownSpeciesFromXi(particle)); + } + template bool isEfficiencyEventSelected(const TCollision& collision, const int multTrk, float& centrality) { @@ -2981,6 +3042,65 @@ struct FlowGenericFramework { } } + template + void fillLambdaFeeddownReco(const TV0& v0, const TCollision& collision, const TTracks& tracks, float centrality) + { + if (resoSwitchVals[UseParticle][Lambda] == 0) { + return; + } + + using V0TrackTable = std::decay_t; + auto postrack = v0.template posTrack_as(); + auto negtrack = v0.template negTrack_as(); + + if (!postrack.has_mcParticle() || !negtrack.has_mcParticle()) { + return; + } + + auto posMcParticle = postrack.template mcParticle_as(); + auto negMcParticle = negtrack.template mcParticle_as(); + if (!posMcParticle.has_mothers() || !negMcParticle.has_mothers()) { + return; + } + + for (const auto& posMother : posMcParticle.template mothers_as()) { + for (const auto& negMother : negMcParticle.template mothers_as()) { + if (posMother.globalIndex() != negMother.globalIndex() || std::abs(posMother.pdgCode()) != PDG_t::kLambda0) { + continue; + } + + if (!posMother.has_mothers()) { + continue; + } + for (const auto& xiMother : posMother.template mothers_as()) { + if (!isGeneratedFeeddownXi(xiMother)) { + continue; + } + + const bool isLambda = posMother.pdgCode() == PDG_t::kLambda0 && xiMother.pdgCode() == PDG_t::kXiMinus; + const bool isAntiLambda = posMother.pdgCode() == -PDG_t::kLambda0 && xiMother.pdgCode() == -PDG_t::kXiMinus; + if (!isLambda && !isAntiLambda) { + continue; + } + + auto selection = selectLambda(collision, v0, tracks, false); + if (!selection.selected || (isLambda && !selection.isL) || (isAntiLambda && !selection.isAL)) { + return; + } + if (!isWithinEfficiencyEtaAcceptance(posMcParticle) || !isWithinEfficiencyEtaAcceptance(negMcParticle)) { + return; + } + if (!isWithinEfficiencyEtaAcceptance(postrack) || !isWithinEfficiencyEtaAcceptance(negtrack)) { + return; + } + + registry.fill(HIST("Efficiency/lambdaFeeddownRecoXi"), v0.pt(), xiMother.pt(), centrality, getLambdaFeeddownSpeciesFromXi(xiMother)); + return; + } + } + } + } + template void fillEfficiencyRecoTrack(const TTrack& track, int field, float centrality) { @@ -3152,6 +3272,7 @@ struct FlowGenericFramework { continue; } fillGeneratedEfficiencyTrack(particle, selectedCentrality); + fillGeneratedLambdaFeeddownXi(particle, selectedCentrality); if (isGeneratedEfficiencyV0(particle, PDG_t::kK0Short, K0) && resoSwitchVals[UseParticle][K0] != 0) { fillGeneratedEfficiencyV0(particle, EfficiencyK0, selectedCentrality); } @@ -3176,6 +3297,7 @@ struct FlowGenericFramework { if (v0.collisionId() != bestCollisionIndex) { continue; } + fillLambdaFeeddownReco(v0, collision, tracks, selectedCentrality); fillEfficiencyRecoV0(v0, collision, tracks, selectedCentrality); } break; From 1ca81d5634957dce4609a65f2f3e199ef524d3ff Mon Sep 17 00:00:00 2001 From: Emil Gorm Nielsen Date: Mon, 10 Aug 2026 15:57:24 +0200 Subject: [PATCH 4/4] codecheck --- .../Tasks/flowGenericFramework.cxx | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx b/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx index 10149c3c272..c2481bd8d0f 100644 --- a/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx +++ b/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx @@ -2254,25 +2254,23 @@ struct FlowGenericFramework { // Only accept daughters consistent with the expected identities of K0 or Lambda decay. if (cfgPIDCuts.cfgDaughterPIDRejection) { if (cfgPIDCuts.cfgUseOnlyTPC) { - if (pid == Pions && std::abs(track.tpcNSigmaPi()) > cfgPIDCuts.cfgTPCNsigmaCut) { - return false; - } else if (pid == Protons && std::abs(track.tpcNSigmaPr()) > cfgPIDCuts.cfgTPCNsigmaCut) { - return false; - } else if (pid != Pions && pid != Protons) { - return false; + if (pid == Pions) { + return std::abs(track.tpcNSigmaPi()) <= cfgPIDCuts.cfgTPCNsigmaCut; } - } else { - int partIndex = cfgPIDCuts.cfgUseAsymmetricPID ? getNsigmaPIDAssymmetric(track) : getNsigmaPID(track); - int pidIndex = partIndex - 1; // 0 = pion, 1 = kaon, 2 = proton - if (pid != Pions && pid != Protons) { - return false; - } - if (pidIndex != pid) { - return false; + if (pid == Protons) { + return std::abs(track.tpcNSigmaPr()) <= cfgPIDCuts.cfgTPCNsigmaCut; } + return false; + } + int partIndex = cfgPIDCuts.cfgUseAsymmetricPID ? getNsigmaPIDAssymmetric(track) : getNsigmaPID(track); + int pidIndex = partIndex - 1; // 0 = pion, 1 = kaon, 2 = proton + if (pid != Pions && pid != Protons) { + return false; + } + if (pidIndex != pid) { + return false; } } - return true; }