From 7d2b2d086573134962ba7c38e8180d0fc9300455 Mon Sep 17 00:00:00 2001 From: Fabio Catalano Date: Wed, 9 Oct 2024 15:44:36 +0200 Subject: [PATCH 1/6] Add Bs to reduced data model --- PWGHF/D2H/DataModel/ReducedDataModel.h | 106 +++++++++++++++++- PWGHF/D2H/Tasks/taskBs.cxx | 6 - .../DataModel/CandidateReconstructionTables.h | 21 ++-- PWGHF/TableProducer/candidateCreatorBs.cxx | 18 ++- .../candidateSelectorBsToDsPi.cxx | 11 -- 5 files changed, 126 insertions(+), 36 deletions(-) diff --git a/PWGHF/D2H/DataModel/ReducedDataModel.h b/PWGHF/D2H/DataModel/ReducedDataModel.h index b4df5bf4ec2..3176521d4d0 100644 --- a/PWGHF/D2H/DataModel/ReducedDataModel.h +++ b/PWGHF/D2H/DataModel/ReducedDataModel.h @@ -16,6 +16,7 @@ /// /// \author Alexandre Bigot , IPHC Strasbourg /// \author Antonio Palasciano , Università degli Studi di Bari & INFN, Bari +/// \author Fabio Catalano , CERN #ifndef PWGHF_D2H_DATAMODEL_REDUCEDDATAMODEL_H_ #define PWGHF_D2H_DATAMODEL_REDUCEDDATAMODEL_H_ @@ -259,7 +260,7 @@ DECLARE_SOA_COLUMN(Prong0MlScoreNonprompt, prong0MlScoreNonprompt, float); //! N DECLARE_SOA_TABLE(HfRedBplusProngs, "AOD", "HFREDBPPRONG", hf_cand_bplus_reduced::Prong0Id, hf_cand_bplus_reduced::Prong1Id); -DECLARE_SOA_TABLE(HfRedBplusD0Mls, "AOD", "HFREDBPLUSD0ML", //! Table with ML scores for the D+ daughter +DECLARE_SOA_TABLE(HfRedBplusD0Mls, "AOD", "HFREDBPLUSD0ML", //! Table with ML scores for the D0 daughter hf_cand_bplus_reduced::Prong0MlScoreBkg, hf_cand_bplus_reduced::Prong0MlScorePrompt, hf_cand_bplus_reduced::Prong0MlScoreNonprompt, @@ -267,6 +268,26 @@ DECLARE_SOA_TABLE(HfRedBplusD0Mls, "AOD", "HFREDBPLUSD0ML", //! Table with ML sc using HfRedCandBplus = soa::Join; +namespace hf_cand_bs_reduced +{ +DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfRed3Prongs, "_0"); //! Prong0 index +DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, HfRedTrackBases, "_1"); //! Prong1 index +DECLARE_SOA_COLUMN(Prong0MlScoreBkg, prong0MlScoreBkg, float); //! Bkg ML score of the D daughter +DECLARE_SOA_COLUMN(Prong0MlScorePrompt, prong0MlScorePrompt, float); //! Prompt ML score of the D daughter +DECLARE_SOA_COLUMN(Prong0MlScoreNonprompt, prong0MlScoreNonprompt, float); //! Nonprompt ML score of the D daughter +} // namespace hf_cand_bs_reduced + +DECLARE_SOA_TABLE(HfRedBsProngs, "AOD", "HFREDBSPRONG", //! Table with Bs daughter indices + hf_cand_bs_reduced::Prong0Id, hf_cand_bs_reduced::Prong1Id); + +DECLARE_SOA_TABLE(HfRedBsDsMls, "AOD", "HFREDBSDSML", //! Table with ML scores for the Ds daughter + hf_cand_bs_reduced::Prong0MlScoreBkg, + hf_cand_bs_reduced::Prong0MlScorePrompt, + hf_cand_bs_reduced::Prong0MlScoreNonprompt, + o2::soa::Marker<1>); + +using HfRedCandBs = soa::Join; + namespace hf_b0_mc { // MC Rec @@ -428,6 +449,89 @@ DECLARE_SOA_TABLE(HfCandBpConfigs, "AOD", "HFCANDBPCONFIG", //! Table with confi hf_cand_bplus_config::MySelectionFlagD0bar, hf_cand_bplus_config::MyInvMassWindowD0Pi); +namespace hf_bs_mc +{ +// MC Rec +DECLARE_SOA_COLUMN(PtMother, ptMother, float); //! Transverse momentum of the mother in GeV/c +// MC Gen +DECLARE_SOA_COLUMN(PtTrack, ptTrack, float); //! Transverse momentum of the track in GeV/c +DECLARE_SOA_COLUMN(YTrack, yTrack, float); //! Rapidity of the track +DECLARE_SOA_COLUMN(EtaTrack, etaTrack, float); //! Pseudorapidity of the track +DECLARE_SOA_COLUMN(PtProng0, ptProng0, float); //! Transverse momentum of the track's prong0 in GeV/c +DECLARE_SOA_COLUMN(YProng0, yProng0, float); //! Rapidity of the track's prong0 +DECLARE_SOA_COLUMN(EtaProng0, etaProng0, float); //! Pseudorapidity of the track's prong0 +DECLARE_SOA_COLUMN(PtProng1, ptProng1, float); //! Transverse momentum of the track's prong1 in GeV/c +DECLARE_SOA_COLUMN(YProng1, yProng1, float); //! Rapidity of the track's prong1 +DECLARE_SOA_COLUMN(EtaProng1, etaProng1, float); //! Pseudorapidity of the track's prong1 + +DECLARE_SOA_COLUMN(PdgCodeBeautyMother, pdgCodeBeautyMother, int); //! Pdg code of beauty mother +DECLARE_SOA_COLUMN(PdgCodeCharmMother, pdgCodeCharmMother, int); //! Pdg code of charm mother +DECLARE_SOA_COLUMN(PdgCodeProng0, pdgCodeProng0, int); //! Pdg code of prong0 +DECLARE_SOA_COLUMN(PdgCodeProng1, pdgCodeProng1, int); //! Pdg code of prong1 +DECLARE_SOA_COLUMN(PdgCodeProng2, pdgCodeProng2, int); //! Pdg code of prong2 +DECLARE_SOA_COLUMN(PdgCodeProng3, pdgCodeProng3, int); //! Pdg code of prong3 +} // namespace hf_bs_mc + +// table with results of reconstruction level MC matching +DECLARE_SOA_TABLE(HfMcRecRedDsPis, "AOD", "HFMCRECREDDSPI", //! Table with reconstructed MC information on DsPi(<-Bs) pairs for reduced workflow + hf_cand_bs_reduced::Prong0Id, + hf_cand_bs_reduced::Prong1Id, + hf_cand_bs::FlagMcMatchRec, + hf_cand_bs::FlagWrongCollision, + hf_cand_bs::DebugMcRec, + hf_bs_mc::PtMother); + +// try with extended table ? +// DECLARE_SOA_EXTENDED_TABLE_USER(ExTable, Tracks, "EXTABLE", +DECLARE_SOA_TABLE(HfMcCheckDsPis, "AOD", "HFMCCHECKDSPI", //! Table with reconstructed MC information on DsPi(<-Bs) pairs for MC checks in reduced workflow + hf_bs_mc::PdgCodeBeautyMother, + hf_bs_mc::PdgCodeCharmMother, + hf_bs_mc::PdgCodeProng0, + hf_bs_mc::PdgCodeProng1, + hf_bs_mc::PdgCodeProng2, + hf_bs_mc::PdgCodeProng3, + o2::soa::Marker<1>); + +// Table with same size as HFCANDBS +DECLARE_SOA_TABLE(HfMcRecRedBss, "AOD", "HFMCRECREDBS", //! Reconstruction-level MC information on Bs candidates for reduced workflow + hf_cand_bs::FlagMcMatchRec, + hf_cand_bs::FlagWrongCollision, + hf_cand_bs::DebugMcRec, + hf_bs_mc::PtMother); + +DECLARE_SOA_TABLE(HfMcCheckBss, "AOD", "HFMCCHECKBS", //! Table with reconstructed MC information on Bs candidates for MC checks in reduced workflow + hf_bs_mc::PdgCodeBeautyMother, + hf_bs_mc::PdgCodeCharmMother, + hf_bs_mc::PdgCodeProng0, + hf_bs_mc::PdgCodeProng1, + hf_bs_mc::PdgCodeProng2, + hf_bs_mc::PdgCodeProng3, + o2::soa::Marker<2>); + +DECLARE_SOA_TABLE(HfMcGenRedBss, "AOD", "HFMCGENREDBS", //! Generation-level MC information on Bs candidates for reduced workflow + hf_cand_bs::FlagMcMatchGen, + hf_bs_mc::PtTrack, + hf_bs_mc::YTrack, + hf_bs_mc::EtaTrack, + hf_bs_mc::PtProng0, + hf_bs_mc::YProng0, + hf_bs_mc::EtaProng0, + hf_bs_mc::PtProng1, + hf_bs_mc::YProng1, + hf_bs_mc::EtaProng1); + +// store all configurables values used in the first part of the workflow +// so we can use them in the Bs part +namespace hf_cand_bs_config +{ +DECLARE_SOA_COLUMN(MySelectionFlagD, mySelectionFlagD, int8_t); //! Flag to filter selected Ds mesons +DECLARE_SOA_COLUMN(MyInvMassWindowDPi, myInvMassWindowDPi, float); //! Half-width of the Bs invariant-mass window in GeV/c2 +} // namespace hf_cand_bs_config + +DECLARE_SOA_TABLE(HfCandBsConfigs, "AOD", "HFCANDBSCONFIG", //! Table with configurables information for reduced workflow + hf_cand_bs_config::MySelectionFlagD, + hf_cand_bs_config::MyInvMassWindowDPi); + // Charm resonances analysis namespace hf_reso_3_prong { diff --git a/PWGHF/D2H/Tasks/taskBs.cxx b/PWGHF/D2H/Tasks/taskBs.cxx index 29c424f869b..3f5356412c1 100644 --- a/PWGHF/D2H/Tasks/taskBs.cxx +++ b/PWGHF/D2H/Tasks/taskBs.cxx @@ -155,9 +155,6 @@ struct HfTaskBs { TracksWithSel const&) { for (const auto& candidate : candidates) { - if (!TESTBIT(candidate.hfflag(), hf_cand_bs::DecayType::BsToDsPi)) { - continue; - } if (yCandRecoMax >= 0. && std::abs(hfHelper.yBs(candidate)) > yCandRecoMax) { continue; } @@ -194,9 +191,6 @@ struct HfTaskBs { { // MC rec for (const auto& candidate : candidates) { - if (!TESTBIT(candidate.hfflag(), hf_cand_bs::DecayType::BsToDsPi)) { - continue; - } if (yCandRecoMax >= 0. && std::abs(hfHelper.yBs(candidate)) > yCandRecoMax) { continue; } diff --git a/PWGHF/DataModel/CandidateReconstructionTables.h b/PWGHF/DataModel/CandidateReconstructionTables.h index 13bdd7b378e..78ea4d0dd95 100644 --- a/PWGHF/DataModel/CandidateReconstructionTables.h +++ b/PWGHF/DataModel/CandidateReconstructionTables.h @@ -1675,7 +1675,7 @@ enum DecayTypeMc : uint8_t { B0ToDplusPiToPiKPiPi = 0, BsToDsPiToKKPiPi, PartlyRecoDecay, OtherDecay, - NDecayTypeMc }; + NDecayTypeMc}; } // namespace hf_cand_b0 // declare dedicated B0 decay candidate table @@ -1735,8 +1735,12 @@ namespace hf_cand_bs { DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfCand3Prong, "_0"); // Ds index // MC matching result: -DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); // reconstruction level -DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); // generator level +DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); // reconstruction level +DECLARE_SOA_COLUMN(FlagWrongCollision, flagWrongCollision, int8_t); // reconstruction level +DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); // generator level +DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); // particle origin, reconstruction level +DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); // particle origin, generator level +DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int8_t); // debug flag for mis-association reconstruction level // mapping of decay types enum DecayType { BsToDsPi }; @@ -1744,6 +1748,7 @@ enum DecayType { BsToDsPi }; enum DecayTypeMc : uint8_t { BsToDsPiToKKPiPi = 0, // Bs(bar) → Ds∓ π± → (Phi π∓) π± → (K- K+ π∓) π± B0ToDsPiToKKPiPi, // B0(bar) → Ds± π∓ → (Phi π±) π∓ → (K- K+ π±) π∓ PartlyRecoDecay, // 4 final state particles have another common b-hadron ancestor + OtherDecay, NDecayTypeMc }; // counter of differentiated MC decay types } // namespace hf_cand_bs @@ -1757,8 +1762,6 @@ DECLARE_SOA_TABLE(HfCandBsBase, "AOD", "HFCANDBSBASE", hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1, hf_cand::ImpactParameter0, hf_cand::ImpactParameter1, hf_cand::ErrorImpactParameter0, hf_cand::ErrorImpactParameter1, - hf_cand_bs::Prong0Id, hf_track_index::Prong1Id, - hf_track_index::HFflag, /* dynamic columns */ hf_cand_2prong::M, hf_cand_2prong::M2, @@ -1780,13 +1783,17 @@ DECLARE_SOA_TABLE(HfCandBsBase, "AOD", "HFCANDBSBASE", hf_cand::Phi, hf_cand::Y, hf_cand::E, - hf_cand::E2); + hf_cand::E2, + o2::soa::Marker<1>); // extended table with expression columns that can be used as arguments of dynamic columns DECLARE_SOA_EXTENDED_TABLE_USER(HfCandBsExt, HfCandBsBase, "HFCANDBSEXT", hf_cand_2prong::Px, hf_cand_2prong::Py, hf_cand_2prong::Pz); -using HfCandBs = HfCandBsExt; +DECLARE_SOA_TABLE(HfCandBsProngs, "AOD", "HFCANDBSPRONGS", + hf_cand_bs::Prong0Id, hf_track_index::Prong1Id); + +using HfCandBs = soa::Join; // table with results of reconstruction level MC matching DECLARE_SOA_TABLE(HfCandBsMcRec, "AOD", "HFCANDBSMCREC", diff --git a/PWGHF/TableProducer/candidateCreatorBs.cxx b/PWGHF/TableProducer/candidateCreatorBs.cxx index 69fb0c3f178..83548c6ff50 100644 --- a/PWGHF/TableProducer/candidateCreatorBs.cxx +++ b/PWGHF/TableProducer/candidateCreatorBs.cxx @@ -42,6 +42,7 @@ using namespace o2::hf_trkcandsel; /// Reconstruction of Bs candidates struct HfCandidateCreatorBs { Produces rowCandidateBase; // table defined in CandidateReconstructionTables.h + Produces rowCandidateProngs; // table defined in CandidateReconstructionTables.h // vertexing Configurable propagateToPCA{"propagateToPCA", true, "create tracks version propagated to PCA"}; @@ -320,8 +321,6 @@ struct HfCandidateCreatorBs { auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); auto errorDecayLengthXY = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, 0.) + getRotatedCovMatrixXX(covMatrixPCA, phi, 0.)); - int hfFlag = BIT(hf_cand_bs::DecayType::BsToDsPi); - // fill output histograms for Bs candidates hMassDsToKKPi->Fill(hfHelper.invMassDsToKKPi(candDs), candDs.pt()); hCovSVXX->Fill(covMatrixPCA[0]); @@ -340,9 +339,9 @@ struct HfCandidateCreatorBs { pVecDs[0], pVecDs[1], pVecDs[2], pVecPion[0], pVecPion[1], pVecPion[2], dcaDs.getY(), dcaPion.getY(), - std::sqrt(dcaDs.getSigmaY2()), std::sqrt(dcaPion.getSigmaY2()), - candDs.globalIndex(), trackPion.globalIndex(), - hfFlag); + std::sqrt(dcaDs.getSigmaY2()), std::sqrt(dcaPion.getSigmaY2())); + + rowCandidateProngs(candDs.globalIndex(), trackPion.globalIndex()); } // pi loop } // Ds loop } // collision loop @@ -359,11 +358,9 @@ struct HfCandidateCreatorBsExpressions { void processMc(aod::HfCand3Prong const& ds, aod::TracksWMc const& tracks, - aod::McParticles const& mcParticles) + aod::McParticles const& mcParticles, + aod::HfCandBsProngs const& candsBs) { - rowCandidateBs->bindExternalIndices(&tracks); - rowCandidateBs->bindExternalIndices(&ds); - int indexRec = -1; int8_t sign = 0; int8_t flag = 0; @@ -372,8 +369,7 @@ struct HfCandidateCreatorBsExpressions { std::array arrPDGResonantDsPhiPi = {Pdg::kPhi, kPiPlus}; // Ds± → Phi π± // Match reconstructed candidates. - // Spawned table can be used directly - for (const auto& candidate : *rowCandidateBs) { + for (const auto& candidate : candsBs) { flag = 0; arrDaughDsIndex.clear(); auto candDs = candidate.prong0(); diff --git a/PWGHF/TableProducer/candidateSelectorBsToDsPi.cxx b/PWGHF/TableProducer/candidateSelectorBsToDsPi.cxx index 5c0c230c11f..e6818c6e0a6 100644 --- a/PWGHF/TableProducer/candidateSelectorBsToDsPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorBsToDsPi.cxx @@ -149,17 +149,6 @@ struct HfCandidateSelectorBsToDsPi { int statusBsToDsPi = 0; auto ptCandBs = hfCandBs.pt(); - // check if flagged as Bs → Ds π - if (!TESTBIT(hfCandBs.hfflag(), hf_cand_bs::DecayType::BsToDsPi)) { - hfSelBsToDsPiCandidate(statusBsToDsPi); - if (applyMl) { - hfMlBsToDsPiCandidate(outputMl); - } - if (activateQA) { - registry.fill(HIST("hSelections"), 1, ptCandBs); - } - continue; - } SETBIT(statusBsToDsPi, SelectionStep::RecoSkims); // RecoSkims = 0 --> statusBsToDsPi = 1 if (activateQA) { registry.fill(HIST("hSelections"), 2 + SelectionStep::RecoSkims, ptCandBs); From 0c446654a7105181b8c073e51c1075d0b7263616 Mon Sep 17 00:00:00 2001 From: Fabio Catalano Date: Wed, 9 Oct 2024 17:52:08 +0200 Subject: [PATCH 2/6] clang format --- PWGHF/DataModel/CandidateReconstructionTables.h | 4 ++-- PWGHF/TableProducer/candidateCreatorBs.cxx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/PWGHF/DataModel/CandidateReconstructionTables.h b/PWGHF/DataModel/CandidateReconstructionTables.h index 78ea4d0dd95..28685bdaaee 100644 --- a/PWGHF/DataModel/CandidateReconstructionTables.h +++ b/PWGHF/DataModel/CandidateReconstructionTables.h @@ -1675,7 +1675,7 @@ enum DecayTypeMc : uint8_t { B0ToDplusPiToPiKPiPi = 0, BsToDsPiToKKPiPi, PartlyRecoDecay, OtherDecay, - NDecayTypeMc}; + NDecayTypeMc }; } // namespace hf_cand_b0 // declare dedicated B0 decay candidate table @@ -1749,7 +1749,7 @@ enum DecayTypeMc : uint8_t { BsToDsPiToKKPiPi = 0, // Bs(bar) → Ds∓ π± → B0ToDsPiToKKPiPi, // B0(bar) → Ds± π∓ → (Phi π±) π∓ → (K- K+ π±) π∓ PartlyRecoDecay, // 4 final state particles have another common b-hadron ancestor OtherDecay, - NDecayTypeMc }; // counter of differentiated MC decay types + NDecayTypeMc }; // counter of differentiated MC decay types } // namespace hf_cand_bs diff --git a/PWGHF/TableProducer/candidateCreatorBs.cxx b/PWGHF/TableProducer/candidateCreatorBs.cxx index 83548c6ff50..144d1948edf 100644 --- a/PWGHF/TableProducer/candidateCreatorBs.cxx +++ b/PWGHF/TableProducer/candidateCreatorBs.cxx @@ -495,7 +495,7 @@ struct HfCandidateCreatorBsExpressions { rowMcMatchGen(flag); } // gen - } // processMc + } // processMc PROCESS_SWITCH(HfCandidateCreatorBsExpressions, processMc, "Process MC", false); }; // struct From 806e6a46cc02f6256e21ada173aee6343a3bedad Mon Sep 17 00:00:00 2001 From: Fabio Catalano Date: Thu, 10 Oct 2024 14:33:13 +0200 Subject: [PATCH 3/6] Add Bs to creator of reduced data format --- .../dataCreatorCharmHadPiReduced.cxx | 410 +++++++++++++++++- PWGHF/D2H/Tasks/taskBs.cxx | 14 +- .../DataModel/CandidateReconstructionTables.h | 8 +- PWGHF/TableProducer/candidateCreatorBs.cxx | 8 +- PWGHF/TableProducer/treeCreatorBsToDsPi.cxx | 6 +- 5 files changed, 416 insertions(+), 30 deletions(-) diff --git a/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx index 734a1296835..e3647f3e3db 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx @@ -15,6 +15,7 @@ /// \author Alexandre Bigot , IPHC Strasbourg /// \author Antonio Palasciano , Università degli Studi di Bari /// \author Fabrizio Grosa , CERN +/// \author Fabio Catalano , CERN #include @@ -55,6 +56,7 @@ enum Event : uint8_t { enum DecayChannel : uint8_t { B0ToDminusPi = 0, BplusToD0barPi, + BsToDsminusPi }; enum WrongCollisionType : uint8_t { @@ -92,6 +94,11 @@ struct HfDataCreatorCharmHadPiReduced { Produces rowHfD0PiMcCheckReduced; Produces rowHfBpMcGenReduced; + Produces rowCandidateConfigBs; + Produces rowHfDsPiMcRecReduced; + Produces rowHfDsPiMcCheckReduced; + Produces rowHfBsMcGenReduced; + // vertexing // Configurable bz{"bz", 5., "magnetic field"}; Configurable propagateToPCA{"propagateToPCA", true, "create tracks version propagated to PCA"}; @@ -108,6 +115,7 @@ struct HfDataCreatorCharmHadPiReduced { Configurable> cutsTrackPionDCA{"cutsTrackPionDCA", {hf_cuts_single_track::cutsTrack[0], hf_cuts_single_track::nBinsPtTrack, hf_cuts_single_track::nCutVarsTrack, hf_cuts_single_track::labelsPtTrack, hf_cuts_single_track::labelsCutVarTrack}, "Single-track selections per pT bin for pions"}; Configurable invMassWindowCharmHadPi{"invMassWindowCharmHadPi", 0.3, "invariant-mass window for CharmHad-Pi pair preselections (GeV/c2)"}; Configurable selectionFlagDplus{"selectionFlagDplus", 7, "Selection Flag for D+"}; + Configurable selectionFlagDs{"selectionFlagDs", 7, "Selection Flag for Ds"}; Configurable selectionFlagD0{"selectionFlagD0", 1, "Selection Flag for D0"}; Configurable selectionFlagD0bar{"selectionFlagD0bar", 1, "Selection Flag for D0bar"}; @@ -148,27 +156,37 @@ struct HfDataCreatorCharmHadPiReduced { using CandsDplusFiltered = soa::Filtered>; using CandsDplusFilteredWithMl = soa::Filtered>; + using CandsDsFiltered = soa::Filtered>; + using CandsDsFilteredWithMl = soa::Filtered>; using CandsD0Filtered = soa::Filtered>; using CandsD0FilteredWithMl = soa::Filtered>; using CollisionsWMcLabels = soa::Join; Filter filterSelectDplusCandidates = (aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus); + Filter filterSelectDsCandidates = (aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlagDs || aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlagDs); Filter filterSelectDzeroCandidates = (aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar); Preslice candsDplusPerCollision = aod::track_association::collisionId; Preslice candsDplusPerCollisionWithMl = aod::track_association::collisionId; + Preslice candsDsPerCollision = aod::track_association::collisionId; + Preslice candsDsPerCollisionWithMl = aod::track_association::collisionId; Preslice candsD0PerCollision = aod::track_association::collisionId; Preslice candsD0PerCollisionWithMl = aod::track_association::collisionId; Preslice trackIndicesPerCollision = aod::track_association::collisionId; PresliceUnsorted colPerMcCollision = aod::mccollisionlabel::mcCollisionId; - std::shared_ptr hCandidatesD0, hCandidatesDPlus; + std::shared_ptr hCandidatesD0, hCandidatesDPlus, hCandidatesDs; HistogramRegistry registry{"registry"}; + std::array arrPDGResonantDsPhiPi = {kPhi, kPiPlus}; // Ds± → Phi π± + std::array arrPDGResonantDKstarK = {313, kKPlus}; // Ds± → K*(892)0bar K± and D± → K*(892)0bar K± + void init(InitContext const&) { - std::array doProcess = {doprocessDplusPiData, doprocessDplusPiDataWithMl, doprocessDplusPiMc, doprocessDplusPiMcWithMl, doprocessD0PiData, doprocessD0PiDataWithMl, doprocessD0PiMc, doprocessD0PiMcWithMl}; + std::array doProcess = {doprocessDplusPiData, doprocessDplusPiDataWithMl, doprocessDplusPiMc, doprocessDplusPiMcWithMl, + doprocessDsPiData, doprocessDsPiDataWithMl, doprocessDsPiMc, doprocessDsPiMcWithMl, + doprocessD0PiData, doprocessD0PiDataWithMl, doprocessD0PiMc, doprocessD0PiMcWithMl}; if (std::accumulate(doProcess.begin(), doProcess.end(), 0) != 1) { LOGP(fatal, "One and only one process function can be enabled at a time, please fix your configuration!"); } @@ -178,6 +196,9 @@ struct HfDataCreatorCharmHadPiReduced { if (doprocessDplusPiData || doprocessDplusPiDataWithMl || doprocessDplusPiMc || doprocessDplusPiMcWithMl) { massC = MassDMinus; massB = MassB0; + } else if (doprocessDsPiData || doprocessDsPiDataWithMl || doprocessDsPiMc || doprocessDsPiMcWithMl) { + massC = MassDS; + massB = MassBS; } else if (doprocessD0PiData || doprocessD0PiDataWithMl || doprocessD0PiMc || doprocessD0PiMcWithMl) { massC = MassD0; massB = MassBPlus; @@ -186,7 +207,8 @@ struct HfDataCreatorCharmHadPiReduced { invMass2ChHadPiMax = (massB + invMassWindowCharmHadPi) * (massB + invMassWindowCharmHadPi); // Initialize fitter - if (doprocessDplusPiData || doprocessDplusPiDataWithMl || doprocessDplusPiMc || doprocessDplusPiMcWithMl) { + if (doprocessDplusPiData || doprocessDplusPiDataWithMl || doprocessDplusPiMc || doprocessDplusPiMcWithMl || + doprocessDsPiData || doprocessDsPiDataWithMl || doprocessDsPiMc || doprocessDsPiMcWithMl) { df3.setPropagateToPCA(propagateToPCA); df3.setMaxR(maxR); df3.setMaxDZIni(maxDZIni); @@ -233,6 +255,10 @@ struct HfDataCreatorCharmHadPiReduced { charmHadTitle0 = "D^{#plus}"; histMassTitle0 = "Dplus"; charmHadInvMassTitle = "#it{M}(K#pi#pi)"; + } else if (doprocessDsPiData || doprocessDsPiDataWithMl || doprocessDsPiMc || doprocessDsPiMcWithMl) { + charmHadTitle0 = "D_{s}^{#plus}"; + histMassTitle0 = "Ds"; + charmHadInvMassTitle = "#it{M}(KK#pi)"; } else if (doprocessD0PiData || doprocessD0PiDataWithMl || doprocessD0PiMc || doprocessD0PiMcWithMl) { charmHadTitle0 = "D^{0}"; charmHadTitle1 = "#overline{D}^{0}"; @@ -250,10 +276,12 @@ struct HfDataCreatorCharmHadPiReduced { registry.add(Form("hCpa%s", histMassTitle0.data()), Form("%s candidates;%s cosine of pointing angle;entries", charmHadTitle0.data(), charmHadTitle0.data()), {HistType::kTH1F, {{110, -1.1, 1.1}}}); /// candidate monitoring - hCandidatesD0 = registry.add("hCandidatesD0", "D candidate counter", {HistType::kTH1D, {axisCands}}); - hCandidatesDPlus = registry.add("hCandidatesDPlus", "B candidate counter", {HistType::kTH1D, {axisCands}}); + hCandidatesD0 = registry.add("hCandidatesD0", "D0 candidate counter", {HistType::kTH1D, {axisCands}}); + hCandidatesDPlus = registry.add("hCandidatesDPlus", "Dplus candidate counter", {HistType::kTH1D, {axisCands}}); + hCandidatesDs = registry.add("hCandidatesDs", "Ds candidate counter", {HistType::kTH1D, {axisCands}}); setLabelHistoCands(hCandidatesD0); setLabelHistoCands(hCandidatesDPlus); + setLabelHistoCands(hCandidatesDs); } /// Pion selection (D Pi <-- B0) @@ -472,6 +500,126 @@ struct HfDataCreatorCharmHadPiReduced { rowHfDPiMcCheckReduced(pdgCodeBeautyMother, pdgCodeCharmMother, pdgCodeProng0, pdgCodeProng1, pdgCodeProng2, pdgCodeProng3); } rowHfDPiMcRecReduced(indexHfCandCharm, selectedTracksPion[vecDaughtersB.back().globalIndex()], flag, flagWrongCollision, debug, motherPt); + } else if constexpr (decChannel == DecayChannel::BsToDsminusPi) { + // Bs → Ds- π+ → (K- K+ π-) π+ + auto indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1], vecDaughtersB[2], vecDaughtersB[3]}, Pdg::kBS, std::array{-kKPlus, +kKPlus, -kPiPlus, +kPiPlus}, true, &sign, 3); + if (indexRec > -1) { + // Ds- → K- K+ π- + indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1], vecDaughtersB[2]}, -Pdg::kDS, std::array{-kKPlus, +kKPlus, -kPiPlus}, true, &sign, 2); + if (indexRec > -1) { + std::vector arrDaughDsIndex; + std::array arrPDGDaughDs; + RecoDecay::getDaughters(particlesMc.rawIteratorAt(indexRec), &arrDaughDsIndex, std::array{0}, 1); + if (arrDaughDsIndex.size() == 2) { + for (auto iProng = 0u; iProng < arrDaughDsIndex.size(); ++iProng) { + auto daughI = particlesMc.rawIteratorAt(arrDaughDsIndex[iProng]); + arrPDGDaughDs[iProng] = std::abs(daughI.pdgCode()); + } + // Ds- → Phi π- → K- K+ π- and Ds- → K0* K- → K- K+ π- + if ((arrPDGDaughDs[0] == arrPDGResonantDsPhiPi[0] && arrPDGDaughDs[1] == arrPDGResonantDsPhiPi[1]) || (arrPDGDaughDs[0] == arrPDGResonantDsPhiPi[1] && arrPDGDaughDs[1] == arrPDGResonantDsPhiPi[0])) { + flag = sign * BIT(hf_cand_bs::DecayTypeMc::BsToDsPiToPhiPiPiToKKPiPi); + } else if ((arrPDGDaughDs[0] == arrPDGResonantDKstarK[0] && arrPDGDaughDs[1] == arrPDGResonantDKstarK[1]) || (arrPDGDaughDs[0] == arrPDGResonantDKstarK[1] && arrPDGDaughDs[1] == arrPDGResonantDKstarK[0])) { + flag = sign * BIT(hf_cand_bs::DecayTypeMc::BsToDsPiToK0starKPiToKKPiPi); + } + } + } else { + debug = 1; + LOGF(debug, "Bs decays in the expected final state but the condition on the intermediate state is not fulfilled"); + } + + auto indexMother = RecoDecay::getMother(particlesMc, vecDaughtersB.back().template mcParticle_as(), Pdg::kBS, true); + if (indexMother >= 0) { + auto particleMother = particlesMc.rawIteratorAt(indexMother); + motherPt = particleMother.pt(); + checkWrongCollision(particleMother, collision, indexCollisionMaxNumContrib, flagWrongCollision); + } + } + + // additional checks for correlated backgrounds + if (checkDecayTypeMc) { + // B0 → Ds- π+ → (K- K+ π-) π+ + if (!flag) { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1], vecDaughtersB[2], vecDaughtersB[3]}, Pdg::kB0, std::array{-kKPlus, +kKPlus, -kPiPlus, +kPiPlus}, true, &sign, 3); + if (indexRec > -1) { + // Ds- → K- K+ π- + indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1], vecDaughtersB[2]}, -Pdg::kDS, std::array{-kKPlus, +kKPlus, -kPiPlus}, true, &sign, 2); + if (indexRec > -1) { + std::vector arrDaughDsIndex; + std::array arrPDGDaughDs; + RecoDecay::getDaughters(particlesMc.rawIteratorAt(indexRec), &arrDaughDsIndex, std::array{0}, 1); + if (arrDaughDsIndex.size() == 2) { + for (auto iProng = 0u; iProng < arrDaughDsIndex.size(); ++iProng) { + auto daughI = particlesMc.rawIteratorAt(arrDaughDsIndex[iProng]); + arrPDGDaughDs[iProng] = std::abs(daughI.pdgCode()); + } + // Ds- → Phi π- → K- K+ π- and Ds- → K0* K- → K- K+ π- + if ((arrPDGDaughDs[0] == arrPDGResonantDsPhiPi[0] && arrPDGDaughDs[1] == arrPDGResonantDsPhiPi[1]) || (arrPDGDaughDs[0] == arrPDGResonantDsPhiPi[1] && arrPDGDaughDs[1] == arrPDGResonantDsPhiPi[0])) { + flag = sign * BIT(hf_cand_bs::DecayTypeMc::B0ToDsPiToPhiPiPiToKKPiPi); + } else if ((arrPDGDaughDs[0] == arrPDGResonantDKstarK[0] && arrPDGDaughDs[1] == arrPDGResonantDKstarK[1]) || (arrPDGDaughDs[0] == arrPDGResonantDKstarK[1] && arrPDGDaughDs[1] == arrPDGResonantDKstarK[0])) { + flag = sign * BIT(hf_cand_bs::DecayTypeMc::B0ToDsPiToK0starKPiToKKPiPi); + } + } + } + } + } + // Partly reconstructed decays, i.e. the 4 prongs have a common b-hadron ancestor + // convention: final state particles are prong0,1,2,3 + if (!flag) { + auto particleProng0 = vecDaughtersB[0].mcParticle(); + auto particleProng1 = vecDaughtersB[1].mcParticle(); + auto particleProng2 = vecDaughtersB[2].mcParticle(); + auto particleProng3 = vecDaughtersB[3].mcParticle(); + // b-hadron hypothesis + std::array bHadronMotherHypos = {Pdg::kB0, Pdg::kBS, Pdg::kLambdaB0}; + // c-hadron hypothesis + std::array cHadronMotherHypos = {Pdg::kDPlus, Pdg::kDS, Pdg::kDStar, 433, Pdg::kLambdaCPlus}; // 433 = Ds*+ + + for (const auto& bHadronMotherHypo : bHadronMotherHypos) { + int index0Mother = RecoDecay::getMother(particlesMc, particleProng0, bHadronMotherHypo, true); + int index1Mother = RecoDecay::getMother(particlesMc, particleProng1, bHadronMotherHypo, true); + int index2Mother = RecoDecay::getMother(particlesMc, particleProng2, bHadronMotherHypo, true); + int index3Mother = RecoDecay::getMother(particlesMc, particleProng3, bHadronMotherHypo, true); + + // look for common b-hadron ancestor + if (index0Mother > -1 && index1Mother > -1 && index2Mother > -1 && index3Mother > -1) { + if (index0Mother == index1Mother && index1Mother == index2Mother && index2Mother == index3Mother) { + flag = BIT(hf_cand_bs::DecayTypeMc::PartlyRecoDecay); + pdgCodeBeautyMother = particlesMc.rawIteratorAt(index0Mother).pdgCode(); + pdgCodeCharmMother = 0; + pdgCodeProng0 = particleProng0.pdgCode(); + pdgCodeProng1 = particleProng1.pdgCode(); + pdgCodeProng2 = particleProng2.pdgCode(); + pdgCodeProng3 = particleProng3.pdgCode(); + // look for common c-hadron mother among prongs 0, 1 and 2 + for (const auto& cHadronMotherHypo : cHadronMotherHypos) { + int8_t depthMax = 2; + if (cHadronMotherHypo == Pdg::kDStar || cHadronMotherHypo == 433) { // to include D* -> D π0/γ, D* -> D0 π, and Ds* -> Ds π0/γ + depthMax += 1; + } + int index0CharmMother = RecoDecay::getMother(particlesMc, particleProng0, cHadronMotherHypo, true, &sign, depthMax); + int index1CharmMother = RecoDecay::getMother(particlesMc, particleProng1, cHadronMotherHypo, true, &sign, depthMax); + int index2CharmMother = RecoDecay::getMother(particlesMc, particleProng2, cHadronMotherHypo, true, &sign, depthMax); + if (index0CharmMother > -1 && index1CharmMother > -1 && index2CharmMother > -1) { + if (index0CharmMother == index1CharmMother && index1CharmMother == index2CharmMother) { + // pdgCodeCharmMother = + // Pdg::kDPlus (if D+ is the mother and does not come from D*+) + // Pdg::kDPlus + Pdg::kDStar (if D+ is the mother and D*+ -> D+ π0/γ) + // Pdg::kDStar (if D*+ is the mother and D*+ -> D0 π+) + // Pdg::kDS (if Ds is the mother and does not come from Ds*) + // Pdg::kDs + 433 (if Ds is the mother and Ds* -> Ds π0/γ) + // Pdg::kLambdaCPlus (if Λc+ is the mother) + pdgCodeCharmMother += std::abs(particlesMc.rawIteratorAt(index0CharmMother).pdgCode()); + } + } + } + break; + } + } + } + } + rowHfDsPiMcCheckReduced(pdgCodeBeautyMother, pdgCodeCharmMother, pdgCodeProng0, pdgCodeProng1, pdgCodeProng2, pdgCodeProng3); + } + rowHfDsPiMcRecReduced(indexHfCandCharm, selectedTracksPion[vecDaughtersB.back().globalIndex()], flag, flagWrongCollision, debug, motherPt); } else if constexpr (decChannel == DecayChannel::BplusToD0barPi) { // B+ → D0(bar) π+ → (K+ π-) π+ auto indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1], vecDaughtersB[2]}, Pdg::kBPlus, std::array{+kPiPlus, +kKPlus, -kPiPlus}, true, &sign, 2); @@ -573,6 +721,18 @@ struct HfDataCreatorCharmHadPiReduced { registry.fill(HIST("hMassDplus"), invMassC0); registry.fill(HIST("hPtDplus"), candC.pt()); registry.fill(HIST("hCpaDplus"), candC.cpa()); + } else if constexpr (decChannel == DecayChannel::BsToDsminusPi) { + indexHfCandCharm = hfCand3Prong.lastIndex() + 1; + if (candC.isSelDsToKKPi() >= selectionFlagDs) { + invMassC0 = hfHelper.invMassDsToKKPi(candC); + registry.fill(HIST("hMassDs"), invMassC0); + } + if (candC.isSelDsToPiKK() >= selectionFlagDs) { + invMassC1 = hfHelper.invMassDsToPiKK(candC); + registry.fill(HIST("hMassDs"), invMassC1); + } + registry.fill(HIST("hPtDs"), candC.pt()); + registry.fill(HIST("hCpaDs"), candC.cpa()); } else if constexpr (decChannel == DecayChannel::BplusToD0barPi) { indexHfCandCharm = hfCand2Prong.lastIndex() + 1; if (candC.isSelD0() >= selectionFlagD0) { @@ -611,7 +771,7 @@ struct HfDataCreatorCharmHadPiReduced { } // third track, if it's a 3-prong - if constexpr (decChannel == DecayChannel::B0ToDminusPi) { + if constexpr (decChannel == DecayChannel::B0ToDminusPi || decChannel == DecayChannel::BsToDsminusPi) { charmHadDauTracks.push_back(candC.template prong2_as()); trackParCov2 = getTrackParCov(charmHadDauTracks[2]); pVec2 = charmHadDauTracks[2].pVector(); @@ -626,19 +786,32 @@ struct HfDataCreatorCharmHadPiReduced { // reconstruct charm candidate secondary vertex o2::track::TrackParCov trackParCovCharmHad{}; std::array pVecCharm{}; - if constexpr (decChannel == DecayChannel::B0ToDminusPi) { // D∓ → π∓ K± π∓ + if constexpr (decChannel == DecayChannel::B0ToDminusPi || decChannel == DecayChannel::BsToDsminusPi) { // D∓ → π∓ K± π∓ and Ds∓ → K∓ K± π∓ + + if constexpr (decChannel == DecayChannel::B0ToDminusPi) { + hCandidatesDPlus->Fill(SVFitting::BeforeFit); + } else { + hCandidatesDs->Fill(SVFitting::BeforeFit); + } - hCandidatesDPlus->Fill(SVFitting::BeforeFit); try { if (df3.process(trackParCov0, trackParCov1, trackParCov2) == 0) { continue; } } catch (const std::runtime_error& error) { LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN cannot work, skipping the candidate."; - hCandidatesDPlus->Fill(SVFitting::Fail); + if constexpr (decChannel == DecayChannel::B0ToDminusPi) { + hCandidatesDPlus->Fill(SVFitting::Fail); + } else { + hCandidatesDs->Fill(SVFitting::Fail); + } continue; } - hCandidatesDPlus->Fill(SVFitting::FitOk); + if constexpr (decChannel == DecayChannel::B0ToDminusPi) { + hCandidatesDPlus->Fill(SVFitting::FitOk); + } else { + hCandidatesDs->Fill(SVFitting::FitOk); + } auto secondaryVertexCharm = df3.getPCACandidate(); trackParCov0.propagateTo(secondaryVertexCharm[0], bz); @@ -687,7 +860,7 @@ struct HfDataCreatorCharmHadPiReduced { } // reject pi D with same sign as D - if constexpr (decChannel == DecayChannel::B0ToDminusPi) { // D∓ → π∓ K± π∓ + if constexpr (decChannel == DecayChannel::B0ToDminusPi || decChannel == DecayChannel::BsToDsminusPi) { // D∓ → π∓ K± π∓ and Ds∓ → K∓ K± π∓ if (trackPion.sign() * charmHadDauTracks[0].sign() > 0) { continue; } @@ -741,13 +914,14 @@ struct HfDataCreatorCharmHadPiReduced { fillHfCandCharm = true; } // pion loop if (fillHfCandCharm) { // fill candCplus table only once per D candidate - if constexpr (decChannel == DecayChannel::B0ToDminusPi) { // D∓ → π∓ K± π∓ + if constexpr (decChannel == DecayChannel::B0ToDminusPi || decChannel == DecayChannel::BsToDsminusPi) { // D∓ → π∓ K± π∓ and Ds∓ → K∓ K± π∓ hfCand3Prong(charmHadDauTracks[0].globalIndex(), charmHadDauTracks[1].globalIndex(), charmHadDauTracks[2].globalIndex(), indexHfReducedCollision, trackParCovCharmHad.getX(), trackParCovCharmHad.getAlpha(), trackParCovCharmHad.getY(), trackParCovCharmHad.getZ(), trackParCovCharmHad.getSnp(), trackParCovCharmHad.getTgl(), trackParCovCharmHad.getQ2Pt(), candC.xSecondaryVertex(), candC.ySecondaryVertex(), candC.zSecondaryVertex(), invMassC0); + // TODO: add invMassC1 to the table to support Bs -> Ds Pi hfCand3ProngCov(trackParCovCharmHad.getSigmaY2(), trackParCovCharmHad.getSigmaZY(), trackParCovCharmHad.getSigmaZ2(), trackParCovCharmHad.getSigmaSnpY(), trackParCovCharmHad.getSigmaSnpZ(), trackParCovCharmHad.getSigmaSnp2(), trackParCovCharmHad.getSigmaTglY(), trackParCovCharmHad.getSigmaTglZ(), @@ -755,7 +929,12 @@ struct HfDataCreatorCharmHadPiReduced { trackParCovCharmHad.getSigma1PtY(), trackParCovCharmHad.getSigma1PtZ(), trackParCovCharmHad.getSigma1PtSnp(), trackParCovCharmHad.getSigma1PtTgl(), trackParCovCharmHad.getSigma1Pt2()); if constexpr (withMl) { - hfCand3ProngMl(candC.mlProbDplusToPiKPi()[0], candC.mlProbDplusToPiKPi()[1], candC.mlProbDplusToPiKPi()[2]); + if constexpr (decChannel == DecayChannel::B0ToDminusPi) { + hfCand3ProngMl(candC.mlProbDplusToPiKPi()[0], candC.mlProbDplusToPiKPi()[1], candC.mlProbDplusToPiKPi()[2]); + } else { + hfCand3ProngMl(candC.mlProbDsToKKPi()[0], candC.mlProbDsToKKPi()[1], candC.mlProbDsToKKPi()[2]); + // TODO: add DsToPiKK case to support Bs -> Ds Pi + } } } else if constexpr (decChannel == DecayChannel::BplusToD0barPi) { // D0(bar) → K± π∓ hfCand2Prong(charmHadDauTracks[0].globalIndex(), charmHadDauTracks[1].globalIndex(), @@ -840,6 +1019,81 @@ struct HfDataCreatorCharmHadPiReduced { rowHfB0McGenReduced(flag, ptParticle, yParticle, etaParticle, ptProngs[0], yProngs[0], etaProngs[0], ptProngs[1], yProngs[1], etaProngs[1]); + } else if constexpr (decayChannel == DecayChannel::BsToDsminusPi) { + // Bs → Ds- π+ + if (RecoDecay::isMatchedMCGen(particlesMc, particle, Pdg::kBS, std::array{-static_cast(Pdg::kDS), +kPiPlus}, true)) { + // Match Ds- -> π- K+ π- + auto candCMC = particlesMc.rawIteratorAt(particle.daughtersIds().front()); + if (RecoDecay::isMatchedMCGen(particlesMc, candCMC, -static_cast(Pdg::kDS), std::array{-kKPlus, +kKPlus, -kPiPlus}, true, &sign, 2)) { + std::vector arrDaughDsIndex; + std::array arrPDGDaughDs; + RecoDecay::getDaughters(candCMC, &arrDaughDsIndex, std::array{0}, 1); + if (arrDaughDsIndex.size() == 2) { + for (auto jProng = 0u; jProng < arrDaughDsIndex.size(); ++jProng) { + auto daughJ = particlesMc.rawIteratorAt(arrDaughDsIndex[jProng]); + arrPDGDaughDs[jProng] = std::abs(daughJ.pdgCode()); + } + // Ds- → Phi π- → K- K+ π- and Ds- → K0* K- → K- K+ π- + if ((arrPDGDaughDs[0] == arrPDGResonantDsPhiPi[0] && arrPDGDaughDs[1] == arrPDGResonantDsPhiPi[1]) || (arrPDGDaughDs[0] == arrPDGResonantDsPhiPi[1] && arrPDGDaughDs[1] == arrPDGResonantDsPhiPi[0])) { + flag = sign * BIT(hf_cand_bs::DecayTypeMc::BsToDsPiToPhiPiPiToKKPiPi); + } else if ((arrPDGDaughDs[0] == arrPDGResonantDKstarK[0] && arrPDGDaughDs[1] == arrPDGResonantDKstarK[1]) || (arrPDGDaughDs[0] == arrPDGResonantDKstarK[1] && arrPDGDaughDs[1] == arrPDGResonantDKstarK[0])) { + flag = sign * BIT(hf_cand_bs::DecayTypeMc::BsToDsPiToK0starKPiToKKPiPi); + } + } + } + } + + // additional checks for correlated backgrounds + if (checkDecayTypeMc) { + // B0 → Ds- π+ + if (!flag) { + if (RecoDecay::isMatchedMCGen(particlesMc, particle, Pdg::kB0, std::array{-static_cast(Pdg::kDS), +kPiPlus}, true)) { + // Match Ds- -> π- K+ π- + auto candCMC = particlesMc.rawIteratorAt(particle.daughtersIds().front()); + if (RecoDecay::isMatchedMCGen(particlesMc, candCMC, -static_cast(Pdg::kDS), std::array{-kKPlus, +kKPlus, -kPiPlus}, true, &sign, 2)) { + std::vector arrDaughDsIndex; + std::array arrPDGDaughDs; + RecoDecay::getDaughters(candCMC, &arrDaughDsIndex, std::array{0}, 1); + if (arrDaughDsIndex.size() == 2) { + for (auto jProng = 0u; jProng < arrDaughDsIndex.size(); ++jProng) { + auto daughJ = particlesMc.rawIteratorAt(arrDaughDsIndex[jProng]); + arrPDGDaughDs[jProng] = std::abs(daughJ.pdgCode()); + } + // Ds- → Phi π- → K- K+ π- and Ds- → K0* K- → K- K+ π- + if ((arrPDGDaughDs[0] == arrPDGResonantDsPhiPi[0] && arrPDGDaughDs[1] == arrPDGResonantDsPhiPi[1]) || (arrPDGDaughDs[0] == arrPDGResonantDsPhiPi[1] && arrPDGDaughDs[1] == arrPDGResonantDsPhiPi[0])) { + flag = sign * BIT(hf_cand_bs::DecayTypeMc::B0ToDsPiToPhiPiPiToKKPiPi); + } else if ((arrPDGDaughDs[0] == arrPDGResonantDKstarK[0] && arrPDGDaughDs[1] == arrPDGResonantDKstarK[1]) || (arrPDGDaughDs[0] == arrPDGResonantDKstarK[1] && arrPDGDaughDs[1] == arrPDGResonantDKstarK[0])) { + flag = sign * BIT(hf_cand_bs::DecayTypeMc::B0ToDsPiToK0starKPiToKKPiPi); + } + } + } + } + } + } + + // save information for Bs task + if (!TESTBIT(std::abs(flag), hf_cand_bs::DecayTypeMc::BsToDsPiToPhiPiPiToKKPiPi) && !TESTBIT(std::abs(flag), hf_cand_bs::DecayTypeMc::BsToDsPiToK0starKPiToKKPiPi) && + !TESTBIT(std::abs(flag), hf_cand_bs::DecayTypeMc::B0ToDsPiToPhiPiPiToKKPiPi) && !TESTBIT(std::abs(flag), hf_cand_bs::DecayTypeMc::B0ToDsPiToK0starKPiToKKPiPi)) { + continue; + } + + auto ptParticle = particle.pt(); + auto yParticle = RecoDecay::y(particle.pVector(), massB); + auto etaParticle = particle.eta(); + + std::array ptProngs; + std::array yProngs; + std::array etaProngs; + int counter = 0; + for (const auto& daught : particle.daughters_as()) { + ptProngs[counter] = daught.pt(); + etaProngs[counter] = daught.eta(); + yProngs[counter] = RecoDecay::y(daught.pVector(), pdg->Mass(daught.pdgCode())); + counter++; + } + rowHfBsMcGenReduced(flag, ptParticle, yParticle, etaParticle, + ptProngs[0], yProngs[0], etaProngs[0], + ptProngs[1], yProngs[1], etaProngs[1]); } else if constexpr (decayChannel == DecayChannel::BplusToD0barPi) { // B+ → D0bar π+ if (RecoDecay::isMatchedMCGen(particlesMc, particle, Pdg::kBPlus, std::array{-static_cast(Pdg::kD0), +kPiPlus}, true)) { @@ -940,6 +1194,66 @@ struct HfDataCreatorCharmHadPiReduced { } PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDplusPiDataWithMl, "Process DplusPi without MC info and with ML info", false); + void processDsPiData(soa::Join const& collisions, + CandsDsFiltered const& candsC, + aod::TrackAssoc const& trackIndices, + TracksPidWithSel const& tracks, + aod::BCsWithTimestamps const& bcs) + { + // store configurables needed for Bs workflow + if (!isHfCandBhadConfigFilled) { + rowCandidateConfigBs(selectionFlagDs.value, invMassWindowCharmHadPi.value); + isHfCandBhadConfigFilled = true; + } + + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + + auto thisCollId = collision.globalIndex(); + auto candsCThisColl = candsC.sliceBy(candsDplusPerCollision, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsCThisColl, trackIdsThisCollision, tracks, tracks, -1, bcs); + } + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDsPiData, "Process DsPi without MC info and without ML info", true); + + void processDsPiDataWithMl(soa::Join const& collisions, + CandsDsFilteredWithMl const& candsC, + aod::TrackAssoc const& trackIndices, + TracksPidWithSel const& tracks, + aod::BCsWithTimestamps const& bcs) + { + // store configurables needed for Bs workflow + if (!isHfCandBhadConfigFilled) { + rowCandidateConfigBs(selectionFlagDs.value, invMassWindowCharmHadPi.value); + isHfCandBhadConfigFilled = true; + } + + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + + auto thisCollId = collision.globalIndex(); + auto candsCThisColl = candsC.sliceBy(candsDplusPerCollisionWithMl, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsCThisColl, trackIdsThisCollision, tracks, tracks, -1, bcs); + } + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDsPiDataWithMl, "Process DsPi without MC info and with ML info", false); + void processD0PiData(soa::Join const& collisions, CandsD0Filtered const& candsC, aod::TrackAssoc const& trackIndices, @@ -1073,6 +1387,76 @@ struct HfDataCreatorCharmHadPiReduced { } PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDplusPiMcWithMl, "Process DplusPi with MC info and with ML info", false); + void processDsPiMc(CollisionsWMcLabels const& collisions, + CandsDsFiltered const& candsC, + aod::TrackAssoc const& trackIndices, + TracksPidWithSelAndMc const& tracks, + aod::McParticles const& particlesMc, + aod::BCsWithTimestamps const& bcs, + McCollisions const&) + { + // store configurables needed for Bs workflow + if (!isHfCandBhadConfigFilled) { + rowCandidateConfigBs(selectionFlagDs.value, invMassWindowCharmHadPi.value); + isHfCandBhadConfigFilled = true; + } + + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + + auto thisCollId = collision.globalIndex(); + auto candsCThisColl = candsC.sliceBy(candsDplusPerCollision, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + auto collsSameMcCollision = collisions.sliceBy(colPerMcCollision, collision.mcCollisionId()); + int64_t indexCollisionMaxNumContrib = getIndexCollisionMaxNumContrib(collsSameMcCollision); + runDataCreation(collision, candsCThisColl, trackIdsThisCollision, tracks, particlesMc, indexCollisionMaxNumContrib, bcs); + } + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + runMcGen(particlesMc); + } + PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDsPiMc, "Process DsPi with MC info and without ML info", false); + + void processDsPiMcWithMl(CollisionsWMcLabels const& collisions, + CandsDsFilteredWithMl const& candsC, + aod::TrackAssoc const& trackIndices, + TracksPidWithSelAndMc const& tracks, + aod::McParticles const& particlesMc, + aod::BCsWithTimestamps const& bcs, + McCollisions const&) + { + // store configurables needed for Bs workflow + if (!isHfCandBhadConfigFilled) { + rowCandidateConfigBs(selectionFlagDs.value, invMassWindowCharmHadPi.value); + isHfCandBhadConfigFilled = true; + } + + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + + auto thisCollId = collision.globalIndex(); + auto candsCThisColl = candsC.sliceBy(candsDplusPerCollisionWithMl, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + auto collsSameMcCollision = collisions.sliceBy(colPerMcCollision, collision.mcCollisionId()); + int64_t indexCollisionMaxNumContrib = getIndexCollisionMaxNumContrib(collsSameMcCollision); + runDataCreation(collision, candsCThisColl, trackIdsThisCollision, tracks, particlesMc, indexCollisionMaxNumContrib, bcs); + } + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + runMcGen(particlesMc); + } + PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDsPiMcWithMl, "Process DsPi with MC info and with ML info", false); + void processD0PiMc(CollisionsWMcLabels const& collisions, CandsD0Filtered const& candsC, aod::TrackAssoc const& trackIndices, diff --git a/PWGHF/D2H/Tasks/taskBs.cxx b/PWGHF/D2H/Tasks/taskBs.cxx index 3f5356412c1..e661c8d739b 100644 --- a/PWGHF/D2H/Tasks/taskBs.cxx +++ b/PWGHF/D2H/Tasks/taskBs.cxx @@ -128,8 +128,8 @@ struct HfTaskBs { if (checkDecayTypeMc) { constexpr uint8_t kNBinsDecayTypeMc = hf_cand_bs::DecayTypeMc::NDecayTypeMc + 1; TString labels[kNBinsDecayTypeMc]; - labels[hf_cand_bs::DecayTypeMc::BsToDsPiToKKPiPi] = "B^{0}_{s} #rightarrow (D^{#mp}_{s} #rightarrow K^{#minus} K^{#plus} #pi^{#mp}) #pi^{#pm}"; - labels[hf_cand_bs::DecayTypeMc::B0ToDsPiToKKPiPi] = "B^{0} #rightarrow (D^{#pm}_{s} #rightarrow K^{#minus} K^{#plus} #pi^{#pm}) #pi^{#mp}"; + labels[hf_cand_bs::DecayTypeMc::BsToDsPiToPhiPiPiToKKPiPi] = "B^{0}_{s} #rightarrow (D^{#mp}_{s} #rightarrow K^{#minus} K^{#plus} #pi^{#mp}) #pi^{#pm}"; + labels[hf_cand_bs::DecayTypeMc::B0ToDsPiToPhiPiPiToKKPiPi] = "B^{0} #rightarrow (D^{#pm}_{s} #rightarrow K^{#minus} K^{#plus} #pi^{#pm}) #pi^{#mp}"; labels[hf_cand_bs::DecayTypeMc::PartlyRecoDecay] = "Partly reconstructed decay channel"; labels[hf_cand_bs::DecayTypeMc::NDecayTypeMc] = "Other decays"; static const AxisSpec axisDecayType = {kNBinsDecayTypeMc, 0.5, kNBinsDecayTypeMc + 0.5, ""}; @@ -200,7 +200,7 @@ struct HfTaskBs { auto invMassCandBs = hfHelper.invMassBsToDsPi(candidate); int flagMcMatchRecBs = std::abs(candidate.flagMcMatchRec()); - if (TESTBIT(flagMcMatchRecBs, hf_cand_bs::DecayTypeMc::BsToDsPiToKKPiPi)) { + if (TESTBIT(flagMcMatchRecBs, hf_cand_bs::DecayTypeMc::BsToDsPiToPhiPiPiToKKPiPi)) { auto indexMother = RecoDecay::getMother(mcParticles, candidate.prong1_as().mcParticle_as>(), o2::constants::physics::Pdg::kBS, true); auto particleMother = mcParticles.rawIteratorAt(indexMother); @@ -224,7 +224,7 @@ struct HfTaskBs { registry.fill(HIST("hChi2PCARecSig"), candidate.chi2PCA(), ptCandBs); if (checkDecayTypeMc) { - registry.fill(HIST("hDecayTypeMc"), 1 + hf_cand_bs::DecayTypeMc::BsToDsPiToKKPiPi, invMassCandBs, ptCandBs); + registry.fill(HIST("hDecayTypeMc"), 1 + hf_cand_bs::DecayTypeMc::BsToDsPiToPhiPiPiToKKPiPi, invMassCandBs, ptCandBs); } } else { registry.fill(HIST("hPtRecBg"), ptCandBs); @@ -246,8 +246,8 @@ struct HfTaskBs { registry.fill(HIST("hChi2PCARecBg"), candidate.chi2PCA(), ptCandBs); if (checkDecayTypeMc) { - if (TESTBIT(flagMcMatchRecBs, hf_cand_bs::DecayTypeMc::B0ToDsPiToKKPiPi)) { // B0(bar) → Ds± π∓ → (K- K+ π±) π∓ - registry.fill(HIST("hDecayTypeMc"), 1 + hf_cand_bs::DecayTypeMc::B0ToDsPiToKKPiPi, invMassCandBs, ptCandBs); + if (TESTBIT(flagMcMatchRecBs, hf_cand_bs::DecayTypeMc::B0ToDsPiToPhiPiPiToKKPiPi)) { // B0(bar) → Ds± π∓ → (K- K+ π±) π∓ + registry.fill(HIST("hDecayTypeMc"), 1 + hf_cand_bs::DecayTypeMc::B0ToDsPiToPhiPiPiToKKPiPi, invMassCandBs, ptCandBs); } else if (TESTBIT(flagMcMatchRecBs, hf_cand_bs::DecayTypeMc::PartlyRecoDecay)) { // Partly reconstructed decay channel registry.fill(HIST("hDecayTypeMc"), 1 + hf_cand_bs::DecayTypeMc::PartlyRecoDecay, invMassCandBs, ptCandBs); } else { @@ -259,7 +259,7 @@ struct HfTaskBs { // MC gen. level for (const auto& particle : mcParticles) { - if (TESTBIT(std::abs(particle.flagMcMatchGen()), hf_cand_bs::DecayTypeMc::BsToDsPiToKKPiPi)) { + if (TESTBIT(std::abs(particle.flagMcMatchGen()), hf_cand_bs::DecayTypeMc::BsToDsPiToPhiPiPiToKKPiPi)) { auto ptParticle = particle.pt(); auto yParticle = RecoDecay::y(particle.pVector(), o2::constants::physics::MassBS); diff --git a/PWGHF/DataModel/CandidateReconstructionTables.h b/PWGHF/DataModel/CandidateReconstructionTables.h index 28685bdaaee..a2c2c6e3f88 100644 --- a/PWGHF/DataModel/CandidateReconstructionTables.h +++ b/PWGHF/DataModel/CandidateReconstructionTables.h @@ -1745,9 +1745,11 @@ DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int8_t); // debug fla // mapping of decay types enum DecayType { BsToDsPi }; -enum DecayTypeMc : uint8_t { BsToDsPiToKKPiPi = 0, // Bs(bar) → Ds∓ π± → (Phi π∓) π± → (K- K+ π∓) π± - B0ToDsPiToKKPiPi, // B0(bar) → Ds± π∓ → (Phi π±) π∓ → (K- K+ π±) π∓ - PartlyRecoDecay, // 4 final state particles have another common b-hadron ancestor +enum DecayTypeMc : uint8_t { BsToDsPiToPhiPiPiToKKPiPi = 0, // Bs(bar) → Ds∓ π± → (Phi π∓) π± → (K- K+ π∓) π± + BsToDsPiToK0starKPiToKKPiPi, // Bs(bar) → Ds∓ π± → (K0* K∓) π± → (K- K+ π∓) π± + B0ToDsPiToPhiPiPiToKKPiPi, // B0(bar) → Ds± π∓ → (Phi π±) π∓ → (K- K+ π±) π∓ + B0ToDsPiToK0starKPiToKKPiPi, // B0(bar) → Ds± π∓ → (K0* K±) π∓ → (K- K+ π±) π∓ + PartlyRecoDecay, // 4 final state particles have another common b-hadron ancestor OtherDecay, NDecayTypeMc }; // counter of differentiated MC decay types diff --git a/PWGHF/TableProducer/candidateCreatorBs.cxx b/PWGHF/TableProducer/candidateCreatorBs.cxx index 144d1948edf..4a1bbeb69d3 100644 --- a/PWGHF/TableProducer/candidateCreatorBs.cxx +++ b/PWGHF/TableProducer/candidateCreatorBs.cxx @@ -394,7 +394,7 @@ struct HfCandidateCreatorBsExpressions { arrPDGDaughDs[iProng] = std::abs(daughI.pdgCode()); } if ((arrPDGDaughDs[0] == arrPDGResonantDsPhiPi[0] && arrPDGDaughDs[1] == arrPDGResonantDsPhiPi[1]) || (arrPDGDaughDs[0] == arrPDGResonantDsPhiPi[1] && arrPDGDaughDs[1] == arrPDGResonantDsPhiPi[0])) { - flag = sign * BIT(hf_cand_bs::DecayTypeMc::BsToDsPiToKKPiPi); + flag = sign * BIT(hf_cand_bs::DecayTypeMc::BsToDsPiToPhiPiPiToKKPiPi); } } } @@ -414,7 +414,7 @@ struct HfCandidateCreatorBsExpressions { arrPDGDaughDs[iProng] = std::abs(daughI.pdgCode()); } if ((arrPDGDaughDs[0] == arrPDGResonantDsPhiPi[0] && arrPDGDaughDs[1] == arrPDGResonantDsPhiPi[1]) || (arrPDGDaughDs[0] == arrPDGResonantDsPhiPi[1] && arrPDGDaughDs[1] == arrPDGResonantDsPhiPi[0])) { - flag = sign * BIT(hf_cand_bs::DecayTypeMc::B0ToDsPiToKKPiPi); + flag = sign * BIT(hf_cand_bs::DecayTypeMc::B0ToDsPiToPhiPiPiToKKPiPi); } } } @@ -467,7 +467,7 @@ struct HfCandidateCreatorBsExpressions { arrPDGDaughDs[jProng] = std::abs(daughJ.pdgCode()); } if ((arrPDGDaughDs[0] == arrPDGResonantDsPhiPi[0] && arrPDGDaughDs[1] == arrPDGResonantDsPhiPi[1]) || (arrPDGDaughDs[0] == arrPDGResonantDsPhiPi[1] && arrPDGDaughDs[1] == arrPDGResonantDsPhiPi[0])) { - flag = sign * BIT(hf_cand_bs::DecayTypeMc::BsToDsPiToKKPiPi); + flag = sign * BIT(hf_cand_bs::DecayTypeMc::BsToDsPiToPhiPiPiToKKPiPi); } } } @@ -486,7 +486,7 @@ struct HfCandidateCreatorBsExpressions { arrPDGDaughDs[jProng] = std::abs(daughJ.pdgCode()); } if ((arrPDGDaughDs[0] == arrPDGResonantDsPhiPi[0] && arrPDGDaughDs[1] == arrPDGResonantDsPhiPi[1]) || (arrPDGDaughDs[0] == arrPDGResonantDsPhiPi[1] && arrPDGDaughDs[1] == arrPDGResonantDsPhiPi[0])) { - flag = sign * BIT(hf_cand_bs::DecayTypeMc::B0ToDsPiToKKPiPi); + flag = sign * BIT(hf_cand_bs::DecayTypeMc::B0ToDsPiToPhiPiPiToKKPiPi); } } } diff --git a/PWGHF/TableProducer/treeCreatorBsToDsPi.cxx b/PWGHF/TableProducer/treeCreatorBsToDsPi.cxx index aac534e265e..542ed264892 100644 --- a/PWGHF/TableProducer/treeCreatorBsToDsPi.cxx +++ b/PWGHF/TableProducer/treeCreatorBsToDsPi.cxx @@ -172,8 +172,8 @@ struct HfTreeCreatorBsToDsPi { Filter filterSelectCandidates = aod::hf_sel_candidate_bs::isSelBsToDsPi >= selectionFlagBs; - Partition recSig = nabs(aod::hf_cand_bs::flagMcMatchRec) == (int8_t)BIT(aod::hf_cand_bs::DecayTypeMc::BsToDsPiToKKPiPi); - Partition recBg = nabs(aod::hf_cand_bs::flagMcMatchRec) != (int8_t)BIT(aod::hf_cand_bs::DecayTypeMc::BsToDsPiToKKPiPi); + Partition recSig = nabs(aod::hf_cand_bs::flagMcMatchRec) == (int8_t)BIT(aod::hf_cand_bs::DecayTypeMc::BsToDsPiToPhiPiPiToKKPiPi); + Partition recBg = nabs(aod::hf_cand_bs::flagMcMatchRec) != (int8_t)BIT(aod::hf_cand_bs::DecayTypeMc::BsToDsPiToPhiPiPiToKKPiPi); void init(InitContext const&) { @@ -351,7 +351,7 @@ struct HfTreeCreatorBsToDsPi { // Filling particle properties rowCandidateFullParticles.reserve(particles.size()); for (const auto& particle : particles) { - if (TESTBIT(std::abs(particle.flagMcMatchGen()), aod::hf_cand_bs::DecayTypeMc::BsToDsPiToKKPiPi)) { + if (TESTBIT(std::abs(particle.flagMcMatchGen()), aod::hf_cand_bs::DecayTypeMc::BsToDsPiToPhiPiPiToKKPiPi)) { rowCandidateFullParticles( particle.mcCollision().bcId(), particle.pt(), From 345e95735182c59452a12172fe9c0723886e6cc1 Mon Sep 17 00:00:00 2001 From: Fabio Catalano Date: Fri, 11 Oct 2024 11:52:55 +0200 Subject: [PATCH 4/6] Use name for K0* PDG code --- PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx index e3647f3e3db..37f7027f21b 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx @@ -180,7 +180,7 @@ struct HfDataCreatorCharmHadPiReduced { HistogramRegistry registry{"registry"}; std::array arrPDGResonantDsPhiPi = {kPhi, kPiPlus}; // Ds± → Phi π± - std::array arrPDGResonantDKstarK = {313, kKPlus}; // Ds± → K*(892)0bar K± and D± → K*(892)0bar K± + std::array arrPDGResonantDKstarK = {kK0Star892, kKPlus}; // Ds± → K*(892)0bar K± and D± → K*(892)0bar K± void init(InitContext const&) { From 64b22a10787e6bfce15b724c9950936165335b5c Mon Sep 17 00:00:00 2001 From: Fabio Catalano Date: Fri, 11 Oct 2024 13:27:48 +0200 Subject: [PATCH 5/6] Adapt reduced data model to support Ds mass hypotheses --- PWGHF/D2H/DataModel/ReducedDataModel.h | 15 +++++++----- .../dataCreatorCharmHadPiReduced.cxx | 24 +++++++++++-------- .../dataCreatorCharmResoReduced.cxx | 2 +- PWGHF/D2H/Tasks/taskB0Reduced.cxx | 2 +- PWGHF/D2H/Tasks/taskBplusReduced.cxx | 2 +- 5 files changed, 26 insertions(+), 19 deletions(-) diff --git a/PWGHF/D2H/DataModel/ReducedDataModel.h b/PWGHF/D2H/DataModel/ReducedDataModel.h index 3176521d4d0..c218e870fb8 100644 --- a/PWGHF/D2H/DataModel/ReducedDataModel.h +++ b/PWGHF/D2H/DataModel/ReducedDataModel.h @@ -165,9 +165,8 @@ using HfRedTracks = HfRedTracksExt; namespace hf_charm_cand_reduced { -DECLARE_SOA_COLUMN(InvMass, invMass, float); //! Invariant mass of 2prong candidate in GeV/c2 -DECLARE_SOA_COLUMN(InvMassD0, invMassD0, float); //! Invariant mass of 2prong candidate in GeV/c2 -DECLARE_SOA_COLUMN(InvMassD0Bar, invMassD0Bar, float); //! Invariant mass of 2prong candidate in GeV/c2 +DECLARE_SOA_COLUMN(InvMassHypo0, invMassHypo0, float); //! Invariant mass of candidate in GeV/c2 (mass hypothesis 0) +DECLARE_SOA_COLUMN(InvMassHypo1, invMassHypo1, float); //! Invariant mass of candidate in GeV/c2 (mass hypothesis 1) DECLARE_SOA_COLUMN(MlScoreBkgMassHypo0, mlScoreBkgMassHypo0, float); //! ML score for background class (mass hypothesis 0) DECLARE_SOA_COLUMN(MlScorePromptMassHypo0, mlScorePromptMassHypo0, float); //! ML score for prompt class (mass hypothesis 0) DECLARE_SOA_COLUMN(MlScoreNonpromptMassHypo0, mlScoreNonpromptMassHypo0, float); //! ML score for non-prompt class (mass hypothesis 0) @@ -184,7 +183,7 @@ DECLARE_SOA_TABLE(HfRed2Prongs, "AOD", "HFRED2PRONG", //! Table with 2prong cand hf_track_index_reduced::HfRedCollisionId, HFTRACKPAR_COLUMNS, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, - hf_charm_cand_reduced::InvMassD0, hf_charm_cand_reduced::InvMassD0Bar, + hf_charm_cand_reduced::InvMassHypo0, hf_charm_cand_reduced::InvMassHypo1, aod::track::Px, aod::track::Py, aod::track::Pz, @@ -211,7 +210,7 @@ DECLARE_SOA_TABLE(HfRed3Prongs, "AOD", "HFRED3PRONG", //! Table with 3prong cand hf_track_index_reduced::HfRedCollisionId, HFTRACKPAR_COLUMNS, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, - hf_charm_cand_reduced::InvMass, + hf_charm_cand_reduced::InvMassHypo0, hf_charm_cand_reduced::InvMassHypo1, aod::track::Px, aod::track::Py, aod::track::Pz, @@ -225,7 +224,11 @@ DECLARE_SOA_TABLE(HfRed3ProngsCov, "AOD", "HFRED3PRONGSCOV", //! Table with 3pro DECLARE_SOA_TABLE(HfRed3ProngsMl, "AOD", "HFRED3PRONGML", //! Table with 3prong candidate ML scores hf_charm_cand_reduced::MlScoreBkgMassHypo0, hf_charm_cand_reduced::MlScorePromptMassHypo0, - hf_charm_cand_reduced::MlScoreNonpromptMassHypo0); + hf_charm_cand_reduced::MlScoreNonpromptMassHypo0, + hf_charm_cand_reduced::MlScoreBkgMassHypo1, + hf_charm_cand_reduced::MlScorePromptMassHypo1, + hf_charm_cand_reduced::MlScoreNonpromptMassHypo1, + o2::soa::Marker<1>); // Beauty candidates prongs namespace hf_cand_b0_reduced diff --git a/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx index 37f7027f21b..0f026fe77ad 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx @@ -920,8 +920,7 @@ struct HfDataCreatorCharmHadPiReduced { trackParCovCharmHad.getX(), trackParCovCharmHad.getAlpha(), trackParCovCharmHad.getY(), trackParCovCharmHad.getZ(), trackParCovCharmHad.getSnp(), trackParCovCharmHad.getTgl(), trackParCovCharmHad.getQ2Pt(), - candC.xSecondaryVertex(), candC.ySecondaryVertex(), candC.zSecondaryVertex(), invMassC0); - // TODO: add invMassC1 to the table to support Bs -> Ds Pi + candC.xSecondaryVertex(), candC.ySecondaryVertex(), candC.zSecondaryVertex(), invMassC0, invMassC1); hfCand3ProngCov(trackParCovCharmHad.getSigmaY2(), trackParCovCharmHad.getSigmaZY(), trackParCovCharmHad.getSigmaZ2(), trackParCovCharmHad.getSigmaSnpY(), trackParCovCharmHad.getSigmaSnpZ(), trackParCovCharmHad.getSigmaSnp2(), trackParCovCharmHad.getSigmaTglY(), trackParCovCharmHad.getSigmaTglZ(), @@ -930,10 +929,16 @@ struct HfDataCreatorCharmHadPiReduced { trackParCovCharmHad.getSigma1PtTgl(), trackParCovCharmHad.getSigma1Pt2()); if constexpr (withMl) { if constexpr (decChannel == DecayChannel::B0ToDminusPi) { - hfCand3ProngMl(candC.mlProbDplusToPiKPi()[0], candC.mlProbDplusToPiKPi()[1], candC.mlProbDplusToPiKPi()[2]); + hfCand3ProngMl(candC.mlProbDplusToPiKPi()[0], candC.mlProbDplusToPiKPi()[1], candC.mlProbDplusToPiKPi()[2], -1., -1., -1.); } else { - hfCand3ProngMl(candC.mlProbDsToKKPi()[0], candC.mlProbDsToKKPi()[1], candC.mlProbDsToKKPi()[2]); - // TODO: add DsToPiKK case to support Bs -> Ds Pi + std::array mlScores = {-1.f, -1.f, -1.f, -1.f, -1.f, -1.f}; + if (candC.mlProbDsToKKPi().size() == 3) { + std::copy(candC.mlProbDsToKKPi().begin(), candC.mlProbDsToKKPi().end(), mlScores.begin()); + } + if (candC.mlProbDsToPiKK().size() == 3) { + std::copy(candC.mlProbDsToPiKK().begin(), candC.mlProbDsToPiKK().end(), mlScores.begin() + 3); + } + hfCand3ProngMl(mlScores[0], mlScores[1], mlScores[2], mlScores[3], mlScores[4], mlScores[5]); } } } else if constexpr (decChannel == DecayChannel::BplusToD0barPi) { // D0(bar) → K± π∓ @@ -950,15 +955,14 @@ struct HfDataCreatorCharmHadPiReduced { trackParCovCharmHad.getSigma1PtY(), trackParCovCharmHad.getSigma1PtZ(), trackParCovCharmHad.getSigma1PtSnp(), trackParCovCharmHad.getSigma1PtTgl(), trackParCovCharmHad.getSigma1Pt2()); if constexpr (withMl) { - std::array bdtScores = {-1.f, -1.f, -1.f, -1.f, -1.f, -1.f}; + std::array mlScores = {-1.f, -1.f, -1.f, -1.f, -1.f, -1.f}; if (candC.mlProbD0().size() == 3) { - std::copy(candC.mlProbD0().begin(), candC.mlProbD0().end(), bdtScores.begin()); + std::copy(candC.mlProbD0().begin(), candC.mlProbD0().end(), mlScores.begin()); } if (candC.mlProbD0bar().size() == 3) { - std::copy(candC.mlProbD0bar().begin(), candC.mlProbD0bar().end(), bdtScores.begin() + 3); + std::copy(candC.mlProbD0bar().begin(), candC.mlProbD0bar().end(), mlScores.begin() + 3); } - - hfCand2ProngMl(bdtScores[0], bdtScores[1], bdtScores[2], bdtScores[3], bdtScores[4], bdtScores[5]); + hfCand2ProngMl(mlScores[0], mlScores[1], mlScores[2], mlScores[3], mlScores[4], mlScores[5]); } } fillHfReducedCollision = true; diff --git a/PWGHF/D2H/TableProducer/dataCreatorCharmResoReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorCharmResoReduced.cxx index 2f680bad026..5e57bbd8598 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorCharmResoReduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorCharmResoReduced.cxx @@ -790,7 +790,7 @@ struct HfDataCreatorCharmResoReduced { pVecProng2[0], pVecProng2[1], pVecProng2[2], dtype); if constexpr (withMl) { - hfCandDMl(bdtScores[0], bdtScores[1], bdtScores[2]); + hfCandDMl(bdtScores[0], bdtScores[1], bdtScores[2], -1., -1., -1.); } fillHfReducedCollision = true; if constexpr (DecayChannel == DecayChannel::DstarV0 || DecayChannel == DecayChannel::DstarTrack) { diff --git a/PWGHF/D2H/Tasks/taskB0Reduced.cxx b/PWGHF/D2H/Tasks/taskB0Reduced.cxx index 3f4350d93ad..3bb3738d41b 100644 --- a/PWGHF/D2H/Tasks/taskB0Reduced.cxx +++ b/PWGHF/D2H/Tasks/taskB0Reduced.cxx @@ -334,7 +334,7 @@ struct HfTaskB0Reduced { auto invMassB0 = hfHelper.invMassB0ToDPi(candidate); auto candD = candidate.template prong0_as(); auto ptD = candidate.ptProng0(); - auto invMassD = candD.invMass(); + auto invMassD = candD.invMassHypo0(); std::array posPv{candidate.posX(), candidate.posY(), candidate.posZ()}; std::array posSvD{candD.xSecondaryVertex(), candD.ySecondaryVertex(), candD.zSecondaryVertex()}; std::array momD{candD.pVector()}; diff --git a/PWGHF/D2H/Tasks/taskBplusReduced.cxx b/PWGHF/D2H/Tasks/taskBplusReduced.cxx index 282194f57b5..8a6db08d913 100644 --- a/PWGHF/D2H/Tasks/taskBplusReduced.cxx +++ b/PWGHF/D2H/Tasks/taskBplusReduced.cxx @@ -351,7 +351,7 @@ struct HfTaskBplusReduced { auto candD0 = candidate.template prong0_as(); auto candPi = candidate.template prong1_as(); auto ptD0 = candidate.ptProng0(); - auto invMassD0 = (candPi.signed1Pt() < 0) ? candD0.invMassD0() : candD0.invMassD0Bar(); + auto invMassD0 = (candPi.signed1Pt() < 0) ? candD0.invMassHypo0() : candD0.invMassHypo1(); std::array posPv{candidate.posX(), candidate.posY(), candidate.posZ()}; std::array posSvD{candD0.xSecondaryVertex(), candD0.ySecondaryVertex(), candD0.zSecondaryVertex()}; std::array momD{candD0.pVector()}; From d5ad18f5ee379eb9f1b9b074ca1f9507ce8d2116 Mon Sep 17 00:00:00 2001 From: Fabio Catalano Date: Fri, 11 Oct 2024 13:42:38 +0200 Subject: [PATCH 6/6] Rework inv mass histograms and add Ds mass hypotheses --- .../dataCreatorCharmHadPiReduced.cxx | 45 ++++++++----------- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx index 0f026fe77ad..0c815d72486 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx @@ -179,8 +179,8 @@ struct HfDataCreatorCharmHadPiReduced { std::shared_ptr hCandidatesD0, hCandidatesDPlus, hCandidatesDs; HistogramRegistry registry{"registry"}; - std::array arrPDGResonantDsPhiPi = {kPhi, kPiPlus}; // Ds± → Phi π± - std::array arrPDGResonantDKstarK = {kK0Star892, kKPlus}; // Ds± → K*(892)0bar K± and D± → K*(892)0bar K± + std::array arrPDGResonantDsPhiPi = {kPhi, kPiPlus}; // Ds± → Phi π± + std::array arrPDGResonantDKstarK = {kK0Star892, kKPlus}; // Ds± → K*(892)0bar K± and D± → K*(892)0bar K± void init(InitContext const&) { @@ -246,34 +246,27 @@ struct HfDataCreatorCharmHadPiReduced { registry.get(HIST("hEvents"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin].data()); } - std::string charmHadInvMassTitle = ""; - std::string charmHadTitle0 = ""; - std::string charmHadTitle1 = ""; - std::string histMassTitle0 = ""; - std::string histMassTitle1 = ""; + std::string charmHadTitle = ""; + std::string histMassTitle = ""; if (doprocessDplusPiData || doprocessDplusPiDataWithMl || doprocessDplusPiMc || doprocessDplusPiMcWithMl) { - charmHadTitle0 = "D^{#plus}"; - histMassTitle0 = "Dplus"; - charmHadInvMassTitle = "#it{M}(K#pi#pi)"; + charmHadTitle = "D^{#plus}"; + histMassTitle = "Dplus"; + registry.add("hMassDplus", "D^{#plus} candidates; #it{M}(K#pi#pi) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{500, 0., 5.}}}); } else if (doprocessDsPiData || doprocessDsPiDataWithMl || doprocessDsPiMc || doprocessDsPiMcWithMl) { - charmHadTitle0 = "D_{s}^{#plus}"; - histMassTitle0 = "Ds"; - charmHadInvMassTitle = "#it{M}(KK#pi)"; + charmHadTitle = "D_{s}^{#plus}"; + histMassTitle = "Ds"; + registry.add("hMassDsToKKPi", "D_{s}^{#plus} to KKpi candidates; #it{M}(KK#pi) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{500, 0., 5.}}}); + registry.add("hMassDsToPiKK", "D_{s}^{#plus} to piKK candidates; #it{M}(KK#pi) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{500, 0., 5.}}}); } else if (doprocessD0PiData || doprocessD0PiDataWithMl || doprocessD0PiMc || doprocessD0PiMcWithMl) { - charmHadTitle0 = "D^{0}"; - charmHadTitle1 = "#overline{D}^{0}"; - histMassTitle0 = "D0"; - histMassTitle1 = "D0bar"; - charmHadInvMassTitle = "#it{M}(K#pi)"; + charmHadTitle = "D^{0}"; + histMassTitle = "D0"; + registry.add("hMassD0", "D^{0} candidates; #it{M}(K#pi) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{500, 0., 5.}}}); + registry.add("hMassD0bar", "#overline{D}^{0} candidates; #it{M}(K#pi) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{500, 0., 5.}}}); } - registry.add(Form("hMass%s", histMassTitle0.data()), Form("%s candidates; %s (GeV/#it{c}^{2});entries", charmHadTitle0.data(), charmHadInvMassTitle.data()), {HistType::kTH1F, {{500, 0., 5.}}}); - if (doprocessD0PiData || doprocessD0PiDataWithMl || doprocessD0PiMc || doprocessD0PiMcWithMl) { - registry.add(Form("hMass%s", histMassTitle1.data()), Form("%s candidates; %s (GeV/#it{c}^{2});entries", charmHadTitle1.data(), charmHadInvMassTitle.data()), {HistType::kTH1F, {{500, 0., 5.}}}); - } - registry.add(Form("hPt%s", histMassTitle0.data()), Form("%s candidates candidates;%s candidate #it{p}_{T} (GeV/#it{c});entries", charmHadTitle0.data(), charmHadTitle0.data()), {HistType::kTH1F, {{100, 0., 10.}}}); + registry.add(Form("hPt%s", histMassTitle.data()), Form("%s candidates candidates;%s candidate #it{p}_{T} (GeV/#it{c});entries", charmHadTitle.data(), charmHadTitle.data()), {HistType::kTH1F, {{100, 0., 10.}}}); registry.add("hPtPion", "#pi^{#plus} candidates;#pi^{#plus} candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}); - registry.add(Form("hCpa%s", histMassTitle0.data()), Form("%s candidates;%s cosine of pointing angle;entries", charmHadTitle0.data(), charmHadTitle0.data()), {HistType::kTH1F, {{110, -1.1, 1.1}}}); + registry.add(Form("hCpa%s", histMassTitle.data()), Form("%s candidates;%s cosine of pointing angle;entries", charmHadTitle.data(), charmHadTitle.data()), {HistType::kTH1F, {{110, -1.1, 1.1}}}); /// candidate monitoring hCandidatesD0 = registry.add("hCandidatesD0", "D0 candidate counter", {HistType::kTH1D, {axisCands}}); @@ -725,11 +718,11 @@ struct HfDataCreatorCharmHadPiReduced { indexHfCandCharm = hfCand3Prong.lastIndex() + 1; if (candC.isSelDsToKKPi() >= selectionFlagDs) { invMassC0 = hfHelper.invMassDsToKKPi(candC); - registry.fill(HIST("hMassDs"), invMassC0); + registry.fill(HIST("hMassDsToKKPi"), invMassC0); } if (candC.isSelDsToPiKK() >= selectionFlagDs) { invMassC1 = hfHelper.invMassDsToPiKK(candC); - registry.fill(HIST("hMassDs"), invMassC1); + registry.fill(HIST("hMassDsToPiKK"), invMassC1); } registry.fill(HIST("hPtDs"), candC.pt()); registry.fill(HIST("hCpaDs"), candC.cpa());