From 1f03fa219a43bde71a76d84a544ede1983248600 Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Wed, 6 Aug 2025 22:23:13 +0200 Subject: [PATCH 01/18] apply clang-format --- PWGDQ/Tasks/v0selector.cxx | 54 ++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/PWGDQ/Tasks/v0selector.cxx b/PWGDQ/Tasks/v0selector.cxx index 0c970d80c91..9d60ca7773e 100644 --- a/PWGDQ/Tasks/v0selector.cxx +++ b/PWGDQ/Tasks/v0selector.cxx @@ -17,35 +17,39 @@ // Comments, questions, complaints, suggestions? // Please write to: daiki.sekihata@cern.ch // -#include -#include -#include -#include -#include -#include "Math/Vector4D.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/Core/trackUtilities.h" +#include "PWGDQ/Core/HistogramManager.h" +#include "PWGDQ/Core/HistogramsLibrary.h" +#include "PWGDQ/Core/VarManager.h" +#include "PWGDQ/DataModel/ReducedInfoTables.h" #include "PWGLF/DataModel/LFStrangenessTables.h" + +#include "Common/Core/RecoDecay.h" #include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" +#include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponse.h" -#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.h" #include "DCAFitter/DCAFitterN.h" -#include "PWGDQ/DataModel/ReducedInfoTables.h" -#include "PWGDQ/Core/VarManager.h" -#include "PWGDQ/Core/HistogramManager.h" -#include "PWGDQ/Core/HistogramsLibrary.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" #include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" + +#include "Math/Vector4D.h" + +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -112,7 +116,7 @@ struct v0selector { // // K0S cuts // const float cutQTK0S[2] = {0.1075, 0.215}; - // const float cutAPK0S[2] = {0.199, 0.8}; // parameters for curved QT cut + // const float cutAPK0S[2] = {0.199, 0.8}; // parameters for curved QT cut // // Lambda & A-Lambda cuts // const float cutQTL = 0.03; @@ -574,7 +578,7 @@ struct trackPIDQA { } } // end of track loop - } // end of process + } // end of process void DefineHistograms(TString histClasses) { From f452fd38eb0e02867b369926b724f3624df2e9b8 Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Wed, 6 Aug 2025 22:24:05 +0200 Subject: [PATCH 02/18] init cascade processing in v0selector --- PWGDQ/DataModel/ReducedInfoTables.h | 8 +++++++ PWGDQ/Tasks/v0selector.cxx | 35 ++++++++++++++++++++++++++--- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/PWGDQ/DataModel/ReducedInfoTables.h b/PWGDQ/DataModel/ReducedInfoTables.h index 244a1f7417c..3537b37d50a 100644 --- a/PWGDQ/DataModel/ReducedInfoTables.h +++ b/PWGDQ/DataModel/ReducedInfoTables.h @@ -1124,6 +1124,14 @@ DECLARE_SOA_COLUMN(V0AddID, v0addid, int8_t); //! DECLARE_SOA_TABLE(V0MapID, "AOD", "V0MAPID", //! v0mapID::V0AddID); +namespace cascmapId +{ +DECLARE_SOA_COLUMN(CascAddID, cascaddid, int8_t); //! +} // namespace cascmapId + +DECLARE_SOA_TABLE(CascMapID, "AOD", "CASCMAPID", //! + cascmapID::CascAddID); + namespace DalBits { DECLARE_SOA_COLUMN(DALITZBits, dalitzBits, uint8_t); //! diff --git a/PWGDQ/Tasks/v0selector.cxx b/PWGDQ/Tasks/v0selector.cxx index 9d60ca7773e..849c59e70a7 100644 --- a/PWGDQ/Tasks/v0selector.cxx +++ b/PWGDQ/Tasks/v0selector.cxx @@ -90,6 +90,7 @@ struct v0selector { Configurable cutAPL2{"cutAPL2", -0.69, "cutAPL2"}; Configurable cutAPL3{"cutAPL3", 0.5, "cutAPL3"}; Configurable produceV0ID{"produceV0ID", false, "Produce additional V0ID table"}; + Configurable produceCascID{"produceCascID", false, "Produce additional CascID table"}; enum { // Reconstructed V0 kUndef = -1, @@ -97,11 +98,13 @@ struct v0selector { kK0S = 1, kLambda = 2, kAntiLambda = 3, - kOmega = 4 + kOmega = 4, + kAntiOmega = 5 }; Produces v0bits; Produces v0mapID; + Produces cascMapID; // int checkV0(const array& ppos, const array& pneg) int checkV0(const float alpha, const float qt) @@ -116,7 +119,7 @@ struct v0selector { // // K0S cuts // const float cutQTK0S[2] = {0.1075, 0.215}; - // const float cutAPK0S[2] = {0.199, 0.8}; // parameters for curved QT cut + // const float cutAPK0S[2] = {0.199, 0.8}; // parameters for curved QT cut // // Lambda & A-Lambda cuts // const float cutQTL = 0.03; @@ -158,6 +161,12 @@ struct v0selector { return kUndef; } + int checkCascade() + { + // to be implemented; + return kOmega; + } + // Configurables Configurable v0max_mee{"v0max_mee", 0.1, "max mee for photon"}; Configurable maxpsipair{"maxpsipair", 1.6, "max psi_pair for photon"}; @@ -180,6 +189,7 @@ struct v0selector { { if (fillhisto) { registry.add("hV0Candidate", "hV0Candidate", HistType::kTH1F, {{2, 0.5f, 2.5f}}); + registry.add("hCascCandidate", "hCascCandidate", HistType::kTH1F, {{2, 0.5f, 2.5f}}); registry.add("hMassGamma", "hMassGamma", HistType::kTH2F, {{900, 0.0f, 90.0f}, {100, 0.0f, 0.1f}}); registry.add("hGammaRxy", "hGammaRxy", HistType::kTH2F, {{1800, -90.0f, 90.0f}, {1800, -90.0f, 90.0f}}); registry.add("hMassK0S", "hMassK0S", HistType::kTH2F, {{900, 0.0f, 90.0f}, {100, 0.45, 0.55}}); @@ -203,7 +213,7 @@ struct v0selector { } } - void process(aod::V0Datas const& V0s, FullTracksExt const& tracks, aod::Collisions const&) + void process(aod::V0Datas const& V0s, aod::CascDatas const& Cascs, FullTracksExt const& tracks, aod::Collisions const&) { std::vector pidmap; pidmap.clear(); @@ -214,6 +224,11 @@ struct v0selector { if (produceV0ID.value) { v0pidmap.resize(V0s.size(), -1); } + std::vector cascpidmap; + cascpidmap.clear(); + if (produceCascID.value) { + cascpidmap.resize(V0s.size(), kUndef); + } for (auto& V0 : V0s) { // if (!(V0.posTrack_as().trackType() & o2::aod::track::TPCrefit)) { // continue; @@ -380,6 +395,20 @@ struct v0selector { v0mapID(v0pidmap[V0.globalIndex()]); } } + for (const auto& Casc : Cascs) { + if (fillhisto) { + registry.fill(HIST("hCascCandidate"), 1); + } + + // topological selections + + if (fillhisto) { + registry.fill(HIST("hCascCandidate"), 2); + } + + const float mOmega = Casc.mOmega(); + + } // end of Casc loop for (auto& track : tracks) { // printf("setting pidmap[%lld] = %d\n",track.globalIndex(),pidmap[track.globalIndex()]); v0bits(pidmap[track.globalIndex()]); From ac4b67b1d9f16d5dfb395dd05510438f9e044924 Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Fri, 8 Aug 2025 11:50:42 +0200 Subject: [PATCH 03/18] bugfix namespace spelling --- PWGDQ/DataModel/ReducedInfoTables.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PWGDQ/DataModel/ReducedInfoTables.h b/PWGDQ/DataModel/ReducedInfoTables.h index 3537b37d50a..dd92f5a9c76 100644 --- a/PWGDQ/DataModel/ReducedInfoTables.h +++ b/PWGDQ/DataModel/ReducedInfoTables.h @@ -1124,10 +1124,10 @@ DECLARE_SOA_COLUMN(V0AddID, v0addid, int8_t); //! DECLARE_SOA_TABLE(V0MapID, "AOD", "V0MAPID", //! v0mapID::V0AddID); -namespace cascmapId +namespace cascmapID { DECLARE_SOA_COLUMN(CascAddID, cascaddid, int8_t); //! -} // namespace cascmapId +} // namespace cascmapID DECLARE_SOA_TABLE(CascMapID, "AOD", "CASCMAPID", //! cascmapID::CascAddID); From 395f55a3ebf3d537d1d2f05aac6ce6b30cd855d4 Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Fri, 8 Aug 2025 14:49:02 +0200 Subject: [PATCH 04/18] implement cascade processing in v0selector (1-st working version) --- PWGDQ/Tasks/v0selector.cxx | 109 +++++++++++++++++++++++++++++++++++-- 1 file changed, 105 insertions(+), 4 deletions(-) diff --git a/PWGDQ/Tasks/v0selector.cxx b/PWGDQ/Tasks/v0selector.cxx index 849c59e70a7..ba6e9ea931a 100644 --- a/PWGDQ/Tasks/v0selector.cxx +++ b/PWGDQ/Tasks/v0selector.cxx @@ -49,6 +49,7 @@ #include #include #include +#include #include using namespace o2; @@ -89,6 +90,18 @@ struct v0selector { Configurable cutAPL1{"cutAPL1", 0.107, "cutAPL1"}; Configurable cutAPL2{"cutAPL2", -0.69, "cutAPL2"}; Configurable cutAPL3{"cutAPL3", 0.5, "cutAPL3"}; + // Omega & A-Omega cuts + Configurable cutAPOmegaUp1{"cutAPOmegaUp1", 0.25, "cutAPOmegaUp1"}; + Configurable cutAPOmegaUp2{"cutAPOmegaUp2", 0.358, "cutAPOmegaUp2"}; + Configurable cutAPOmegaUp3{"cutAPOmegaUp3", 0.35, "cutAPOmegaUp3"}; + Configurable cutAPOmegaDown1{"cutAPOmegaDown1", 0.15, "cutAPOmegaDown1"}; + Configurable cutAPOmegaDown2{"cutAPOmegaDown2", 0.358, "cutAPOmegaDown2"}; + Configurable cutAPOmegaDown3{"cutAPOmegaDown3", 0.16, "cutAPOmegaDown3"}; + Configurable cutAlphaOmegaHigh{"cutAlphaOmegaHigh", 0.358, "cutAlphaOmegaHigh"}; + Configurable cutAlphaOmegaLow{"cutAlphaOmegaLow", 0., "cutAlphaOmegaLow"}; + Configurable cutMassOmegaHigh{"cutMassOmegaHigh", 1.677, "cutMassOmegaHigh"}; + Configurable cutMassOmegaLow{"cutMassOmegaLow", 1.667, "cutMassOmegaLow"}; + Configurable produceV0ID{"produceV0ID", false, "Produce additional V0ID table"}; Configurable produceCascID{"produceCascID", false, "Produce additional CascID table"}; @@ -104,7 +117,7 @@ struct v0selector { Produces v0bits; Produces v0mapID; - Produces cascMapID; + Produces cascmapID; // int checkV0(const array& ppos, const array& pneg) int checkV0(const float alpha, const float qt) @@ -161,10 +174,49 @@ struct v0selector { return kUndef; } - int checkCascade() + std::pair evalArmenterosPodolanskiCascade(aod::CascData const& casc) + { + const float pxv0 = casc.pxpos() + casc.pxneg(); + const float pyv0 = casc.pypos() + casc.pyneg(); + const float pzv0 = casc.pzpos() + casc.pzneg(); + + const float pxbach = casc.pxbach(); + const float pybach = casc.pybach(); + const float pzbach = casc.pzbach(); + + const double momTot = RecoDecay::p2(pxv0 + pxbach, pyv0 + pybach, pzv0 + pzbach); + + const float lQlv0 = RecoDecay::dotProd(std::array{pxv0, pyv0, pzv0}, std::array{pxv0 + pxbach, pyv0 + pybach, pzv0 + pzbach}) / momTot; + const float lQlbach = RecoDecay::dotProd(std::array{pxbach, pybach, pzbach}, std::array{pxv0 + pxbach, pyv0 + pybach, pzv0 + pzbach}) / momTot; + const float dp = RecoDecay::dotProd(std::array{pxbach, pybach, pzbach}, std::array{pxv0 + pxbach, pyv0 + pybach, pzv0 + pzbach}); + + float alpha = (lQlv0 - lQlbach) / (lQlv0 + lQlbach); + const float qtarm = std::sqrt(RecoDecay::p2(pxbach, pybach, pzbach) - dp * dp / momTot / momTot); + + if (casc.sign() > 0) { + alpha = -alpha; + } + + return std::make_pair(alpha, qtarm); + } + + int checkCascade(float alpha, float qt) { - // to be implemented; - return kOmega; + const bool isAlphaPos = alpha > 0; + alpha = std::fabs(alpha); + + const float qUp = cutAPOmegaUp1 * std::sqrt(std::abs(1.0f - ((alpha - cutAPOmegaUp2) * (alpha - cutAPOmegaUp2)) / (cutAPOmegaUp3 * cutAPOmegaUp3))); + const float qDown = cutAPOmegaDown1 * std::sqrt(std::abs(1.0f - ((alpha - cutAPOmegaDown2) * (alpha - cutAPOmegaDown2)) / (cutAPOmegaDown3 * cutAPOmegaDown3))); + + if (alpha < cutAlphaOmegaLow || alpha > cutAlphaOmegaHigh || qt < qDown || qt > qUp) { + return kUndef; + } + + if (isAlphaPos) { + return kOmega; + } else { + return kAntiOmega; + } } // Configurables @@ -210,6 +262,10 @@ struct v0selector { registry.add("hV0APplot", "hV0APplot", HistType::kTH2F, {{200, -1.0f, +1.0f}, {250, 0.0f, 0.25f}}); registry.add("hV0APplotSelected", "hV0APplotSelected", HistType::kTH2F, {{200, -1.0f, +1.0f}, {250, 0.0f, 0.25f}}); registry.add("hV0Psi", "hV0Psi", HistType::kTH2F, {{100, 0, TMath::PiOver2()}, {100, 0, 0.1}}); + registry.add("hCascAPplot", "hCascAPplot", HistType::kTH2F, {{200, -1.0f, +1.0f}, {500, 0.0f, 0.5f}}); + registry.add("hCascAPplotSelected", "hCascAPplotSelected", HistType::kTH2F, {{200, -1.0f, +1.0f}, {500, 0.0f, 0.5f}}); + registry.add("hMassOmega", "hMassOmega", HistType::kTH2F, {{900, 0.0f, 90.0f}, {100, 1.62f, 1.72f}}); + registry.add("hMassAntiOmega", "hMassAntiOmega", HistType::kTH2F, {{900, 0.0f, 90.0f}, {100, 1.62f, 1.72f}}); } } @@ -395,6 +451,7 @@ struct v0selector { v0mapID(v0pidmap[V0.globalIndex()]); } } + for (const auto& Casc : Cascs) { if (fillhisto) { registry.fill(HIST("hCascCandidate"), 1); @@ -406,9 +463,53 @@ struct v0selector { registry.fill(HIST("hCascCandidate"), 2); } + const float Cascradius = Casc.cascradius(); + const float mOmega = Casc.mOmega(); + auto [alpha, qt] = evalArmenterosPodolanskiCascade(Casc); + + if (fillhisto) { + registry.fill(HIST("hCascAPplot"), alpha, qt); + } + + const int cascid = checkCascade(alpha, qt); + if (cascid < 0) { + continue; + } + if (fillhisto) { + registry.fill(HIST("hCascAPplotSelected"), alpha, qt); + } + + auto storeCascAddID = [&](auto gix, auto id) { + if (produceCascID.value) { + cascpidmap[gix] = id; + } + }; + + if (cascid == kOmega) { + if (fillhisto) { + registry.fill(HIST("hMassOmega"), Cascradius, mOmega); + } + if (cutMassOmegaLow < mOmega && mOmega < cutMassOmegaHigh) { + pidmap[Casc.bachelorId()] |= (uint8_t(1) << kOmega); + storeCascAddID(Casc.globalIndex(), kOmega); + } + } else if (cascid == kAntiOmega) { + if (fillhisto) { + registry.fill(HIST("hMassAntiOmega"), Cascradius, mOmega); + } + if (cutMassOmegaLow < mOmega && mOmega < cutMassOmegaHigh) { + pidmap[Casc.bachelorId()] |= (uint8_t(1) << kAntiOmega); + storeCascAddID(Casc.globalIndex(), kAntiOmega); + } + } } // end of Casc loop + if (produceCascID.value) { + for (auto& Casc : Cascs) { + cascmapID(cascpidmap[Casc.globalIndex()]); + } + } for (auto& track : tracks) { // printf("setting pidmap[%lld] = %d\n",track.globalIndex(),pidmap[track.globalIndex()]); v0bits(pidmap[track.globalIndex()]); From d2d4b91e4ad5083548305405728da9832218b245 Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Fri, 8 Aug 2025 18:55:35 +0200 Subject: [PATCH 05/18] mv Cascade AP-variables to Datamodel; bugfix qtarm eval --- PWGDQ/Tasks/v0selector.cxx | 39 ++++------------- PWGLF/DataModel/LFStrangenessTables.h | 60 +++++++++++++++++++++++++-- 2 files changed, 63 insertions(+), 36 deletions(-) diff --git a/PWGDQ/Tasks/v0selector.cxx b/PWGDQ/Tasks/v0selector.cxx index ba6e9ea931a..e6d824fa4ed 100644 --- a/PWGDQ/Tasks/v0selector.cxx +++ b/PWGDQ/Tasks/v0selector.cxx @@ -174,39 +174,13 @@ struct v0selector { return kUndef; } - std::pair evalArmenterosPodolanskiCascade(aod::CascData const& casc) - { - const float pxv0 = casc.pxpos() + casc.pxneg(); - const float pyv0 = casc.pypos() + casc.pyneg(); - const float pzv0 = casc.pzpos() + casc.pzneg(); - - const float pxbach = casc.pxbach(); - const float pybach = casc.pybach(); - const float pzbach = casc.pzbach(); - - const double momTot = RecoDecay::p2(pxv0 + pxbach, pyv0 + pybach, pzv0 + pzbach); - - const float lQlv0 = RecoDecay::dotProd(std::array{pxv0, pyv0, pzv0}, std::array{pxv0 + pxbach, pyv0 + pybach, pzv0 + pzbach}) / momTot; - const float lQlbach = RecoDecay::dotProd(std::array{pxbach, pybach, pzbach}, std::array{pxv0 + pxbach, pyv0 + pybach, pzv0 + pzbach}) / momTot; - const float dp = RecoDecay::dotProd(std::array{pxbach, pybach, pzbach}, std::array{pxv0 + pxbach, pyv0 + pybach, pzv0 + pzbach}); - - float alpha = (lQlv0 - lQlbach) / (lQlv0 + lQlbach); - const float qtarm = std::sqrt(RecoDecay::p2(pxbach, pybach, pzbach) - dp * dp / momTot / momTot); - - if (casc.sign() > 0) { - alpha = -alpha; - } - - return std::make_pair(alpha, qtarm); - } - int checkCascade(float alpha, float qt) { const bool isAlphaPos = alpha > 0; alpha = std::fabs(alpha); - const float qUp = cutAPOmegaUp1 * std::sqrt(std::abs(1.0f - ((alpha - cutAPOmegaUp2) * (alpha - cutAPOmegaUp2)) / (cutAPOmegaUp3 * cutAPOmegaUp3))); - const float qDown = cutAPOmegaDown1 * std::sqrt(std::abs(1.0f - ((alpha - cutAPOmegaDown2) * (alpha - cutAPOmegaDown2)) / (cutAPOmegaDown3 * cutAPOmegaDown3))); + const float qUp = std::abs(alpha - cutAPOmegaUp2) > std::abs(cutAPOmegaUp3) ? 0. : cutAPOmegaUp1 * std::sqrt(1.0f - ((alpha - cutAPOmegaUp2) * (alpha - cutAPOmegaUp2)) / (cutAPOmegaUp3 * cutAPOmegaUp3)); + const float qDown = std::abs(alpha - cutAPOmegaDown2) > std::abs(cutAPOmegaDown3) ? 0. : cutAPOmegaDown1 * std::sqrt(1.0f - ((alpha - cutAPOmegaDown2) * (alpha - cutAPOmegaDown2)) / (cutAPOmegaDown3 * cutAPOmegaDown3)); if (alpha < cutAlphaOmegaLow || alpha > cutAlphaOmegaHigh || qt < qDown || qt > qUp) { return kUndef; @@ -262,8 +236,8 @@ struct v0selector { registry.add("hV0APplot", "hV0APplot", HistType::kTH2F, {{200, -1.0f, +1.0f}, {250, 0.0f, 0.25f}}); registry.add("hV0APplotSelected", "hV0APplotSelected", HistType::kTH2F, {{200, -1.0f, +1.0f}, {250, 0.0f, 0.25f}}); registry.add("hV0Psi", "hV0Psi", HistType::kTH2F, {{100, 0, TMath::PiOver2()}, {100, 0, 0.1}}); - registry.add("hCascAPplot", "hCascAPplot", HistType::kTH2F, {{200, -1.0f, +1.0f}, {500, 0.0f, 0.5f}}); - registry.add("hCascAPplotSelected", "hCascAPplotSelected", HistType::kTH2F, {{200, -1.0f, +1.0f}, {500, 0.0f, 0.5f}}); + registry.add("hCascAPplot", "hCascAPplot", HistType::kTH2F, {{200, -1.0f, +1.0f}, {300, 0.0f, 0.3f}}); + registry.add("hCascAPplotSelected", "hCascAPplotSelected", HistType::kTH2F, {{200, -1.0f, +1.0f}, {300, 0.0f, 0.3f}}); registry.add("hMassOmega", "hMassOmega", HistType::kTH2F, {{900, 0.0f, 90.0f}, {100, 1.62f, 1.72f}}); registry.add("hMassAntiOmega", "hMassAntiOmega", HistType::kTH2F, {{900, 0.0f, 90.0f}, {100, 1.62f, 1.72f}}); } @@ -283,7 +257,7 @@ struct v0selector { std::vector cascpidmap; cascpidmap.clear(); if (produceCascID.value) { - cascpidmap.resize(V0s.size(), kUndef); + cascpidmap.resize(Cascs.size(), kUndef); } for (auto& V0 : V0s) { // if (!(V0.posTrack_as().trackType() & o2::aod::track::TPCrefit)) { @@ -467,7 +441,8 @@ struct v0selector { const float mOmega = Casc.mOmega(); - auto [alpha, qt] = evalArmenterosPodolanskiCascade(Casc); + const float alpha = Casc.alpha(); + const float qt = Casc.qtarm(); if (fillhisto) { registry.fill(HIST("hCascAPplot"), alpha, qt); diff --git a/PWGLF/DataModel/LFStrangenessTables.h b/PWGLF/DataModel/LFStrangenessTables.h index ca58973dff8..f5cea82c2be 100644 --- a/PWGLF/DataModel/LFStrangenessTables.h +++ b/PWGLF/DataModel/LFStrangenessTables.h @@ -713,21 +713,21 @@ DECLARE_SOA_DYNAMIC_COLUMN(MLambda, mLambda, //! mass under lambda hypothesis [](int v0type, float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { if ((v0type & (0x1 << o2::dataformats::V0Index::kPhotonOnly)) != 0) { return 0.0f; // provide mass only if NOT a photon with TPC-only tracks (special handling) - }; + } return RecoDecay::m(std::array{std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged}); }); DECLARE_SOA_DYNAMIC_COLUMN(MAntiLambda, mAntiLambda, //! mass under antilambda hypothesis [](int v0type, float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { if ((v0type & (0x1 << o2::dataformats::V0Index::kPhotonOnly)) != 0) { return 0.0f; // provide mass only if NOT a photon with TPC-only tracks (special handling) - }; + } return RecoDecay::m(std::array{std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}}, std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassProton}); }); DECLARE_SOA_DYNAMIC_COLUMN(MK0Short, mK0Short, //! mass under K0short hypothesis [](int v0type, float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { if ((v0type & (0x1 << o2::dataformats::V0Index::kPhotonOnly)) != 0) { return 0.0f; // provide mass only if NOT a photon with TPC-only tracks (special handling) - }; + } return RecoDecay::m(std::array{std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}}, std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassPionCharged}); }); DECLARE_SOA_DYNAMIC_COLUMN(MLambda_unchecked, mLambda_unchecked, //! mass under lambda hypothesis without v0 type check (will include TPC only and potentially duplicates! use with care) @@ -1417,6 +1417,53 @@ DECLARE_SOA_DYNAMIC_COLUMN(Phi, phi, //! Cascade phi in the range [0, 2pi) [](float px, float py) -> float { return RecoDecay::phi(px, py); }); DECLARE_SOA_DYNAMIC_COLUMN(Eta, eta, //! Cascade pseudorapidity [](float px, float py, float pz) -> float { return RecoDecay::eta(std::array{px, py, pz}); }); + +// Armenteros-Podolanski variables +DECLARE_SOA_DYNAMIC_COLUMN(Alpha, alpha, //! Armenteros Alpha + [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg, float pxbach, float pybach, float pzbach, int sign) { + const float pxv0 = pxpos + pxneg; + const float pyv0 = pypos + pyneg; + const float pzv0 = pzpos + pzneg; + + // No need to divide by momentum of the cascade (as in the v0data namespace) since the ratio of lQl is evaluated + const float lQlBach = RecoDecay::dotProd(std::array{pxbach, pybach, pzbach}, std::array{pxv0 + pxbach, pyv0 + pybach, pzv0 + pzbach}); + const float lQlV0 = RecoDecay::dotProd(std::array{pxv0, pyv0, pzv0}, std::array{pxv0 + pxbach, pyv0 + pybach, pzv0 + pzbach}); + float alpha = (lQlBach - lQlV0) / (lQlV0 + lQlBach); // alphacascade + if (sign < 0) { + alpha = -alpha; + } + return alpha; + }); + +DECLARE_SOA_DYNAMIC_COLUMN(QtArm, qtarm, //! Armenteros Qt + [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg, float pxbach, float pybach, float pzbach) { + const float pxv0 = pxpos + pxneg; + const float pyv0 = pypos + pyneg; + const float pzv0 = pzpos + pzneg; + + const float momTot2 = RecoDecay::p2(pxv0 + pxbach, pyv0 + pybach, pzv0 + pzbach); + const float dp = RecoDecay::dotProd(std::array{pxbach, pybach, pzbach}, std::array{pxv0 + pxbach, pyv0 + pybach, pzv0 + pzbach}); + return std::sqrt(RecoDecay::p2(pxbach, pybach, pzbach) - dp * dp / momTot2); // qtarm + }); + +// Psi pair angle: angle between the plane defined by the v0 and bachelor momenta and the xy plane +DECLARE_SOA_DYNAMIC_COLUMN(PsiPair, psipair, //! psi pair angle + [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg, float pxbach, float pybach, float pzbach, int sign) { + auto clipToPM1 = [](float x) { return x < -1.f ? -1.f : (x > 1.f ? 1.f : x); }; + const float pxv0 = pxpos + pxneg; + const float pyv0 = pypos + pyneg; + const float pzv0 = pzpos + pzneg; + + const float ptot2 = RecoDecay::p2(pxbach, pybach, pzbach) * RecoDecay::p2(pxv0, pyv0, pzv0); + const float argcos = RecoDecay::dotProd(std::array{pxbach, pybach, pzbach}, std::array{pxv0, pyv0, pzv0}) / std::sqrt(ptot2); + const float thetaV0 = std::atan2(RecoDecay::sqrtSumOfSquares(pxv0, pyv0), pzv0); + const float thetaBach = std::atan2(RecoDecay::sqrtSumOfSquares(pxbach, pybach), pzbach); + float argsin = (thetaV0 - thetaBach) / std::acos(clipToPM1(argcos)); + if (sign < 0) { + argsin = -argsin; + } + return std::asin(clipToPM1(argsin)); + }); } // namespace cascdata //______________________________________________________ @@ -1493,7 +1540,12 @@ DECLARE_SOA_TABLE(StoredCascCores, "AOD", "CASCCORE", //! core information about cascdata::PositiveEta, cascdata::PositivePhi, cascdata::BachelorEta, - cascdata::BachelorPhi); + cascdata::BachelorPhi, + + // Armenteros-Podolanski + cascdata::Alpha, + cascdata::QtArm, + cascdata::PsiPair); DECLARE_SOA_TABLE(StoredKFCascCores, "AOD", "KFCASCCORE", //! cascdata::Sign, cascdata::MXi, cascdata::MOmega, From 3b627a2c5209f5c9f54bb24e4024677373c184b9 Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Fri, 8 Aug 2025 18:57:16 +0200 Subject: [PATCH 06/18] init kaons from cascade filling in tpcSkimsTableCreator --- DPG/Tasks/TPC/tpcSkimsTableCreator.cxx | 30 +++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx b/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx index 2a2d644e7c4..029f4d3850e 100644 --- a/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx +++ b/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx @@ -60,6 +60,7 @@ struct TreeWriterTpcV0 { using Colls = soa::Join; using MyBCTable = soa::Join; using V0sWithID = soa::Join; + using CascsWithID = soa::Join; /// Tables to be produced Produces rowTPCTree; @@ -80,9 +81,21 @@ struct TreeWriterTpcV0 { Configurable downsamplingTsalisPions{"downsamplingTsalisPions", -1., "Downsampling factor to reduce the number of pions"}; Configurable downsamplingTsalisProtons{"downsamplingTsalisProtons", -1., "Downsampling factor to reduce the number of protons"}; Configurable downsamplingTsalisElectrons{"downsamplingTsalisElectrons", -1., "Downsampling factor to reduce the number of electrons"}; + Configurable downsamplingTsalisKaons{"downsamplingTsalisKaons", -1., "Downsampling factor to reduce the number of kaons"}; Configurable maxPt4dwnsmplTsalisPions{"maxPt4dwnsmplTsalisPions", 100., "Maximum Pt for applying downsampling factor of pions"}; Configurable maxPt4dwnsmplTsalisProtons{"maxPt4dwnsmplTsalisProtons", 100., "Maximum Pt for applying downsampling factor of protons"}; Configurable maxPt4dwnsmplTsalisElectrons{"maxPt4dwnsmplTsalisElectrons", 100., "Maximum Pt for applying downsampling factor of electrons"}; + Configurable maxPt4dwnsmplTsalisKaons{"maxPt4dwnsmplTsalisKaons", 100., "Maximum Pt for applying downsampling factor of kaons"}; + + enum { // Reconstructed V0 + kUndef = -1, + kGamma = 0, + kK0S = 1, + kLambda = 2, + kAntiLambda = 3, + kOmega = 4, + kAntiOmega = 5 + }; Filter trackFilter = (trackSelection.node() == 0) || ((trackSelection.node() == 1) && requireGlobalTrackInFilter()) || @@ -336,7 +349,7 @@ struct TreeWriterTpcV0 { } /// Apply a track quality selection with a filter! - void processStandard(Colls::iterator const& collision, soa::Filtered const& tracks, V0sWithID const& v0s, aod::BCsWithTimestamps const&) + void processStandard(Colls::iterator const& collision, soa::Filtered const& tracks, V0sWithID const& v0s, CascsWithID const& cascs, aod::BCsWithTimestamps const&) { /// Check event slection if (!isEventSelected(collision, tracks)) { @@ -396,6 +409,21 @@ struct TreeWriterTpcV0 { } } } + + /// Loop over cascade candidates + for (const auto& casc : cascs) { + auto bachTrack = casc.bachelor_as>(); + if (casc.cascaddid() == kUndef) { + continue; + } + // Omega + if (static_cast(bachTrack.pidbit() & (1 << kOmega))) { + if (downsampleTsalisCharged(bachTrack.pt(), downsamplingTsalisKaons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Kaon], maxPt4dwnsmplTsalisKaons)) { + // fillSkimmedV0Table(casc, bachTrack, collision, bachTrack.tpcNSigmaPr(), bachTrack.tofNSigmaPr(), bachTrack.tpcExpSignalPr(bachTrack.tpcSignal()), o2::track::PID::Proton, runnumber, dwnSmplFactor_Pr, hadronicRate); + } + } + } + } /// process Standard PROCESS_SWITCH(TreeWriterTpcV0, processStandard, "Standard V0 Samples for PID", true); From 089d3f6c20e2bac0df7f93daec2f6b28cd9db7a0 Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Fri, 8 Aug 2025 20:04:28 +0200 Subject: [PATCH 07/18] try to use cascCosPA (WIP) --- DPG/Tasks/TPC/tpcSkimsTableCreator.cxx | 42 ++++++++++++++++++++------ 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx b/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx index 029f4d3850e..9fc4856a01b 100644 --- a/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx +++ b/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx @@ -107,8 +107,8 @@ struct TreeWriterTpcV0 { ctpRateFetcher mRateFetcher; /// Funktion to fill skimmed tables - template - void fillSkimmedV0Table(V0 const& v0, T const& track, C const& collision, const float nSigmaTPC, const float nSigmaTOF, const float dEdxExp, const o2::track::PID::ID id, int runnumber, double dwnSmplFactor, float hadronicRate) + template + void fillSkimmedV0Table(V0Casc const& v0casc, T const& track, C const& collision, const float nSigmaTPC, const float nSigmaTOF, const float dEdxExp, const o2::track::PID::ID id, int runnumber, double dwnSmplFactor, float hadronicRate) { const double ncl = track.tpcNClsFound(); @@ -120,12 +120,12 @@ struct TreeWriterTpcV0 { auto trackocc = collision.trackOccupancyInTimeRange(); auto ft0occ = collision.ft0cOccupancyInTimeRange(); - const float alpha = v0.alpha(); - const float qt = v0.qtarm(); - const float cosPA = v0.v0cosPA(); - const float pT = v0.pt(); - const float v0radius = v0.v0radius(); - const float gammapsipair = v0.psipair(); + const float alpha = v0casc.alpha(); + const float qt = v0casc.qtarm(); + const float cosPA = GetCosPA(v0casc); + const float pT = v0casc.pt(); + const float v0radius = GetRadius(v0casc); + const float gammapsipair = v0casc.psipair(); const double pseudoRndm = track.pt() * 1000. - static_cast(track.pt() * 1000); if (pseudoRndm < dwnSmplFactor) { @@ -348,6 +348,30 @@ struct TreeWriterTpcV0 { ccdb->setFatalWhenNull(false); } + /// Evaluate cosPA of the v0 + double GetCosPA(V0sWithID::iterator const& v0) + { + return v0.v0cosPA(); + } + + /// Evaluate cosPA of the cascade + double GetCosPA(CascsWithID::iterator const& casc) + { + return casc.casccosPA(); + } + + /// Evaluate radius of the v0 + double GetRadius(V0sWithID::iterator const& v0) + { + return v0.v0radius(); + } + + /// Evaluate radius of the cascade + double GetRadius(CascsWithID::iterator const& casc) + { + return casc.cascradius(); + } + /// Apply a track quality selection with a filter! void processStandard(Colls::iterator const& collision, soa::Filtered const& tracks, V0sWithID const& v0s, CascsWithID const& cascs, aod::BCsWithTimestamps const&) { @@ -419,7 +443,7 @@ struct TreeWriterTpcV0 { // Omega if (static_cast(bachTrack.pidbit() & (1 << kOmega))) { if (downsampleTsalisCharged(bachTrack.pt(), downsamplingTsalisKaons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Kaon], maxPt4dwnsmplTsalisKaons)) { - // fillSkimmedV0Table(casc, bachTrack, collision, bachTrack.tpcNSigmaPr(), bachTrack.tofNSigmaPr(), bachTrack.tpcExpSignalPr(bachTrack.tpcSignal()), o2::track::PID::Proton, runnumber, dwnSmplFactor_Pr, hadronicRate); + fillSkimmedV0Table(casc, bachTrack, collision, bachTrack.tpcNSigmaPr(), bachTrack.tofNSigmaPr(), bachTrack.tpcExpSignalPr(bachTrack.tpcSignal()), o2::track::PID::Proton, runnumber, dwnSmplFactor_Pr, hadronicRate); } } } From 95ab00e651b5968caec5648c8155352b4d278dcd Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Fri, 8 Aug 2025 23:40:54 +0200 Subject: [PATCH 08/18] bugfix cascCosPA, fix typos, dev kaons from cascade filling --- DPG/Tasks/TPC/tpcSkimsTableCreator.cxx | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx b/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx index 9fc4856a01b..68b1a3490c3 100644 --- a/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx +++ b/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx @@ -77,6 +77,7 @@ struct TreeWriterTpcV0 { Configurable dwnSmplFactor_Pi{"dwnSmplFactor_Pi", 1., "downsampling factor for pions, default fraction to keep is 1."}; Configurable dwnSmplFactor_Pr{"dwnSmplFactor_Pr", 1., "downsampling factor for protons, default fraction to keep is 1."}; Configurable dwnSmplFactor_El{"dwnSmplFactor_El", 1., "downsampling factor for electrons, default fraction to keep is 1."}; + Configurable dwnSmplFactor_Ka{"dwnSmplFactor_Ka", 1., "downsampling factor for kaons, default fraction to keep is 1."}; Configurable sqrtSNN{"sqrt_s_NN", 0., "sqrt(s_NN), used for downsampling with the Tsallis distribution"}; Configurable downsamplingTsalisPions{"downsamplingTsalisPions", -1., "Downsampling factor to reduce the number of pions"}; Configurable downsamplingTsalisProtons{"downsamplingTsalisProtons", -1., "Downsampling factor to reduce the number of protons"}; @@ -122,7 +123,7 @@ struct TreeWriterTpcV0 { const float alpha = v0casc.alpha(); const float qt = v0casc.qtarm(); - const float cosPA = GetCosPA(v0casc); + const float cosPA = GetCosPA(v0casc, collision); const float pT = v0casc.pt(); const float v0radius = GetRadius(v0casc); const float gammapsipair = v0casc.psipair(); @@ -349,15 +350,17 @@ struct TreeWriterTpcV0 { } /// Evaluate cosPA of the v0 - double GetCosPA(V0sWithID::iterator const& v0) + template + double GetCosPA(V0sWithID::iterator const& v0, CollisionType const&) { return v0.v0cosPA(); } /// Evaluate cosPA of the cascade - double GetCosPA(CascsWithID::iterator const& casc) + template + double GetCosPA(CascsWithID::iterator const& casc, CollisionType const& collision) { - return casc.casccosPA(); + return casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()); } /// Evaluate radius of the v0 @@ -440,10 +443,10 @@ struct TreeWriterTpcV0 { if (casc.cascaddid() == kUndef) { continue; } - // Omega - if (static_cast(bachTrack.pidbit() & (1 << kOmega))) { + // Omega and antiomega + if (static_cast(bachTrack.pidbit() & (1 << kOmega)) || static_cast(bachTrack.pidbit() & (1 << kAntiOmega))) { if (downsampleTsalisCharged(bachTrack.pt(), downsamplingTsalisKaons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Kaon], maxPt4dwnsmplTsalisKaons)) { - fillSkimmedV0Table(casc, bachTrack, collision, bachTrack.tpcNSigmaPr(), bachTrack.tofNSigmaPr(), bachTrack.tpcExpSignalPr(bachTrack.tpcSignal()), o2::track::PID::Proton, runnumber, dwnSmplFactor_Pr, hadronicRate); + fillSkimmedV0Table(casc, bachTrack, collision, bachTrack.tpcNSigmaKa(), bachTrack.tofNSigmaKa(), bachTrack.tpcExpSignalKa(bachTrack.tpcSignal()), o2::track::PID::Kaon, runnumber, dwnSmplFactor_Ka, hadronicRate); } } } From cc67213a68b09a14c6b5d53e56d05522e380f842 Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Mon, 11 Aug 2025 19:02:32 +0200 Subject: [PATCH 09/18] add AP V0<-Casc; implement selection of cascades --- PWGDQ/Tasks/v0selector.cxx | 232 ++++++++++++++++++++------ PWGLF/DataModel/LFStrangenessTables.h | 21 ++- 2 files changed, 204 insertions(+), 49 deletions(-) diff --git a/PWGDQ/Tasks/v0selector.cxx b/PWGDQ/Tasks/v0selector.cxx index e6d824fa4ed..46061ef254a 100644 --- a/PWGDQ/Tasks/v0selector.cxx +++ b/PWGDQ/Tasks/v0selector.cxx @@ -103,6 +103,7 @@ struct v0selector { Configurable cutMassOmegaLow{"cutMassOmegaLow", 1.667, "cutMassOmegaLow"}; Configurable produceV0ID{"produceV0ID", false, "Produce additional V0ID table"}; + Configurable selectCascades{"selectCascades", false, "Select cascades in addition to v0s"}; Configurable produceCascID{"produceCascID", false, "Produce additional CascID table"}; enum { // Reconstructed V0 @@ -205,10 +206,21 @@ struct v0selector { Configurable mincrossedrows{"mincrossedrows", 70, "min crossed rows"}; Configurable maxchi2tpc{"maxchi2tpc", 4.0, "max chi2/NclsTPC"}; Configurable fillhisto{"fillhisto", false, "flag to fill histograms"}; - // cutNsigmaElTPC, cutNsigmaPiTPC, cutNsigmaPrTPC + // Cascade-related Configurables + Configurable cascDcaMax{"cascDcaMax", 0.3, "DCA cascade daughters"}; + Configurable cascV0DcaMax{"cascV0DcaMax", 0.3, "DCA V0 daughters of the cascade"}; + Configurable cascRadiusMin{"cascRadiusMin", 0.0, "Cascade Radius min"}; + Configurable cascRadiusMax{"cascRadiusMax", 90.0, "Cascade Radius max"}; + Configurable cascV0RadiusMin{"cascV0RadiusMin", 0.0, "V0 of the Cascade Radius min"}; + Configurable cascV0RadiusMax{"cascV0RadiusMax", 90.0, "V0 of the Cascade Radius max"}; + Configurable cascCosinePAMin{"cascCosinePAMin", 0.998, "Cascade CosPA min"}; + Configurable cascV0CosinePAMin{"cascV0CosinePAMin", 0.995, "V0 of the Cascade CosPA min"}; + Configurable cascV0CosinePAMax{"cascV0CosinePAMax", 1.000, "V0 of the Cascade CosPA max"}; + // cutNsigmaElTPC, cutNsigmaPiTPC, cutNsigmaPrTPC, cutNsigmaKaTPC Configurable cutNsigmaElTPC{"cutNsigmaElTPC", 5.0, "cutNsigmaElTPC"}; Configurable cutNsigmaPiTPC{"cutNsigmaPiTPC", 5.0, "cutNsigmaPiTPC"}; Configurable cutNsigmaPrTPC{"cutNsigmaPrTPC", 5.0, "cutNsigmaPrTPC"}; + Configurable cutNsigmaKaTPC{"cutNsigmaKaTPC", 5.0, "cutNsigmaKaTPC"}; HistogramRegistry registry{"registry"}; void init(o2::framework::InitContext&) @@ -236,10 +248,35 @@ struct v0selector { registry.add("hV0APplot", "hV0APplot", HistType::kTH2F, {{200, -1.0f, +1.0f}, {250, 0.0f, 0.25f}}); registry.add("hV0APplotSelected", "hV0APplotSelected", HistType::kTH2F, {{200, -1.0f, +1.0f}, {250, 0.0f, 0.25f}}); registry.add("hV0Psi", "hV0Psi", HistType::kTH2F, {{100, 0, TMath::PiOver2()}, {100, 0, 0.1}}); - registry.add("hCascAPplot", "hCascAPplot", HistType::kTH2F, {{200, -1.0f, +1.0f}, {300, 0.0f, 0.3f}}); - registry.add("hCascAPplotSelected", "hCascAPplotSelected", HistType::kTH2F, {{200, -1.0f, +1.0f}, {300, 0.0f, 0.3f}}); - registry.add("hMassOmega", "hMassOmega", HistType::kTH2F, {{900, 0.0f, 90.0f}, {100, 1.62f, 1.72f}}); - registry.add("hMassAntiOmega", "hMassAntiOmega", HistType::kTH2F, {{900, 0.0f, 90.0f}, {100, 1.62f, 1.72f}}); + if (selectCascades) { + registry.add("hCascPt", "pT", HistType::kTH1F, {{100, 0.0f, 10}}); + registry.add("hCascEtaPhi", "#eta vs. #varphi", HistType::kTH2F, {{63, 0, 6.3}, {20, -1.0f, 1.0f}}); + registry.add("hCascDCAxyPosToPV", "hCascDCAxyPosToPV", HistType::kTH1F, {{1000, -5.0f, 5.0f}}); + registry.add("hCascDCAxyNegToPV", "hCascDCAxyNegToPV", HistType::kTH1F, {{1000, -5.0f, 5.0f}}); + registry.add("hCascDCAxyBachToPV", "hCascDCAxyBachToPV", HistType::kTH1F, {{1000, -5.0f, 5.0f}}); + registry.add("hCascDCAzPosToPV", "hCascDCAzPosToPV", HistType::kTH1F, {{1000, -5.0f, 5.0f}}); + registry.add("hCascDCAzNegToPV", "hCascDCAzNegToPV", HistType::kTH1F, {{1000, -5.0f, 5.0f}}); + registry.add("hCascDCAzBachToPV", "hCascDCAzBachToPV", HistType::kTH1F, {{1000, -5.0f, 5.0f}}); + registry.add("hCascAPplot", "hCascAPplot", HistType::kTH2F, {{200, -1.0f, +1.0f}, {300, 0.0f, 0.3f}}); + registry.add("hCascV0APplot", "hCascV0APplot", HistType::kTH2F, {{200, -1.0f, +1.0f}, {250, 0.0f, 0.25f}}); + registry.add("hCascAPplotSelected", "hCascAPplotSelected", HistType::kTH2F, {{200, -1.0f, +1.0f}, {300, 0.0f, 0.3f}}); + registry.add("hCascV0APplotSelected", "hCascV0APplotSelected", HistType::kTH2F, {{200, -1.0f, +1.0f}, {250, 0.0f, 0.25f}}); + registry.add("hCascRadius", "hCascRadius", HistType::kTH1F, {{1000, 0.0f, 100.0f}}); + registry.add("hCascV0Radius", "hCascV0Radius", HistType::kTH1F, {{1000, 0.0f, 100.0f}}); + registry.add("hCascCosPA", "hCascCosPA", HistType::kTH1F, {{50, 0.95f, 1.0f}}); + registry.add("hCascV0CosPA", "hCascV0CosPA", HistType::kTH1F, {{50, 0.95f, 1.0f}}); + registry.add("hMassOmega", "hMassOmega", HistType::kTH2F, {{900, 0.0f, 90.0f}, {100, 1.62f, 1.72f}}); + registry.add("hMassAntiOmega", "hMassAntiOmega", HistType::kTH2F, {{900, 0.0f, 90.0f}, {100, 1.62f, 1.72f}}); + registry.add("hCascDCADau", "hCascDCADau", HistType::kTH1F, {{1000, 0.0f, 10.0f}}); + registry.add("hCascV0DCADau", "hCascV0DCADau", HistType::kTH1F, {{1000, 0.0f, 10.0f}}); + } + } + + if (selectCascades == false && produceCascID == true) { + LOGP(error, "produceCascID is available only when selectCascades is enabled"); + } + if (cutAPOmegaUp1 < cutAPOmegaDown1) { + LOGP(error, "cutAPOmegaUp1 must be greater than cutAPOmegaDown1"); } } @@ -426,64 +463,165 @@ struct v0selector { } } - for (const auto& Casc : Cascs) { - if (fillhisto) { - registry.fill(HIST("hCascCandidate"), 1); - } - - // topological selections + if (selectCascades) { + for (const auto& casc : Cascs) { + if (fillhisto) { + registry.fill(HIST("hCascCandidate"), 1); + } - if (fillhisto) { - registry.fill(HIST("hCascCandidate"), 2); - } + if (std::fabs(casc.posTrack_as().eta()) > 0.9) { + continue; + } + if (std::fabs(casc.negTrack_as().eta()) > 0.9) { + continue; + } + if (std::fabs(casc.negTrack_as().eta()) > 0.9) { + continue; + } - const float Cascradius = Casc.cascradius(); + if (casc.posTrack_as().tpcNClsCrossedRows() < mincrossedrows) { + continue; + } + if (casc.negTrack_as().tpcNClsCrossedRows() < mincrossedrows) { + continue; + } + if (casc.bachelor_as().tpcNClsCrossedRows() < mincrossedrows) { + continue; + } + if (casc.posTrack_as().tpcChi2NCl() > maxchi2tpc) { + continue; + } + if (casc.negTrack_as().tpcChi2NCl() > maxchi2tpc) { + continue; + } + if (casc.bachelor_as().tpcChi2NCl() > maxchi2tpc) { + continue; + } + if (std::fabs(casc.posTrack_as().dcaXY()) < dcamin) { + continue; + } + if (std::fabs(casc.negTrack_as().dcaXY()) < dcamin) { + continue; + } + if (std::fabs(casc.bachelor_as().dcaXY()) < dcamin) { + continue; + } + if (std::fabs(casc.posTrack_as().dcaXY()) > dcamax) { + continue; + } + if (std::fabs(casc.negTrack_as().dcaXY()) > dcamax) { + continue; + } + if (std::fabs(casc.bachelor_as().dcaXY()) > dcamax) { + continue; + } - const float mOmega = Casc.mOmega(); + if (casc.posTrack_as().sign() * casc.negTrack_as().sign() > 0) { // reject same sign pair + continue; + } - const float alpha = Casc.alpha(); - const float qt = Casc.qtarm(); + if (fillhisto) { + registry.fill(HIST("hCascCandidate"), 2); + } - if (fillhisto) { - registry.fill(HIST("hCascAPplot"), alpha, qt); - } + auto collision = casc.collision_as(); + const float collisionX = collision.posX(); + const float collisionY = collision.posY(); + const float collisionZ = collision.posZ(); - const int cascid = checkCascade(alpha, qt); - if (cascid < 0) { - continue; - } - if (fillhisto) { - registry.fill(HIST("hCascAPplotSelected"), alpha, qt); - } + const float cascDca = casc.dcacascdaughters(); // NOTE the name of getter is misleading. In case of no-KF this is sqrt(Chi2) + const float cascV0Dca = casc.dcaV0daughters(); // NOTE the name of getter is misleading. In case of kfDoDCAFitterPreMinimV0 this is sqrt(Chi2) + const float cascRadius = casc.cascradius(); + const float cascV0Radius = casc.dcaV0daughters(); + const float cascCosinePA = casc.casccosPA(collisionX, collisionY, collisionZ); + const float cascV0CosinePA = casc.v0cosPA(collisionX, collisionY, collisionZ); - auto storeCascAddID = [&](auto gix, auto id) { - if (produceCascID.value) { - cascpidmap[gix] = id; + if (cascDca > cascDcaMax) { + continue; } - }; + if (cascV0Dca > cascV0DcaMax) { + continue; + } + if (cascRadius < cascRadiusMin || cascRadius > cascRadiusMax) { + continue; + } + if (cascV0Radius < cascV0RadiusMin || cascV0Radius > cascV0RadiusMax) { + continue; + } + if (cascCosinePA < cascCosinePAMin) { + continue; + } + if (cascV0CosinePA < cascV0CosinePAMin || cascV0CosinePA > cascV0CosinePAMax) { + continue; + } + + const float mOmega = casc.mOmega(); + const float alpha = casc.alpha(); + const float qt = casc.qtarm(); + const float v0Alpha = casc.v0Alpha(); + const float v0Qt = casc.v0Qtarm(); - if (cascid == kOmega) { if (fillhisto) { - registry.fill(HIST("hMassOmega"), Cascradius, mOmega); + registry.fill(HIST("hCascPt"), casc.pt()); + registry.fill(HIST("hCascEtaPhi"), casc.phi(), casc.eta()); + registry.fill(HIST("hCascDCAxyPosToPV"), casc.posTrack_as().dcaXY()); + registry.fill(HIST("hCascDCAxyNegToPV"), casc.negTrack_as().dcaXY()); + registry.fill(HIST("hCascDCAxyBachToPV"), casc.bachelor_as().dcaXY()); + registry.fill(HIST("hCascDCAzPosToPV"), casc.posTrack_as().dcaZ()); + registry.fill(HIST("hCascDCAzNegToPV"), casc.negTrack_as().dcaZ()); + registry.fill(HIST("hCascDCAzBachToPV"), casc.bachelor_as().dcaZ()); + registry.fill(HIST("hCascAPplot"), alpha, qt); + registry.fill(HIST("hCascV0APplot"), v0Alpha, v0Qt); + registry.fill(HIST("hCascRadius"), cascRadius); + registry.fill(HIST("hCascV0Radius"), cascV0Radius); + registry.fill(HIST("hCascCosPA"), cascCosinePA); + registry.fill(HIST("hCascV0CosPA"), cascV0CosinePA); + registry.fill(HIST("hCascDCADau"), cascDca); + registry.fill(HIST("hCascV0DCADau"), cascV0Dca); } - if (cutMassOmegaLow < mOmega && mOmega < cutMassOmegaHigh) { - pidmap[Casc.bachelorId()] |= (uint8_t(1) << kOmega); - storeCascAddID(Casc.globalIndex(), kOmega); + + const int cascid = checkCascade(alpha, qt); + const int v0id = checkV0(v0Alpha, v0Qt); + if (cascid < 0) { + continue; + } + if (v0id != kLambda && v0id != kAntiLambda) { + continue; } - } else if (cascid == kAntiOmega) { if (fillhisto) { - registry.fill(HIST("hMassAntiOmega"), Cascradius, mOmega); + registry.fill(HIST("hCascAPplotSelected"), alpha, qt); + registry.fill(HIST("hCascV0APplotSelected"), v0Alpha, v0Qt); + } + + auto storeCascAddID = [&](auto gix, auto id) { + if (produceCascID.value) { + cascpidmap[gix] = id; + } + }; + + if (cascid == kOmega) { + if (fillhisto) { + registry.fill(HIST("hMassOmega"), cascRadius, mOmega); + } + if (cutMassOmegaLow < mOmega && mOmega < cutMassOmegaHigh && std::abs(casc.posTrack_as().tpcNSigmaPr()) < cutNsigmaPrTPC && std::abs(casc.negTrack_as().tpcNSigmaPi()) < cutNsigmaPiTPC && std::abs(casc.bachelor_as().tpcNSigmaKa()) < cutNsigmaKaTPC) { + pidmap[casc.bachelorId()] |= (uint8_t(1) << kOmega); + storeCascAddID(casc.globalIndex(), kOmega); + } + } else if (cascid == kAntiOmega) { + if (fillhisto) { + registry.fill(HIST("hMassAntiOmega"), cascRadius, mOmega); + } + if (cutMassOmegaLow < mOmega && mOmega < cutMassOmegaHigh && std::abs(casc.posTrack_as().tpcNSigmaPi()) < cutNsigmaPiTPC && std::abs(casc.negTrack_as().tpcNSigmaPr()) < cutNsigmaPrTPC && std::abs(casc.bachelor_as().tpcNSigmaKa()) < cutNsigmaKaTPC) { + pidmap[casc.bachelorId()] |= (uint8_t(1) << kAntiOmega); + storeCascAddID(casc.globalIndex(), kAntiOmega); + } } - if (cutMassOmegaLow < mOmega && mOmega < cutMassOmegaHigh) { - pidmap[Casc.bachelorId()] |= (uint8_t(1) << kAntiOmega); - storeCascAddID(Casc.globalIndex(), kAntiOmega); + } // end of Casc loop + if (produceCascID.value) { + for (auto& casc : Cascs) { + cascmapID(cascpidmap[casc.globalIndex()]); } } - } // end of Casc loop - if (produceCascID.value) { - for (auto& Casc : Cascs) { - cascmapID(cascpidmap[Casc.globalIndex()]); - } } for (auto& track : tracks) { // printf("setting pidmap[%lld] = %d\n",track.globalIndex(),pidmap[track.globalIndex()]); diff --git a/PWGLF/DataModel/LFStrangenessTables.h b/PWGLF/DataModel/LFStrangenessTables.h index f5cea82c2be..2bb5c2f06f2 100644 --- a/PWGLF/DataModel/LFStrangenessTables.h +++ b/PWGLF/DataModel/LFStrangenessTables.h @@ -1464,6 +1464,21 @@ DECLARE_SOA_DYNAMIC_COLUMN(PsiPair, psipair, //! psi pair angle } return std::asin(clipToPM1(argsin)); }); + +DECLARE_SOA_DYNAMIC_COLUMN(V0Alpha, v0Alpha, //! Armenteros Alpha + [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) { + // No need to divide by momentum of the v0 (as in the v0data namespace) since the ratio of lQl is evaluated + const float lQlPos = RecoDecay::dotProd(std::array{pxpos, pypos, pzpos}, std::array{pxneg + pxpos, pyneg + pypos, pzneg + pzpos}); + const float lQlNeg = RecoDecay::dotProd(std::array{pxneg, pyneg, pzneg}, std::array{pxneg + pxpos, pyneg + pypos, pzneg + pzpos}); + return (lQlPos - lQlNeg) / (lQlPos + lQlNeg); + }); + +DECLARE_SOA_DYNAMIC_COLUMN(V0QtArm, v0Qtarm, //! Armenteros Qt + [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) { + const float momTot2 = RecoDecay::p2(pxpos + pxneg, pypos + pyneg, pzpos + pzneg); + const float dp = RecoDecay::dotProd(std::array{pxneg, pyneg, pzneg}, std::array{pxpos + pxneg, pypos + pyneg, pzpos + pzneg}); + return std::sqrt(RecoDecay::p2(pxneg, pyneg, pzneg) - dp * dp / momTot2); // qtarm + }); } // namespace cascdata //______________________________________________________ @@ -1542,10 +1557,12 @@ DECLARE_SOA_TABLE(StoredCascCores, "AOD", "CASCCORE", //! core information about cascdata::BachelorEta, cascdata::BachelorPhi, - // Armenteros-Podolanski + // Armenteros-Podolanski and psi-pair cascdata::Alpha, cascdata::QtArm, - cascdata::PsiPair); + cascdata::PsiPair, + cascdata::V0Alpha, + cascdata::V0QtArm); DECLARE_SOA_TABLE(StoredKFCascCores, "AOD", "KFCASCCORE", //! cascdata::Sign, cascdata::MXi, cascdata::MOmega, From 5a37f1eeff9e9a86da34be8f7036ef7abbd4a737 Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Fri, 22 Aug 2025 11:11:54 +0200 Subject: [PATCH 10/18] add check for V0 in cascade filling --- PWGDQ/Tasks/v0selector.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PWGDQ/Tasks/v0selector.cxx b/PWGDQ/Tasks/v0selector.cxx index 46061ef254a..e236b9d31ab 100644 --- a/PWGDQ/Tasks/v0selector.cxx +++ b/PWGDQ/Tasks/v0selector.cxx @@ -599,7 +599,7 @@ struct v0selector { } }; - if (cascid == kOmega) { + if (cascid == kOmega && v0id == kLambda) { if (fillhisto) { registry.fill(HIST("hMassOmega"), cascRadius, mOmega); } @@ -607,7 +607,7 @@ struct v0selector { pidmap[casc.bachelorId()] |= (uint8_t(1) << kOmega); storeCascAddID(casc.globalIndex(), kOmega); } - } else if (cascid == kAntiOmega) { + } else if (cascid == kAntiOmega && v0id == kAntiLambda) { if (fillhisto) { registry.fill(HIST("hMassAntiOmega"), cascRadius, mOmega); } From 7107b7ff77e7dc90bd01f5c6e4ba6d1771aa791f Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Wed, 27 Aug 2025 13:02:23 +0200 Subject: [PATCH 11/18] add check for V0's inv. mass in cascade's selection --- PWGDQ/Tasks/v0selector.cxx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/PWGDQ/Tasks/v0selector.cxx b/PWGDQ/Tasks/v0selector.cxx index e236b9d31ab..9d41bac24cc 100644 --- a/PWGDQ/Tasks/v0selector.cxx +++ b/PWGDQ/Tasks/v0selector.cxx @@ -101,6 +101,8 @@ struct v0selector { Configurable cutAlphaOmegaLow{"cutAlphaOmegaLow", 0., "cutAlphaOmegaLow"}; Configurable cutMassOmegaHigh{"cutMassOmegaHigh", 1.677, "cutMassOmegaHigh"}; Configurable cutMassOmegaLow{"cutMassOmegaLow", 1.667, "cutMassOmegaLow"}; + Configurable cutMassCascV0Low{"cutMassCascV0Low", 1.110, "cutMassCascV0Low"}; + Configurable cutMassCascV0High{"cutMassCascV0High", 1.120, "cutMassCascV0High"}; Configurable produceV0ID{"produceV0ID", false, "Produce additional V0ID table"}; Configurable selectCascades{"selectCascades", false, "Select cascades in addition to v0s"}; @@ -556,6 +558,7 @@ struct v0selector { } const float mOmega = casc.mOmega(); + const float mV0Lambda = casc.mLambda(); const float alpha = casc.alpha(); const float qt = casc.qtarm(); const float v0Alpha = casc.v0Alpha(); @@ -603,7 +606,7 @@ struct v0selector { if (fillhisto) { registry.fill(HIST("hMassOmega"), cascRadius, mOmega); } - if (cutMassOmegaLow < mOmega && mOmega < cutMassOmegaHigh && std::abs(casc.posTrack_as().tpcNSigmaPr()) < cutNsigmaPrTPC && std::abs(casc.negTrack_as().tpcNSigmaPi()) < cutNsigmaPiTPC && std::abs(casc.bachelor_as().tpcNSigmaKa()) < cutNsigmaKaTPC) { + if (cutMassOmegaLow < mOmega && mOmega < cutMassOmegaHigh && cutMassCascV0Low < mV0Lambda && mV0Lambda < cutMassCascV0High && std::abs(casc.posTrack_as().tpcNSigmaPr()) < cutNsigmaPrTPC && std::abs(casc.negTrack_as().tpcNSigmaPi()) < cutNsigmaPiTPC && std::abs(casc.bachelor_as().tpcNSigmaKa()) < cutNsigmaKaTPC) { pidmap[casc.bachelorId()] |= (uint8_t(1) << kOmega); storeCascAddID(casc.globalIndex(), kOmega); } @@ -611,7 +614,7 @@ struct v0selector { if (fillhisto) { registry.fill(HIST("hMassAntiOmega"), cascRadius, mOmega); } - if (cutMassOmegaLow < mOmega && mOmega < cutMassOmegaHigh && std::abs(casc.posTrack_as().tpcNSigmaPi()) < cutNsigmaPiTPC && std::abs(casc.negTrack_as().tpcNSigmaPr()) < cutNsigmaPrTPC && std::abs(casc.bachelor_as().tpcNSigmaKa()) < cutNsigmaKaTPC) { + if (cutMassOmegaLow < mOmega && mOmega < cutMassOmegaHigh && cutMassCascV0Low < mV0Lambda && mV0Lambda < cutMassCascV0High && std::abs(casc.posTrack_as().tpcNSigmaPi()) < cutNsigmaPiTPC && std::abs(casc.negTrack_as().tpcNSigmaPr()) < cutNsigmaPrTPC && std::abs(casc.bachelor_as().tpcNSigmaKa()) < cutNsigmaKaTPC) { pidmap[casc.bachelorId()] |= (uint8_t(1) << kAntiOmega); storeCascAddID(casc.globalIndex(), kAntiOmega); } From bd06003aee63b6506df06b7decef4e224c906169 Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Wed, 27 Aug 2025 17:20:41 +0200 Subject: [PATCH 12/18] refactor prongs selection --- PWGDQ/Tasks/v0selector.cxx | 115 ++++++++----------------------------- 1 file changed, 23 insertions(+), 92 deletions(-) diff --git a/PWGDQ/Tasks/v0selector.cxx b/PWGDQ/Tasks/v0selector.cxx index 9d41bac24cc..676a5dfc113 100644 --- a/PWGDQ/Tasks/v0selector.cxx +++ b/PWGDQ/Tasks/v0selector.cxx @@ -310,55 +310,21 @@ struct v0selector { if (fillhisto) { registry.fill(HIST("hV0Candidate"), 1); } - if (std::fabs(V0.posTrack_as().eta()) > 0.9) { - continue; - } - if (std::fabs(V0.negTrack_as().eta()) > 0.9) { - continue; - } - if (V0.posTrack_as().tpcNClsCrossedRows() < mincrossedrows) { - continue; - } - if (V0.negTrack_as().tpcNClsCrossedRows() < mincrossedrows) { - continue; - } - if (V0.posTrack_as().tpcChi2NCl() > maxchi2tpc) { - continue; - } - if (V0.negTrack_as().tpcChi2NCl() > maxchi2tpc) { - continue; - } - if (std::fabs(V0.posTrack_as().dcaXY()) < dcamin) { - continue; - } - if (std::fabs(V0.negTrack_as().dcaXY()) < dcamin) { - continue; - } - if (std::fabs(V0.posTrack_as().dcaXY()) > dcamax) { - continue; - } - if (std::fabs(V0.negTrack_as().dcaXY()) > dcamax) { - continue; - } + const auto& posTrack = casc.posTrack_as(); + const auto& negTrack = casc.negTrack_as(); - if (V0.posTrack_as().sign() * V0.negTrack_as().sign() > 0) { // reject same sign pair - continue; + bool isRejectV0{false}; + for(const auto& prong : std::array{posTrack, negTrack}) { + isRejectV0 = isRejectV0 || std::fabs(prong.eta()) > 0.9; + isRejectV0 = isRejectV0 || prong.tpcNClsCrossedRows() < mincrossedrows; + isRejectV0 = isRejectV0 || prong.tpcChi2NCl() > maxchi2tpc; + isRejectV0 = isRejectV0 || std::fabs(prong.dcaXY()) < dcamin; + isRejectV0 = isRejectV0 || std::fabs(prong.dcaXY()) > dcamax; } + isRejectV0 = isRejectV0 || (posTrack.sign() * negTrack.sign() > 0); - // if (V0.posTrack_as().collisionId() != V0.negTrack_as().collisionId()) { - // continue; - // } - - // if (!V0.posTrack_as().has_collision() || !V0.negTrack_as().has_collision()) { - // continue; - // } - - // auto const& collision = V0.collision_as(); - - // if (V0.collisionId() != collision.globalIndex()) { - // continue; - // } + if (isRejectV0) continue; float V0dca = V0.dcaV0daughters(); float V0CosinePA = V0.v0cosPA(); @@ -471,56 +437,21 @@ struct v0selector { registry.fill(HIST("hCascCandidate"), 1); } - if (std::fabs(casc.posTrack_as().eta()) > 0.9) { - continue; - } - if (std::fabs(casc.negTrack_as().eta()) > 0.9) { - continue; - } - if (std::fabs(casc.negTrack_as().eta()) > 0.9) { - continue; - } + const auto& posTrack = casc.posTrack_as(); + const auto& negTrack = casc.negTrack_as(); + const auto& bachelor = casc.bachelor_as(); - if (casc.posTrack_as().tpcNClsCrossedRows() < mincrossedrows) { - continue; - } - if (casc.negTrack_as().tpcNClsCrossedRows() < mincrossedrows) { - continue; - } - if (casc.bachelor_as().tpcNClsCrossedRows() < mincrossedrows) { - continue; - } - if (casc.posTrack_as().tpcChi2NCl() > maxchi2tpc) { - continue; - } - if (casc.negTrack_as().tpcChi2NCl() > maxchi2tpc) { - continue; - } - if (casc.bachelor_as().tpcChi2NCl() > maxchi2tpc) { - continue; - } - if (std::fabs(casc.posTrack_as().dcaXY()) < dcamin) { - continue; - } - if (std::fabs(casc.negTrack_as().dcaXY()) < dcamin) { - continue; - } - if (std::fabs(casc.bachelor_as().dcaXY()) < dcamin) { - continue; - } - if (std::fabs(casc.posTrack_as().dcaXY()) > dcamax) { - continue; - } - if (std::fabs(casc.negTrack_as().dcaXY()) > dcamax) { - continue; - } - if (std::fabs(casc.bachelor_as().dcaXY()) > dcamax) { - continue; + bool isRejectCascade{false}; + for(const auto& prong : std::array{posTrack, negTrack, bachelor}) { + isRejectCascade = isRejectCascade || std::fabs(prong.eta()) > 0.9; + isRejectCascade = isRejectCascade || prong.tpcNClsCrossedRows() < mincrossedrows; + isRejectCascade = isRejectCascade || prong.tpcChi2NCl() > maxchi2tpc; + isRejectCascade = isRejectCascade || std::fabs(prong.dcaXY()) < dcamin; + isRejectCascade = isRejectCascade || std::fabs(prong.dcaXY()) > dcamax; } + isRejectCascade = isRejectCascade || (posTrack.sign() * negTrack.sign() > 0); - if (casc.posTrack_as().sign() * casc.negTrack_as().sign() > 0) { // reject same sign pair - continue; - } + if (isRejectCascade) continue; if (fillhisto) { registry.fill(HIST("hCascCandidate"), 2); From 31e350d89197e40350e8764cb9e7ed4c258a67f0 Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Wed, 27 Aug 2025 17:25:31 +0200 Subject: [PATCH 13/18] fix typo casc->V0 --- PWGDQ/Tasks/v0selector.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PWGDQ/Tasks/v0selector.cxx b/PWGDQ/Tasks/v0selector.cxx index 676a5dfc113..d98d199bf47 100644 --- a/PWGDQ/Tasks/v0selector.cxx +++ b/PWGDQ/Tasks/v0selector.cxx @@ -311,8 +311,8 @@ struct v0selector { registry.fill(HIST("hV0Candidate"), 1); } - const auto& posTrack = casc.posTrack_as(); - const auto& negTrack = casc.negTrack_as(); + const auto& posTrack = V0.posTrack_as(); + const auto& negTrack = V0.negTrack_as(); bool isRejectV0{false}; for(const auto& prong : std::array{posTrack, negTrack}) { From 740f5f53d5326e32ac5260c81b31f71b580e5c54 Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Fri, 5 Sep 2025 17:08:49 +0200 Subject: [PATCH 14/18] replace std::array with initializer list --- PWGDQ/Tasks/v0selector.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PWGDQ/Tasks/v0selector.cxx b/PWGDQ/Tasks/v0selector.cxx index d98d199bf47..ec420c9c2d9 100644 --- a/PWGDQ/Tasks/v0selector.cxx +++ b/PWGDQ/Tasks/v0selector.cxx @@ -315,7 +315,7 @@ struct v0selector { const auto& negTrack = V0.negTrack_as(); bool isRejectV0{false}; - for(const auto& prong : std::array{posTrack, negTrack}) { + for(const auto& prong : {posTrack, negTrack}) { isRejectV0 = isRejectV0 || std::fabs(prong.eta()) > 0.9; isRejectV0 = isRejectV0 || prong.tpcNClsCrossedRows() < mincrossedrows; isRejectV0 = isRejectV0 || prong.tpcChi2NCl() > maxchi2tpc; @@ -442,7 +442,7 @@ struct v0selector { const auto& bachelor = casc.bachelor_as(); bool isRejectCascade{false}; - for(const auto& prong : std::array{posTrack, negTrack, bachelor}) { + for(const auto& prong : {posTrack, negTrack, bachelor}) { isRejectCascade = isRejectCascade || std::fabs(prong.eta()) > 0.9; isRejectCascade = isRejectCascade || prong.tpcNClsCrossedRows() < mincrossedrows; isRejectCascade = isRejectCascade || prong.tpcChi2NCl() > maxchi2tpc; From 5a241aa1deade9c3f6620ccfe2f19bf0612ac573 Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Wed, 10 Sep 2025 16:50:27 +0200 Subject: [PATCH 15/18] extend dev to other fillSkimmedV0 functions and fillSkimmedV0Table --- DPG/Tasks/TPC/tpcSkimsTableCreator.cxx | 50 ++++++++++++++++---------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx b/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx index 68b1a3490c3..f3dd6e9e9e3 100644 --- a/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx +++ b/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx @@ -165,8 +165,8 @@ struct TreeWriterTpcV0 { } }; - template - void fillSkimmedV0TableWithdEdxTrQA(V0 const& v0, T const& track, TQA const& trackQA, bool existTrkQA, C const& collision, const float nSigmaTPC, const float nSigmaTOF, const float dEdxExp, const o2::track::PID::ID id, int runnumber, double dwnSmplFactor, float hadronicRate) + template + void fillSkimmedV0TableWithdEdxTrQA(V0Casc const& v0casc, T const& track, TQA const& trackQA, bool existTrkQA, C const& collision, const float nSigmaTPC, const float nSigmaTOF, const float dEdxExp, const o2::track::PID::ID id, int runnumber, double dwnSmplFactor, float hadronicRate) { const double ncl = track.tpcNClsFound(); @@ -178,12 +178,12 @@ struct TreeWriterTpcV0 { auto trackocc = collision.trackOccupancyInTimeRange(); auto ft0occ = collision.ft0cOccupancyInTimeRange(); - const float alpha = v0.alpha(); - const float qt = v0.qtarm(); - const float cosPA = v0.v0cosPA(); - const float pT = v0.pt(); - const float v0radius = v0.v0radius(); - const float gammapsipair = v0.psipair(); + const float alpha = v0casc.alpha(); + const float qt = v0casc.qtarm(); + const float cosPA = GetCosPA(v0casc, collision); + const float pT = v0casc.pt(); + const float v0radius = GetRadius(v0casc); + const float gammapsipair = v0casc.psipair(); const double pseudoRndm = track.pt() * 1000. - static_cast(track.pt() * 1000); if (pseudoRndm < dwnSmplFactor) { @@ -224,8 +224,8 @@ struct TreeWriterTpcV0 { }; /// Function to fill skimmed tables - template - void fillSkimmedV0TableWithTrQA(V0 const& v0, T const& track, TQA const& trackQA, bool existTrkQA, C const& collision, const float nSigmaTPC, const float nSigmaTOF, const float dEdxExp, const o2::track::PID::ID id, int runnumber, double dwnSmplFactor, float hadronicRate, int bcGlobalIndex, int bcTimeFrameId, int bcBcInTimeFrame) + template + void fillSkimmedV0TableWithTrQA(V0Casc const& v0casc, T const& track, TQA const& trackQA, bool existTrkQA, C const& collision, const float nSigmaTPC, const float nSigmaTOF, const float dEdxExp, const o2::track::PID::ID id, int runnumber, double dwnSmplFactor, float hadronicRate, int bcGlobalIndex, int bcTimeFrameId, int bcBcInTimeFrame) { const double ncl = track.tpcNClsFound(); @@ -237,12 +237,12 @@ struct TreeWriterTpcV0 { auto trackocc = collision.trackOccupancyInTimeRange(); auto ft0occ = collision.ft0cOccupancyInTimeRange(); - const float alpha = v0.alpha(); - const float qt = v0.qtarm(); - const float cosPA = v0.v0cosPA(); - const float pT = v0.pt(); - const float v0radius = v0.v0radius(); - const float gammapsipair = v0.psipair(); + const float alpha = v0casc.alpha(); + const float qt = v0casc.qtarm(); + const float cosPA = GetCosPA(v0casc, collision); + const float pT = v0casc.pt(); + const float v0radius = GetRadius(v0casc); + const float gammapsipair = v0casc.psipair(); const double pseudoRndm = track.pt() * 1000. - static_cast(track.pt() * 1000); if (pseudoRndm < dwnSmplFactor) { @@ -454,7 +454,7 @@ struct TreeWriterTpcV0 { } /// process Standard PROCESS_SWITCH(TreeWriterTpcV0, processStandard, "Standard V0 Samples for PID", true); - void processStandardWithCorrecteddEdx(Colls::iterator const& collision, soa::Filtered const& tracks, V0sWithID const& v0s, aod::BCsWithTimestamps const&) + void processStandardWithCorrecteddEdx(Colls::iterator const& collision, soa::Filtered const& tracks, V0sWithID const& v0s, CascsWithID const& cascs, aod::BCsWithTimestamps const&) { /// Check event slection if (!isEventSelected(collision, tracks)) { @@ -514,7 +514,21 @@ struct TreeWriterTpcV0 { } } } - } /// process Standard + + /// Loop over cascade candidates + for (const auto& casc : cascs) { + auto bachTrack = casc.bachelor_as>(); + if (casc.cascaddid() == kUndef) { + continue; + } + // Omega and antiomega + if (static_cast(bachTrack.pidbit() & (1 << kOmega)) || static_cast(bachTrack.pidbit() & (1 << kAntiOmega))) { + if (downsampleTsalisCharged(bachTrack.pt(), downsamplingTsalisKaons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Kaon], maxPt4dwnsmplTsalisKaons)) { + fillSkimmedV0Table(casc, bachTrack, collision, bachTrack.tpcNSigmaKa(), bachTrack.tofNSigmaKa(), bachTrack.tpcExpSignalKa(bachTrack.tpcSignal()), o2::track::PID::Kaon, runnumber, dwnSmplFactor_Ka, hadronicRate); + } + } + } + } /// process StandardWithCorrecteddEdx PROCESS_SWITCH(TreeWriterTpcV0, processStandardWithCorrecteddEdx, "Standard V0 Samples for PID with corrected dEdx", false); Preslice perCollisionTracks = aod::track::collisionId; From 831132dbeac52c179ac8a3d12c466c74e86ed417 Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Wed, 10 Sep 2025 18:06:10 +0200 Subject: [PATCH 16/18] extend dev to other process functions --- DPG/Tasks/TPC/tpcSkimsTableCreator.cxx | 113 ++++++++++++++++++++++++- 1 file changed, 109 insertions(+), 4 deletions(-) diff --git a/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx b/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx index f3dd6e9e9e3..136af7ab61c 100644 --- a/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx +++ b/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx @@ -533,7 +533,8 @@ struct TreeWriterTpcV0 { Preslice perCollisionTracks = aod::track::collisionId; Preslice perCollisionV0s = aod::v0data::collisionId; - void processWithdEdxTrQA(Colls const& collisions, Trks const& myTracks, V0sWithID const& myV0s, aod::BCsWithTimestamps const&, aod::TracksQAVersion const& tracksQA) + Preslice perCollisionCascs = aod::cascdata::collisionId; + void processWithdEdxTrQA(Colls const& collisions, Trks const& myTracks, V0sWithID const& myV0s, CascsWithID const& myCascs, aod::BCsWithTimestamps const&, aod::TracksQAVersion const& tracksQA) { std::vector labelTrack2TrackQA; labelTrack2TrackQA.clear(); @@ -546,6 +547,7 @@ struct TreeWriterTpcV0 { for (const auto& collision : collisions) { auto tracks = myTracks.sliceBy(perCollisionTracks, collision.globalIndex()); auto v0s = myV0s.sliceBy(perCollisionV0s, collision.globalIndex()); + auto cascs = myCascs.sliceBy(perCollisionCascs, collision.globalIndex()); /// Check event slection if (!isEventSelected(collision, tracks)) { continue; @@ -621,12 +623,37 @@ struct TreeWriterTpcV0 { } } } + + /// Loop over cascade candidates + for (const auto& casc : cascs) { + auto bachTrack = casc.bachelor_as(); + if (casc.cascaddid() == kUndef) { + continue; + } + + aod::TracksQA bachTrackQA; + bool existBachTrkQA; + if (labelTrack2TrackQA[bachTrack.globalIndex()] != -1) { + bachTrackQA = tracksQA.iteratorAt(labelTrack2TrackQA[bachTrack.globalIndex()]); + existBachTrkQA = true; + } else { + bachTrackQA = tracksQA.iteratorAt(0); + existBachTrkQA = false; + } + + // Omega and antiomega + if (static_cast(bachTrack.pidbit() & (1 << kOmega)) || static_cast(bachTrack.pidbit() & (1 << kAntiOmega))) { + if (downsampleTsalisCharged(bachTrack.pt(), downsamplingTsalisKaons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Kaon], maxPt4dwnsmplTsalisKaons)) { + fillSkimmedV0TableWithdEdxTrQA(casc, bachTrack, bachTrackQA, existBachTrkQA, collision, bachTrack.tpcNSigmaKa(), bachTrack.tofNSigmaKa(), bachTrack.tpcExpSignalKa(bachTrack.tpcSignal()), o2::track::PID::Kaon, runnumber, dwnSmplFactor_Ka, hadronicRate); + } + } + } } } /// process with dEdx from TrackQA PROCESS_SWITCH(TreeWriterTpcV0, processWithdEdxTrQA, "Standard V0 Samples with dEdx from Track QA for PID", false); Preslice perCollisionTracksWithNewDEdx = aod::track::collisionId; - void processWithdEdxTrQAWithCorrecteddEdx(Colls const& collisions, TrksWithDEdxCorrection const& myTracks, V0sWithID const& myV0s, aod::BCsWithTimestamps const&, aod::TracksQAVersion const& tracksQA) + void processWithdEdxTrQAWithCorrecteddEdx(Colls const& collisions, TrksWithDEdxCorrection const& myTracks, V0sWithID const& myV0s, CascsWithID const& myCascs, aod::BCsWithTimestamps const&, aod::TracksQAVersion const& tracksQA) { std::vector labelTrack2TrackQA; labelTrack2TrackQA.clear(); @@ -639,6 +666,7 @@ struct TreeWriterTpcV0 { for (const auto& collision : collisions) { auto tracks = myTracks.sliceBy(perCollisionTracksWithNewDEdx, collision.globalIndex()); auto v0s = myV0s.sliceBy(perCollisionV0s, collision.globalIndex()); + auto cascs = myCascs.sliceBy(perCollisionCascs, collision.globalIndex()); /// Check event slection if (!isEventSelected(collision, tracks)) { continue; @@ -714,11 +742,36 @@ struct TreeWriterTpcV0 { } } } + + /// Loop over cascade candidates + for (const auto& casc : cascs) { + auto bachTrack = casc.bachelor_as(); + if (casc.cascaddid() == kUndef) { + continue; + } + + aod::TracksQA bachTrackQA; + bool existBachTrkQA; + if (labelTrack2TrackQA[bachTrack.globalIndex()] != -1) { + bachTrackQA = tracksQA.iteratorAt(labelTrack2TrackQA[bachTrack.globalIndex()]); + existBachTrkQA = true; + } else { + bachTrackQA = tracksQA.iteratorAt(0); + existBachTrkQA = false; + } + + // Omega and antiomega + if (static_cast(bachTrack.pidbit() & (1 << kOmega)) || static_cast(bachTrack.pidbit() & (1 << kAntiOmega))) { + if (downsampleTsalisCharged(bachTrack.pt(), downsamplingTsalisKaons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Kaon], maxPt4dwnsmplTsalisKaons)) { + fillSkimmedV0TableWithdEdxTrQA(casc, bachTrack, bachTrackQA, existBachTrkQA, collision, bachTrack.tpcNSigmaKa(), bachTrack.tofNSigmaKa(), bachTrack.tpcExpSignalKa(bachTrack.tpcSignal()), o2::track::PID::Kaon, runnumber, dwnSmplFactor_Ka, hadronicRate); + } + } + } } } /// process with dEdx from TrackQA PROCESS_SWITCH(TreeWriterTpcV0, processWithdEdxTrQAWithCorrecteddEdx, "Standard V0 Samples with dEdx from Track QA for PID with corrected dEdx", false); - void processWithTrQA(Colls const& collisions, Trks const& myTracks, V0sWithID const& myV0s, MyBCTable const&, aod::TracksQAVersion const& tracksQA) + void processWithTrQA(Colls const& collisions, Trks const& myTracks, V0sWithID const& myV0s, CascsWithID const& myCascs, MyBCTable const&, aod::TracksQAVersion const& tracksQA) { std::vector labelTrack2TrackQA; labelTrack2TrackQA.clear(); @@ -731,6 +784,7 @@ struct TreeWriterTpcV0 { for (const auto& collision : collisions) { auto tracks = myTracks.sliceBy(perCollisionTracks, collision.globalIndex()); auto v0s = myV0s.sliceBy(perCollisionV0s, collision.globalIndex()); + auto cascs = myCascs.sliceBy(perCollisionCascs, collision.globalIndex()); /// Check event slection if (!isEventSelected(collision, tracks)) { continue; @@ -809,11 +863,36 @@ struct TreeWriterTpcV0 { } } } + + /// Loop over cascade candidates + for (const auto& casc : cascs) { + auto bachTrack = casc.bachelor_as(); + if (casc.cascaddid() == kUndef) { + continue; + } + + aod::TracksQA bachTrackQA; + bool existBachTrkQA; + if (labelTrack2TrackQA[bachTrack.globalIndex()] != -1) { + bachTrackQA = tracksQA.iteratorAt(labelTrack2TrackQA[bachTrack.globalIndex()]); + existBachTrkQA = true; + } else { + bachTrackQA = tracksQA.iteratorAt(0); + existBachTrkQA = false; + } + + // Omega and antiomega + if (static_cast(bachTrack.pidbit() & (1 << kOmega)) || static_cast(bachTrack.pidbit() & (1 << kAntiOmega))) { + if (downsampleTsalisCharged(bachTrack.pt(), downsamplingTsalisKaons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Kaon], maxPt4dwnsmplTsalisKaons)) { + fillSkimmedV0TableWithTrQA(casc, bachTrack, bachTrackQA, existBachTrkQA, collision, bachTrack.tpcNSigmaKa(), bachTrack.tofNSigmaKa(), bachTrack.tpcExpSignalKa(bachTrack.tpcSignal()), o2::track::PID::Kaon, runnumber, dwnSmplFactor_Ka, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } + } + } } } /// process with TrackQA PROCESS_SWITCH(TreeWriterTpcV0, processWithTrQA, "Standard V0 Samples with Track QA for PID", false); - void processWithTrQAWithCorrecteddEdx(Colls const& collisions, TrksWithDEdxCorrection const& myTracks, V0sWithID const& myV0s, MyBCTable const&, aod::TracksQAVersion const& tracksQA) + void processWithTrQAWithCorrecteddEdx(Colls const& collisions, TrksWithDEdxCorrection const& myTracks, V0sWithID const& myV0s, CascsWithID const& myCascs, MyBCTable const&, aod::TracksQAVersion const& tracksQA) { std::vector labelTrack2TrackQA; labelTrack2TrackQA.clear(); @@ -826,6 +905,7 @@ struct TreeWriterTpcV0 { for (const auto& collision : collisions) { auto tracks = myTracks.sliceBy(perCollisionTracksWithNewDEdx, collision.globalIndex()); auto v0s = myV0s.sliceBy(perCollisionV0s, collision.globalIndex()); + auto cascs = myCascs.sliceBy(perCollisionCascs, collision.globalIndex()); /// Check event slection if (!isEventSelected(collision, tracks)) { continue; @@ -904,6 +984,31 @@ struct TreeWriterTpcV0 { } } } + + /// Loop over cascade candidates + for (const auto& casc : cascs) { + auto bachTrack = casc.bachelor_as(); + if (casc.cascaddid() == kUndef) { + continue; + } + + aod::TracksQA bachTrackQA; + bool existBachTrkQA; + if (labelTrack2TrackQA[bachTrack.globalIndex()] != -1) { + bachTrackQA = tracksQA.iteratorAt(labelTrack2TrackQA[bachTrack.globalIndex()]); + existBachTrkQA = true; + } else { + bachTrackQA = tracksQA.iteratorAt(0); + existBachTrkQA = false; + } + + // Omega and antiomega + if (static_cast(bachTrack.pidbit() & (1 << kOmega)) || static_cast(bachTrack.pidbit() & (1 << kAntiOmega))) { + if (downsampleTsalisCharged(bachTrack.pt(), downsamplingTsalisKaons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Kaon], maxPt4dwnsmplTsalisKaons)) { + fillSkimmedV0TableWithTrQA(casc, bachTrack, bachTrackQA, existBachTrkQA, collision, bachTrack.tpcNSigmaKa(), bachTrack.tofNSigmaKa(), bachTrack.tpcExpSignalKa(bachTrack.tpcSignal()), o2::track::PID::Kaon, runnumber, dwnSmplFactor_Ka, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } + } + } } } /// process with TrackQA PROCESS_SWITCH(TreeWriterTpcV0, processWithTrQAWithCorrecteddEdx, "Standard V0 Samples with Track QA for PID with corrected dEdx", false); From 034632207a7f60dbc24caa2103c162ca0e872354 Mon Sep 17 00:00:00 2001 From: ALICE Builder Date: Wed, 10 Sep 2025 18:34:57 +0200 Subject: [PATCH 17/18] Please consider the following formatting changes (#7) --- PWGDQ/Tasks/v0selector.cxx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/PWGDQ/Tasks/v0selector.cxx b/PWGDQ/Tasks/v0selector.cxx index ec420c9c2d9..f37fd9c62f4 100644 --- a/PWGDQ/Tasks/v0selector.cxx +++ b/PWGDQ/Tasks/v0selector.cxx @@ -315,7 +315,7 @@ struct v0selector { const auto& negTrack = V0.negTrack_as(); bool isRejectV0{false}; - for(const auto& prong : {posTrack, negTrack}) { + for (const auto& prong : {posTrack, negTrack}) { isRejectV0 = isRejectV0 || std::fabs(prong.eta()) > 0.9; isRejectV0 = isRejectV0 || prong.tpcNClsCrossedRows() < mincrossedrows; isRejectV0 = isRejectV0 || prong.tpcChi2NCl() > maxchi2tpc; @@ -324,7 +324,8 @@ struct v0selector { } isRejectV0 = isRejectV0 || (posTrack.sign() * negTrack.sign() > 0); - if (isRejectV0) continue; + if (isRejectV0) + continue; float V0dca = V0.dcaV0daughters(); float V0CosinePA = V0.v0cosPA(); @@ -442,7 +443,7 @@ struct v0selector { const auto& bachelor = casc.bachelor_as(); bool isRejectCascade{false}; - for(const auto& prong : {posTrack, negTrack, bachelor}) { + for (const auto& prong : {posTrack, negTrack, bachelor}) { isRejectCascade = isRejectCascade || std::fabs(prong.eta()) > 0.9; isRejectCascade = isRejectCascade || prong.tpcNClsCrossedRows() < mincrossedrows; isRejectCascade = isRejectCascade || prong.tpcChi2NCl() > maxchi2tpc; @@ -451,7 +452,8 @@ struct v0selector { } isRejectCascade = isRejectCascade || (posTrack.sign() * negTrack.sign() > 0); - if (isRejectCascade) continue; + if (isRejectCascade) + continue; if (fillhisto) { registry.fill(HIST("hCascCandidate"), 2); From 640adca639f77cd142689e93c6e9b72baa8807f1 Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Fri, 12 Sep 2025 11:26:46 +0200 Subject: [PATCH 18/18] add lower-value qT cut for Omega near to Xi location --- PWGDQ/Tasks/v0selector.cxx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/PWGDQ/Tasks/v0selector.cxx b/PWGDQ/Tasks/v0selector.cxx index f37fd9c62f4..1af3fb2cf0e 100644 --- a/PWGDQ/Tasks/v0selector.cxx +++ b/PWGDQ/Tasks/v0selector.cxx @@ -99,6 +99,7 @@ struct v0selector { Configurable cutAPOmegaDown3{"cutAPOmegaDown3", 0.16, "cutAPOmegaDown3"}; Configurable cutAlphaOmegaHigh{"cutAlphaOmegaHigh", 0.358, "cutAlphaOmegaHigh"}; Configurable cutAlphaOmegaLow{"cutAlphaOmegaLow", 0., "cutAlphaOmegaLow"}; + Configurable cutQTOmegaLowOuterArc{"cutQTOmegaLowOuterArc", 0.14, "cutQTOmegaLowOuterArc"}; Configurable cutMassOmegaHigh{"cutMassOmegaHigh", 1.677, "cutMassOmegaHigh"}; Configurable cutMassOmegaLow{"cutMassOmegaLow", 1.667, "cutMassOmegaLow"}; Configurable cutMassCascV0Low{"cutMassCascV0Low", 1.110, "cutMassCascV0Low"}; @@ -189,6 +190,10 @@ struct v0selector { return kUndef; } + if (alpha > cutAPOmegaUp2 && qt < cutQTOmegaLowOuterArc) { + return kUndef; + } + if (isAlphaPos) { return kOmega; } else {