From b28c6d9137e0bcf07f9201318ac79645bd41b8a2 Mon Sep 17 00:00:00 2001 From: allesgrau Date: Mon, 3 Aug 2026 17:05:14 +0200 Subject: [PATCH 1/6] [PWGCF] Add TOF nsigma selection for V0 and cascade daughters and bachelors --- PWGCF/Femto/Core/cascadeBuilder.h | 37 +++++++++++++++++++++++++++++-- PWGCF/Femto/Core/v0Builder.h | 31 +++++++++++++++++++++++++- 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/PWGCF/Femto/Core/cascadeBuilder.h b/PWGCF/Femto/Core/cascadeBuilder.h index 01148794aca..95a2ccce964 100644 --- a/PWGCF/Femto/Core/cascadeBuilder.h +++ b/PWGCF/Femto/Core/cascadeBuilder.h @@ -76,18 +76,24 @@ struct ConfCascadeFilters : o2::framework::ConfigurableGroup { o2::framework::Configurable> dauAbsDcaxyMin{"dauAbsDcaxyMin", {0.05f}, "Minimum |DCAxy| of the daughters and bachelor from primary vertex (cm)"}; \ o2::framework::Configurable> dauTpcClustersMin{"dauTpcClustersMin", {80.f}, "Minimum number of TPC clusters for daughter tracks"}; \ o2::framework::Configurable> posDauTpc{"posDauTpc", {5.f}, "Maximum |nsimga_Pion/Proton| TPC for positive daughter tracks"}; \ - o2::framework::Configurable> negDauTpc{"negDauTpc", {5.f}, "Maximum |nsimga_Pion/Proton| TPC for negative daughter tracks"}; + o2::framework::Configurable> negDauTpc{"negDauTpc", {5.f}, "Maximum |nsimga_Pion/Proton| TPC for negative daughter tracks"}; \ + o2::framework::Configurable> posDauTof{"posDauTof", {}, "Maximum |nsimga_Pion/Proton| TOF for positive daughter tracks"}; \ + o2::framework::Configurable> negDauTof{"negDauTof", {}, "Maximum |nsigma_Pion/Proton| TOF for negative daughter tracks"}; + struct ConfXiBits : o2::framework::ConfigurableGroup { std::string prefix = std::string("XiBits"); CASCADE_DEFAULT_BITS o2::framework::Configurable> bachelorTpcPion{"bachelorTpcPion", {5.f}, "Maximum |nsimga_Pion| TPC for bachelor tracks"}; + o2::framework::Configurable> bachelorTofPion{"bachelorTofPion", {}, "Maximum |nsimga_Pion| TOF for bachelor tracks"}; + }; struct ConfOmegaBits : o2::framework::ConfigurableGroup { std::string prefix = std::string("OmegaBits"); CASCADE_DEFAULT_BITS o2::framework::Configurable> bachelorTpcKaon{"bachelorTpcKaon", {5.f}, "Maximum |nsimga_Kaon| TPC for bachelor tracks"}; + o2::framework::Configurable> bachelorTofKaon{"bachelorTofKaon", {}, "Maximum |nsimga_Kaon| TOF for bachelor tracks"}; }; #undef CASCADE_DEFAULT_BITS @@ -139,10 +145,14 @@ enum CascadeSels { // PID selection for cascade bachelor kBachelorTpcPion, ///< TPC Pion PID for bachelor kBachelorTpcKaon, ///< TPC Kaon PID for bachelor + kBachelorTofPion, ///< TOF Pion PID for bachelor + kBachelorTofKaon, ///< TOF Kaon PID for bachelor /// // PID selection for lambda daughers kPosDauTpc, ///< TPC PID for positive daughter kNegDauTpc, ///< TPC PID for negative daughter + kPosDauTof, ///< TOF PID for positive daughter + kNegDauTof, ///< TOF PID for negative daughter kCascadeSelsMax }; @@ -166,9 +176,12 @@ const std::unordered_map cascadeSelectionNames = { {kBachelorTpcPion, "Bachelor TPC Pion PID"}, {kBachelorTpcKaon, "Bachelor TPC Kaon PID"}, - + {kBachelorTofPion, "Bachelor TOF Pion PID"}, + {kBachelorTofKaon, "Bachelor TOF Kaon PID"}, {kPosDauTpc, "Positive Daughter TPC PID"}, {kNegDauTpc, "Negative Daughter TPC PID"}, + {kPosDauTof, "Positive Daughter TOF PID"}, + {kNegDauTof, "Negative Daughter TOF PID"}, {kCascadeSelsMax, "Cascade Selections Max"}}; @@ -231,6 +244,7 @@ class CascadeSelection : public baseselection::BaseSelectionaddSelection(kBachelorTpcPion, cascadeSelectionNames.at(kBachelorTpcPion), config.bachelorTpcPion.value, limits::kAbsUpperLimit, true, true, false); + this->addSelection(kBachelorTofPion, cascadeSelectionNames.at(kBachelorTofPion), config.bachelorTofPion.value, limits::kAbsUpperLimit, true, true, false); } if constexpr (modes::isEqual(cascadeType, modes::Cascade::kOmega)) { mOmegaMassLowerLimit = filter.massOmegaMin.value; @@ -239,6 +253,7 @@ class CascadeSelection : public baseselection::BaseSelectionaddSelection(kBachelorTpcKaon, cascadeSelectionNames.at(kBachelorTpcKaon), config.bachelorTpcKaon.value, limits::kAbsUpperLimit, true, true, false); + this->addSelection(kBachelorTofKaon, cascadeSelectionNames.at(kBachelorTofKaon), config.bachelorTofKaon.value, limits::kAbsUpperLimit, true, true, false); } mPtMin = filter.ptMin.value; @@ -252,6 +267,8 @@ class CascadeSelection : public baseselection::BaseSelectionaddSelection(kPosDauTpc, cascadeSelectionNames.at(kPosDauTpc), config.posDauTpc.value, limits::kAbsUpperLimit, true, true, false); this->addSelection(kNegDauTpc, cascadeSelectionNames.at(kNegDauTpc), config.negDauTpc.value, limits::kAbsUpperLimit, true, true, false); + this->addSelection(kPosDauTof, cascadeSelectionNames.at(kPosDauTof), config.posDauTof.value, limits::kAbsUpperLimit, true, true, false); + this->addSelection(kNegDauTof, cascadeSelectionNames.at(kNegDauTof), config.negDauTof.value, limits::kAbsUpperLimit, true, true, false); this->addSelection(kCascadeCpaMin, cascadeSelectionNames.at(kCascadeCpaMin), config.cascadeCpaMin.value, limits::kLowerLimit, true, true, false); this->addSelection(kCascadeTransRadMin, cascadeSelectionNames.at(kCascadeTransRadMin), config.cascadeTransRadMin.value, limits::kLowerLimit, true, true, false); @@ -318,14 +335,30 @@ class CascadeSelection : public baseselection::BaseSelectionevaluateObservable(kBachelorTpcPion, bachelor.tpcNSigmaPi()); this->evaluateObservable(kBachelorTpcKaon, bachelor.tpcNSigmaKa()); + if (bachelor.hasTOF()) { + this->evaluateObservable(kBachelorTofPion, bachelor.tofNSigmaPi()); + this->evaluateObservable(kBachelorTofKaon, bachelor.tofNSigmaKa()); + } // depending on the charge, we check lambda or antilambda hypothesis if (cascade.sign() < 0) { this->evaluateObservable(kPosDauTpc, posDaughter.tpcNSigmaPr()); this->evaluateObservable(kNegDauTpc, negDaughter.tpcNSigmaPi()); + if (posDaughter.hasTOF()) { + this->evaluateObservable(kPosDauTof, posDaughter.tofNSigmaPr()); + } + if (negDaughter.hasTOF()) { + this->evaluateObservable(kNegDauTof, negDaughter.tofNSigmaPi()); + } } else if (cascade.sign() > 0) { this->evaluateObservable(kPosDauTpc, posDaughter.tpcNSigmaPi()); this->evaluateObservable(kNegDauTpc, negDaughter.tpcNSigmaPr()); + if (posDaughter.hasTOF()) { + this->evaluateObservable(kPosDauTof, posDaughter.tofNSigmaPi()); + } + if (negDaughter.hasTOF()) { + this->evaluateObservable(kNegDauTof, negDaughter.tofNSigmaPr()); + } } else { LOG(warn) << "Encountered Cascade candidate with 0 charge"; } diff --git a/PWGCF/Femto/Core/v0Builder.h b/PWGCF/Femto/Core/v0Builder.h index 4dac03ed8ae..1956df08357 100644 --- a/PWGCF/Femto/Core/v0Builder.h +++ b/PWGCF/Femto/Core/v0Builder.h @@ -81,6 +81,10 @@ struct ConfLambdaBits : o2::framework::ConfigurableGroup { o2::framework::Configurable> posDauTpcProton{"posDauTpcProton", {5.f}, "Maximum |nsimga_Proton| TPC for positive daughter tracks"}; o2::framework::Configurable> negDauTpcPion{"negDauTpcPion", {5.f}, "Maximum |nsimga_Pion| TPC for negative daughter tracks"}; o2::framework::Configurable> negDauTpcProton{"negDauTpcProton", {5.f}, "Maximum |nsimga_Proton| TPC negative for daughter tracks"}; + o2::framework::Configurable> posDauTofPion{"posDauTofPion", {}, "Maximum |nsigma_Pion| TOF for positive daughter tracks"}; + o2::framework::Configurable> posDauTofProton{"posDauTofProton", {}, "Maximum |nsigma_Proton| TOF for positive daughter tracks"}; + o2::framework::Configurable> negDauTofPion{"negDauTofPion", {}, "Maximum |nsigma_Pion| TOF for negative daughter tracks"}; + o2::framework::Configurable> negDauTofProton{"negDauTofProton", {}, "Maximum |nsigma_Proton| TOF for negative daughter tracks"}; }; // derived selection bits for K0Short @@ -89,6 +93,8 @@ struct ConfK0shortBits : o2::framework::ConfigurableGroup { V0_DEFAULT_BITS o2::framework::Configurable> posDauTpcPion{"posDauTpcPion", {5.f}, "Maximum |nsimga_Pion| TPC for positive daughter tracks"}; o2::framework::Configurable> negDauTpcPion{"negDauTpcPion", {5.f}, "Maximum |nsimga_Pion| TPC for negative daughter tracks"}; + o2::framework::Configurable> posDauTofPion{"posDauTofPion", {}, "Maximum |nsigma_Pion| TOF for positive daughter tracks"}; + o2::framework::Configurable> negDauTofPion{"negDauTofPion", {}, "Maximum |nsigma_Pion| TOF for negative daughter tracks"}; }; #undef V0_DEFAULT_BITS @@ -154,6 +160,11 @@ enum V0Sels { kNegDaughTpcPion, ///< TPC Pion PID for negative daughter kNegDaughTpcProton, ///< TPC Proton PID for negative daughter + kPosDaughTofPion, ///< TOF Pion PID for positive daughter + kPosDaughTofProton, ///< TOF Proton PID for positive daughter + kNegDaughTofPion, ///< TOF Pion PID for negative daughter + kNegDaughTofProton, ///< TOF Proton PID for negative daughter + kV0SelsMax }; @@ -175,7 +186,11 @@ const std::unordered_map v0SelectionNames = { {kPosDaughTpcPion, "TPC Pion PID for positive daughter"}, {kPosDaughTpcProton, "TPC Proton PID for positive daughter"}, {kNegDaughTpcPion, "TPC Pion PID for negative daughter"}, - {kNegDaughTpcProton, "TPC Proton PID for negative daughter"}}; + {kNegDaughTpcProton, "TPC Proton PID for negative daughter"}, + {kPosDaughTofPion, "TOF Pion PID for positive daughter"}, + {kPosDaughTofProton, "TOF Proton PID for positive daughter"}, + {kNegDaughTofPion, "TOF Pion PID for negative daughter"}, + {kNegDaughTofProton, "TOF Proton PID for negative daughter"}}; // enum for all track filters (loose pre-selection, applied before quality/PID cuts) enum V0Filters { @@ -242,11 +257,15 @@ class V0Selection : public baseselection::BaseSelectionaddSelection(kPosDaughTpcProton, v0SelectionNames.at(kPosDaughTpcProton), config.posDauTpcProton.value, limits::kAbsUpperLimit, true, true, false); this->addSelection(kNegDaughTpcPion, v0SelectionNames.at(kNegDaughTpcPion), config.negDauTpcPion.value, limits::kAbsUpperLimit, true, true, false); + this->addSelection(kPosDaughTofProton, v0SelectionNames.at(kPosDaughTofProton), config.posDauTofProton.value, limits::kAbsUpperLimit, true, true, false); + this->addSelection(kNegDaughTofPion, v0SelectionNames.at(kNegDaughTofPion), config.negDauTofPion.value, limits::kAbsUpperLimit, true, true, false); } if constexpr (modes::isEqual(v0Type, modes::V0::kAntiLambda)) { this->addSelection(kPosDaughTpcPion, v0SelectionNames.at(kPosDaughTpcPion), config.posDauTpcPion.value, limits::kAbsUpperLimit, true, true, false); this->addSelection(kNegDaughTpcProton, v0SelectionNames.at(kNegDaughTpcProton), config.negDauTpcProton.value, limits::kAbsUpperLimit, true, true, false); + this->addSelection(kPosDaughTofPion, v0SelectionNames.at(kPosDaughTofPion), config.posDauTofPion.value, limits::kAbsUpperLimit, true, true, false); + this->addSelection(kNegDaughTofProton, v0SelectionNames.at(kNegDaughTofProton), config.negDauTofProton.value, limits::kAbsUpperLimit, true, true, false); } } if constexpr (modes::isEqual(v0Type, modes::V0::kK0short)) { @@ -258,6 +277,8 @@ class V0Selection : public baseselection::BaseSelectionaddSelection(kPosDaughTpcPion, v0SelectionNames.at(kPosDaughTpcPion), config.posDauTpcPion.value, limits::kAbsUpperLimit, true, true, false); this->addSelection(kNegDaughTpcPion, v0SelectionNames.at(kNegDaughTpcPion), config.negDauTpcPion.value, limits::kAbsUpperLimit, true, true, false); + this->addSelection(kPosDaughTofPion, v0SelectionNames.at(kPosDaughTofPion), config.posDauTofPion.value, limits::kAbsUpperLimit, true, true, false); + this->addSelection(kNegDaughTofPion, v0SelectionNames.at(kNegDaughTofPion), config.negDauTofPion.value, limits::kAbsUpperLimit, true, true, false); } this->addSelection(kDcaDaughMax, v0SelectionNames.at(kDcaDaughMax), config.dcaDauMax.value, limits::kAbsUpperLimit, true, true, false); @@ -321,6 +342,14 @@ class V0Selection : public baseselection::BaseSelectionevaluateObservable(kPosDaughTpcProton, posDaughter.tpcNSigmaPr()); this->evaluateObservable(kNegDaughTpcPion, negDaughter.tpcNSigmaPi()); this->evaluateObservable(kNegDaughTpcProton, negDaughter.tpcNSigmaPr()); + if (posDaughter.hasTOF()) { + this->evaluateObservable(kPosDaughTofPion, posDaughter.tofNSigmaPi()); + this->evaluateObservable(kPosDaughTofProton, posDaughter.tofNSigmaPr()); + } + if (negDaughter.hasTOF()) { + this->evaluateObservable(kNegDaughTofPion, negDaughter.tofNSigmaPi()); + this->evaluateObservable(kNegDaughTofProton, negDaughter.tofNSigmaPr()); + } this->assembleBitmask(); } From 70c0485af6146d31c02f68bbc23ce2307f722aa2 Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Mon, 3 Aug 2026 15:12:11 +0000 Subject: [PATCH 2/6] Please consider the following formatting changes --- PWGCF/Femto/Core/cascadeBuilder.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/PWGCF/Femto/Core/cascadeBuilder.h b/PWGCF/Femto/Core/cascadeBuilder.h index 95a2ccce964..1cd12cc1c7b 100644 --- a/PWGCF/Femto/Core/cascadeBuilder.h +++ b/PWGCF/Femto/Core/cascadeBuilder.h @@ -80,20 +80,18 @@ struct ConfCascadeFilters : o2::framework::ConfigurableGroup { o2::framework::Configurable> posDauTof{"posDauTof", {}, "Maximum |nsimga_Pion/Proton| TOF for positive daughter tracks"}; \ o2::framework::Configurable> negDauTof{"negDauTof", {}, "Maximum |nsigma_Pion/Proton| TOF for negative daughter tracks"}; - struct ConfXiBits : o2::framework::ConfigurableGroup { std::string prefix = std::string("XiBits"); CASCADE_DEFAULT_BITS o2::framework::Configurable> bachelorTpcPion{"bachelorTpcPion", {5.f}, "Maximum |nsimga_Pion| TPC for bachelor tracks"}; o2::framework::Configurable> bachelorTofPion{"bachelorTofPion", {}, "Maximum |nsimga_Pion| TOF for bachelor tracks"}; - }; struct ConfOmegaBits : o2::framework::ConfigurableGroup { std::string prefix = std::string("OmegaBits"); CASCADE_DEFAULT_BITS o2::framework::Configurable> bachelorTpcKaon{"bachelorTpcKaon", {5.f}, "Maximum |nsimga_Kaon| TPC for bachelor tracks"}; - o2::framework::Configurable> bachelorTofKaon{"bachelorTofKaon", {}, "Maximum |nsimga_Kaon| TOF for bachelor tracks"}; + o2::framework::Configurable> bachelorTofKaon{"bachelorTofKaon", {}, "Maximum |nsimga_Kaon| TOF for bachelor tracks"}; }; #undef CASCADE_DEFAULT_BITS From c9f4528fdf71973899f5343d0cff5fab08a234a9 Mon Sep 17 00:00:00 2001 From: allesgrau Date: Tue, 4 Aug 2026 14:18:31 +0200 Subject: [PATCH 3/6] [PWGCF] Don't reject V0s with daughters that don't have TOF. --- PWGCF/Femto/Core/cascadeBuilder.h | 24 +++++++++++++++++++----- PWGCF/Femto/Core/v0Builder.h | 23 +++++++++++++++++------ 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/PWGCF/Femto/Core/cascadeBuilder.h b/PWGCF/Femto/Core/cascadeBuilder.h index 1cd12cc1c7b..0a5981605fe 100644 --- a/PWGCF/Femto/Core/cascadeBuilder.h +++ b/PWGCF/Femto/Core/cascadeBuilder.h @@ -78,7 +78,8 @@ struct ConfCascadeFilters : o2::framework::ConfigurableGroup { o2::framework::Configurable> posDauTpc{"posDauTpc", {5.f}, "Maximum |nsimga_Pion/Proton| TPC for positive daughter tracks"}; \ o2::framework::Configurable> negDauTpc{"negDauTpc", {5.f}, "Maximum |nsimga_Pion/Proton| TPC for negative daughter tracks"}; \ o2::framework::Configurable> posDauTof{"posDauTof", {}, "Maximum |nsimga_Pion/Proton| TOF for positive daughter tracks"}; \ - o2::framework::Configurable> negDauTof{"negDauTof", {}, "Maximum |nsigma_Pion/Proton| TOF for negative daughter tracks"}; + o2::framework::Configurable> negDauTof{"negDauTof", {}, "Maximum |nsigma_Pion/Proton| TOF for negative daughter tracks"}; \ + o2::framework::Configurable requireTof{"requireTof", false, "If true, only keep candidates whose daughters have a TOF signal"}; struct ConfXiBits : o2::framework::ConfigurableGroup { std::string prefix = std::string("XiBits"); @@ -242,7 +243,7 @@ class CascadeSelection : public baseselection::BaseSelectionaddSelection(kBachelorTpcPion, cascadeSelectionNames.at(kBachelorTpcPion), config.bachelorTpcPion.value, limits::kAbsUpperLimit, true, true, false); - this->addSelection(kBachelorTofPion, cascadeSelectionNames.at(kBachelorTofPion), config.bachelorTofPion.value, limits::kAbsUpperLimit, true, true, false); + this->addSelection(kBachelorTofPion, cascadeSelectionNames.at(kBachelorTofPion), config.bachelorTofPion.value, limits::kAbsUpperLimit, true, false, false); } if constexpr (modes::isEqual(cascadeType, modes::Cascade::kOmega)) { mOmegaMassLowerLimit = filter.massOmegaMin.value; @@ -251,7 +252,7 @@ class CascadeSelection : public baseselection::BaseSelectionaddSelection(kBachelorTpcKaon, cascadeSelectionNames.at(kBachelorTpcKaon), config.bachelorTpcKaon.value, limits::kAbsUpperLimit, true, true, false); - this->addSelection(kBachelorTofKaon, cascadeSelectionNames.at(kBachelorTofKaon), config.bachelorTofKaon.value, limits::kAbsUpperLimit, true, true, false); + this->addSelection(kBachelorTofKaon, cascadeSelectionNames.at(kBachelorTofKaon), config.bachelorTofKaon.value, limits::kAbsUpperLimit, true, false, false); } mPtMin = filter.ptMin.value; @@ -262,11 +263,12 @@ class CascadeSelection : public baseselection::BaseSelectionaddSelection(kPosDauTpc, cascadeSelectionNames.at(kPosDauTpc), config.posDauTpc.value, limits::kAbsUpperLimit, true, true, false); this->addSelection(kNegDauTpc, cascadeSelectionNames.at(kNegDauTpc), config.negDauTpc.value, limits::kAbsUpperLimit, true, true, false); - this->addSelection(kPosDauTof, cascadeSelectionNames.at(kPosDauTof), config.posDauTof.value, limits::kAbsUpperLimit, true, true, false); - this->addSelection(kNegDauTof, cascadeSelectionNames.at(kNegDauTof), config.negDauTof.value, limits::kAbsUpperLimit, true, true, false); + this->addSelection(kPosDauTof, cascadeSelectionNames.at(kPosDauTof), config.posDauTof.value, limits::kAbsUpperLimit, true, false, false); + this->addSelection(kNegDauTof, cascadeSelectionNames.at(kNegDauTof), config.negDauTof.value, limits::kAbsUpperLimit, true, false, false); this->addSelection(kCascadeCpaMin, cascadeSelectionNames.at(kCascadeCpaMin), config.cascadeCpaMin.value, limits::kLowerLimit, true, true, false); this->addSelection(kCascadeTransRadMin, cascadeSelectionNames.at(kCascadeTransRadMin), config.cascadeTransRadMin.value, limits::kLowerLimit, true, true, false); @@ -336,6 +338,9 @@ class CascadeSelection : public baseselection::BaseSelectionevaluateObservable(kBachelorTofPion, bachelor.tofNSigmaPi()); this->evaluateObservable(kBachelorTofKaon, bachelor.tofNSigmaKa()); + } else if (!mRequireTof) { + this->setBitmask(kBachelorTofPion, std::numeric_limits::max()); + this->setBitmask(kBachelorTofKaon, std::numeric_limits::max()); } // depending on the charge, we check lambda or antilambda hypothesis @@ -344,18 +349,26 @@ class CascadeSelection : public baseselection::BaseSelectionevaluateObservable(kNegDauTpc, negDaughter.tpcNSigmaPi()); if (posDaughter.hasTOF()) { this->evaluateObservable(kPosDauTof, posDaughter.tofNSigmaPr()); + } else if (!mRequireTof) { + this->setBitmask(kPosDauTof, std::numeric_limits::max()); } if (negDaughter.hasTOF()) { this->evaluateObservable(kNegDauTof, negDaughter.tofNSigmaPi()); + } else if (!mRequireTof) { + this->setBitmask(kNegDauTof, std::numeric_limits::max()); } } else if (cascade.sign() > 0) { this->evaluateObservable(kPosDauTpc, posDaughter.tpcNSigmaPi()); this->evaluateObservable(kNegDauTpc, negDaughter.tpcNSigmaPr()); if (posDaughter.hasTOF()) { this->evaluateObservable(kPosDauTof, posDaughter.tofNSigmaPi()); + } else if (!mRequireTof) { + this->setBitmask(kPosDauTof, std::numeric_limits::max()); } if (negDaughter.hasTOF()) { this->evaluateObservable(kNegDauTof, negDaughter.tofNSigmaPr()); + } else if (!mRequireTof) { + this->setBitmask(kNegDauTof, std::numeric_limits::max()); } } else { LOG(warn) << "Encountered Cascade candidate with 0 charge"; @@ -468,6 +481,7 @@ class CascadeSelection : public baseselection::BaseSelection> posDauTofProton{"posDauTofProton", {}, "Maximum |nsigma_Proton| TOF for positive daughter tracks"}; o2::framework::Configurable> negDauTofPion{"negDauTofPion", {}, "Maximum |nsigma_Pion| TOF for negative daughter tracks"}; o2::framework::Configurable> negDauTofProton{"negDauTofProton", {}, "Maximum |nsigma_Proton| TOF for negative daughter tracks"}; + o2::framework::Configurable requireTof{"requireTof", false, "If true, only keep candidates whose daughters have a TOF signal"}; }; // derived selection bits for K0Short @@ -95,6 +96,7 @@ struct ConfK0shortBits : o2::framework::ConfigurableGroup { o2::framework::Configurable> negDauTpcPion{"negDauTpcPion", {5.f}, "Maximum |nsimga_Pion| TPC for negative daughter tracks"}; o2::framework::Configurable> posDauTofPion{"posDauTofPion", {}, "Maximum |nsigma_Pion| TOF for positive daughter tracks"}; o2::framework::Configurable> negDauTofPion{"negDauTofPion", {}, "Maximum |nsigma_Pion| TOF for negative daughter tracks"}; + o2::framework::Configurable requireTof{"requireTof", false, "If true, only keep candidates whose daughters have a TOF signal"}; }; #undef V0_DEFAULT_BITS @@ -246,6 +248,7 @@ class V0Selection : public baseselection::BaseSelectionaddSelection(kPosDaughTpcProton, v0SelectionNames.at(kPosDaughTpcProton), config.posDauTpcProton.value, limits::kAbsUpperLimit, true, true, false); this->addSelection(kNegDaughTpcPion, v0SelectionNames.at(kNegDaughTpcPion), config.negDauTpcPion.value, limits::kAbsUpperLimit, true, true, false); - this->addSelection(kPosDaughTofProton, v0SelectionNames.at(kPosDaughTofProton), config.posDauTofProton.value, limits::kAbsUpperLimit, true, true, false); - this->addSelection(kNegDaughTofPion, v0SelectionNames.at(kNegDaughTofPion), config.negDauTofPion.value, limits::kAbsUpperLimit, true, true, false); + this->addSelection(kPosDaughTofProton, v0SelectionNames.at(kPosDaughTofProton), config.posDauTofProton.value, limits::kAbsUpperLimit, true, false, false); + this->addSelection(kNegDaughTofPion, v0SelectionNames.at(kNegDaughTofPion), config.negDauTofPion.value, limits::kAbsUpperLimit, true, false, false); } if constexpr (modes::isEqual(v0Type, modes::V0::kAntiLambda)) { this->addSelection(kPosDaughTpcPion, v0SelectionNames.at(kPosDaughTpcPion), config.posDauTpcPion.value, limits::kAbsUpperLimit, true, true, false); this->addSelection(kNegDaughTpcProton, v0SelectionNames.at(kNegDaughTpcProton), config.negDauTpcProton.value, limits::kAbsUpperLimit, true, true, false); - this->addSelection(kPosDaughTofPion, v0SelectionNames.at(kPosDaughTofPion), config.posDauTofPion.value, limits::kAbsUpperLimit, true, true, false); - this->addSelection(kNegDaughTofProton, v0SelectionNames.at(kNegDaughTofProton), config.negDauTofProton.value, limits::kAbsUpperLimit, true, true, false); + this->addSelection(kPosDaughTofPion, v0SelectionNames.at(kPosDaughTofPion), config.posDauTofPion.value, limits::kAbsUpperLimit, true, false, false); + this->addSelection(kNegDaughTofProton, v0SelectionNames.at(kNegDaughTofProton), config.negDauTofProton.value, limits::kAbsUpperLimit, true, false, false); } } if constexpr (modes::isEqual(v0Type, modes::V0::kK0short)) { @@ -277,8 +280,8 @@ class V0Selection : public baseselection::BaseSelectionaddSelection(kPosDaughTpcPion, v0SelectionNames.at(kPosDaughTpcPion), config.posDauTpcPion.value, limits::kAbsUpperLimit, true, true, false); this->addSelection(kNegDaughTpcPion, v0SelectionNames.at(kNegDaughTpcPion), config.negDauTpcPion.value, limits::kAbsUpperLimit, true, true, false); - this->addSelection(kPosDaughTofPion, v0SelectionNames.at(kPosDaughTofPion), config.posDauTofPion.value, limits::kAbsUpperLimit, true, true, false); - this->addSelection(kNegDaughTofPion, v0SelectionNames.at(kNegDaughTofPion), config.negDauTofPion.value, limits::kAbsUpperLimit, true, true, false); + this->addSelection(kPosDaughTofPion, v0SelectionNames.at(kPosDaughTofPion), config.posDauTofPion.value, limits::kAbsUpperLimit, true, false, false); + this->addSelection(kNegDaughTofPion, v0SelectionNames.at(kNegDaughTofPion), config.negDauTofPion.value, limits::kAbsUpperLimit, true, false, false); } this->addSelection(kDcaDaughMax, v0SelectionNames.at(kDcaDaughMax), config.dcaDauMax.value, limits::kAbsUpperLimit, true, true, false); @@ -345,10 +348,16 @@ class V0Selection : public baseselection::BaseSelectionevaluateObservable(kPosDaughTofPion, posDaughter.tofNSigmaPi()); this->evaluateObservable(kPosDaughTofProton, posDaughter.tofNSigmaPr()); + } else if (!mRequireTof) { + this->setBitmask(kPosDaughTofPion, std::numeric_limits::max()); + this->setBitmask(kPosDaughTofProton, std::numeric_limits::max()); } if (negDaughter.hasTOF()) { this->evaluateObservable(kNegDaughTofPion, negDaughter.tofNSigmaPi()); this->evaluateObservable(kNegDaughTofProton, negDaughter.tofNSigmaPr()); + } else if (!mRequireTof) { + this->setBitmask(kNegDaughTofPion, std::numeric_limits::max()); + this->setBitmask(kNegDaughTofProton, std::numeric_limits::max()); } this->assembleBitmask(); @@ -452,6 +461,8 @@ class V0Selection : public baseselection::BaseSelection Date: Tue, 4 Aug 2026 14:44:30 +0200 Subject: [PATCH 4/6] linter fix: include where numeric_limits is used --- PWGCF/Femto/Core/cascadeBuilder.h | 1 + PWGCF/Femto/Core/v0Builder.h | 1 + 2 files changed, 2 insertions(+) diff --git a/PWGCF/Femto/Core/cascadeBuilder.h b/PWGCF/Femto/Core/cascadeBuilder.h index 0a5981605fe..2640514fa6d 100644 --- a/PWGCF/Femto/Core/cascadeBuilder.h +++ b/PWGCF/Femto/Core/cascadeBuilder.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include diff --git a/PWGCF/Femto/Core/v0Builder.h b/PWGCF/Femto/Core/v0Builder.h index c8f6ed9e3f1..358cc3d1cc3 100644 --- a/PWGCF/Femto/Core/v0Builder.h +++ b/PWGCF/Femto/Core/v0Builder.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include From 3d37d83e12970e0a7366418a8958f911eaa2a011 Mon Sep 17 00:00:00 2001 From: allesgrau Date: Tue, 4 Aug 2026 21:52:02 +0200 Subject: [PATCH 5/6] Add requireTof and keepTracksWithoutTof configurables, change setBitmask value to 0 --- PWGCF/Femto/Core/cascadeBuilder.h | 35 +++++++++++++++++-------------- PWGCF/Femto/Core/v0Builder.h | 32 +++++++++++++++------------- 2 files changed, 37 insertions(+), 30 deletions(-) diff --git a/PWGCF/Femto/Core/cascadeBuilder.h b/PWGCF/Femto/Core/cascadeBuilder.h index 2640514fa6d..b7f2047b993 100644 --- a/PWGCF/Femto/Core/cascadeBuilder.h +++ b/PWGCF/Femto/Core/cascadeBuilder.h @@ -80,7 +80,8 @@ struct ConfCascadeFilters : o2::framework::ConfigurableGroup { o2::framework::Configurable> negDauTpc{"negDauTpc", {5.f}, "Maximum |nsimga_Pion/Proton| TPC for negative daughter tracks"}; \ o2::framework::Configurable> posDauTof{"posDauTof", {}, "Maximum |nsimga_Pion/Proton| TOF for positive daughter tracks"}; \ o2::framework::Configurable> negDauTof{"negDauTof", {}, "Maximum |nsigma_Pion/Proton| TOF for negative daughter tracks"}; \ - o2::framework::Configurable requireTof{"requireTof", false, "If true, only keep candidates whose daughters have a TOF signal"}; + o2::framework::Configurable requireTof{"requireTof", false, "If true, TOF PID is a mandatory selection"}; \ + o2::framework::Configurable keepTracksWithoutTof{"keepTracksWithoutTof", true, "If true, candidates whose daughters have no TOF signal are kept"}; struct ConfXiBits : o2::framework::ConfigurableGroup { std::string prefix = std::string("XiBits"); @@ -244,7 +245,7 @@ class CascadeSelection : public baseselection::BaseSelectionaddSelection(kBachelorTpcPion, cascadeSelectionNames.at(kBachelorTpcPion), config.bachelorTpcPion.value, limits::kAbsUpperLimit, true, true, false); - this->addSelection(kBachelorTofPion, cascadeSelectionNames.at(kBachelorTofPion), config.bachelorTofPion.value, limits::kAbsUpperLimit, true, false, false); + this->addSelection(kBachelorTofPion, cascadeSelectionNames.at(kBachelorTofPion), config.bachelorTofPion.value, limits::kAbsUpperLimit, true, mRequireTof, false); } if constexpr (modes::isEqual(cascadeType, modes::Cascade::kOmega)) { mOmegaMassLowerLimit = filter.massOmegaMin.value; @@ -253,7 +254,7 @@ class CascadeSelection : public baseselection::BaseSelectionaddSelection(kBachelorTpcKaon, cascadeSelectionNames.at(kBachelorTpcKaon), config.bachelorTpcKaon.value, limits::kAbsUpperLimit, true, true, false); - this->addSelection(kBachelorTofKaon, cascadeSelectionNames.at(kBachelorTofKaon), config.bachelorTofKaon.value, limits::kAbsUpperLimit, true, false, false); + this->addSelection(kBachelorTofKaon, cascadeSelectionNames.at(kBachelorTofKaon), config.bachelorTofKaon.value, limits::kAbsUpperLimit, true, mRequireTof, false); } mPtMin = filter.ptMin.value; @@ -265,11 +266,12 @@ class CascadeSelection : public baseselection::BaseSelectionaddSelection(kPosDauTpc, cascadeSelectionNames.at(kPosDauTpc), config.posDauTpc.value, limits::kAbsUpperLimit, true, true, false); this->addSelection(kNegDauTpc, cascadeSelectionNames.at(kNegDauTpc), config.negDauTpc.value, limits::kAbsUpperLimit, true, true, false); - this->addSelection(kPosDauTof, cascadeSelectionNames.at(kPosDauTof), config.posDauTof.value, limits::kAbsUpperLimit, true, false, false); - this->addSelection(kNegDauTof, cascadeSelectionNames.at(kNegDauTof), config.negDauTof.value, limits::kAbsUpperLimit, true, false, false); + this->addSelection(kPosDauTof, cascadeSelectionNames.at(kPosDauTof), config.posDauTof.value, limits::kAbsUpperLimit, true, mRequireTof, false); + this->addSelection(kNegDauTof, cascadeSelectionNames.at(kNegDauTof), config.negDauTof.value, limits::kAbsUpperLimit, true, mRequireTof, false); this->addSelection(kCascadeCpaMin, cascadeSelectionNames.at(kCascadeCpaMin), config.cascadeCpaMin.value, limits::kLowerLimit, true, true, false); this->addSelection(kCascadeTransRadMin, cascadeSelectionNames.at(kCascadeTransRadMin), config.cascadeTransRadMin.value, limits::kLowerLimit, true, true, false); @@ -339,9 +341,9 @@ class CascadeSelection : public baseselection::BaseSelectionevaluateObservable(kBachelorTofPion, bachelor.tofNSigmaPi()); this->evaluateObservable(kBachelorTofKaon, bachelor.tofNSigmaKa()); - } else if (!mRequireTof) { - this->setBitmask(kBachelorTofPion, std::numeric_limits::max()); - this->setBitmask(kBachelorTofKaon, std::numeric_limits::max()); + } else if (mKeepTracksWithoutTof) { + this->setBitmask(kBachelorTofPion, 0); + this->setBitmask(kBachelorTofKaon, 0); } // depending on the charge, we check lambda or antilambda hypothesis @@ -350,26 +352,26 @@ class CascadeSelection : public baseselection::BaseSelectionevaluateObservable(kNegDauTpc, negDaughter.tpcNSigmaPi()); if (posDaughter.hasTOF()) { this->evaluateObservable(kPosDauTof, posDaughter.tofNSigmaPr()); - } else if (!mRequireTof) { - this->setBitmask(kPosDauTof, std::numeric_limits::max()); + } else if (mKeepTracksWithoutTof) { + this->setBitmask(kPosDauTof, 0); } if (negDaughter.hasTOF()) { this->evaluateObservable(kNegDauTof, negDaughter.tofNSigmaPi()); - } else if (!mRequireTof) { - this->setBitmask(kNegDauTof, std::numeric_limits::max()); + } else if (mKeepTracksWithoutTof) { + this->setBitmask(kNegDauTof, 0); } } else if (cascade.sign() > 0) { this->evaluateObservable(kPosDauTpc, posDaughter.tpcNSigmaPi()); this->evaluateObservable(kNegDauTpc, negDaughter.tpcNSigmaPr()); if (posDaughter.hasTOF()) { this->evaluateObservable(kPosDauTof, posDaughter.tofNSigmaPi()); - } else if (!mRequireTof) { - this->setBitmask(kPosDauTof, std::numeric_limits::max()); + } else if (mKeepTracksWithoutTof) { + this->setBitmask(kPosDauTof, 0); } if (negDaughter.hasTOF()) { this->evaluateObservable(kNegDauTof, negDaughter.tofNSigmaPr()); - } else if (!mRequireTof) { - this->setBitmask(kNegDauTof, std::numeric_limits::max()); + } else if (mKeepTracksWithoutTof) { + this->setBitmask(kNegDauTof, 0); } } else { LOG(warn) << "Encountered Cascade candidate with 0 charge"; @@ -483,6 +485,7 @@ class CascadeSelection : public baseselection::BaseSelection> posDauTofProton{"posDauTofProton", {}, "Maximum |nsigma_Proton| TOF for positive daughter tracks"}; o2::framework::Configurable> negDauTofPion{"negDauTofPion", {}, "Maximum |nsigma_Pion| TOF for negative daughter tracks"}; o2::framework::Configurable> negDauTofProton{"negDauTofProton", {}, "Maximum |nsigma_Proton| TOF for negative daughter tracks"}; - o2::framework::Configurable requireTof{"requireTof", false, "If true, only keep candidates whose daughters have a TOF signal"}; + o2::framework::Configurable requireTof{"requireTof", false, "If true, TOF PID is a mandatory selection"}; + o2::framework::Configurable keepTracksWithoutTof{"keepTracksWithoutTof", true, "If true, candidates whose daughters have no TOF signal are kept"}; }; // derived selection bits for K0Short @@ -97,7 +98,8 @@ struct ConfK0shortBits : o2::framework::ConfigurableGroup { o2::framework::Configurable> negDauTpcPion{"negDauTpcPion", {5.f}, "Maximum |nsimga_Pion| TPC for negative daughter tracks"}; o2::framework::Configurable> posDauTofPion{"posDauTofPion", {}, "Maximum |nsigma_Pion| TOF for positive daughter tracks"}; o2::framework::Configurable> negDauTofPion{"negDauTofPion", {}, "Maximum |nsigma_Pion| TOF for negative daughter tracks"}; - o2::framework::Configurable requireTof{"requireTof", false, "If true, only keep candidates whose daughters have a TOF signal"}; + o2::framework::Configurable requireTof{"requireTof", false, "If true, TOF PID is a mandatory selection"}; + o2::framework::Configurable keepTracksWithoutTof{"keepTracksWithoutTof", true, "If true, candidates whose daughters have no TOF signal are kept"}; }; #undef V0_DEFAULT_BITS @@ -250,6 +252,7 @@ class V0Selection : public baseselection::BaseSelectionaddSelection(kPosDaughTpcProton, v0SelectionNames.at(kPosDaughTpcProton), config.posDauTpcProton.value, limits::kAbsUpperLimit, true, true, false); this->addSelection(kNegDaughTpcPion, v0SelectionNames.at(kNegDaughTpcPion), config.negDauTpcPion.value, limits::kAbsUpperLimit, true, true, false); - this->addSelection(kPosDaughTofProton, v0SelectionNames.at(kPosDaughTofProton), config.posDauTofProton.value, limits::kAbsUpperLimit, true, false, false); - this->addSelection(kNegDaughTofPion, v0SelectionNames.at(kNegDaughTofPion), config.negDauTofPion.value, limits::kAbsUpperLimit, true, false, false); + this->addSelection(kPosDaughTofProton, v0SelectionNames.at(kPosDaughTofProton), config.posDauTofProton.value, limits::kAbsUpperLimit, true, mRequireTof, false); + this->addSelection(kNegDaughTofPion, v0SelectionNames.at(kNegDaughTofPion), config.negDauTofPion.value, limits::kAbsUpperLimit, true, mRequireTof, false); } if constexpr (modes::isEqual(v0Type, modes::V0::kAntiLambda)) { this->addSelection(kPosDaughTpcPion, v0SelectionNames.at(kPosDaughTpcPion), config.posDauTpcPion.value, limits::kAbsUpperLimit, true, true, false); this->addSelection(kNegDaughTpcProton, v0SelectionNames.at(kNegDaughTpcProton), config.negDauTpcProton.value, limits::kAbsUpperLimit, true, true, false); - this->addSelection(kPosDaughTofPion, v0SelectionNames.at(kPosDaughTofPion), config.posDauTofPion.value, limits::kAbsUpperLimit, true, false, false); - this->addSelection(kNegDaughTofProton, v0SelectionNames.at(kNegDaughTofProton), config.negDauTofProton.value, limits::kAbsUpperLimit, true, false, false); + this->addSelection(kPosDaughTofPion, v0SelectionNames.at(kPosDaughTofPion), config.posDauTofPion.value, limits::kAbsUpperLimit, true, mRequireTof, false); + this->addSelection(kNegDaughTofProton, v0SelectionNames.at(kNegDaughTofProton), config.negDauTofProton.value, limits::kAbsUpperLimit, true, mRequireTof, false); } } if constexpr (modes::isEqual(v0Type, modes::V0::kK0short)) { @@ -281,8 +284,8 @@ class V0Selection : public baseselection::BaseSelectionaddSelection(kPosDaughTpcPion, v0SelectionNames.at(kPosDaughTpcPion), config.posDauTpcPion.value, limits::kAbsUpperLimit, true, true, false); this->addSelection(kNegDaughTpcPion, v0SelectionNames.at(kNegDaughTpcPion), config.negDauTpcPion.value, limits::kAbsUpperLimit, true, true, false); - this->addSelection(kPosDaughTofPion, v0SelectionNames.at(kPosDaughTofPion), config.posDauTofPion.value, limits::kAbsUpperLimit, true, false, false); - this->addSelection(kNegDaughTofPion, v0SelectionNames.at(kNegDaughTofPion), config.negDauTofPion.value, limits::kAbsUpperLimit, true, false, false); + this->addSelection(kPosDaughTofPion, v0SelectionNames.at(kPosDaughTofPion), config.posDauTofPion.value, limits::kAbsUpperLimit, true, mRequireTof, false); + this->addSelection(kNegDaughTofPion, v0SelectionNames.at(kNegDaughTofPion), config.negDauTofPion.value, limits::kAbsUpperLimit, true, mRequireTof, false); } this->addSelection(kDcaDaughMax, v0SelectionNames.at(kDcaDaughMax), config.dcaDauMax.value, limits::kAbsUpperLimit, true, true, false); @@ -349,16 +352,16 @@ class V0Selection : public baseselection::BaseSelectionevaluateObservable(kPosDaughTofPion, posDaughter.tofNSigmaPi()); this->evaluateObservable(kPosDaughTofProton, posDaughter.tofNSigmaPr()); - } else if (!mRequireTof) { - this->setBitmask(kPosDaughTofPion, std::numeric_limits::max()); - this->setBitmask(kPosDaughTofProton, std::numeric_limits::max()); + } else if (mKeepTracksWithoutTof) { + this->setBitmask(kPosDaughTofPion, 0); + this->setBitmask(kPosDaughTofProton, 0); } if (negDaughter.hasTOF()) { this->evaluateObservable(kNegDaughTofPion, negDaughter.tofNSigmaPi()); this->evaluateObservable(kNegDaughTofProton, negDaughter.tofNSigmaPr()); - } else if (!mRequireTof) { - this->setBitmask(kNegDaughTofPion, std::numeric_limits::max()); - this->setBitmask(kNegDaughTofProton, std::numeric_limits::max()); + } else if (mKeepTracksWithoutTof) { + this->setBitmask(kNegDaughTofPion, 0); + this->setBitmask(kNegDaughTofProton, 0); } this->assembleBitmask(); @@ -464,6 +467,7 @@ class V0Selection : public baseselection::BaseSelection Date: Tue, 4 Aug 2026 19:53:01 +0000 Subject: [PATCH 6/6] Please consider the following formatting changes --- PWGCF/Femto/Core/cascadeBuilder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGCF/Femto/Core/cascadeBuilder.h b/PWGCF/Femto/Core/cascadeBuilder.h index b7f2047b993..e2f2d7767c4 100644 --- a/PWGCF/Femto/Core/cascadeBuilder.h +++ b/PWGCF/Femto/Core/cascadeBuilder.h @@ -80,7 +80,7 @@ struct ConfCascadeFilters : o2::framework::ConfigurableGroup { o2::framework::Configurable> negDauTpc{"negDauTpc", {5.f}, "Maximum |nsimga_Pion/Proton| TPC for negative daughter tracks"}; \ o2::framework::Configurable> posDauTof{"posDauTof", {}, "Maximum |nsimga_Pion/Proton| TOF for positive daughter tracks"}; \ o2::framework::Configurable> negDauTof{"negDauTof", {}, "Maximum |nsigma_Pion/Proton| TOF for negative daughter tracks"}; \ - o2::framework::Configurable requireTof{"requireTof", false, "If true, TOF PID is a mandatory selection"}; \ + o2::framework::Configurable requireTof{"requireTof", false, "If true, TOF PID is a mandatory selection"}; \ o2::framework::Configurable keepTracksWithoutTof{"keepTracksWithoutTof", true, "If true, candidates whose daughters have no TOF signal are kept"}; struct ConfXiBits : o2::framework::ConfigurableGroup {