diff --git a/PWGHF/Core/HfMlResponseXic0ToXiPi.h b/PWGHF/Core/HfMlResponseXic0ToXiPi.h new file mode 100644 index 00000000000..88c402617f8 --- /dev/null +++ b/PWGHF/Core/HfMlResponseXic0ToXiPi.h @@ -0,0 +1,131 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file HfMlResponseXic0ToXiPi.h +/// \brief Class to compute the ML response for Ξc^0 → Ξ∓ π± analysis selections +/// \author Tao Fang , Central China Normal University + +#ifndef PWGHF_CORE_HFMLRESPONSEXIC0TOXIPI_H_ +#define PWGHF_CORE_HFMLRESPONSEXIC0TOXIPI_H_ + +#include "PWGHF/Core/HfMlResponse.h" + +#include "Tools/ML/MlResponse.h" + +#include +#include + +// Fill the map of available input features +// the key is the feature's name (std::string) +// the value is the corresponding value in EnumInputFeatures +#define FILL_MAP_XIC0TOXIPI(FEATURE) \ + { \ + #FEATURE, static_cast(InputFeaturesXic0ToXiPi::FEATURE) \ + } + +// Check if the index of mCachedIndices (index associated to a FEATURE) +// matches the entry in EnumInputFeatures associated to this FEATURE +// if so, the inputFeatures vector is filled with the FEATURE's value +// by calling the corresponding GETTER from OBJECT +#define CHECK_AND_FILL_VEC_XIC0TOXIPI_FULL(OBJECT, FEATURE, GETTER) \ + case static_cast(InputFeaturesXic0ToXiPi::FEATURE): { \ + inputFeatures.emplace_back(OBJECT.GETTER()); \ + break; \ + } + +// where OBJECT is named candidate and FEATURE = GETTER +#define CHECK_AND_FILL_VEC_XIC0TOXIPI(GETTER) \ + case static_cast(InputFeaturesXic0ToXiPi::GETTER): { \ + inputFeatures.emplace_back(candidate.GETTER()); \ + break; \ + } + +namespace o2::analysis +{ + +enum class InputFeaturesXic0ToXiPi : uint8_t { + tpcNSigmaPiFromLambda, + tpcNSigmaPiFromCasc, + tpcNSigmaPiFromCharmBaryon, + dcaCascDau, + dcaCharmBaryonDau, + cosPACharmBaryon, + cosPACasc, + cosPAV0, + impactParBachFromCharmBaryonXY, + impactParCascXY +}; + +template +class HfMlResponseXic0ToXiPi : public HfMlResponse +{ + public: + /// Default constructor + HfMlResponseXic0ToXiPi() = default; + /// Default destructor + virtual ~HfMlResponseXic0ToXiPi() = default; + + /// Method to get the input features vector needed for ML inference + /// \param candidate is the Xic0 candidate + /// \return inputFeatures vector + template + // std::vector getInputFeatures(T1 const& candidate) + std::vector getInputFeatures(T1 const& candidate, T2 const& lamProngPi, T2 const& cascProngPi, T3 const& charmBaryonProngPi) + { + std::vector inputFeatures; + + for (const auto& idx : MlResponse::mCachedIndices) { + switch (idx) { + // PID variables + CHECK_AND_FILL_VEC_XIC0TOXIPI_FULL(lamProngPi, tpcNSigmaPiFromLambda, tpcNSigmaPi); + CHECK_AND_FILL_VEC_XIC0TOXIPI_FULL(cascProngPi, tpcNSigmaPiFromCasc, tpcNSigmaPi); + CHECK_AND_FILL_VEC_XIC0TOXIPI_FULL(charmBaryonProngPi, tpcNSigmaPiFromCharmBaryon, tpcNSigmaPi); + // DCA + CHECK_AND_FILL_VEC_XIC0TOXIPI(dcaCascDau); + CHECK_AND_FILL_VEC_XIC0TOXIPI(dcaCharmBaryonDau); + // CosPA + CHECK_AND_FILL_VEC_XIC0TOXIPI(cosPACharmBaryon); + CHECK_AND_FILL_VEC_XIC0TOXIPI(cosPACasc); + CHECK_AND_FILL_VEC_XIC0TOXIPI(cosPAV0); + // ImpactPar + CHECK_AND_FILL_VEC_XIC0TOXIPI(impactParBachFromCharmBaryonXY); + CHECK_AND_FILL_VEC_XIC0TOXIPI(impactParCascXY); + } + } + + return inputFeatures; + } + + protected: + /// Method to fill the map of available input features + void setAvailableInputFeatures() + { + MlResponse::mAvailableInputFeatures = { + FILL_MAP_XIC0TOXIPI(tpcNSigmaPiFromLambda), + FILL_MAP_XIC0TOXIPI(tpcNSigmaPiFromCasc), + FILL_MAP_XIC0TOXIPI(tpcNSigmaPiFromCharmBaryon), + FILL_MAP_XIC0TOXIPI(dcaCascDau), + FILL_MAP_XIC0TOXIPI(dcaCharmBaryonDau), + FILL_MAP_XIC0TOXIPI(cosPACharmBaryon), + FILL_MAP_XIC0TOXIPI(cosPACasc), + FILL_MAP_XIC0TOXIPI(cosPAV0), + FILL_MAP_XIC0TOXIPI(impactParBachFromCharmBaryonXY), + FILL_MAP_XIC0TOXIPI(impactParCascXY)}; + } +}; + +} // namespace o2::analysis + +#undef FILL_MAP_XIC0TOXIPI +#undef CHECK_AND_FILL_VEC_XIC0TOXIPI_FULL +#undef CHECK_AND_FILL_VEC_XIC0TOXIPI + +#endif // PWGHF_CORE_HFMLRESPONSEXIC0TOXIPI_H_ diff --git a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx index a7c954f9720..4aa872b7e4e 100644 --- a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx +++ b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx @@ -133,7 +133,7 @@ struct HfTaskFlowCharmHadrons { using CandXicData = soa::Filtered>; using CandXicDataWMl = soa::Filtered>; using CandXic0Data = soa::Filtered>; - using CandXic0DataWMl = soa::Filtered>; + using CandXic0DataWMl = soa::Filtered>; using CandD0DataWMl = soa::Filtered>; using CandD0Data = soa::Filtered>; using CollsWithQvecs = soa::Join; diff --git a/PWGHF/D2H/Tasks/taskXic0ToXiPi.cxx b/PWGHF/D2H/Tasks/taskXic0ToXiPi.cxx index 55bfe924842..5c923dc4309 100644 --- a/PWGHF/D2H/Tasks/taskXic0ToXiPi.cxx +++ b/PWGHF/D2H/Tasks/taskXic0ToXiPi.cxx @@ -10,7 +10,7 @@ // or submit itself to any jurisdiction. /// \file taskXic0ToXiPi.cxx -/// \brief Task for Ξc^0 → Ξ∓ π± Kf analysis +/// \brief Task for Ξc^0 → Ξ∓ π± analysis /// \author Tao Fang , Central China Normal University /// \author Ran Tu , Fudan University @@ -62,11 +62,15 @@ struct HfTaskXic0ToXiPi { using TracksMc = soa::Join; + using Xic0Cands = soa::Filtered>; using Xic0CandsKF = soa::Filtered>; + using Xic0CandsMc = soa::Filtered>; using Xic0CandsMcKF = soa::Filtered>; - using Xic0CandsMlKF = soa::Filtered>; - using Xic0CandsMlMcKF = soa::Filtered>; + using Xic0CandsMl = soa::Filtered>; + using Xic0CandsMlKF = soa::Filtered>; + using Xic0CandsMlMc = soa::Filtered>; + using Xic0CandsMlMcKF = soa::Filtered>; using Xic0Gen = soa::Filtered>; @@ -78,7 +82,9 @@ struct HfTaskXic0ToXiPi { Filter filterSelectXic0Candidates = aod::hf_sel_toxipi::resultSelections == true; Filter filterXicMatchedRec = nabs(aod::hf_cand_xic0_omegac0::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_xic0_omegac0::DecayType::XiczeroToXiPi)); Filter filterXicMatchedGen = nabs(aod::hf_cand_xic0_omegac0::flagMcMatchGen) == static_cast(BIT(aod::hf_cand_xic0_omegac0::DecayType::XiczeroToXiPi)); + Preslice candXicPerCollision = aod::hf_cand_xic0_omegac0::collisionId; Preslice candXicKFPerCollision = aod::hf_cand_xic0_omegac0::collisionId; + Preslice candXicMlPerCollision = aod::hf_cand_xic0_omegac0::collisionId; Preslice candXicKFMlPerCollision = aod::hf_cand_xic0_omegac0::collisionId; PresliceUnsorted colPerMcCollision = aod::mccollisionlabel::mcCollisionId; @@ -100,7 +106,9 @@ struct HfTaskXic0ToXiPi { void init(InitContext&) { - std::array doprocess{doprocessDataWithKFParticle, doprocessMcWithKFParticle, doprocessDataWithKFParticleMl, doprocessMcWithKFParticleMl, doprocessDataWithKFParticleFT0C, doprocessDataWithKFParticleMlFT0C, doprocessDataWithKFParticleFT0M, doprocessDataWithKFParticleMlFT0M}; + std::array doprocess{doprocessDataWithDCAFitter, doprocessDataWithDCAFitterMl, doprocessDataWithDCAFitterFT0C, doprocessDataWithDCAFitterFT0M, doprocessDataWithDCAFitterMlFT0C, doprocessDataWithDCAFitterMlFT0M, + doprocessDataWithKFParticle, doprocessDataWithKFParticleMl, doprocessDataWithKFParticleFT0C, doprocessDataWithKFParticleFT0M, doprocessDataWithKFParticleMlFT0C, doprocessDataWithKFParticleMlFT0M, + doprocessMcWithKFParticle, doprocessMcWithKFParticleMl, doprocessMcWithDCAFitter, doprocessMcWithDCAFitterMl}; if ((std::accumulate(doprocess.begin(), doprocess.end(), 0)) != 1) { LOGP(fatal, "One and only one process function should be enabled at a time."); } @@ -150,75 +158,50 @@ struct HfTaskXic0ToXiPi { } } - template - void processData(const CandType& candidates, CollType const&) + template + void processDataCent(const CandType& candidate, CollType const& collision) { - for (const auto& candidate : candidates) { - if (candidate.resultSelections() != true) { - continue; - } - if (yCandRecMax >= 0. && std::abs(candidate.kfRapXic()) > yCandRecMax) { - continue; - } - - if constexpr (ApplyMl) { - registry.fill(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsXic0Type"), candidate.mlProbToXiPi()[0], candidate.invMassCharmBaryon(), candidate.kfptXic(), candidate.kfRapXic()); - } else { - registry.fill(HIST("hMassVsPtVsPtBVsYVsOriginVsXic0Type"), candidate.invMassCharmBaryon(), candidate.kfptXic(), candidate.kfRapXic()); - } + if (candidate.resultSelections() != true) { + return; + } + double yCharmBaryon; + if constexpr (UseKfParticle) { + yCharmBaryon = candidate.kfRapXic(); + } else { + yCharmBaryon = candidate.y(o2::constants::physics::MassXiC0); + } + if (yCandRecMax >= 0. && std::abs(yCharmBaryon) > yCandRecMax) { + return; } - } - - template - void processDataCent(const CandType& candidates, CollType const& collisions) - { - for (const auto& collision : collisions) { - - auto thisCollId = collision.globalIndex(); - auto groupedXicCandidates = ApplyMl - ? candidates.sliceBy(candXicKFMlPerCollision, thisCollId) - : candidates.sliceBy(candXicKFPerCollision, thisCollId); - // auto numPvContributors = collision.numContrib(); - for (const auto& candidate : groupedXicCandidates) { - if (candidate.resultSelections() != true) { - continue; - } - if (yCandRecMax >= 0. && std::abs(candidate.kfRapXic()) > yCandRecMax) { - continue; - } - - auto numPvContributors = candidate.template collision_as().numContrib(); - float centrality = -999.f; - if constexpr (UseCentrality) { - auto const& collision = candidate.template collision_as(); - centrality = o2::hf_centrality::getCentralityColl(collision); - } - double const kfptXic = RecoDecay::sqrtSumOfSquares(candidate.pxCharmBaryon(), candidate.pyCharmBaryon()); - double const kfptPiFromXic = RecoDecay::sqrtSumOfSquares(candidate.pxBachFromCharmBaryon(), candidate.pyBachFromCharmBaryon()); - if constexpr (ApplyMl) { - registry.fill(HIST("hBdtScoreVsMassVsPtVsYVsCentVsPtPion"), - candidate.mlProbToXiPi()[0], - candidate.invMassCharmBaryon(), - kfptXic, - candidate.kfRapXic(), - centrality, - kfptPiFromXic, - numPvContributors); - } else { - registry.fill(HIST("hMassVsPtVsYVsCentVsPtPion"), - candidate.invMassCharmBaryon(), - kfptXic, - candidate.kfRapXic(), - centrality, - kfptPiFromXic, - numPvContributors); - } - } + auto numPvContributors = collision.numContrib(); + float centrality = -999.f; + if constexpr (UseCentrality) { + centrality = o2::hf_centrality::getCentralityColl(collision); + } + double const ptXic = RecoDecay::pt(candidate.pxCharmBaryon(), candidate.pyCharmBaryon()); + double const ptPiFromXic = RecoDecay::pt(candidate.pxBachFromCharmBaryon(), candidate.pyBachFromCharmBaryon()); + if constexpr (ApplyMl) { + registry.fill(HIST("hBdtScoreVsMassVsPtVsYVsCentVsPtPion"), + candidate.mlProbToXiPi()[0], + candidate.invMassCharmBaryon(), + ptXic, + yCharmBaryon, + centrality, + ptPiFromXic, + numPvContributors); + } else { + registry.fill(HIST("hMassVsPtVsYVsCentVsPtPion"), + candidate.invMassCharmBaryon(), + ptXic, + yCharmBaryon, + centrality, + ptPiFromXic, + numPvContributors); } } - template + template void processMc(const CandType& candidates, Xic0Gen const& mcParticles, TracksMc const&, @@ -230,18 +213,24 @@ struct HfTaskXic0ToXiPi { if (candidate.resultSelections() != true) { continue; } - if (yCandRecMax >= 0. && std::abs(candidate.kfRapXic()) > yCandRecMax) { + double yCharmBaryon; + if constexpr (UseKfParticle) { + yCharmBaryon = candidate.kfRapXic(); + } else { + yCharmBaryon = candidate.y(o2::constants::physics::MassXiC0); + } + if (yCandRecMax >= 0. && std::abs(yCharmBaryon) > yCandRecMax) { continue; } auto numPvContributors = candidate.template collision_as().numContrib(); - double const kfptXic = RecoDecay::sqrtSumOfSquares(candidate.pxCharmBaryon(), candidate.pyCharmBaryon()); + double const ptXic = RecoDecay::pt(candidate.pxCharmBaryon(), candidate.pyCharmBaryon()); if constexpr (ApplyMl) { registry.fill(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsXic0Type"), candidate.mlProbToXiPi()[0], candidate.invMassCharmBaryon(), - kfptXic, - candidate.kfRapXic(), + ptXic, + yCharmBaryon, candidate.ptBhadMotherPart(), candidate.originMcRec(), candidate.flagMcMatchRec(), @@ -249,8 +238,8 @@ struct HfTaskXic0ToXiPi { } else { registry.fill(HIST("hMassVsPtVsPtBVsYVsOriginVsXic0Type"), candidate.invMassCharmBaryon(), - kfptXic, - candidate.kfRapXic(), + ptXic, + yCharmBaryon, candidate.ptBhadMotherPart(), candidate.originMcRec(), candidate.flagMcMatchRec(), @@ -292,47 +281,171 @@ struct HfTaskXic0ToXiPi { } } + void processDataWithDCAFitter(Xic0Cands const& candidates, + CollisionsWithEvSels const& collisions) + { + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto groupedXicCandidates = candidates.sliceBy(candXicPerCollision, thisCollId); + for (const auto& candidate : groupedXicCandidates) { + processDataCent(candidate, collision); + } + } + } + PROCESS_SWITCH(HfTaskXic0ToXiPi, processDataWithDCAFitter, "process HfTaskXic0ToXiPi with DCAFitter", true); + void processDataWithKFParticle(Xic0CandsKF const& candidates, CollisionsWithEvSels const& collisions) { - processDataCent(candidates, collisions); + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto groupedXicCandidates = candidates.sliceBy(candXicKFPerCollision, thisCollId); + for (const auto& candidate : groupedXicCandidates) { + processDataCent(candidate, collision); + } + } } - PROCESS_SWITCH(HfTaskXic0ToXiPi, processDataWithKFParticle, "process HfTaskXic0ToXiPi with KFParticle", true); + PROCESS_SWITCH(HfTaskXic0ToXiPi, processDataWithKFParticle, "process HfTaskXic0ToXiPi with KFParticle", true); + + void processDataWithDCAFitterMl(Xic0CandsMl const& candidates, + CollisionsWithEvSels const& collisions) + { + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto groupedXicCandidates = candidates.sliceBy(candXicMlPerCollision, thisCollId); + for (const auto& candidate : groupedXicCandidates) { + processDataCent(candidate, collision); + } + } + } + PROCESS_SWITCH(HfTaskXic0ToXiPi, processDataWithDCAFitterMl, "process HfTaskXic0ToXiPi with DCAFitter and ML selections", false); void processDataWithKFParticleMl(Xic0CandsMlKF const& candidates, CollisionsWithEvSels const& collisions) { - processDataCent(candidates, collisions); + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto groupedXicCandidates = candidates.sliceBy(candXicKFMlPerCollision, thisCollId); + for (const auto& candidate : groupedXicCandidates) { + processDataCent(candidate, collision); + } + } } - PROCESS_SWITCH(HfTaskXic0ToXiPi, processDataWithKFParticleMl, "process HfTaskXic0ToXiPi with KFParticle and ML selections", false); + PROCESS_SWITCH(HfTaskXic0ToXiPi, processDataWithKFParticleMl, "process HfTaskXic0ToXiPi with KFParticle and ML selections", false); + + void processDataWithDCAFitterFT0C(Xic0Cands const& candidates, + CollisionsWithFT0C const& collisions) + { + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto groupedXicCandidates = candidates.sliceBy(candXicPerCollision, thisCollId); + for (const auto& candidate : groupedXicCandidates) { + processDataCent(candidate, collision); + } + } + } + PROCESS_SWITCH(HfTaskXic0ToXiPi, processDataWithDCAFitterFT0C, "process HfTaskXic0ToXiPi with DCAFitter and with FT0C centrality", false); void processDataWithKFParticleFT0C(Xic0CandsKF const& candidates, CollisionsWithFT0C const& collisions) { - processDataCent(candidates, collisions); + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto groupedXicCandidates = candidates.sliceBy(candXicKFPerCollision, thisCollId); + for (const auto& candidate : groupedXicCandidates) { + processDataCent(candidate, collision); + } + } } - PROCESS_SWITCH(HfTaskXic0ToXiPi, processDataWithKFParticleFT0C, "process HfTaskXic0ToXiPi with KFParticle and with FT0C centrality", false); + PROCESS_SWITCH(HfTaskXic0ToXiPi, processDataWithKFParticleFT0C, "process HfTaskXic0ToXiPi with KFParticle and with FT0C centrality", false); + + void processDataWithDCAFitterFT0M(Xic0Cands const& candidates, + CollisionsWithFT0M const& collisions) + { + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto groupedXicCandidates = candidates.sliceBy(candXicPerCollision, thisCollId); + for (const auto& candidate : groupedXicCandidates) { + processDataCent(candidate, collision); + } + } + } + PROCESS_SWITCH(HfTaskXic0ToXiPi, processDataWithDCAFitterFT0M, "process HfTaskXic0ToXiPi with DCAFitter and with FT0M centrality", false); void processDataWithKFParticleFT0M(Xic0CandsKF const& candidates, CollisionsWithFT0M const& collisions) { - processDataCent(candidates, collisions); + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto groupedXicCandidates = candidates.sliceBy(candXicKFPerCollision, thisCollId); + for (const auto& candidate : groupedXicCandidates) { + processDataCent(candidate, collision); + } + } + } + PROCESS_SWITCH(HfTaskXic0ToXiPi, processDataWithKFParticleFT0M, "process HfTaskXic0ToXiPi with KFParticle and with FT0M centrality", false); + + void processDataWithDCAFitterMlFT0C(Xic0CandsMl const& candidates, + CollisionsWithFT0C const& collisions) + { + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto groupedXicCandidates = candidates.sliceBy(candXicMlPerCollision, thisCollId); + for (const auto& candidate : groupedXicCandidates) { + processDataCent(candidate, collision); + } + } } - PROCESS_SWITCH(HfTaskXic0ToXiPi, processDataWithKFParticleFT0M, "process HfTaskXic0ToXiPi with KFParticle and with FT0M centrality", false); + PROCESS_SWITCH(HfTaskXic0ToXiPi, processDataWithDCAFitterMlFT0C, "process HfTaskXic0ToXiPi with DCAFitter and ML selections and with FT0C centrality", false); void processDataWithKFParticleMlFT0C(Xic0CandsMlKF const& candidates, CollisionsWithFT0C const& collisions) { - processDataCent(candidates, collisions); + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto groupedXicCandidates = candidates.sliceBy(candXicKFMlPerCollision, thisCollId); + for (const auto& candidate : groupedXicCandidates) { + processDataCent(candidate, collision); + } + } } - PROCESS_SWITCH(HfTaskXic0ToXiPi, processDataWithKFParticleMlFT0C, "process HfTaskXic0ToXiPi with KFParticle and ML selections and with FT0C centrality", false); + PROCESS_SWITCH(HfTaskXic0ToXiPi, processDataWithKFParticleMlFT0C, "process HfTaskXic0ToXiPi with KFParticle and ML selections and with FT0C centrality", false); + + void processDataWithDCAFitterMlFT0M(Xic0CandsMl const& candidates, + CollisionsWithFT0M const& collisions) + { + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto groupedXicCandidates = candidates.sliceBy(candXicMlPerCollision, thisCollId); + for (const auto& candidate : groupedXicCandidates) { + processDataCent(candidate, collision); + } + } + } + PROCESS_SWITCH(HfTaskXic0ToXiPi, processDataWithDCAFitterMlFT0M, "process HfTaskXic0ToXiPi with DCAFitter and ML selections and with FT0M centrality", false); void processDataWithKFParticleMlFT0M(Xic0CandsMlKF const& candidates, CollisionsWithFT0M const& collisions) { - processDataCent(candidates, collisions); + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto groupedXicCandidates = candidates.sliceBy(candXicKFMlPerCollision, thisCollId); + for (const auto& candidate : groupedXicCandidates) { + processDataCent(candidate, collision); + } + } } - PROCESS_SWITCH(HfTaskXic0ToXiPi, processDataWithKFParticleMlFT0M, "process HfTaskXic0ToXiPi with KFParticle and ML selections and with FT0M centrality", false); + PROCESS_SWITCH(HfTaskXic0ToXiPi, processDataWithKFParticleMlFT0M, "process HfTaskXic0ToXiPi with KFParticle and ML selections and with FT0M centrality", false); + + void processMcWithDCAFitter(Xic0CandsMc const& xic0CandidatesMc, + Xic0Gen const& mcParticles, + TracksMc const& tracks, + CollisionsWithMcLabels const& collisions, + aod::McCollisions const& mcCollisions) + { + processMc(xic0CandidatesMc, mcParticles, tracks, collisions, mcCollisions); + } + PROCESS_SWITCH(HfTaskXic0ToXiPi, processMcWithDCAFitter, "Process MC with KFParticle", false); void processMcWithKFParticle(Xic0CandsMcKF const& xic0CandidatesMcKf, Xic0Gen const& mcParticles, @@ -340,17 +453,27 @@ struct HfTaskXic0ToXiPi { CollisionsWithMcLabels const& collisions, aod::McCollisions const& mcCollisions) { - processMc(xic0CandidatesMcKf, mcParticles, tracks, collisions, mcCollisions); + processMc(xic0CandidatesMcKf, mcParticles, tracks, collisions, mcCollisions); } PROCESS_SWITCH(HfTaskXic0ToXiPi, processMcWithKFParticle, "Process MC with KFParticle", false); + void processMcWithDCAFitterMl(Xic0CandsMlMc const& xic0CandidatesMlMc, + Xic0Gen const& mcParticles, + TracksMc const& tracks, + CollisionsWithMcLabels const& collisions, + aod::McCollisions const& mcCollisions) + { + processMc(xic0CandidatesMlMc, mcParticles, tracks, collisions, mcCollisions); + } + PROCESS_SWITCH(HfTaskXic0ToXiPi, processMcWithDCAFitterMl, "Process MC with KFParticle and ML selections", false); + void processMcWithKFParticleMl(Xic0CandsMlMcKF const& xic0CandidatesMlMcKf, Xic0Gen const& mcParticles, TracksMc const& tracks, CollisionsWithMcLabels const& collisions, aod::McCollisions const& mcCollisions) { - processMc(xic0CandidatesMlMcKf, mcParticles, tracks, collisions, mcCollisions); + processMc(xic0CandidatesMlMcKf, mcParticles, tracks, collisions, mcCollisions); } PROCESS_SWITCH(HfTaskXic0ToXiPi, processMcWithKFParticleMl, "Process MC with KFParticle and ML selections", false); }; diff --git a/PWGHF/DataModel/CandidateReconstructionTables.h b/PWGHF/DataModel/CandidateReconstructionTables.h index 37c96d5627a..addd26ab716 100644 --- a/PWGHF/DataModel/CandidateReconstructionTables.h +++ b/PWGHF/DataModel/CandidateReconstructionTables.h @@ -1633,7 +1633,9 @@ DECLARE_SOA_TABLE(HfCandToXiPi, "AOD", "HFCANDTOXIPI", hf_cand_xic0_omegac0::DcaXYToPvV0Dau0, hf_cand_xic0_omegac0::DcaXYToPvV0Dau1, hf_cand_xic0_omegac0::DcaXYToPvCascDau, hf_cand_xic0_omegac0::DcaZToPvV0Dau0, hf_cand_xic0_omegac0::DcaZToPvV0Dau1, hf_cand_xic0_omegac0::DcaZToPvCascDau, hf_cand_xic0_omegac0::DcaCascDau, hf_cand_xic0_omegac0::DcaV0Dau, hf_cand_xic0_omegac0::DcaCharmBaryonDau, - hf_cand_xic0_omegac0::DecLenCharmBaryon, hf_cand_xic0_omegac0::DecLenCascade, hf_cand_xic0_omegac0::DecLenV0, hf_cand_xic0_omegac0::ErrorDecayLengthCharmBaryon, hf_cand_xic0_omegac0::ErrorDecayLengthXYCharmBaryon); + hf_cand_xic0_omegac0::DecLenCharmBaryon, hf_cand_xic0_omegac0::DecLenCascade, hf_cand_xic0_omegac0::DecLenV0, hf_cand_xic0_omegac0::ErrorDecayLengthCharmBaryon, hf_cand_xic0_omegac0::ErrorDecayLengthXYCharmBaryon, + // dynamic + hf_cand::Y); DECLARE_SOA_TABLE(HfCandToOmegaPi, "AOD", "HFCANDTOOMEGAPI", o2::soa::Index<>, diff --git a/PWGHF/DataModel/CandidateSelectionTables.h b/PWGHF/DataModel/CandidateSelectionTables.h index 125b0fb7286..1f7956aadd4 100644 --- a/PWGHF/DataModel/CandidateSelectionTables.h +++ b/PWGHF/DataModel/CandidateSelectionTables.h @@ -381,7 +381,7 @@ DECLARE_SOA_TABLE(HfSelToXiPiKf, "AOD", "HFSELTOXIPIKF", hf_sel_toxipi::TpcNSigmaPiFromCharmBaryon, hf_sel_toxipi::TpcNSigmaPiFromCasc, hf_sel_toxipi::TpcNSigmaPiFromLambda, hf_sel_toxipi::TpcNSigmaPrFromLambda, hf_sel_toxipi::TofNSigmaPiFromCharmBaryon, hf_sel_toxipi::TofNSigmaPiFromCasc, hf_sel_toxipi::TofNSigmaPiFromLambda, hf_sel_toxipi::TofNSigmaPrFromLambda); -DECLARE_SOA_TABLE(HfMlToXiPiKf, "AOD", "HFMLSELTOXIPIKF", +DECLARE_SOA_TABLE(HfMlToXiPi, "AOD", "HFMLSELTOXIPI", hf_sel_toxipi::MlProbToXiPi); namespace hf_sel_toomegapi diff --git a/PWGHF/TableProducer/CMakeLists.txt b/PWGHF/TableProducer/CMakeLists.txt index 9b28ce9e88d..46364eaf9aa 100644 --- a/PWGHF/TableProducer/CMakeLists.txt +++ b/PWGHF/TableProducer/CMakeLists.txt @@ -184,7 +184,7 @@ o2physics_add_dpl_workflow(candidate-selector-xic0-to-xi-pi-kf o2physics_add_dpl_workflow(candidate-selector-to-xi-pi SOURCES candidateSelectorToXiPi.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(candidate-selector-xic-to-p-k-pi diff --git a/PWGHF/TableProducer/candidateSelectorToXiPi.cxx b/PWGHF/TableProducer/candidateSelectorToXiPi.cxx index 3a53c0532f9..ab13519f62e 100644 --- a/PWGHF/TableProducer/candidateSelectorToXiPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorToXiPi.cxx @@ -12,7 +12,10 @@ /// \file candidateSelectorToXiPi.cxx /// \brief Xic0 and Omegac0 → Xi Pi selection task /// \author Federica Zanone , Heidelberg University +/// \author Tao Fang , Central China Normal University +#include "PWGHF/Core/HfMlResponseXic0ToXiPi.h" +#include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsAnalysis.h" @@ -38,6 +41,8 @@ #include #include +#include +#include using namespace o2; using namespace o2::aod; @@ -54,6 +59,7 @@ enum PidInfoStored { /// Struct for applying Omegac0/Xic0 selection cuts struct HfCandidateSelectorToXiPi { Produces hfSelToXiPi; + Produces hfMlToXiPi; // LF analysis selections Configurable radiusCascMin{"radiusCascMin", 0.6, "Min cascade radius"}; @@ -129,6 +135,25 @@ struct HfCandidateSelectorToXiPi { Configurable nClustersItsInnBarrMin{"nClustersItsInnBarrMin", 1, "Minimum number of ITS clusters in inner barrel requirement for pi <- charm baryon"}; Configurable itsChi2PerClusterMax{"itsChi2PerClusterMax", 36, "Maximum value of chi2 fit over ITS clusters for pi <- charm baryon"}; + // ML inference + Configurable applyMl{"applyMl", true, "Flag to apply ML selections"}; + Configurable> binsPtMl{"binsPtMl", std::vector{hf_cuts_ml::vecBinsPt}, "pT bin limits for ML application"}; + Configurable> cutDirMl{"cutDirMl", std::vector{hf_cuts_ml::vecCutDir}, "Whether to reject score values greater or smaller than the threshold"}; + Configurable> cutsMl{"cutsMl", {hf_cuts_ml::Cuts[0], hf_cuts_ml::NBinsPt, hf_cuts_ml::NCutScores, hf_cuts_ml::labelsPt, hf_cuts_ml::labelsCutScore}, "ML selections per pT bin"}; + Configurable nClassesMl{"nClassesMl", static_cast(hf_cuts_ml::NCutScores), "Number of classes in ML model"}; + Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"feature1", "feature2"}, "Names of ML model input features"}; + + // CCDB configuration + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable> modelPathsCCDB{"modelPathsCCDB", std::vector{"EventFiltering/PWGHF/BDTXic0ToXipiKf"}, "Paths of models on CCDB"}; + Configurable> onnxFileNames{"onnxFileNames", std::vector{"ModelHandler_onnx_Xic0ToXipiKf.onnx"}, "ONNX file names for each pT bin (if not from CCDB full path)"}; + Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB"}; + Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + + o2::analysis::HfMlResponseXic0ToXiPi hfMlResponse; + std::vector outputMlXic0ToXiPi = {}; + o2::ccdb::CcdbApi ccdbApi; + TrackSelectorPi selectorPion; TrackSelectorPr selectorProton; @@ -189,6 +214,18 @@ struct HfCandidateSelectorToXiPi { registry.add("hSelMassCharmBaryon", "hSelMassCharmBaryon;status;entries", {HistType::kTH1F, {axisSel}}); registry.add("hSelDcaXYToPvV0Daughters", "hSelDcaXYToPvV0Daughters;status;entries", {HistType::kTH1F, {axisSel}}); registry.add("hSelDcaXYToPvPiFromCasc", "hSelDcaXYToPvPiFromCasc;status;entries", {HistType::kTH1F, {axisSel}}); + + if (applyMl) { + hfMlResponse.configure(binsPtMl, cutsMl, cutDirMl, nClassesMl); + if (loadModelsFromCCDB) { + ccdbApi.init(ccdbUrl); + hfMlResponse.setModelPathsCCDB(onnxFileNames, ccdbApi, modelPathsCCDB, timestampCCDB); + } else { + hfMlResponse.setModelPathsLocal(onnxFileNames); + } + hfMlResponse.cacheInputFeaturesIndices(namesInputFeatures); + hfMlResponse.init(); + } } void process(aod::HfCandToXiPi const& candidates, @@ -204,6 +241,7 @@ struct HfCandidateSelectorToXiPi { bool resultSelections = true; // True if the candidate passes all the selections, False otherwise + auto ptCand = RecoDecay::pt(candidate.pxCharmBaryon(), candidate.pyCharmBaryon()); auto trackV0PosDauId = candidate.posTrackId(); // positive V0 daughter auto trackV0NegDauId = candidate.negTrackId(); // negative V0 daughter auto trackPiFromCascId = candidate.bachelorId(); // pion <- cascade @@ -519,6 +557,17 @@ struct HfCandidateSelectorToXiPi { registry.fill(HIST("hSelMassCharmBaryon"), 0); } + // ML selections + if (applyMl) { + bool isSelectedMlXic0 = false; + std::vector inputFeaturesXic0 = hfMlResponse.getInputFeatures(candidate, trackPiFromLam, trackPiFromCasc, trackPiFromCharm); + isSelectedMlXic0 = hfMlResponse.isSelectedMl(inputFeaturesXic0, ptCand, outputMlXic0ToXiPi); + if (!isSelectedMlXic0) { + continue; + } + hfMlToXiPi(outputMlXic0ToXiPi); + } + hfSelToXiPi(statusPidLambda, statusPidCascade, statusPidCharmBaryon, statusInvMassLambda, statusInvMassCascade, statusInvMassCharmBaryon, resultSelections, infoTpcStored, infoTofStored, trackPiFromCharm.tpcNSigmaPi(), trackPiFromCasc.tpcNSigmaPi(), trackPiFromLam.tpcNSigmaPi(), trackPrFromLam.tpcNSigmaPr(), trackPiFromCharm.tofNSigmaPi(), trackPiFromCasc.tofNSigmaPi(), trackPiFromLam.tofNSigmaPi(), trackPrFromLam.tofNSigmaPr()); diff --git a/PWGHF/TableProducer/candidateSelectorXic0ToXiPiKf.cxx b/PWGHF/TableProducer/candidateSelectorXic0ToXiPiKf.cxx index f40b2c030e5..13e131bbcfb 100644 --- a/PWGHF/TableProducer/candidateSelectorXic0ToXiPiKf.cxx +++ b/PWGHF/TableProducer/candidateSelectorXic0ToXiPiKf.cxx @@ -61,7 +61,7 @@ enum PidInfoStored { /// Struct for applying Xic0 -> Xi pi selection cuts struct HfCandidateSelectorXic0ToXiPiKf { Produces hfSelToXiPi; - Produces hfMlToXiPi; + Produces hfMlToXiPi; // kinematic selections Configurable etaTrackCharmBachMax{"etaTrackCharmBachMax", 0.8, "Max absolute value of eta for charm baryon bachelor"}; diff --git a/PWGHF/TableProducer/treeCreatorToXiPi.cxx b/PWGHF/TableProducer/treeCreatorToXiPi.cxx index ed265daa74a..173856ed7e9 100644 --- a/PWGHF/TableProducer/treeCreatorToXiPi.cxx +++ b/PWGHF/TableProducer/treeCreatorToXiPi.cxx @@ -75,6 +75,8 @@ DECLARE_SOA_COLUMN(PzPiFromCharmBaryon, pzPiFromCharmBaryon, float); DECLARE_SOA_COLUMN(PxLambda, pxLambda, float); DECLARE_SOA_COLUMN(PyLambda, pyLambda, float); DECLARE_SOA_COLUMN(PzLambda, pzLambda, float); +DECLARE_SOA_COLUMN(PtCharmBaryon, ptCharmBaryon, float); +DECLARE_SOA_COLUMN(PtPiFromCharmBaryon, ptPiFromCharmBaryon, float); DECLARE_SOA_COLUMN(PxPiFromCasc, pxPiFromCasc, float); DECLARE_SOA_COLUMN(PyPiFromCasc, pyPiFromCasc, float); DECLARE_SOA_COLUMN(PzPiFromCasc, pzPiFromCasc, float); @@ -169,6 +171,7 @@ DECLARE_SOA_TABLE(HfToXiPiFulls, "AOD", "HFTOXIPIFULL", full::XDecayVtxV0, full::YDecayVtxV0, full::ZDecayVtxV0, full::SignDecay, full::CovVtxCharmBaryonXX, full::CovVtxCharmBaryonYY, full::CovVtxCharmBaryonZZ, + full::PtCharmBaryon, full::PtPiFromCharmBaryon, full::PxCharmBaryon, full::PyCharmBaryon, full::PzCharmBaryon, full::PxCasc, full::PyCasc, full::PzCasc, full::PxPiFromCharmBaryon, full::PyPiFromCharmBaryon, full::PzPiFromCharmBaryon, @@ -202,15 +205,16 @@ DECLARE_SOA_TABLE(HfToXiPiLites, "AOD", "HFTOXIPILITE", full::XDecayVtxCascade, full::YDecayVtxCascade, full::ZDecayVtxCascade, full::XDecayVtxV0, full::YDecayVtxV0, full::ZDecayVtxV0, full::SignDecay, - full::PxCharmBaryon, full::PyCharmBaryon, full::PzCharmBaryon, - full::PxPiFromCharmBaryon, full::PyPiFromCharmBaryon, full::PzPiFromCharmBaryon, + full::PtCharmBaryon, full::PtPiFromCharmBaryon, full::PxPiFromCasc, full::PyPiFromCasc, full::PzPiFromCasc, full::PxPosV0Dau, full::PyPosV0Dau, full::PzPosV0Dau, full::PxNegV0Dau, full::PyNegV0Dau, full::PzNegV0Dau, full::ImpactParCascXY, full::ImpactParPiFromCharmBaryonXY, full::ErrImpactParCascXY, full::ErrImpactParPiFromCharmBaryonXY, full::InvMassLambda, full::InvMassCascade, full::InvMassCharmBaryon, + full::CosPAV0, full::CosPACharmBaryon, full::CosPACasc, full::EtaV0PosDau, full::EtaV0NegDau, full::EtaPiFromCasc, full::EtaPiFromCharmBaryon, + full::EtaCharmBaryon, full::DcaXYToPvV0Dau0, full::DcaXYToPvV0Dau1, full::DcaXYToPvCascDau, full::DcaCascDau, full::DcaV0Dau, full::DcaCharmBaryonDau, full::ErrorDecayLengthCharmBaryon, full::NormImpParCascade, full::NormImpParPiFromCharmBar, @@ -283,6 +287,8 @@ struct HfTreeCreatorToXiPi { candidate.covVtxCharmBaryon0(), candidate.covVtxCharmBaryon3(), candidate.covVtxCharmBaryon5(), + RecoDecay::pt(candidate.pxCharmBaryon(), candidate.pyCharmBaryon()), + RecoDecay::pt(candidate.pxBachFromCharmBaryon(), candidate.pyBachFromCharmBaryon()), candidate.pxCharmBaryon(), candidate.pyCharmBaryon(), candidate.pzCharmBaryon(), @@ -404,15 +410,11 @@ struct HfTreeCreatorToXiPi { candidate.yDecayVtxV0(), candidate.zDecayVtxV0(), candidate.signDecay(), + RecoDecay::pt(candidate.pxCharmBaryon(), candidate.pyCharmBaryon()), + RecoDecay::pt(candidate.pxBachFromCharmBaryon(), candidate.pyBachFromCharmBaryon()), candidate.pxCharmBaryon(), candidate.pyCharmBaryon(), candidate.pzCharmBaryon(), - candidate.pxBachFromCharmBaryon(), - candidate.pyBachFromCharmBaryon(), - candidate.pzBachFromCharmBaryon(), - candidate.pxBachFromCasc(), - candidate.pyBachFromCasc(), - candidate.pzBachFromCasc(), candidate.pxPosV0Dau(), candidate.pyPosV0Dau(), candidate.pzPosV0Dau(), @@ -426,10 +428,14 @@ struct HfTreeCreatorToXiPi { candidate.invMassLambda(), candidate.invMassCascade(), candidate.invMassCharmBaryon(), + candidate.cosPAV0(), + candidate.cosPACharmBaryon(), + candidate.cosPACasc(), candidate.etaV0PosDau(), candidate.etaV0NegDau(), candidate.etaBachFromCasc(), candidate.etaBachFromCharmBaryon(), + candidate.etaCharmBaryon(), candidate.dcaXYToPvV0Dau0(), candidate.dcaXYToPvV0Dau1(), candidate.dcaXYToPvCascDau(),