diff --git a/PWGHF/D2H/DataModel/ReducedDataModel.h b/PWGHF/D2H/DataModel/ReducedDataModel.h index 6e3f2da1da7..414e49dd806 100644 --- a/PWGHF/D2H/DataModel/ReducedDataModel.h +++ b/PWGHF/D2H/DataModel/ReducedDataModel.h @@ -399,7 +399,9 @@ DECLARE_SOA_COLUMN(PtProng0, ptProng0, float); //! Pt of D daughter in DECLARE_SOA_COLUMN(PtProng1, ptProng1, float); //! Pt of V0 daughter in GeV/c DECLARE_SOA_COLUMN(InvMassProng0, invMassProng0, float); //! Invariant Mass of D daughter in GeV/c DECLARE_SOA_COLUMN(InvMassProng1, invMassProng1, float); //! Invariant Mass of V0 daughter in GeV/c - +DECLARE_SOA_COLUMN(MlScoreBkgProng0, mlScoreBkgProng0, float); //! Bkg ML score of the D daughter +DECLARE_SOA_COLUMN(MlScorePromptProng0, mlScorePromptProng0, float); //! Prompt ML score of the D daughter +DECLARE_SOA_COLUMN(MlScoreNonpromptProng0, mlScoreNonpromptProng0, float); //! Nonprompt ML score of the D daughter } // namespace hf_reso_cand_reduced DECLARE_SOA_TABLE(HfRedVzeros, "AOD", "HFREDVZERO", //! Table with V0 candidate information for resonances reduced workflow @@ -439,6 +441,12 @@ DECLARE_SOA_TABLE(HfCandCharmReso, "AOD", "HFCANDCHARMRESO", //! Table with Reso hf_reso_cand_reduced::Cpa, hf_reso_cand_reduced::Dca, hf_reso_cand_reduced::Radius); + +DECLARE_SOA_TABLE(HfCharmResoMLs, "AOD", "HFCHARMRESOML", //! Table with ML scores for the D daughter + hf_reso_cand_reduced::MlScoreBkgProng0, + hf_reso_cand_reduced::MlScorePromptProng0, + hf_reso_cand_reduced::MlScoreNonpromptProng0, + o2::soa::Marker<1>); } // namespace aod namespace soa diff --git a/PWGHF/D2H/TableProducer/candidateCreatorCharmResoReduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorCharmResoReduced.cxx index 83dcb620172..28deede7c74 100644 --- a/PWGHF/D2H/TableProducer/candidateCreatorCharmResoReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateCreatorCharmResoReduced.cxx @@ -39,7 +39,8 @@ enum Selections : uint8_t { enum DecayChannel : uint8_t { Ds1ToDstarK0s = 0, Ds2StarToDplusK0s, - XcToDplusLambda + XcToDplusLambda, + LambdaDminus }; enum V0Type : uint8_t { K0s = 0, @@ -61,6 +62,8 @@ auto vecBins = std::vector{binsPt, binsPt + nBins + 1}; struct HfCandidateCreatorCharmResoReduced { // Produces: Tables with resonance info Produces rowCandidateReso; + // Optional D daughter ML scores table + Produces mlScores; // Configurables Configurable invMassWindowD{"invMassWindowD", 0.5, "invariant-mass window for D candidates (GeV/c2)"}; @@ -70,6 +73,8 @@ struct HfCandidateCreatorCharmResoReduced { // Hist Axis Configurable> binsPt{"binsPt", std::vector{vecBins}, "pT bin limits"}; + using reducedDWithMl = soa::Join; + // Partition of V0 candidates based on v0Type Partition candidatesK0s = aod::hf_reso_cand_reduced::v0Type == (uint8_t)1 || aod::hf_reso_cand_reduced::v0Type == (uint8_t)3 || aod::hf_reso_cand_reduced::v0Type == (uint8_t)5; Partition candidatesLambda = aod::hf_reso_cand_reduced::v0Type == (uint8_t)2 || aod::hf_reso_cand_reduced::v0Type == (uint8_t)4; @@ -85,14 +90,17 @@ struct HfCandidateCreatorCharmResoReduced { void init(InitContext const&) { - for (const auto& value : vecBins) { - LOGF(info, "bin limit %f", value); + // check that only one process function is enabled + std::array doprocess{doprocessDs2StarToDplusK0s, doprocessDs2StarToDplusK0sWithMl, doprocessDs1ToDstarK0s, doprocessDs1ToDstarK0sWithMl, doprocessXcToDplusLambda, doprocessXcToDplusLambdaWithMl, doprocessLambdaDminus, doprocessLambdaDminusWithMl}; + if ((std::accumulate(doprocess.begin(), doprocess.end(), 0)) != 1) { + LOGP(fatal, "Only one process function should be enabled! Please check your configuration!"); } - const AxisSpec axisPt{(std::vector)vecBins, "#it{p}_{T} (GeV/#it{c})"}; // histograms - registry.add("hMassDs1", "Ds1 candidates;m_{Ds1} - m_{D^{*}} (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{100, 2.4, 2.7}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hMassDs2Star", "Ds^{*}2 candidates; Ds^{*}2 - m_{D^{#plus}} (GeV/#it{c}^{2}) ;entries", {HistType::kTH2F, {{100, 2.4, 2.7}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hMassXcRes", "XcRes candidates; XcRes - m_{D^{#plus}} (GeV/#it{c}^{2}) ;entries", {HistType::kTH2F, {{100, 2.9, 3.3}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); + const AxisSpec axisPt{(std::vector)vecBins, "#it{p}_{T} (GeV/#it{c})"}; + registry.add("hMassDs1", "Ds1 candidates;m_{Ds1} (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{100, 2.4, 2.7}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hMassDs2Star", "Ds^{*}2 candidates; m_Ds^{*}2 (GeV/#it{c}^{2}) ;entries", {HistType::kTH2F, {{100, 2.4, 2.7}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hMassXcRes", "XcRes candidates; m_XcRes (GeV/#it{c}^{2}) ;entries", {HistType::kTH2F, {{100, 2.9, 3.3}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hMassLambdaDminus", "LambdaDminus candidates; m_LambdaDminus (GeV/#it{c}^{2}) ;entries", {HistType::kTH2F, {{100, 2.9, 3.3}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); if (activateQA) { constexpr int kNBinsSelections = Selections::NSelSteps; std::string labels[kNBinsSelections]; @@ -105,19 +113,21 @@ struct HfCandidateCreatorCharmResoReduced { registry.get(HIST("hSelections"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin].data()); } } - + // mass constants massK0 = o2::constants::physics::MassK0Short; massLambda = o2::constants::physics::MassLambda; massDplus = o2::constants::physics::MassDPlus; massDstar = o2::constants::physics::MassDStar; } - + /// Basic selection of D candidates + /// \param candD is the reduced D meson candidate + /// \return true if selections are passed template bool isDSelected(DRedTable const& candD) { float massD{0.}; // slection on D candidate mass - if (channel == DecayChannel::Ds2StarToDplusK0s || channel == DecayChannel::XcToDplusLambda) { + if (channel == DecayChannel::Ds2StarToDplusK0s || channel == DecayChannel::XcToDplusLambda || channel == DecayChannel::LambdaDminus) { massD = massDplus; } else if (channel == DecayChannel::Ds1ToDstarK0s) { massD = massDstar; @@ -128,19 +138,27 @@ struct HfCandidateCreatorCharmResoReduced { return true; } + /// Basic selection of V0 candidates + /// \param candV0 is the reduced V0 candidate + /// \param candD is the reduced D meson candidate + /// \return true if selections are passed template bool isV0Selected(V0RedTable const& candV0, DRedTable const& candD) { float massV0{0.}; float invMassV0{0.}; + // slection on V0 candidate mass if (channel == DecayChannel::Ds2StarToDplusK0s || channel == DecayChannel::Ds1ToDstarK0s) { massV0 = massK0; invMassV0 = candV0.invMassK0s(); - } else if (channel == DecayChannel::XcToDplusLambda) { + } else if (channel == DecayChannel::XcToDplusLambda || channel == DecayChannel::LambdaDminus) { massV0 = massLambda; + int wsFact{1}; + if (channel == DecayChannel::LambdaDminus) + wsFact = -1; uint8_t targetV0Type{0}; - if (candD.dType() > 0) { + if (wsFact * candD.dType() > 0) { invMassV0 = candV0.invMassLambda(); targetV0Type = V0Type::Lambda; } else { @@ -157,7 +175,7 @@ struct HfCandidateCreatorCharmResoReduced { return true; } - template + template void runCandidateCreation(Coll const& collisions, DRedTable const& candsD, V0RedTable const& candsV0) @@ -213,6 +231,15 @@ struct HfCandidateCreatorCharmResoReduced { invMassReso = RecoDecay::m(std::array{pVecD, pVecV0}, std::array{massDplus, massLambda}); registry.fill(HIST("hMassXcRes"), invMassReso, ptReso); break; + case DecayChannel::LambdaDminus: + if (candD.dType() < 0) { + invMassV0 = candV0.invMassLambda(); + } else { + invMassV0 = candV0.invMassAntiLambda(); + } + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0}, std::array{massDplus, massLambda}); + registry.fill(HIST("hMassLambdaDminus"), invMassReso, ptReso); + break; default: break; } @@ -227,6 +254,9 @@ struct HfCandidateCreatorCharmResoReduced { candV0.cpa(), candV0.dca(), candV0.radius()); + if constexpr (fillMl) { + mlScores(candD.mlScoreBkgMassHypo0(), candD.mlScorePromptMassHypo0(), candD.mlScoreNonpromptMassHypo0()); + } } } } // main function @@ -235,25 +265,66 @@ struct HfCandidateCreatorCharmResoReduced { aod::HfRed3PrNoTrks const& candsD, aod::HfRedVzeros const&) { - runCandidateCreation(collision, candsD, candidatesK0s); + runCandidateCreation(collision, candsD, candidatesK0s); } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDs2StarToDplusK0s, "Process Ds2* candidates without MC info and without ML info", true); + PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDs2StarToDplusK0s, "Process Ds2* candidates without ML info", true); + + void processDs2StarToDplusK0sWithMl(aod::HfRedCollisions::iterator const& collision, + soa::Join const& candsD, + aod::HfRedVzeros const&) + { + runCandidateCreation(collision, candsD, candidatesK0s); + } + PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDs2StarToDplusK0sWithMl, "Process Ds2* candidates with Ml info", false); void processDs1ToDstarK0s(aod::HfRedCollisions::iterator const& collision, aod::HfRed3PrNoTrks const& candsD, aod::HfRedVzeros const&) { - runCandidateCreation(collision, candsD, candidatesK0s); + runCandidateCreation(collision, candsD, candidatesK0s); + } + PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDs1ToDstarK0s, "Process Ds1 candidates without Ml info", false); + + void processDs1ToDstarK0sWithMl(aod::HfRedCollisions::iterator const& collision, + soa::Join const& candsD, + aod::HfRedVzeros const&) + { + runCandidateCreation(collision, candsD, candidatesK0s); } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDs1ToDstarK0s, "Process Ds1 candidates without MC info and without ML info", false); + PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDs1ToDstarK0sWithMl, "Process Ds1 candidates with Ml info", false); void processXcToDplusLambda(aod::HfRedCollisions::iterator const& collision, aod::HfRed3PrNoTrks const& candsD, aod::HfRedVzeros const&) { - runCandidateCreation(collision, candsD, candidatesLambda); + runCandidateCreation(collision, candsD, candidatesLambda); + } + PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processXcToDplusLambda, "Process Xc candidates without Ml info", false); + + void processXcToDplusLambdaWithMl(aod::HfRedCollisions::iterator const& collision, + soa::Join const& candsD, + aod::HfRedVzeros const&) + { + runCandidateCreation(collision, candsD, candidatesLambda); } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processXcToDplusLambda, "Process Xc candidates without MC info and without ML info", false); + PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processXcToDplusLambdaWithMl, "Process Xc candidates with Ml info", false); + + void processLambdaDminus(aod::HfRedCollisions::iterator const& collision, + aod::HfRed3PrNoTrks const& candsD, + aod::HfRedVzeros const&) + { + runCandidateCreation(collision, candsD, candidatesLambda); + } + PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processLambdaDminus, "Process LambdaDminus candidates without Ml info", false); + + void processLambdaDminusWithMl(aod::HfRedCollisions::iterator const& collision, + soa::Join const& candsD, + aod::HfRedVzeros const&) + { + runCandidateCreation(collision, candsD, candidatesLambda); + } + PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processLambdaDminusWithMl, "Process LambdaDminus candidates with Ml info", false); + }; // struct WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGHF/D2H/TableProducer/dataCreatorCharmResoReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorCharmResoReduced.cxx index a06e69b824c..1acec493668 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorCharmResoReduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorCharmResoReduced.cxx @@ -69,12 +69,15 @@ enum DType : uint8_t { /// Creation of D-V0 pairs struct HfDataCreatorCharmResoReduced { + // Produces AOD tables to store track information Produces hfReducedCollision; // Defined in PWGHF/D2H/DataModel/ReducedDataModel.h Produces hfCollisionCounter; // Defined in PWGHF/D2H/DataModel/ReducedDataModel.h - + // V0 and D candidates reduced tables Produces hfCandV0; // Defined in PWGHF/D2H/DataModel/ReducedDataModel.h Produces hfCandD; // Defined in PWGHF/D2H/DataModel/ReducedDataModel.h + // ML optional Tables + Produces hfCandDMl; // Defined in PWGHF/D2H/DataModel/ReducedDataModel.h // CCDB configuration o2::ccdb::CcdbApi ccdbApi; @@ -106,14 +109,18 @@ struct HfDataCreatorCharmResoReduced { bool isHfCandResoConfigFilled = false; using CandsDplusFiltered = soa::Filtered>; + using CandsDplusFilteredWithMl = soa::Filtered>; using CandDstarFiltered = soa::Filtered>; + using CandDstarFilteredWithMl = soa::Filtered>; using BigTracksPID = soa::Join; Filter filterSelectDplus = (aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus); Filter filterSelectedCandDstar = (aod::hf_sel_candidate_dstar::isSelDstarToD0Pi == selectionFlagDstarToD0Pi); Preslice candsDplusPerCollision = aod::track_association::collisionId; + Preslice candsDplusPerCollisionWithMl = aod::track_association::collisionId; Preslice candsDstarPerCollision = aod::track_association::collisionId; + Preslice candsDstarPerCollisionWithMl = aod::track_association::collisionId; Preslice trackIndicesPerCollision = aod::track_association::collisionId; Preslice candsV0PerCollision = aod::track_association::collisionId; @@ -206,7 +213,7 @@ struct HfDataCreatorCharmResoReduced { return selMap; } - template + template void runDataCreation(aod::Collision const& collision, CCands const& candsD, aod::V0Datas const& V0s, @@ -233,7 +240,8 @@ struct HfDataCreatorCharmResoReduced { std::array prongIdsD; uint8_t v0type; int8_t dtype; - if constexpr (std::is_same::value) { + std::array bdtScores; + if constexpr (DecayChannel == DecayChannel::DstarV0) { if (candD.signSoftPi() > 0) invMassD = candD.invMassDstar(); else @@ -247,7 +255,10 @@ struct HfDataCreatorCharmResoReduced { prongIdsD[1] = candD.prong1Id(); prongIdsD[2] = candD.prongPiId(); dtype = candD.signSoftPi() * DType::Dstar; - } else if constexpr (std::is_same::value) { + if constexpr (withMl) { + std::copy(candD.mlProbDstarToD0Pi().begin(), candD.mlProbDstarToD0Pi().end(), bdtScores.begin()); + } + } else if constexpr (DecayChannel == DecayChannel::DplusV0) { auto prong0 = candD.template prong0_as(); invMassD = hfHelper.invMassDplusToPiKPi(candD); massD = MassDPlus; @@ -259,6 +270,9 @@ struct HfDataCreatorCharmResoReduced { prongIdsD[1] = candD.prong1Id(); prongIdsD[2] = candD.prong2Id(); dtype = static_cast(prong0.sign() * DType::Dplus); + if constexpr (withMl) { + std::copy(candD.mlProbDplusToPiKPi().begin(), candD.mlProbDplusToPiKPi().end(), bdtScores.begin()); + } } // else if // Loop on V0 candidates @@ -340,6 +354,9 @@ struct HfDataCreatorCharmResoReduced { invMassD, pVecD[0], pVecD[1], pVecD[2], dtype); + if constexpr (withMl) { + hfCandDMl(bdtScores[0], bdtScores[1], bdtScores[2]); + } fillHfReducedCollision = true; switch (DecayChannel) { case DecayChannel::DstarV0: @@ -380,11 +397,30 @@ struct HfDataCreatorCharmResoReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollision, thisCollId); auto V0sThisColl = V0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, V0sThisColl, tracks, bcs); + runDataCreation(collision, candsDThisColl, V0sThisColl, tracks, bcs); } } PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDplusV0, "Process Dplus candidates without MC info and without ML info", true); + void processDplusV0WithMl(aod::Collisions const& collisions, + CandsDplusFilteredWithMl const& candsDplus, + aod::TrackAssoc const& trackIndices, + aod::V0Datas const& V0s, + BigTracksPID const& tracks, + aod::BCsWithTimestamps const& bcs) + { + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize()); + + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollisionWithMl, thisCollId); + auto V0sThisColl = V0s.sliceBy(candsV0PerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, V0sThisColl, tracks, bcs); + } + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDplusV0WithMl, "Process Dplus candidates with ML info", false); + void processDstarV0(aod::Collisions const& collisions, CandDstarFiltered const& candsDstar, aod::TrackAssoc const&, @@ -399,10 +435,29 @@ struct HfDataCreatorCharmResoReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollision, thisCollId); auto V0sThisColl = V0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, V0sThisColl, tracks, bcs); + runDataCreation(collision, candsDThisColl, V0sThisColl, tracks, bcs); } } PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDstarV0, "Process DStar candidates without MC info and without ML info", false); + + void processDstarV0WithMl(aod::Collisions const& collisions, + CandDstarFilteredWithMl const& candsDstar, + aod::TrackAssoc const& trackIndices, + aod::V0Datas const& V0s, + BigTracksPID const& tracks, + aod::BCsWithTimestamps const& bcs) + { + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize()); + + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollisionWithMl, thisCollId); + auto V0sThisColl = V0s.sliceBy(candsV0PerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, V0sThisColl, tracks, bcs); + } + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDstarV0WithMl, "Process DStar candidates with ML info", false); }; // struct WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx b/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx index b5c72dfaa1c..75d43c1b490 100644 --- a/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx @@ -93,6 +93,9 @@ DECLARE_SOA_TABLE(HfCandDpLites, "AOD", "HFCANDDPLITE", hf_cand::ImpactParameter0, hf_cand::ImpactParameter1, hf_cand::ImpactParameter2, + hf_cand::ImpactParameterZ0, + hf_cand::ImpactParameterZ1, + hf_cand::ImpactParameterZ2, full::NSigTpcPi0, full::NSigTpcKa0, full::NSigTofPi0, @@ -164,6 +167,12 @@ DECLARE_SOA_TABLE(HfCandDpFulls, "AOD", "HFCANDDPFULL", hf_cand::ErrorImpactParameter0, hf_cand::ErrorImpactParameter1, hf_cand::ErrorImpactParameter2, + hf_cand::ImpactParameterZ0, + hf_cand::ImpactParameterZ1, + hf_cand::ImpactParameterZ2, + hf_cand::ErrorImpactParameterZ0, + hf_cand::ErrorImpactParameterZ1, + hf_cand::ErrorImpactParameterZ2, full::NSigTpcPi0, full::NSigTpcKa0, full::NSigTofPi0, @@ -287,6 +296,9 @@ struct HfTreeCreatorDplusToPiKPi { candidate.impactParameter0(), candidate.impactParameter1(), candidate.impactParameter2(), + candidate.impactParameterZ0(), + candidate.impactParameterZ1(), + candidate.impactParameterZ2(), prong0.tpcNSigmaPi(), prong0.tpcNSigmaKa(), prong0.tofNSigmaPi(), @@ -358,6 +370,12 @@ struct HfTreeCreatorDplusToPiKPi { candidate.errorImpactParameter0(), candidate.errorImpactParameter1(), candidate.errorImpactParameter2(), + candidate.impactParameterZ0(), + candidate.impactParameterZ1(), + candidate.impactParameterZ2(), + candidate.errorImpactParameterZ0(), + candidate.errorImpactParameterZ1(), + candidate.errorImpactParameterZ2(), prong0.tpcNSigmaPi(), prong0.tpcNSigmaKa(), prong0.tofNSigmaPi(),