diff --git a/PWGHF/Core/HfHelper.h b/PWGHF/Core/HfHelper.h index 41239c48179..37798045914 100644 --- a/PWGHF/Core/HfHelper.h +++ b/PWGHF/Core/HfHelper.h @@ -33,6 +33,11 @@ #include #include +template +concept IsB0ToDstarPiChannel = requires(T candidate) { + candidate.prongD0Id(); +}; + class HfHelper { public: @@ -634,6 +639,12 @@ class HfHelper return candidate.m(std::array{o2::constants::physics::MassDMinus, o2::constants::physics::MassPiPlus}); } + template + auto invMassB0ToDPi(const T& candidate) + { + return candidate.m(std::array{o2::constants::physics::MassD0, o2::constants::physics::MassPiPlus, o2::constants::physics::MassPiPlus}); + } + template auto cosThetaStarB0(const T& candidate) { diff --git a/PWGHF/Core/HfMlResponseB0ToDPi.h b/PWGHF/Core/HfMlResponseB0ToDPi.h index 1f6d4940b7f..4874b56543b 100644 --- a/PWGHF/Core/HfMlResponseB0ToDPi.h +++ b/PWGHF/Core/HfMlResponseB0ToDPi.h @@ -75,9 +75,12 @@ namespace o2::analysis enum class InputFeaturesB0ToDPi : uint8_t { ptProng0 = 0, ptProng1, + ptProng2, impactParameter0, impactParameter1, + impactParameter2, impactParameterProduct, + impactParameterProngSqSum, chi2PCA, decayLength, decayLengthXY, @@ -91,7 +94,13 @@ enum class InputFeaturesB0ToDPi : uint8_t { prong0MlScoreNonprompt, tpcNSigmaPi1, tofNSigmaPi1, - tpcTofNSigmaPi1 + tpcTofNSigmaPi1, + tpcNSigmaPiBachPi, + tofNSigmaPiBachPi, + tpcTofNSigmaPiBachPi, + tpcNSigmaPiSoftPi, + tofNSigmaPiSoftPi, + tpcTofNSigmaPiSoftPi }; template @@ -109,7 +118,7 @@ class HfMlResponseB0ToDPi : public HfMlResponse /// \return inputFeatures vector template std::vector getInputFeatures(T1 const& candidate, - T2 const& prong1, + T2 const& prongBachPi, const std::vector* mlScoresD = nullptr) { std::vector inputFeatures; @@ -130,11 +139,77 @@ class HfMlResponseB0ToDPi : public HfMlResponse CHECK_AND_FILL_VEC_B0(cpaXY); CHECK_AND_FILL_VEC_B0(maxNormalisedDeltaIP); // TPC PID variable - CHECK_AND_FILL_VEC_B0_FULL(prong1, tpcNSigmaPi1, tpcNSigmaPi); + CHECK_AND_FILL_VEC_B0_FULL(prongBachPi, tpcNSigmaPi1, tpcNSigmaPi); // TOF PID variable - CHECK_AND_FILL_VEC_B0_FULL(prong1, tofNSigmaPi1, tofNSigmaPi); + CHECK_AND_FILL_VEC_B0_FULL(prongBachPi, tofNSigmaPi1, tofNSigmaPi); // Combined PID variables - CHECK_AND_FILL_VEC_B0_FUNC(prong1, tpcTofNSigmaPi1, o2::pid_tpc_tof_utils::getTpcTofNSigmaPi1); + CHECK_AND_FILL_VEC_B0_FUNC(prongBachPi, tpcTofNSigmaPi1, o2::pid_tpc_tof_utils::getTpcTofNSigmaPi1); + } + if constexpr (withDmesMl) { + if constexpr (reduced) { + switch (idx) { + CHECK_AND_FILL_VEC_B0(prong0MlScoreBkg); + CHECK_AND_FILL_VEC_B0(prong0MlScorePrompt); + CHECK_AND_FILL_VEC_B0(prong0MlScoreNonprompt); + } + } else { + if (mlScoresD) { + switch (idx) { + CHECK_AND_FILL_VEC_B0_INDEX(prong0MlScoreBkg, *mlScoresD, 0); + CHECK_AND_FILL_VEC_B0_INDEX(prong0MlScorePrompt, *mlScoresD, 1); + CHECK_AND_FILL_VEC_B0_INDEX(prong0MlScoreNonprompt, *mlScoresD, 2); + } + } else { + LOG(fatal) << "ML scores of D not provided"; + } + } + } + } + + return inputFeatures; + } + + /// Method to get the input features vector needed for ML inference + /// \param candidate is the B0 candidate + /// \param prongBachPi is the candidate's bachelor pion prong + /// \param prongSoftPi is the candidate's soft pion prong + /// \param mlScoresD is the vector of ML scores for the D meson (if available) + /// \note this method is used for B0 → D*∓ π± candidates with D meson ML scores + /// \return inputFeatures vector + template + std::vector getInputFeaturesDStarPi(T1 const& candidate, + T2 const& prongBachPi, + T3 const& prongSoftPi, + const std::vector* mlScoresD = nullptr) + { + std::vector inputFeatures; + + for (const auto& idx : MlResponse::mCachedIndices) { + switch (idx) { + CHECK_AND_FILL_VEC_B0(ptProng0); + CHECK_AND_FILL_VEC_B0(ptProng1); + CHECK_AND_FILL_VEC_B0(ptProng2); + CHECK_AND_FILL_VEC_B0(impactParameter0); + CHECK_AND_FILL_VEC_B0(impactParameter1); + CHECK_AND_FILL_VEC_B0(impactParameter2); + CHECK_AND_FILL_VEC_B0(impactParameterProngSqSum); + CHECK_AND_FILL_VEC_B0(chi2PCA); + CHECK_AND_FILL_VEC_B0(decayLength); + CHECK_AND_FILL_VEC_B0(decayLengthXY); + CHECK_AND_FILL_VEC_B0(decayLengthNormalised); + CHECK_AND_FILL_VEC_B0(decayLengthXYNormalised); + CHECK_AND_FILL_VEC_B0(cpa); + CHECK_AND_FILL_VEC_B0(cpaXY); + CHECK_AND_FILL_VEC_B0(maxNormalisedDeltaIP); + // TPC PID variable + CHECK_AND_FILL_VEC_B0_FULL(prongBachPi, tpcNSigmaPiBachPi, tpcNSigmaPi); + CHECK_AND_FILL_VEC_B0_FULL(prongSoftPi, tpcNSigmaPiSoftPi, tpcNSigmaPiSoftPi); + // TOF PID variable + CHECK_AND_FILL_VEC_B0_FULL(prongBachPi, tofNSigmaPiBachPi, tofNSigmaPi); + CHECK_AND_FILL_VEC_B0_FULL(prongSoftPi, tofNSigmaPiSoftPi, tofNSigmaPiSoftPi); + // Combined PID variables + CHECK_AND_FILL_VEC_B0_FUNC(prongBachPi, tpcTofNSigmaPiBachPi, o2::pid_tpc_tof_utils::getTpcTofNSigmaPi1); + CHECK_AND_FILL_VEC_B0_FUNC(prongSoftPi, tpcTofNSigmaPiSoftPi, o2::pid_tpc_tof_utils::getTpcTofNSigmaSoftPi); } if constexpr (withDmesMl) { if constexpr (reduced) { @@ -167,9 +242,12 @@ class HfMlResponseB0ToDPi : public HfMlResponse MlResponse::mAvailableInputFeatures = { FILL_MAP_B0(ptProng0), FILL_MAP_B0(ptProng1), + FILL_MAP_B0(ptProng2), FILL_MAP_B0(impactParameter0), FILL_MAP_B0(impactParameter1), + FILL_MAP_B0(impactParameter2), FILL_MAP_B0(impactParameterProduct), + FILL_MAP_B0(impactParameterProngSqSum), FILL_MAP_B0(chi2PCA), FILL_MAP_B0(decayLength), FILL_MAP_B0(decayLengthXY), @@ -183,10 +261,16 @@ class HfMlResponseB0ToDPi : public HfMlResponse FILL_MAP_B0(prong0MlScoreNonprompt), // TPC PID variable FILL_MAP_B0(tpcNSigmaPi1), + FILL_MAP_B0(tpcNSigmaPiSoftPi), + FILL_MAP_B0(tpcNSigmaPiBachPi), // TOF PID variable FILL_MAP_B0(tofNSigmaPi1), + FILL_MAP_B0(tofNSigmaPiSoftPi), + FILL_MAP_B0(tofNSigmaPiBachPi), // Combined PID variable - FILL_MAP_B0(tpcTofNSigmaPi1)}; + FILL_MAP_B0(tpcTofNSigmaPi1), + FILL_MAP_B0(tpcTofNSigmaPiSoftPi), + FILL_MAP_B0(tpcTofNSigmaPiBachPi)}; } }; diff --git a/PWGHF/D2H/DataModel/ReducedDataModel.h b/PWGHF/D2H/DataModel/ReducedDataModel.h index 82df09123da..377f1a87bb3 100644 --- a/PWGHF/D2H/DataModel/ReducedDataModel.h +++ b/PWGHF/D2H/DataModel/ReducedDataModel.h @@ -293,24 +293,12 @@ DECLARE_SOA_TABLE(HfRedTracksCov, "AOD", "HFREDTRACKCOV", //! Table with track c HFTRACKPARCOV_COLUMNS, o2::soa::Marker<1>); -DECLARE_SOA_TABLE(HfRedSoftPiBases, "AOD", "HFREDSOFTPIBASE", //! Table with track information for reduced workflow - soa::Index<>, - hf_track_index_reduced::TrackId, - hf_track_index_reduced::HfRedCollisionId, - HFTRACKPAR_COLUMNS, - hf_track_vars_reduced::ItsNCls, - hf_track_vars_reduced::TpcNClsCrossedRows, - hf_track_vars_reduced::TpcChi2NCl, - aod::track::Px, - aod::track::Py, - aod::track::Pz, - aod::track::PVector, - o2::soa::Marker<2>); - -DECLARE_SOA_TABLE(HfRedSoftPiCov, "AOD", "HFREDSOFTPICOV", //! Table with track covariance information for reduced workflow +DECLARE_SOA_TABLE(HfRedTracksMom, "AOD", "HFREDTRACKMOM", //! Table with track momentum information for reduced workflow soa::Index<>, - HFTRACKPARCOV_COLUMNS, - o2::soa::Marker<2>); + hf_track_vars_reduced::Px, + hf_track_vars_reduced::Py, + hf_track_vars_reduced::Pz, + hf_track_vars_reduced::Sign); // CAREFUL: need to follow convention [Name = Description + 's'] in DECLARE_SOA_TABLE(Name, "AOD", Description) // to call DECLARE_SOA_INDEX_COLUMN_FULL later on @@ -546,6 +534,39 @@ DECLARE_SOA_TABLE(HfRed2ProngsMl, "AOD", "HFRED2PRONGML", //! Table with 2prong hf_charm_cand_reduced::MlScorePromptMassHypo1, hf_charm_cand_reduced::MlScoreNonpromptMassHypo1); +// CAREFUL: need to follow convention [Name = Description + 's'] in DECLARE_SOA_TABLE(Name, "AOD", Description) +// to call DECLARE_SOA_INDEX_COLUMN_FULL later on +DECLARE_SOA_TABLE(HfRedSoftPiBases, "AOD", "HFREDSOFTPIBASE", //! Table with track information for reduced workflow + soa::Index<>, + hf_track_index_reduced::TrackId, + hf_track_index_reduced::HfRedCollisionId, + HFTRACKPAR_COLUMNS, + hf_track_vars_reduced::ItsNCls, + hf_track_vars_reduced::TpcNClsCrossedRows, + hf_track_vars_reduced::TpcChi2NCl, + aod::track::Px, + aod::track::Py, + aod::track::Pz, + aod::track::PVector); + +DECLARE_SOA_TABLE(HfRedSoftPiCov, "AOD", "HFREDSOFTPICOV", //! Table with track covariance information for reduced workflow + soa::Index<>, + HFTRACKPARCOV_COLUMNS, + o2::soa::Marker<2>); + +DECLARE_SOA_TABLE(HfRedSoftPiPid, "AOD", "HFREDSOFTPIPID", + soa::Index<>, + hf_cand_dstar::TPCNSigmaPiSoftPi, + hf_cand_dstar::TOFNSigmaPiSoftPi, + hf_track_vars_reduced::HasTOF, + hf_track_vars_reduced::HasTPC, + hf_cand_dstar::TPCTOFNSigmaPiSoftPi) + +namespace hf_track_index_reduced +{ +DECLARE_SOA_INDEX_COLUMN_FULL(SoftPi, softPi, int, HfRedSoftPiBases, ""); //! ReducedCollision index +}; // namespace hf_track_index_reduced + // CAREFUL: need to follow convention [Name = Description + 's'] in DECLARE_SOA_TABLE(Name, "AOD", Description) // to call DECLARE_SOA_INDEX_COLUMN_FULL later on DECLARE_SOA_TABLE(HfRed3Prongs, "AOD", "HFRED3PRONG", //! Table with 3prong candidate information for reduced workflow @@ -583,6 +604,17 @@ DECLARE_SOA_TABLE_VERSIONED(HfRed3ProngsMl_001, "AOD", "HFRED3PRONGML", 1, //! T using HfRed3ProngsMl = HfRed3ProngsMl_001; +DECLARE_SOA_TABLE(HfRedMomDDaugs, "AOD", "HFREDMOMDDAUGS", //! Table with 2prong candidate ML scores + hf_cand::PxProng0, + hf_cand::PyProng0, + hf_cand::PzProng0, + hf_cand::PxProng1, + hf_cand::PyProng1, + hf_cand::PzProng1, + hf_cand::PxProng2, + hf_cand::PyProng2, + hf_cand::PzProng2); + // CAREFUL: need to follow convention [Name = Description + 's'] in DECLARE_SOA_TABLE(Name, "AOD", Description) // to call DECLARE_SOA_INDEX_COLUMN_FULL later on DECLARE_SOA_TABLE(HfRedJpsis, "AOD", "HFREDJPSI", //! Table with J/Psi candidate information for reduced workflow @@ -711,11 +743,15 @@ using HfRedPidDau2s = HfRedPidDau2s_001; using HfRedPidDau0 = HfRedPidDau0s::iterator; using HfRedPidDau1 = HfRedPidDau1s::iterator; using HfRedPidDau2 = HfRedPidDau2s::iterator; + // Beauty candidates prongs namespace hf_cand_b0_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_INDEX_COLUMN_FULL(ProngD0, prongD0, int, HfRed2Prongs, "_0"); //! ProngD0 index +DECLARE_SOA_INDEX_COLUMN_FULL(ProngBachPi, prongBachPi, int, HfRedTrackBases, "_1"); //! ProngBachPi index +DECLARE_SOA_INDEX_COLUMN_FULL(ProngSoftPi, prongSoftPi, int, HfRedSoftPiBases, "_2"); //! ProngSoftPi 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 @@ -724,6 +760,9 @@ DECLARE_SOA_COLUMN(Prong0MlScoreNonprompt, prong0MlScoreNonprompt, float); //! N DECLARE_SOA_TABLE(HfRedB0Prongs, "AOD", "HFREDB0PRONG", //! Table with B0 daughter indices hf_cand_b0_reduced::Prong0Id, hf_cand_b0_reduced::Prong1Id); +DECLARE_SOA_TABLE(HfRedB0ProngDStars, "AOD", "HFREDB0PRONGDST", //! Table with B0 daughter indices + hf_cand_b0_reduced::ProngD0Id, hf_cand_b0_reduced::ProngBachPiId, hf_cand_b0_reduced::ProngSoftPiId); + DECLARE_SOA_TABLE(HfRedB0DpMls, "AOD", "HFREDB0DPML", //! Table with ML scores for the D+ daughter hf_cand_b0_reduced::Prong0MlScoreBkg, hf_cand_b0_reduced::Prong0MlScorePrompt, @@ -731,6 +770,7 @@ DECLARE_SOA_TABLE(HfRedB0DpMls, "AOD", "HFREDB0DPML", //! Table with ML scores f o2::soa::Marker<1>); using HfRedCandB0 = soa::Join; +using HfRedCandB0DStar = soa::Join; namespace hf_cand_bplus_reduced { @@ -848,6 +888,15 @@ DECLARE_SOA_TABLE(HfMcCheckDpPis, "AOD", "HFMCCHECKDPPI", //! Table with reconst hf_b0_mc::PdgCodeProng3, o2::soa::Marker<1>); +// table with results of reconstruction level MC matching +DECLARE_SOA_TABLE(HfMcRecRedDStarPis, "AOD", "HFMCRECREDDSTPI", //! Table with reconstructed MC information on DStarPi pairs for reduced workflow + hf_cand_b0_reduced::ProngD0Id, + hf_cand_b0_reduced::ProngBachPiId, + hf_cand_b0::FlagMcMatchRec, + hf_cand_b0::FlagWrongCollision, + hf_cand_b0::DebugMcRec, + hf_b0_mc::PtMother); + // Table with same size as HFCANDB0 DECLARE_SOA_TABLE(HfMcRecRedB0s, "AOD", "HFMCRECREDB0", //! Reconstruction-level MC information on B0 candidates for reduced workflow hf_cand_b0::FlagMcMatchRec, diff --git a/PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx index a5815359f4b..fd6a2b4098c 100644 --- a/PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx @@ -51,9 +51,11 @@ using namespace o2::hf_trkcandsel; /// Reconstruction of B0 candidates struct HfCandidateCreatorB0Reduced { - Produces rowCandidateBase; // table defined in CandidateReconstructionTables.h - Produces rowCandidateProngs; // table defined in ReducedDataModel.h - Produces rowCandidateDmesMlScores; // table defined in ReducedDataModel.h + Produces rowCandidateBase; // table defined in CandidateReconstructionTables.h + Produces rowCandidateB0DStar; // table defined in CandidateReconstructionTables.h + Produces rowCandidateProngs; // table defined in ReducedDataModel.h + Produces rowCandidateProngsDStar; // table defined in ReducedDataModel.h + Produces rowCandidateDmesMlScores; // table defined in ReducedDataModel.h // vertexing Configurable propagateToPCA{"propagateToPCA", true, "create tracks version propagated to PCA"}; @@ -67,17 +69,18 @@ struct HfCandidateCreatorB0Reduced { Configurable invMassWindowDPiTolerance{"invMassWindowDPiTolerance", 0.01, "invariant-mass window tolerance for DPi pair preselections (GeV/c2)"}; float myInvMassWindowDPi{1.}; // variable that will store the value of invMassWindowDPi (defined in dataCreatorDplusPiReduced.cxx) - float massPi{0.}; - float massD{0.}; - float massB0{0.}; float bz{0.}; - o2::vertexing::DCAFitterN<2> df2; // fitter for B vertex (2-prong vertex fitter) + o2::vertexing::DCAFitterN<2> df2; // fitter for B vertex (2-prong vertex fitter for DpPi candidates) + o2::vertexing::DCAFitterN<3> df3; // fitter for B vertex (3-prong vertex fitter for DstarPi candidates) using HfRedCollisionsWithExtras = soa::Join; + using HfSoftPiWCovAndPid = soa::Join; - Preslice> candsDPerCollision = hf_track_index_reduced::hfRedCollisionId; - Preslice> candsDWithMlPerCollision = hf_track_index_reduced::hfRedCollisionId; + Preslice> candsDplusPerCollision = hf_track_index_reduced::hfRedCollisionId; + Preslice> candsDplusWithMlPerCollision = hf_track_index_reduced::hfRedCollisionId; + Preslice> candsDstarPerCollision = hf_track_index_reduced::hfRedCollisionId; + Preslice> candsDstarWithMlPerCollision = hf_track_index_reduced::hfRedCollisionId; Preslice> tracksPionPerCollision = hf_track_index_reduced::hfRedCollisionId; std::shared_ptr hCandidates; @@ -85,16 +88,11 @@ struct HfCandidateCreatorB0Reduced { void init(InitContext const&) { - std::array doprocess{doprocessData, doprocessDataWithDmesMl}; + std::array doprocess{doprocessDataDplusPi, doprocessDataDplusPiWithDmesMl, doprocessDataDstarPi, doprocessDataDstarPiWithDmesMl}; if ((std::accumulate(doprocess.begin(), doprocess.end(), 0)) != 1) { LOGP(fatal, "Only one process function for data should be enabled at a time."); } - // invariant-mass window cut - massPi = o2::constants::physics::MassPiPlus; - massD = o2::constants::physics::MassDMinus; - massB0 = o2::constants::physics::MassB0; - // Initialize fitter df2.setPropagateToPCA(propagateToPCA); df2.setMaxR(maxR); @@ -104,8 +102,20 @@ struct HfCandidateCreatorB0Reduced { df2.setUseAbsDCA(useAbsDCA); df2.setWeightedFinalPCA(useWeightedFinalPCA); + df3.setPropagateToPCA(propagateToPCA); + df3.setMaxR(maxR); + df3.setMaxDZIni(maxDZIni); + df3.setMinParamChange(minParamChange); + df3.setMinRelChi2Change(minRelChi2Change); + df3.setUseAbsDCA(useAbsDCA); + df3.setWeightedFinalPCA(useWeightedFinalPCA); + // histograms - registry.add("hMassB0ToDPi", "2-prong candidates;inv. mass (B^{0} #rightarrow D^{#minus}#pi^{#plus} #rightarrow #pi^{#minus}K^{#plus}#pi^{#minus}#pi^{#plus}) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{500, 3., 8.}}}); + if (doprocessDataDplusPi || doprocessDataDplusPiWithDmesMl) { + registry.add("hMassB0ToDPi", "2-prong candidates;inv. mass (B^{0} #rightarrow D^{#minus}#pi^{#plus} #rightarrow #pi^{#minus}K^{#plus}#pi^{#minus}#pi^{#plus}) (GeV/#it{c}^{2});entries", {HistType::kTH1D, {{500, 3., 8.}}}); + } else if (doprocessDataDstarPi || doprocessDataDstarPiWithDmesMl) { + registry.add("hMassB0ToDPi", "3-prong candidates;inv. mass (B^{0} #rightarrow D^{0}#pi^{#plus}#pi^{#plus} #rightarrow #pi^{#minus}K^{#plus}#pi^{#minus}#pi^{#plus}) (GeV/#it{c}^{2});entries", {HistType::kTH1D, {{500, 3., 8.}}}); + } registry.add("hCovPVXX", "2-prong candidates;XX element of cov. matrix of prim. vtx. position (cm^{2});entries", {HistType::kTH1F, {{100, 0., 1.e-4}}}); registry.add("hCovSVXX", "2-prong candidates;XX element of cov. matrix of sec. vtx. position (cm^{2});entries", {HistType::kTH1F, {{100, 0., 0.2}}}); registry.add("hEvents", "Events;;entries", HistType::kTH1F, {{1, 0.5, 1.5}}); @@ -115,6 +125,118 @@ struct HfCandidateCreatorB0Reduced { setLabelHistoCands(hCandidates); } + /// Main function to perform B0 candidate creation + /// \param withDmesMl is the flag to use the table with ML scores for the D- daughter (only possible if present in the derived data) + /// \param collision the collision + /// \param candsDThisColl B0 candidates in this collision + /// \param tracksPionThisCollision pion tracks in this collision + /// \param invMass2DPiMin minimum B0 invariant-mass + /// \param invMass2DPiMax maximum B0 invariant-mass + template + void runCandidateCreationDStar(Coll const& collision, + Cands const& candsDThisColl, + SoftPions const& softPions, + Pions const& tracksPionThisCollision, + const float invMass2DPiMin, + const float invMass2DPiMax) + { + auto primaryVertex = getPrimaryVertex(collision); + auto covMatrixPV = primaryVertex.getCov(); + + // Set the magnetic field from ccdb + bz = collision.bz(); + df3.setBz(bz); + + for (const auto& candD : candsDThisColl) { + auto trackParCovD = getTrackParCov(candD); + std::array pVecD0 = candD.pVector(); + auto trackSoftPion = softPions.rawIteratorAt(candD.globalIndex()); + std::array pVecSoftPion = trackSoftPion.pVector(); + auto trackParCovSoftPi = getTrackParCov(trackSoftPion); + + for (const auto& trackBachPion : tracksPionThisCollision) { + // this track is among daughters + if (trackBachPion.trackId() == candD.prong0Id() || trackBachPion.trackId() == candD.prong1Id() || trackBachPion.trackId() == trackSoftPion.trackId()) { + continue; + } + + auto trackParCovPi = getTrackParCov(trackBachPion); + std::array pVecBachPion = trackBachPion.pVector(); + + // compute invariant mass square and apply selection + auto invMass2DPi = RecoDecay::m2(std::array{pVecD0, pVecSoftPion, pVecBachPion}, std::array{o2::constants::physics::MassD0, o2::constants::physics::MassPiPlus, o2::constants::physics::MassPiPlus}); + if ((invMass2DPi < invMass2DPiMin) || (invMass2DPi > invMass2DPiMax)) { + continue; + } + + // --------------------------------- + // reconstruct the 3-prong B0 vertex + hCandidates->Fill(SVFitting::BeforeFit); + try { + if (df3.process(trackParCovD, trackParCovSoftPi, trackParCovPi) == 0) { + continue; + } + } catch (const std::runtime_error& error) { + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN cannot work, skipping the candidate."; + hCandidates->Fill(SVFitting::Fail); + continue; + } + hCandidates->Fill(SVFitting::FitOk); + + // DPi passed B0 reconstruction + + // calculate relevant properties + const auto& secondaryVertexB0 = df3.getPCACandidate(); + auto chi2PCA = df3.getChi2AtPCACandidate(); + auto covMatrixPCA = df3.calcPCACovMatrixFlat(); + registry.fill(HIST("hCovSVXX"), covMatrixPCA[0]); + registry.fill(HIST("hCovPVXX"), covMatrixPV[0]); + + // propagate D and Pi to the B0 vertex + df3.propagateTracksToVertex(); + // track.getPxPyPzGlo(pVec) modifies pVec of track + df3.getTrack(0).getPxPyPzGlo(pVecD0); // momentum of D at the B0 vertex + df3.getTrack(1).getPxPyPzGlo(pVecSoftPion); // momentum of SoftPi at the B0 vertex + df3.getTrack(2).getPxPyPzGlo(pVecBachPion); // momentum of Pi at the B0 vertex + + registry.fill(HIST("hMassB0ToDPi"), std::sqrt(invMass2DPi)); + + // compute impact parameters of D and Pi + o2::dataformats::DCA dcaD; + o2::dataformats::DCA dcaSoftPion; + o2::dataformats::DCA dcaBachPion; + trackParCovD.propagateToDCA(primaryVertex, bz, &dcaD); + trackParCovSoftPi.propagateToDCA(primaryVertex, bz, &dcaSoftPion); + trackParCovPi.propagateToDCA(primaryVertex, bz, &dcaBachPion); + + // get uncertainty of the decay length + float phi, theta; + // getPointDirection modifies phi and theta + getPointDirection(std::array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertexB0, phi, theta); + auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); + auto errorDecayLengthXY = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, 0.) + getRotatedCovMatrixXX(covMatrixPCA, phi, 0.)); + + // fill the candidate table for the B0 here: + rowCandidateB0DStar(collision.globalIndex(), + collision.posX(), collision.posY(), collision.posZ(), + secondaryVertexB0[0], secondaryVertexB0[1], secondaryVertexB0[2], + errorDecayLength, errorDecayLengthXY, + chi2PCA, + pVecD0[0], pVecD0[1], pVecD0[2], + pVecSoftPion[0], pVecSoftPion[1], pVecSoftPion[2], + pVecBachPion[0], pVecBachPion[1], pVecBachPion[2], + dcaD.getY(), dcaSoftPion.getY(), dcaBachPion.getY(), + std::sqrt(dcaD.getSigmaY2()), std::sqrt(dcaSoftPion.getSigmaY2()), std::sqrt(dcaBachPion.getSigmaY2())); + + rowCandidateProngsDStar(candD.globalIndex(), trackBachPion.globalIndex(), trackSoftPion.globalIndex()); + + if constexpr (withDmesMl) { + rowCandidateDmesMlScores(candD.mlScoreBkgMassHypo0(), candD.mlScorePromptMassHypo0(), candD.mlScoreNonpromptMassHypo0()); + } + } // pi loop + } // D loop + } + /// Main function to perform B0 candidate creation /// \param withDmesMl is the flag to use the table with ML scores for the D- daughter (only possible if present in the derived data) /// \param collision the collision @@ -126,8 +248,8 @@ struct HfCandidateCreatorB0Reduced { void runCandidateCreation(Coll const& collision, Cands const& candsDThisColl, Pions const& tracksPionThisCollision, - const float& invMass2DPiMin, - const float& invMass2DPiMax) + const float invMass2DPiMin, + const float invMass2DPiMax) { auto primaryVertex = getPrimaryVertex(collision); auto covMatrixPV = primaryVertex.getCov(); @@ -150,7 +272,7 @@ struct HfCandidateCreatorB0Reduced { std::array pVecPion = trackPion.pVector(); // compute invariant mass square and apply selection - auto invMass2DPi = RecoDecay::m2(std::array{pVecD, pVecPion}, std::array{massD, massPi}); + auto invMass2DPi = RecoDecay::m2(std::array{pVecD, pVecPion}, std::array{o2::constants::physics::MassDMinus, o2::constants::physics::MassPiPlus}); if ((invMass2DPi < invMass2DPiMin) || (invMass2DPi > invMass2DPiMax)) { continue; } @@ -218,11 +340,11 @@ struct HfCandidateCreatorB0Reduced { } // D loop } - void processData(HfRedCollisionsWithExtras const& collisions, - soa::Join const& candsD, - soa::Join const& tracksPion, - aod::HfOrigColCounts const& collisionsCounter, - aod::HfCandB0Configs const& configs) + void processDataDplusPi(HfRedCollisionsWithExtras const& collisions, + soa::Join const& candsD, + soa::Join const& tracksPion, + aod::HfOrigColCounts const& collisionsCounter, + aod::HfCandB0Configs const& configs) { // DPi invariant-mass window cut for (const auto& config : configs) { @@ -230,8 +352,8 @@ struct HfCandidateCreatorB0Reduced { } // invMassWindowDPiTolerance is used to apply a slightly tighter cut than in DPi pair preselection // to avoid accepting DPi pairs that were not formed in DPi pair creator - float invMass2DPiMin = (massB0 - myInvMassWindowDPi + invMassWindowDPiTolerance) * (massB0 - myInvMassWindowDPi + invMassWindowDPiTolerance); - float invMass2DPiMax = (massB0 + myInvMassWindowDPi - invMassWindowDPiTolerance) * (massB0 + myInvMassWindowDPi - invMassWindowDPiTolerance); + float invMass2DPiMin = (o2::constants::physics::MassB0 - myInvMassWindowDPi + invMassWindowDPiTolerance) * (o2::constants::physics::MassB0 - myInvMassWindowDPi + invMassWindowDPiTolerance); + float invMass2DPiMax = (o2::constants::physics::MassB0 + myInvMassWindowDPi - invMassWindowDPiTolerance) * (o2::constants::physics::MassB0 + myInvMassWindowDPi - invMassWindowDPiTolerance); for (const auto& collisionCounter : collisionsCounter) { registry.fill(HIST("hEvents"), 1, collisionCounter.originalCollisionCount()); @@ -240,7 +362,7 @@ struct HfCandidateCreatorB0Reduced { static int ncol = 0; for (const auto& collision : collisions) { auto thisCollId = collision.globalIndex(); - auto candsDThisColl = candsD.sliceBy(candsDPerCollision, thisCollId); + auto candsDThisColl = candsD.sliceBy(candsDplusPerCollision, thisCollId); auto tracksPionThisCollision = tracksPion.sliceBy(tracksPionPerCollision, thisCollId); runCandidateCreation(collision, candsDThisColl, tracksPionThisCollision, invMass2DPiMin, invMass2DPiMax); if (ncol % 10000 == 0) { @@ -248,15 +370,15 @@ struct HfCandidateCreatorB0Reduced { } ncol++; } - } // processData + } // processDataDplusPi - PROCESS_SWITCH(HfCandidateCreatorB0Reduced, processData, "Process data without any ML score", true); + PROCESS_SWITCH(HfCandidateCreatorB0Reduced, processDataDplusPi, "Process data D-pi without any ML score", true); - void processDataWithDmesMl(HfRedCollisionsWithExtras const& collisions, - soa::Join const& candsD, - soa::Join const& tracksPion, - aod::HfOrigColCounts const& collisionsCounter, - aod::HfCandB0Configs const& configs) + void processDataDplusPiWithDmesMl(HfRedCollisionsWithExtras const& collisions, + soa::Join const& candsD, + soa::Join const& tracksPion, + aod::HfOrigColCounts const& collisionsCounter, + aod::HfCandB0Configs const& configs) { // DPi invariant-mass window cut for (const auto& config : configs) { @@ -264,8 +386,8 @@ struct HfCandidateCreatorB0Reduced { } // invMassWindowDPiTolerance is used to apply a slightly tighter cut than in DPi pair preselection // to avoid accepting DPi pairs that were not formed in DPi pair creator - float invMass2DPiMin = (massB0 - myInvMassWindowDPi + invMassWindowDPiTolerance) * (massB0 - myInvMassWindowDPi + invMassWindowDPiTolerance); - float invMass2DPiMax = (massB0 + myInvMassWindowDPi - invMassWindowDPiTolerance) * (massB0 + myInvMassWindowDPi - invMassWindowDPiTolerance); + float invMass2DPiMin = (o2::constants::physics::MassB0 - myInvMassWindowDPi + invMassWindowDPiTolerance) * (o2::constants::physics::MassB0 - myInvMassWindowDPi + invMassWindowDPiTolerance); + float invMass2DPiMax = (o2::constants::physics::MassB0 + myInvMassWindowDPi - invMassWindowDPiTolerance) * (o2::constants::physics::MassB0 + myInvMassWindowDPi - invMassWindowDPiTolerance); for (const auto& collisionCounter : collisionsCounter) { registry.fill(HIST("hEvents"), 1, collisionCounter.originalCollisionCount()); @@ -274,7 +396,7 @@ struct HfCandidateCreatorB0Reduced { static int ncol = 0; for (const auto& collision : collisions) { auto thisCollId = collision.globalIndex(); - auto candsDThisColl = candsD.sliceBy(candsDPerCollision, thisCollId); + auto candsDThisColl = candsD.sliceBy(candsDplusPerCollision, thisCollId); auto tracksPionThisCollision = tracksPion.sliceBy(tracksPionPerCollision, thisCollId); runCandidateCreation(collision, candsDThisColl, tracksPionThisCollision, invMass2DPiMin, invMass2DPiMax); if (ncol % 10000 == 0) { @@ -282,14 +404,86 @@ struct HfCandidateCreatorB0Reduced { } ncol++; } - } // processDataWithDmesMl + } // processDataDplusPiWithDmesMl + + PROCESS_SWITCH(HfCandidateCreatorB0Reduced, processDataDplusPiWithDmesMl, "Process data D-pi with ML scores of D mesons", false); + + void processDataDstarPi(HfRedCollisionsWithExtras const& collisions, + soa::Join const& candsD, + HfSoftPiWCovAndPid const& softPions, + soa::Join const& tracksPion, + aod::HfOrigColCounts const& collisionsCounter, + aod::HfCandB0Configs const& configs) + { + // DPi invariant-mass window cut + for (const auto& config : configs) { + myInvMassWindowDPi = config.myInvMassWindowDPi(); + } + // invMassWindowDPiTolerance is used to apply a slightly tighter cut than in DPi pair preselection + // to avoid accepting DPi pairs that were not formed in DPi pair creator + float invMass2DPiMin = (o2::constants::physics::MassB0 - myInvMassWindowDPi + invMassWindowDPiTolerance) * (o2::constants::physics::MassB0 - myInvMassWindowDPi + invMassWindowDPiTolerance); + float invMass2DPiMax = (o2::constants::physics::MassB0 + myInvMassWindowDPi - invMassWindowDPiTolerance) * (o2::constants::physics::MassB0 + myInvMassWindowDPi - invMassWindowDPiTolerance); + + for (const auto& collisionCounter : collisionsCounter) { + registry.fill(HIST("hEvents"), 1, collisionCounter.originalCollisionCount()); + } + + static int ncol = 0; + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsD.sliceBy(candsDstarPerCollision, thisCollId); + auto tracksPionThisCollision = tracksPion.sliceBy(tracksPionPerCollision, thisCollId); + runCandidateCreationDStar(collision, candsDThisColl, softPions, tracksPionThisCollision, invMass2DPiMin, invMass2DPiMax); + if (ncol % 10000 == 0) { + LOGP(debug, "collisions parsed {}", ncol); + } + ncol++; + } + } // processDataDstarPi + + PROCESS_SWITCH(HfCandidateCreatorB0Reduced, processDataDstarPi, "Process data D*pi without any ML score", false); + + void processDataDstarPiWithDmesMl(HfRedCollisionsWithExtras const& collisions, + soa::Join const& candsD, + HfSoftPiWCovAndPid const& softPions, + soa::Join const& tracksPion, + aod::HfOrigColCounts const& collisionsCounter, + aod::HfCandB0Configs const& configs) + { + // DPi invariant-mass window cut + for (const auto& config : configs) { + myInvMassWindowDPi = config.myInvMassWindowDPi(); + } + // invMassWindowDPiTolerance is used to apply a slightly tighter cut than in DPi pair preselection + // to avoid accepting DPi pairs that were not formed in DPi pair creator + float invMass2DPiMin = (o2::constants::physics::MassB0 - myInvMassWindowDPi + invMassWindowDPiTolerance) * (o2::constants::physics::MassB0 - myInvMassWindowDPi + invMassWindowDPiTolerance); + float invMass2DPiMax = (o2::constants::physics::MassB0 + myInvMassWindowDPi - invMassWindowDPiTolerance) * (o2::constants::physics::MassB0 + myInvMassWindowDPi - invMassWindowDPiTolerance); + + for (const auto& collisionCounter : collisionsCounter) { + registry.fill(HIST("hEvents"), 1, collisionCounter.originalCollisionCount()); + } + + static int ncol = 0; + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsD.sliceBy(candsDstarWithMlPerCollision, thisCollId); + auto tracksPionThisCollision = tracksPion.sliceBy(tracksPionPerCollision, thisCollId); + runCandidateCreationDStar(collision, candsDThisColl, softPions, tracksPionThisCollision, invMass2DPiMin, invMass2DPiMax); + if (ncol % 10000 == 0) { + LOGP(debug, "collisions parsed {}", ncol); + } + ncol++; + } + } // processDataDstarPiWithDmesMl + + PROCESS_SWITCH(HfCandidateCreatorB0Reduced, processDataDstarPiWithDmesMl, "Process data D*pi with ML scores of D mesons", false); - PROCESS_SWITCH(HfCandidateCreatorB0Reduced, processDataWithDmesMl, "Process data with ML scores of D mesons", false); }; // struct /// Extends the table base with expression columns and performs MC matching. struct HfCandidateCreatorB0ReducedExpressions { Spawns rowCandidateB0; + Spawns rowCandidateB0DSt; Spawns rowTracksExt; Produces rowB0McRec; Produces rowB0McCheck; @@ -298,14 +492,20 @@ struct HfCandidateCreatorB0ReducedExpressions { /// \param checkDecayTypeMc /// \param rowsDPiMcRec MC reco information on DPi pairs /// \param candsB0 prong global indices of B0 candidates - template - void fillB0McRec(McRec const& rowsDPiMcRec, HfRedB0Prongs const& candsB0) + template + void fillB0McRec(McRec const& rowsDPiMcRec, B0Prongs const& candsB0) { for (const auto& candB0 : candsB0) { bool filledMcInfo{false}; for (const auto& rowDPiMcRec : rowsDPiMcRec) { - if ((rowDPiMcRec.prong0Id() != candB0.prong0Id()) || (rowDPiMcRec.prong1Id() != candB0.prong1Id())) { - continue; + if constexpr (std::is_same_v) { + if ((rowDPiMcRec.prong0Id() != candB0.prong0Id()) || (rowDPiMcRec.prong1Id() != candB0.prong1Id())) { + continue; + } + } else if constexpr (std::is_same_v) { // No need to check ID of soft pion, it is the same as D0 + if ((rowDPiMcRec.prongD0Id() != candB0.prongD0Id()) || (rowDPiMcRec.prongBachPiId() != candB0.prongBachPiId())) { + continue; + } } rowB0McRec(rowDPiMcRec.flagMcMatchRec(), -1 /*channel*/, rowDPiMcRec.flagWrongCollision(), rowDPiMcRec.debugMcRec(), rowDPiMcRec.ptMother()); filledMcInfo = true; @@ -328,17 +528,29 @@ struct HfCandidateCreatorB0ReducedExpressions { } } - void processMc(HfMcRecRedDpPis const& rowsDPiMcRec, HfRedB0Prongs const& candsB0) + void processMcDplusPi(HfMcRecRedDpPis const& rowsDPiMcRec, HfRedB0Prongs const& candsB0) + { + fillB0McRec(rowsDPiMcRec, candsB0); + } + PROCESS_SWITCH(HfCandidateCreatorB0ReducedExpressions, processMcDplusPi, "Process MC for DplusPi", false); + + void processMcDplusPiWithDecayTypeCheck(soa::Join const& rowsDPiMcRec, HfRedB0Prongs const& candsB0) + { + fillB0McRec(rowsDPiMcRec, candsB0); + } + PROCESS_SWITCH(HfCandidateCreatorB0ReducedExpressions, processMcDplusPiWithDecayTypeCheck, "Process MC with decay type checks for DplusPi", false); + + void processMcDstarPi(HfMcRecRedDStarPis const& rowsDPiMcRec, HfRedB0ProngDStars const& candsB0) { fillB0McRec(rowsDPiMcRec, candsB0); } - PROCESS_SWITCH(HfCandidateCreatorB0ReducedExpressions, processMc, "Process MC", false); + PROCESS_SWITCH(HfCandidateCreatorB0ReducedExpressions, processMcDstarPi, "Process MC for DstarPi", false); - void processMcWithDecayTypeCheck(soa::Join const& rowsDPiMcRec, HfRedB0Prongs const& candsB0) + void processMcDstarPiWithDecayTypeCheck(soa::Join const& rowsDPiMcRec, HfRedB0ProngDStars const& candsB0) { fillB0McRec(rowsDPiMcRec, candsB0); } - PROCESS_SWITCH(HfCandidateCreatorB0ReducedExpressions, processMcWithDecayTypeCheck, "Process MC with decay type checks", false); + PROCESS_SWITCH(HfCandidateCreatorB0ReducedExpressions, processMcDstarPiWithDecayTypeCheck, "Process MC with decay type checks for DstarPi", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx b/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx index 53609fc66c9..51ba23c8511 100644 --- a/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx @@ -103,13 +103,14 @@ struct HfCandidateSelectorB0ToDPiReduced { TrackSelectorPi selectorPion; HfHelper hfHelper; - using TracksPion = soa::Join; + using TracksBachPion = soa::Join; + using TracksSoftPions = soa::Join; HistogramRegistry registry{"registry"}; void init(InitContext const&) { - std::array doprocess{doprocessSelection, doprocessSelectionWithDmesMl}; + std::array doprocess{doprocessSelectionDplusPi, doprocessSelectionDplusPiWithDmesMl, doprocessSelectionDstarPi, doprocessSelectionDstarPiWithDmesMl}; if ((std::accumulate(doprocess.begin(), doprocess.end(), 0)) != 1) { LOGP(fatal, "Only one process function for data should be enabled at a time."); } @@ -155,6 +156,55 @@ struct HfCandidateSelectorB0ToDPiReduced { } } + /// Utility function to retrieve the bach pion track + /// from the B0 candidate in the D*-pi decay channel + /// \param candidate is the B0 candidate + /// \return bach pion track + template + auto getTrackBachPi(const T1& candidate) + { + return candidate.template prongBachPi_as(); + } + + /// Method to get the input features vector needed for ML inference + /// \param candidate is the B0 candidate + /// \param prongBachPi is the candidate's bachelor pion prong + /// \note this method is used for B0 → D*- π+ candidates with D meson ML scores + template + auto getMlInputFeatures(const T1& candB0, const T2& prongBachPi) + { + auto prongSoftPi = candB0.template prongSoftPi_as(); + if constexpr (withDmesMl) { + return hfMlResponse.getInputFeaturesDStarPi(candB0, prongBachPi, prongSoftPi); + } else { + return hfMlResponse.getInputFeaturesDStarPi(candB0, prongBachPi, prongSoftPi); + } + } + + /// Utility function to retrieve the bach pion track + /// from the B0 candidate in the D-pi decay channel + /// \param candidate is the B0 candidate + /// \return bach pion track + template + auto getTrackBachPi(const T1& candidate) + { + return candidate.template prong1_as(); + } + + /// Method to get the input features vector needed for ML inference + /// \param candB0 is the B0 candidate + /// \param prongBachPi is the candidate's bachelor pion prong + /// \note this method is used for B0 → D- π+ candidates with D meson ML scores + template + auto getMlInputFeatures(const T1& candB0, const T2& prongBachPi) + { + if constexpr (withDmesMl) { + return hfMlResponse.getInputFeatures(candB0, prongBachPi); + } else { + return hfMlResponse.getInputFeatures(candB0, prongBachPi); + } + } + /// Main function to perform B0 candidate creation /// \param withDmesMl is the flag to use the table with ML scores for the D- daughter (only possible if present in the derived data) /// \param hfCandsB0 B0 candidates @@ -162,7 +212,7 @@ struct HfCandidateSelectorB0ToDPiReduced { /// \param configs config inherited from the Dpi data creator template void runSelection(Cands const& hfCandsB0, - TracksPion const&, + TracksBachPion const&, HfCandB0Configs const& configs) { // get DplusPi creator configurable @@ -205,16 +255,15 @@ struct HfCandidateSelectorB0ToDPiReduced { registry.fill(HIST("hSelections"), 2 + SelectionStep::RecoTopol, ptCandB0); } - // track-level PID selection - auto trackPi = hfCandB0.template prong1_as(); + auto trackBachPi = getTrackBachPi(hfCandB0); if (pionPidMethod == PidMethod::TpcOrTof || pionPidMethod == PidMethod::TpcAndTof) { - int pidTrackPi{TrackSelectorPID::Status::NotApplicable}; + int pidTrackBachPi{TrackSelectorPID::Status::NotApplicable}; if (pionPidMethod == PidMethod::TpcOrTof) { - pidTrackPi = selectorPion.statusTpcOrTof(trackPi); + pidTrackBachPi = selectorPion.statusTpcOrTof(trackBachPi); } else if (pionPidMethod == PidMethod::TpcAndTof) { - pidTrackPi = selectorPion.statusTpcAndTof(trackPi); + pidTrackBachPi = selectorPion.statusTpcAndTof(trackBachPi); } - if (!hfHelper.selectionB0ToDPiPid(pidTrackPi, acceptPIDNotApplicable.value)) { + if (!hfHelper.selectionB0ToDPiPid(pidTrackBachPi, acceptPIDNotApplicable.value)) { // LOGF(info, "B0 candidate selection failed at PID selection"); hfSelB0ToDPiCandidate(statusB0ToDPi); if (applyB0Ml) { @@ -227,10 +276,9 @@ struct HfCandidateSelectorB0ToDPiReduced { registry.fill(HIST("hSelections"), 2 + SelectionStep::RecoPID, ptCandB0); } } - if (applyB0Ml) { // B0 ML selections - std::vector inputFeatures = hfMlResponse.getInputFeatures(hfCandB0, trackPi); + std::vector inputFeatures = getMlInputFeatures(hfCandB0, trackBachPi); bool isSelectedMl = hfMlResponse.isSelectedMl(inputFeatures, ptCandB0, outputMl); hfMlB0ToDPiCandidate(outputMl[1]); // storing ML score for signal class @@ -249,23 +297,43 @@ struct HfCandidateSelectorB0ToDPiReduced { } } - void processSelection(HfRedCandB0 const& hfCandsB0, - TracksPion const& pionTracks, - HfCandB0Configs const& configs) + void processSelectionDplusPi(HfRedCandB0 const& hfCandsB0, + TracksBachPion const& pionTracks, + HfCandB0Configs const& configs) + { + runSelection(hfCandsB0, pionTracks, configs); + } // processSelectionDplusPi + + PROCESS_SWITCH(HfCandidateSelectorB0ToDPiReduced, processSelectionDplusPi, "Process selection DplusPi without ML scores of D mesons", true); + + void processSelectionDplusPiWithDmesMl(soa::Join const& hfCandsB0, + TracksBachPion const& pionTracks, + HfCandB0Configs const& configs) + { + runSelection(hfCandsB0, pionTracks, configs); + } // processSelectionDplusPiWithDmesMl + + PROCESS_SWITCH(HfCandidateSelectorB0ToDPiReduced, processSelectionDplusPiWithDmesMl, "Process selection DplusPi with ML scores of D mesons", false); + + void processSelectionDstarPi(HfRedCandB0DStar const& hfCandsB0, + TracksBachPion const& pionTracks, + HfCandB0Configs const& configs, + TracksSoftPions const& /*softPions*/) { runSelection(hfCandsB0, pionTracks, configs); - } // processSelection + } // processSelectionDstarPi - PROCESS_SWITCH(HfCandidateSelectorB0ToDPiReduced, processSelection, "Process selection without ML scores of D mesons", true); + PROCESS_SWITCH(HfCandidateSelectorB0ToDPiReduced, processSelectionDstarPi, "Process selection DstarPi without ML scores of D mesons", false); - void processSelectionWithDmesMl(soa::Join const& hfCandsB0, - TracksPion const& pionTracks, - HfCandB0Configs const& configs) + void processSelectionDstarPiWithDmesMl(soa::Join const& hfCandsB0, + TracksBachPion const& pionTracks, + HfCandB0Configs const& configs, + TracksSoftPions const& /*softPions*/) { runSelection(hfCandsB0, pionTracks, configs); - } // processSelectionWithDmesMl + } // processSelectionDstarPiWithDmesMl - PROCESS_SWITCH(HfCandidateSelectorB0ToDPiReduced, processSelectionWithDmesMl, "Process selection with ML scores of D mesons", false); + PROCESS_SWITCH(HfCandidateSelectorB0ToDPiReduced, processSelectionDstarPiWithDmesMl, "Process selection DstarPi with ML scores of D mesons", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx index 0b73b385893..52ff971df9e 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx @@ -122,6 +122,7 @@ struct HfDataCreatorCharmHadPiReduced { Produces hfTrackPion; Produces hfTrackCovPion; Produces hfTrackPidPion; + Produces hfTrackMomPion; // charm hadron related tables Produces hfCand2Prong; Produces hfCand2ProngCov; @@ -129,9 +130,11 @@ struct HfDataCreatorCharmHadPiReduced { Produces hfCand3Prong; Produces hfCand3ProngCov; Produces hfCand3ProngMl; - // D* soft pion related tables + Produces hfMomDMesDaugs; + // D* related tables Produces hfTrackSoftPion; Produces hfTrackCovSoftPion; + Produces hfTrackPidSoftPion; // PID tables for charm-hadron candidate daughter tracks Produces hfCandPidProng0; Produces hfCandPidProng1; @@ -141,6 +144,7 @@ struct HfDataCreatorCharmHadPiReduced { Produces rowCandidateConfigB0; Produces rowHfDPiMcRecReduced; Produces rowHfDPiMcCheckReduced; + Produces rowHfDStarPiMcRecReduced; Produces rowHfB0McGenReduced; Produces rowCandidateConfigBplus; @@ -266,7 +270,7 @@ struct HfDataCreatorCharmHadPiReduced { PresliceUnsorted colPerMcCollision = aod::mccollisionlabel::mcCollisionId; } preslices; - std::shared_ptr hCandidatesD0, hCandidatesDPlus, hCandidatesDs, hCandidatesLc, hCandidatesDstar; + std::shared_ptr hCandidatesD0, hCandidatesDPlus, hCandidatesDs, hCandidatesLc, hCandidatesD0FromDstar; HistogramRegistry registry{"registry"}; std::array arrPDGResonantDsPhiPi = {kPhi, kPiPlus}; // Ds± → Phi π± @@ -306,8 +310,7 @@ struct HfDataCreatorCharmHadPiReduced { // Initialize fitter if (doprocessDplusPiData || doprocessDplusPiDataWithMl || doprocessDplusPiDataWithQvec || doprocessDplusPiDataWithMlAndQvec || doprocessDplusPiMc || doprocessDplusPiMcWithMl || doprocessDsPiData || doprocessDsPiDataWithMl || doprocessDsPiDataWithQvec || doprocessDsPiDataWithMlAndQvec || doprocessDsPiMc || doprocessDsPiMcWithMl || - doprocessLcPiData || doprocessLcPiDataWithMl || doprocessLcPiMc || doprocessLcPiMcWithMl || - doprocessDstarPiData || doprocessDstarPiDataWithMl || doprocessDstarPiDataWithQvec || doprocessDstarPiDataWithMlAndQvec || doprocessDstarPiMc || doprocessDstarPiMcWithMl) { + doprocessLcPiData || doprocessLcPiDataWithMl || doprocessLcPiMc || doprocessLcPiMcWithMl) { df3.setPropagateToPCA(vertexConfigurations.propagateToPCA); df3.setMaxR(vertexConfigurations.maxR); df3.setMaxDZIni(vertexConfigurations.maxDZIni); @@ -316,7 +319,8 @@ struct HfDataCreatorCharmHadPiReduced { df3.setUseAbsDCA(vertexConfigurations.useAbsDCA); df3.setWeightedFinalPCA(vertexConfigurations.useWeightedFinalPCA); df3.setMatCorrType(noMatCorr); - } else if (doprocessD0PiData || doprocessD0PiDataWithMl || doprocessD0PiDataWithQvec || doprocessD0PiDataWithMlAndQvec || doprocessD0PiMc || doprocessD0PiMcWithMl) { + } else if (doprocessD0PiData || doprocessD0PiDataWithMl || doprocessD0PiDataWithQvec || doprocessD0PiDataWithMlAndQvec || doprocessD0PiMc || doprocessD0PiMcWithMl || + doprocessDstarPiData || doprocessDstarPiDataWithMl || doprocessDstarPiDataWithQvec || doprocessDstarPiDataWithMlAndQvec || doprocessDstarPiMc || doprocessDstarPiMcWithMl) { df2.setPropagateToPCA(vertexConfigurations.propagateToPCA); df2.setMaxR(vertexConfigurations.maxR); df2.setMaxDZIni(vertexConfigurations.maxDZIni); @@ -381,13 +385,13 @@ struct HfDataCreatorCharmHadPiReduced { hCandidatesDPlus = registry.add("hCandidatesDPlus", "Dplus candidate counter", {HistType::kTH1D, {axisCands}}); hCandidatesDs = registry.add("hCandidatesDs", "Ds candidate counter", {HistType::kTH1D, {axisCands}}); hCandidatesLc = registry.add("hCandidatesLc", "Lc candidate counter", {HistType::kTH1D, {axisCands}}); - hCandidatesDstar = registry.add("hCandidatesDstar", "Dstar candidate counter", {HistType::kTH1D, {axisCands}}); + hCandidatesD0FromDstar = registry.add("hCandidatesD0FromDstar", "D0 from D* candidate counter", {HistType::kTH1D, {axisCands}}); setLabelHistoCands(hCandidatesD0); setLabelHistoCands(hCandidatesDPlus); setLabelHistoCands(hCandidatesDs); setLabelHistoCands(hCandidatesLc); - setLabelHistoCands(hCandidatesDstar); + setLabelHistoCands(hCandidatesD0FromDstar); // init HF event selection helper hfEvSel.init(registry); @@ -1006,7 +1010,7 @@ struct HfDataCreatorCharmHadPiReduced { checkWrongCollision(particleMother, collision, indexCollisionMaxNumContrib, flagWrongCollision); } } - tables.rowHfDPiMcRecReduced(indexHfCandCharm, selectedTracksPion[vecDaughtersB.back().globalIndex()], flag, flagWrongCollision, debug, motherPt); + tables.rowHfDStarPiMcRecReduced(indexHfCandCharm, selectedTracksPion[vecDaughtersB.back().globalIndex()], flag, flagWrongCollision, debug, motherPt); } } @@ -1050,6 +1054,7 @@ struct HfDataCreatorCharmHadPiReduced { LOG(info) << ">>>>>>>>>>>> Magnetic field: " << bz; runNumber = bc.runNumber(); } + df2.setBz(bz); df3.setBz(bz); auto thisCollId = collision.globalIndex(); @@ -1099,7 +1104,7 @@ struct HfDataCreatorCharmHadPiReduced { registry.fill(HIST("hPtLc"), candC.pt()); registry.fill(HIST("hCpaLc"), candC.cpa()); } else if constexpr (decChannel == DecayChannel::B0ToDstarPi) { - indexHfCandCharm = tables.hfCand3Prong.lastIndex() + 1; + indexHfCandCharm = tables.hfCand2Prong.lastIndex() + 1; if (candC.signSoftPi() > 0) { invMassC0 = candC.invMassDstar() - candC.invMassD0(); } else { @@ -1219,7 +1224,7 @@ struct HfDataCreatorCharmHadPiReduced { trackParCovCharmHad.setAbsCharge(0); // to be sure } else if constexpr (decChannel == DecayChannel::B0ToDstarPi) { - hCandidatesDstar->Fill(SVFitting::BeforeFit); + hCandidatesD0FromDstar->Fill(SVFitting::BeforeFit); try { // D0 vertex if (df2.process(trackParCov0, trackParCov1) == 0) { @@ -1227,10 +1232,10 @@ struct HfDataCreatorCharmHadPiReduced { } } catch (const std::runtime_error& error) { LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN cannot work, skipping the candidate."; - hCandidatesDstar->Fill(SVFitting::Fail); + hCandidatesD0FromDstar->Fill(SVFitting::Fail); continue; } - hCandidatesDstar->Fill(SVFitting::FitOk); + hCandidatesD0FromDstar->Fill(SVFitting::FitOk); auto secondaryVertexCharm = df2.getPCACandidate(); trackParCov0.propagateTo(secondaryVertexCharm[0], bz); trackParCov1.propagateTo(secondaryVertexCharm[0], bz); @@ -1312,6 +1317,7 @@ struct HfDataCreatorCharmHadPiReduced { trackParCovPion.getSigma1PtTgl(), trackParCovPion.getSigma1Pt2()); tables.hfTrackPidPion(trackPion.hasTPC(), trackPion.hasTOF(), trackPion.tpcNSigmaPi(), trackPion.tofNSigmaPi()); + tables.hfTrackMomPion(pVecPion[0], pVecPion[1], pVecPion[2], trackPion.sign()); // add trackPion.globalIndex() to a list // to keep memory of the pions filled in the table and avoid refilling them if they are paired to another D candidate // and keep track of their index in tables.hfTrackPion for McRec purposes @@ -1445,13 +1451,18 @@ struct HfDataCreatorCharmHadPiReduced { trackParCovSoftPion.getSigmaTglSnp(), trackParCovSoftPion.getSigmaTgl2(), trackParCovSoftPion.getSigma1PtY(), trackParCovSoftPion.getSigma1PtZ(), trackParCovSoftPion.getSigma1PtSnp(), trackParCovSoftPion.getSigma1PtTgl(), trackParCovSoftPion.getSigma1Pt2()); + tables.hfTrackPidSoftPion(candC.nSigTpcPi2(), candC.nSigTofPi2(), charmHadDauTracks[2].hasTOF(), charmHadDauTracks[2].hasTPC()); if constexpr (withMl) { std::array mlScores = {-1.f, -1.f, -1.f, -1.f, -1.f, -1.f}; if (candC.mlProbDstarToD0Pi().size() == NSizeMLScore) { std::copy(candC.mlProbDstarToD0Pi().begin(), candC.mlProbDstarToD0Pi().end(), mlScores.begin()); } - tables.hfCand3ProngMl(mlScores[0], mlScores[1], mlScores[2], -1.f, -1.f, -1.f); + tables.hfCand3ProngMl(mlScores[0], mlScores[1], mlScores[2], mlScores[3], mlScores[4], mlScores[5]); } + + tables.hfMomDMesDaugs(pVec0[0], pVec0[1], pVec0[2], + pVec1[0], pVec1[1], pVec1[2], + pVecSoftPion[0], pVecSoftPion[1], pVecSoftPion[2]); } fillHfReducedCollision = true; } diff --git a/PWGHF/D2H/Tasks/taskB0Reduced.cxx b/PWGHF/D2H/Tasks/taskB0Reduced.cxx index e1e30490f18..169e4fcd834 100644 --- a/PWGHF/D2H/Tasks/taskB0Reduced.cxx +++ b/PWGHF/D2H/Tasks/taskB0Reduced.cxx @@ -40,6 +40,7 @@ #include #include #include +#include using namespace o2; using namespace o2::aod; @@ -191,8 +192,10 @@ struct HfTaskB0Reduced { HfHelper hfHelper; - using TracksPion = soa::Join; + using TracksBachPions = soa::Join; using CandsDplus = soa::Join; + using CandsDstar = soa::Join; + using TracksSoftPions = soa::Join; Filter filterSelectCandidates = (aod::hf_sel_candidate_b0::isSelB0ToDPi >= selectionFlagB0); @@ -200,11 +203,13 @@ struct HfTaskB0Reduced { void init(InitContext&) { - std::array processFuncData{doprocessData, doprocessDataWithDmesMl, doprocessDataWithB0Ml}; + std::array processFuncData{doprocessDataDplusPi, doprocessDataDplusPiWithDmesMl, doprocessDataDplusPiWithB0Ml, + doprocessDataDstarPi, doprocessDataDstarPiWithDmesMl}; if ((std::accumulate(processFuncData.begin(), processFuncData.end(), 0)) > 1) { LOGP(fatal, "Only one process function for data can be enabled at a time."); } - std::array processFuncMc{doprocessMc, doprocessMcWithDecayTypeCheck, doprocessMcWithDmesMl, doprocessMcWithDmesMlAndDecayTypeCheck, doprocessMcWithB0Ml, doprocessMcWithB0MlAndDecayTypeCheck}; + std::array processFuncMc{doprocessMcDplusPi, doprocessMcDplusPiWithDecayTypeCheck, doprocessMcDplusPiWithDmesMl, doprocessMcDplusPiWithDmesMlAndDecayTypeCheck, doprocessMcDplusPiWithB0Ml, doprocessMcDplusPiWithB0MlAndDecayTypeCheck, + doprocessMcDstarPi, doprocessMcDstarPiWithDmesMl}; if ((std::accumulate(processFuncMc.begin(), processFuncMc.end(), 0)) > 1) { LOGP(fatal, "Only one process function for MC can be enabled at a time."); } @@ -212,6 +217,7 @@ struct HfTaskB0Reduced { const AxisSpec axisMlScore{100, 0.f, 1.f}; const AxisSpec axisMassB0{300, 4.5f, 6.0f}; const AxisSpec axisMassDminus{300, 1.75f, 2.05f}; + const AxisSpec axisMassDeltaMassDStar{300, 0.05f, 0.3f}; const AxisSpec axisDecayLength{200, 0.f, 0.4f}; const AxisSpec axisNormDecayLength{100, 0.f, 50.f}; const AxisSpec axisDca{100, -0.05f, 0.05f}; @@ -219,63 +225,94 @@ struct HfTaskB0Reduced { const AxisSpec axisEta{30, -1.5f, 1.5f}; const AxisSpec axisError{100, 0.f, 1.f}; const AxisSpec axisImpParProd{100, -1.e-3, 1.e-3}; + const AxisSpec axisImpParProngSqSum{100, 0, 1.e-3}; const AxisSpec axisPtB0{100, 0.f, 50.f}; const AxisSpec axisPtDminus{100, 0.f, 50.f}; const AxisSpec axisPtPi{100, 0.f, 10.f}; + const AxisSpec axisPtSoftPi{100, 0.f, 1.f}; - if (doprocessData || doprocessDataWithDmesMl || doprocessDataWithB0Ml) { + std::array processFuncDplusPi = {doprocessDataDplusPi, doprocessDataDplusPiWithDmesMl, doprocessDataDplusPiWithB0Ml, + doprocessMcDplusPi, doprocessMcDplusPiWithDecayTypeCheck, doprocessMcDplusPiWithDmesMl, + doprocessMcDplusPiWithDmesMlAndDecayTypeCheck, doprocessMcDplusPiWithB0Ml, + doprocessMcDplusPiWithB0MlAndDecayTypeCheck}; + const AxisSpec axisMass = ((std::accumulate(processFuncDplusPi.begin(), processFuncDplusPi.end(), 0)) > 0) ? axisMassDminus : axisMassDeltaMassDStar; + std::string dMesSpecie{""}; + if ((std::accumulate(processFuncDplusPi.begin(), processFuncDplusPi.end(), 0)) > 0) { + dMesSpecie += "D^{#minus}"; + } else { + dMesSpecie += "D^{0}#pi^{#minus}"; + } + + if (doprocessDataDplusPi || doprocessDataDplusPiWithDmesMl || doprocessDataDplusPiWithB0Ml || doprocessDataDstarPi || doprocessDataDstarPiWithDmesMl) { if (fillHistograms) { registry.add("hMass", "B^{0} candidates;#it{p}_{T}(B^{0}) (GeV/#it{c});#it{M} (D#pi) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {axisPtB0, axisMassB0}}); registry.add("hDecLength", "B^{0} candidates;#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate decay length (cm);entries", {HistType::kTH2F, {axisPtB0, axisDecayLength}}); registry.add("hDecLengthXy", "B^{0} candidates;#it{p}_{T}(B^{0}) (GeV/#it{c});decay length XY (cm);entries", {HistType::kTH2F, {axisPtB0, axisDecayLength}}); registry.add("hNormDecLengthXy", "B^{0} candidates;#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate norm. decay length XY (cm);entries", {HistType::kTH2F, {axisPtB0, axisNormDecayLength}}); - registry.add("hDcaProng0", "B^{0} candidates;#it{p}_{T}(B^{0}) (GeV/#it{c});prong 0 (D^{#minus}) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {axisPtB0, axisDca}}); + registry.add("hDcaProng0", Form("B^{0} candidates;#it{p}_{T}(B^{0}) (GeV/#it{c});prong 0 (%s) DCAxy to prim. vertex (cm);entries", dMesSpecie.c_str()), {HistType::kTH2F, {axisPtB0, axisDca}}); registry.add("hDcaProng1", "B^{0} candidates;#it{p}_{T}(B^{0}) (GeV/#it{c});prong 1 (#pi^{#plus}) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {axisPtB0, axisDca}}); - registry.add("hPtProng0", "B^{0} candidates;#it{p}_{T}(B^{0}) (GeV/#it{c});#it{p}_{T}(D^{#minus}) (GeV/#it{c});entries", {HistType::kTH2F, {axisPtB0, axisPtDminus}}); - registry.add("hPtProng1", "B^{0} candidates;#it{p}_{T}(B^{0}) (GeV/#it{c});#it{p}_{T}(#pi^{#plus}) (GeV/#it{c});entries", {HistType::kTH2F, {axisPtB0, axisPtPi}}); registry.add("hCosp", "B^{0} candidates;#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate cos(#vartheta_{P});entries", {HistType::kTH2F, {axisPtB0, axisCosp}}); registry.add("hCospXy", "B^{0} candidates;#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate cos(#vartheta_{P}^{XY});entries", {HistType::kTH2F, {axisPtB0, axisCosp}}); registry.add("hEta", "B^{0} candidates;#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate #it{#eta};entries", {HistType::kTH2F, {axisPtB0, axisEta}}); registry.add("hRapidity", "B^{0} candidates;#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate #it{y};entries", {HistType::kTH2F, {axisPtB0, axisEta}}); - registry.add("hImpParProd", "B^{0} candidates;#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate impact parameter product;entries", {HistType::kTH2F, {axisPtB0, axisImpParProd}}); - registry.add("hInvMassD", "B^{0} candidates;#it{p}_{T}(D^{#minus}) (GeV/#it{c});prong0, #it{M}(K#pi) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {axisPtDminus, axisMassDminus}}); - registry.add("hDecLengthD", "B^{0} candidates;#it{p}_{T}(D^{#minus}) (GeV/#it{c});D^{#minus} candidate decay length (cm);entries", {HistType::kTH2F, {axisPtDminus, axisDecayLength}}); - registry.add("hDecLengthXyD", "B^{0} candidates;#it{p}_{T}(D^{#minus}) (GeV/#it{c});decay length XY (cm);entries", {HistType::kTH2F, {axisPtDminus, axisDecayLength}}); - registry.add("hCospD", "B^{0} candidates;#it{p}_{T}(D^{#minus}) (GeV/#it{c});D^{#minus} candidate cos(#vartheta_{P});entries", {HistType::kTH2F, {axisPtDminus, axisCosp}}); - registry.add("hCospXyD", "B^{0} candidates;#it{p}_{T}(D^{#minus}) (GeV/#it{c});D^{#minus} candidate cos(#vartheta_{P}^{XY});entries", {HistType::kTH2F, {axisPtDminus, axisCosp}}); + registry.add("hInvMassD", Form("B^{0} candidates;#it{p}_{T}(%s) (GeV/#it{c});prong0, #it{M}(K#pi) (GeV/#it{c}^{2});entries", dMesSpecie.c_str()), {HistType::kTH2F, {axisPtDminus, axisMass}}); + registry.add("hDecLengthD", Form("B^{0} candidates;#it{p}_{T}(%s) (GeV/#it{c});%s candidate decay length (cm);entries", dMesSpecie.c_str(), dMesSpecie.c_str()), {HistType::kTH2F, {axisPtDminus, axisDecayLength}}); + registry.add("hDecLengthXyD", Form("B^{0} candidates;#it{p}_{T}(%s) (GeV/#it{c});decay length XY (cm);entries", dMesSpecie.c_str()), {HistType::kTH2F, {axisPtDminus, axisDecayLength}}); + registry.add("hCospD", Form("B^{0} candidates;#it{p}_{T}(%s) (GeV/#it{c});%s candidate cos(#vartheta_{P});entries", dMesSpecie.c_str(), dMesSpecie.c_str()), {HistType::kTH2F, {axisPtDminus, axisCosp}}); + registry.add("hCospXyD", Form("B^{0} candidates;#it{p}_{T}(%s) (GeV/#it{c});%s candidate cos(#vartheta_{P}^{XY});entries", dMesSpecie.c_str(), dMesSpecie.c_str()), {HistType::kTH2F, {axisPtDminus, axisCosp}}); + if ((std::accumulate(processFuncDplusPi.begin(), processFuncDplusPi.end(), 0)) > 0) { + registry.add("hImpParProd", "B^{0} candidates;#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate impact parameter product;entries", {HistType::kTH2F, {axisPtB0, axisImpParProd}}); + registry.add("hPtProng0", Form("B^{0} candidates;#it{p}_{T}(B^{0}) (GeV/#it{c});#it{p}_{T}(%s) (GeV/#it{c});entries", dMesSpecie.c_str()), {HistType::kTH2F, {axisPtB0, axisPtDminus}}); + registry.add("hPtProng1", "B^{0} candidates;#it{p}_{T}(B^{0}) (GeV/#it{c});#it{p}_{T}(#pi^{#plus}) (GeV/#it{c});entries", {HistType::kTH2F, {axisPtB0, axisPtPi}}); + } else { + registry.add("hImpParProngSqSum", "B^{0} candidates;#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate impact parameter sum;entries", {HistType::kTH2F, {axisPtB0, axisImpParProngSqSum}}); + registry.add("hPtProngD0", Form("B^{0} candidates;#it{p}_{T}(B^{0}) (GeV/#it{c});#it{p}_{T}(%s) (GeV/#it{c});entries", dMesSpecie.c_str()), {HistType::kTH2F, {axisPtB0, axisPtDminus}}); + registry.add("hPtProngSoftPi", "B^{0} candidates;#it{p}_{T}(B^{0}) (GeV/#it{c});#it{p}_{T}(#pi^{#plus}) (GeV/#it{c});entries", {HistType::kTH2F, {axisPtB0, axisPtSoftPi}}); + registry.add("hPtProngBachPi", "B^{0} candidates;#it{p}_{T}(B^{0}) (GeV/#it{c});#it{p}_{T}(#pi^{#plus}) (GeV/#it{c});entries", {HistType::kTH2F, {axisPtB0, axisPtPi}}); + registry.add("hDcaProng2", "B^{0} candidates;#it{p}_{T}(B^{0}) (GeV/#it{c});prong 2 (#pi^{#plus}) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {axisPtB0, axisDca}}); + } // ML scores of D- daughter - if (doprocessDataWithDmesMl) { - registry.add("hMlScoreBkgD", "B^{0} candidates;#it{p}_{T}(D^{#minus}) (GeV/#it{c});prong0, D^{#minus} ML background score;entries", {HistType::kTH2F, {axisPtDminus, axisMlScore}}); - registry.add("hMlScorePromptD", "B^{0} candidates;#it{p}_{T}(D^{#minus}) (GeV/#it{c});prong0, D^{#minus} ML prompt score;entries", {HistType::kTH2F, {axisPtDminus, axisMlScore}}); - registry.add("hMlScoreNonPromptD", "B^{0} candidates;#it{p}_{T}(D^{#minus}) (GeV/#it{c});prong0, D^{#minus} ML nonprompt score;entries", {HistType::kTH2F, {axisPtDminus, axisMlScore}}); + if (doprocessDataDplusPiWithDmesMl || doprocessDataDstarPiWithDmesMl) { + registry.add("hMlScoreBkgD", Form("B^{0} candidates;#it{p}_{T}(%s) (GeV/#it{c});prong0, %s ML background score;entries", dMesSpecie.c_str(), dMesSpecie.c_str()), {HistType::kTH2F, {axisPtDminus, axisMlScore}}); + registry.add("hMlScorePromptD", Form("B^{0} candidates;#it{p}_{T}(%s) (GeV/#it{c});prong0, %s ML prompt score;entries", dMesSpecie.c_str(), dMesSpecie.c_str()), {HistType::kTH2F, {axisPtDminus, axisMlScore}}); + registry.add("hMlScoreNonPromptD", Form("B^{0} candidates;#it{p}_{T}(%s) (GeV/#it{c});prong0, %s ML nonprompt score;entries", dMesSpecie.c_str(), dMesSpecie.c_str()), {HistType::kTH2F, {axisPtDminus, axisMlScore}}); } // ML scores of B0 candidate - if (doprocessDataWithB0Ml) { + if (doprocessDataDplusPiWithB0Ml) { registry.add("hMlScoreSigB0", "B^{0} candidates;#it{p}_{T}(B^{0}) (GeV/#it{c});prong0, B^{0} ML signal score;entries", {HistType::kTH2F, {axisPtB0, axisMlScore}}); } } if (fillSparses) { - if (!(doprocessDataWithDmesMl || doprocessDataWithB0Ml)) { - registry.add("hMassPtCutVars", "B^{0} candidates;#it{M} (D#pi) (GeV/#it{c}^{2});#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate decay length (cm);B^{0} candidate norm. decay length XY (cm);B^{0} candidate impact parameter product (cm);B^{0} candidate cos(#vartheta_{P});#it{M} (K#pi) (GeV/#it{c}^{2});#it{p}_{T}(D^{#minus}) (GeV/#it{c});D^{#minus} candidate decay length (cm);D^{#minus} candidate cos(#vartheta_{P})", {HistType::kTHnSparseF, {axisMassB0, axisPtB0, axisDecayLength, axisNormDecayLength, axisImpParProd, axisCosp, axisMassDminus, axisPtDminus, axisDecayLength, axisCosp}}); + if (!(doprocessDataDplusPiWithDmesMl || doprocessDataDplusPiWithB0Ml || doprocessDataDstarPiWithDmesMl)) { + if ((std::accumulate(processFuncDplusPi.begin(), processFuncDplusPi.end(), 0)) > 0) { + registry.add("hMassPtCutVars", "B^{0} candidates;#it{M} (D#pi) (GeV/#it{c}^{2});#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate decay length (cm);B^{0} candidate norm. decay length XY (cm);B^{0} candidate impact parameter product (cm);B^{0} candidate cos(#vartheta_{P});#it{M} (K#pi) (GeV/#it{c}^{2});#it{p}_{T}(%s) (GeV/#it{c});%s candidate decay length (cm);%s candidate cos(#vartheta_{P})", {HistType::kTHnSparseF, {axisMassB0, axisPtB0, axisDecayLength, axisNormDecayLength, axisImpParProd, axisCosp, axisMass, axisPtDminus, axisDecayLength, axisCosp}}); + } else { + registry.add("hMassPtCutVars", "B^{0} candidates;#it{M} (D#pi) (GeV/#it{c}^{2});#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate decay length (cm);B^{0} candidate norm. decay length XY (cm);B^{0} candidate impact parameter product (cm);B^{0} candidate cos(#vartheta_{P});#it{M} (K#pi) (GeV/#it{c}^{2});#it{p}_{T}(%s) (GeV/#it{c});%s candidate decay length (cm);%s candidate cos(#vartheta_{P})", {HistType::kTHnSparseF, {axisMassB0, axisPtB0, axisDecayLength, axisNormDecayLength, axisImpParProngSqSum, axisCosp, axisMass, axisPtDminus, axisDecayLength, axisCosp}}); + } } else { - registry.add("hMassPtCutVars", "B^{0} candidates;#it{M} (D#pi) (GeV/#it{c}^{2});#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate decay length (cm);B^{0} candidate norm. decay length XY (cm);B^{0} candidate impact parameter product (cm);B^{0} candidate cos(#vartheta_{P});#it{M} (K#pi) (GeV/#it{c}^{2});#it{p}_{T}(D^{#minus}) (GeV/#it{c});D^{#minus} candidate ML score bkg;D^{#minus} candidate ML score nonprompt", {HistType::kTHnSparseF, {axisMassB0, axisPtB0, axisDecayLength, axisNormDecayLength, axisImpParProd, axisCosp, axisMassDminus, axisPtDminus, axisMlScore, axisMlScore}}); + if ((std::accumulate(processFuncDplusPi.begin(), processFuncDplusPi.end(), 0)) > 0) { + registry.add("hMassPtCutVars", "B^{0} candidates;#it{M} (D#pi) (GeV/#it{c}^{2});#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate decay length (cm);B^{0} candidate norm. decay length XY (cm);B^{0} candidate impact parameter product (cm);B^{0} candidate cos(#vartheta_{P});#it{M} (K#pi) (GeV/#it{c}^{2});#it{p}_{T}(%s) (GeV/#it{c});%s candidate ML score bkg;%s candidate ML score nonprompt", {HistType::kTHnSparseF, {axisMassB0, axisPtB0, axisDecayLength, axisNormDecayLength, axisImpParProd, axisCosp, axisMass, axisPtDminus, axisMlScore, axisMlScore}}); + } else { + registry.add("hMassPtCutVars", "B^{0} candidates;#it{M} (D#pi) (GeV/#it{c}^{2});#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate decay length (cm);B^{0} candidate norm. decay length XY (cm);B^{0} candidate impact parameter product (cm);B^{0} candidate cos(#vartheta_{P});#it{M} (K#pi) (GeV/#it{c}^{2});#it{p}_{T}(%s) (GeV/#it{c});%s candidate ML score bkg;%s candidate ML score nonprompt", {HistType::kTHnSparseF, {axisMassB0, axisPtB0, axisDecayLength, axisNormDecayLength, axisImpParProngSqSum, axisCosp, axisMass, axisPtDminus, axisMlScore, axisMlScore}}); + } } } } - if (doprocessMc || doprocessMcWithDecayTypeCheck || doprocessMcWithDmesMl || doprocessMcWithDmesMlAndDecayTypeCheck || doprocessMcWithB0Ml || doprocessMcWithB0MlAndDecayTypeCheck) { + if (doprocessMcDplusPi || doprocessMcDplusPiWithDecayTypeCheck || doprocessMcDplusPiWithDmesMl || doprocessMcDplusPiWithDmesMlAndDecayTypeCheck || doprocessMcDplusPiWithB0Ml || doprocessMcDplusPiWithB0MlAndDecayTypeCheck || + doprocessMcDstarPi || doprocessMcDstarPiWithDmesMl) { if (fillHistograms) { // gen histos registry.add("hEtaGen", "B^{0} particles (generated);#it{p}_{T}^{gen}(B^{0}) (GeV/#it{c});#it{#eta}^{gen}(B^{0});entries", {HistType::kTH2F, {axisPtB0, axisEta}}); registry.add("hYGen", "B^{0} particles (generated);#it{p}_{T}^{gen}(B^{0}) (GeV/#it{c});#it{y}^{gen}(B^{0});entries", {HistType::kTH2F, {axisPtB0, axisEta}}); registry.add("hYGenWithProngsInAcceptance", "MC particles (generated-daughters in acceptance);#it{p}_{T}^{gen}(B^{0}) (GeV/#it{c});#it{y}^{gen}(B^{0});entries", {HistType::kTH2F, {axisPtB0, axisEta}}); - registry.add("hPtProng0Gen", "B^{0} particles (generated);#it{p}_{T}^{gen}(B^{0}) (GeV/#it{c});#it{p}_{T}^{gen}(D^{#minus}) (GeV/#it{c});entries", {HistType::kTH2F, {axisPtB0, axisPtDminus}}); + registry.add("hPtProng0Gen", Form("B^{0} particles (generated);#it{p}_{T}^{gen}(B^{0}) (GeV/#it{c});#it{p}_{T}^{gen}(%s) (GeV/#it{c});entries", dMesSpecie.c_str()), {HistType::kTH2F, {axisPtB0, axisPtDminus}}); registry.add("hPtProng1Gen", "B^{0} particles (generated);#it{p}_{T}^{gen}(B^{0}) (GeV/#it{c});#it{p}_{T}^{gen}(#pi^{#plus}) (GeV/#it{c});entries", {HistType::kTH2F, {axisPtB0, axisPtPi}}); - registry.add("hYProng0Gen", "B^{0} particles (generated);#it{p}_{T}^{gen}(B^{0}) (GeV/#it{c});#it{y}^{gen}(D^{#minus});entries", {HistType::kTH2F, {axisPtB0, axisEta}}); + registry.add("hYProng0Gen", Form("B^{0} particles (generated);#it{p}_{T}^{gen}(B^{0}) (GeV/#it{c});#it{y}^{gen}(%s);entries", dMesSpecie.c_str()), {HistType::kTH2F, {axisPtB0, axisEta}}); registry.add("hYProng1Gen", "B^{0} particles (generated);#it{p}_{T}^{gen}(B^{0}) (GeV/#it{c});#it{y}^{gen}(#pi^{#plus});entries", {HistType::kTH2F, {axisPtB0, axisEta}}); - registry.add("hEtaProng0Gen", "B^{0} particles (generated);#it{p}_{T}^{gen}(B^{0}) (GeV/#it{c});#it{#eta}^{gen}(D^{#minus});entries", {HistType::kTH2F, {axisPtB0, axisEta}}); + registry.add("hEtaProng0Gen", Form("B^{0} particles (generated);#it{p}_{T}^{gen}(B^{0}) (GeV/#it{c});#it{#eta}^{gen}(%s);entries", dMesSpecie.c_str()), {HistType::kTH2F, {axisPtB0, axisEta}}); registry.add("hEtaProng1Gen", "B^{0} particles (generated);#it{p}_{T}^{gen}(B^{0}) (GeV/#it{c});#it{#eta}^{gen}(#pi^{#plus});entries", {HistType::kTH2F, {axisPtB0, axisEta}}); // reco histos @@ -284,49 +321,68 @@ struct HfTaskB0Reduced { registry.add("hDecLengthRecSig", "B^{0} candidates (matched);#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate decay length (cm);entries", {HistType::kTH2F, {axisPtB0, axisDecayLength}}); registry.add("hDecLengthXyRecSig", "B^{0} candidates (matched);#it{p}_{T}(B^{0}) (GeV/#it{c});decay length XY (cm);entries", {HistType::kTH2F, {axisPtB0, axisDecayLength}}); registry.add("hNormDecLengthXyRecSig", "B^{0} candidates (matched);#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate norm. decay length XY (cm);entries", {HistType::kTH2F, {axisPtB0, axisNormDecayLength}}); - registry.add("hDcaProng0RecSig", "B^{0} candidates (matched);#it{p}_{T}(B^{0}) (GeV/#it{c});prong 0 (D^{#minus}) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {axisPtB0, axisDca}}); + registry.add("hDcaProng0RecSig", Form("B^{0} candidates (matched);#it{p}_{T}(B^{0}) (GeV/#it{c});prong 0 (%s) DCAxy to prim. vertex (cm);entries", dMesSpecie.c_str()), {HistType::kTH2F, {axisPtB0, axisDca}}); registry.add("hDcaProng1RecSig", "B^{0} candidates (matched);#it{p}_{T}(B^{0}) (GeV/#it{c});prong 1 (#pi^{#plus}) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {axisPtB0, axisDca}}); - registry.add("hPtProng0RecSig", "B^{0} candidates (matched);#it{p}_{T}(B^{0}) (GeV/#it{c});#it{p}_{T}(D^{#minus}) (GeV/#it{c});entries", {HistType::kTH2F, {axisPtB0, axisPtDminus}}); - registry.add("hPtProng1RecSig", "B^{0} candidates (matched);#it{p}_{T}(B^{0}) (GeV/#it{c});#it{p}_{T}(#pi^{#plus}) (GeV/#it{c});entries", {HistType::kTH2F, {axisPtB0, axisPtPi}}); registry.add("hCospRecSig", "B^{0} candidates (matched);#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate cos(#vartheta_{P});entries", {HistType::kTH2F, {axisPtB0, axisCosp}}); registry.add("hCospXyRecSig", "B^{0} candidates (matched);#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate cos(#vartheta_{P}^{XY});entries", {HistType::kTH2F, {axisPtB0, axisCosp}}); registry.add("hEtaRecSig", "B^{0} candidates (matched);#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate #it{#eta};entries", {HistType::kTH2F, {axisPtB0, axisEta}}); registry.add("hRapidityRecSig", "B^{0} candidates (matched);#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate #it{y};entries", {HistType::kTH2F, {axisPtB0, axisEta}}); - registry.add("hImpParProdRecSig", "B^{0} candidates (matched);#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate impact parameter product;entries", {HistType::kTH2F, {axisPtB0, axisImpParProd}}); - registry.add("hInvMassDRecSig", "B^{0} candidates (matched);#it{p}_{T}(D^{#minus}) (GeV/#it{c});prong0, #it{M}(K#pi) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {axisPtDminus, axisMassDminus}}); - registry.add("hDecLengthDRecSig", "B^{0} candidates (matched);#it{p}_{T}(D^{#minus}) (GeV/#it{c});D^{#minus} candidate decay length (cm);entries", {HistType::kTH2F, {axisPtDminus, axisDecayLength}}); - registry.add("hDecLengthXyDRecSig", "B^{0} candidates (matched);#it{p}_{T}(D^{#minus}) (GeV/#it{c});decay length XY (cm);entries", {HistType::kTH2F, {axisPtDminus, axisDecayLength}}); - registry.add("hCospDRecSig", "B^{0} candidates (matched);#it{p}_{T}(D^{#minus}) (GeV/#it{c});D^{#minus} candidate cos(#vartheta_{P});entries", {HistType::kTH2F, {axisPtDminus, axisCosp}}); - registry.add("hCospXyDRecSig", "B^{0} candidates (matched);#it{p}_{T}(D^{#minus}) (GeV/#it{c});D^{#minus} candidate cos(#vartheta_{P}^{XY});entries", {HistType::kTH2F, {axisPtDminus, axisCosp}}); + registry.add("hInvMassDRecSig", Form("B^{0} candidates (matched);#it{p}_{T}(%s) (GeV/#it{c});prong0, #it{M}(K#pi) (GeV/#it{c}^{2});entries", dMesSpecie.c_str()), {HistType::kTH2F, {axisPtDminus, axisMass}}); + registry.add("hDecLengthDRecSig", Form("B^{0} candidates (matched);#it{p}_{T}(%s) (GeV/#it{c});%s candidate decay length (cm);entries", dMesSpecie.c_str(), dMesSpecie.c_str()), {HistType::kTH2F, {axisPtDminus, axisDecayLength}}); + registry.add("hDecLengthXyDRecSig", Form("B^{0} candidates (matched);#it{p}_{T}(%s) (GeV/#it{c});decay length XY (cm);entries", dMesSpecie.c_str()), {HistType::kTH2F, {axisPtDminus, axisDecayLength}}); + registry.add("hCospDRecSig", Form("B^{0} candidates (matched);#it{p}_{T}(%s) (GeV/#it{c});%s candidate cos(#vartheta_{P});entries", dMesSpecie.c_str(), dMesSpecie.c_str()), {HistType::kTH2F, {axisPtDminus, axisCosp}}); + registry.add("hCospXyDRecSig", Form("B^{0} candidates (matched);#it{p}_{T}(%s) (GeV/#it{c});%s candidate cos(#vartheta_{P}^{XY});entries", dMesSpecie.c_str(), dMesSpecie.c_str()), {HistType::kTH2F, {axisPtDminus, axisCosp}}); + + if ((std::accumulate(processFuncDplusPi.begin(), processFuncDplusPi.end(), 0)) > 0) { + registry.add("hPtProng0RecSig", Form("B^{0} candidates (matched);#it{p}_{T}(B^{0}) (GeV/#it{c});#it{p}_{T}(%s) (GeV/#it{c});entries", dMesSpecie.c_str()), {HistType::kTH2F, {axisPtB0, axisPtDminus}}); + registry.add("hPtProng1RecSig", "B^{0} candidates (matched);#it{p}_{T}(B^{0}) (GeV/#it{c});#it{p}_{T}(#pi^{#plus}) (GeV/#it{c});entries", {HistType::kTH2F, {axisPtB0, axisPtPi}}); + registry.add("hImpParProdRecSig", "B^{0} candidates (matched);#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate impact parameter product;entries", {HistType::kTH2F, {axisPtB0, axisImpParProd}}); + } else { + registry.add("hPtProngD0RecSig", Form("B^{0} candidates (matched);#it{p}_{T}(B^{0}) (GeV/#it{c});#it{p}_{T}(%s) (GeV/#it{c});entries", dMesSpecie.c_str()), {HistType::kTH2F, {axisPtB0, axisPtDminus}}); + registry.add("hPtProngSoftPiRecSig", "B^{0} candidates (matched);#it{p}_{T}(B^{0}) (GeV/#it{c});#it{p}_{T}(#pi^{#plus}) (GeV/#it{c});entries", {HistType::kTH2F, {axisPtB0, axisPtSoftPi}}); + registry.add("hPtProngBachPiRecSig", "B^{0} candidates (matched);#it{p}_{T}(B^{0}) (GeV/#it{c});#it{p}_{T}(#pi^{#plus}) (GeV/#it{c});entries", {HistType::kTH2F, {axisPtB0, axisPtPi}}); + registry.add("hDcaProng2RecSig", "B^{0} candidates (matched);#it{p}_{T}(B^{0}) (GeV/#it{c});prong 2 (#pi^{#minus}) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {axisPtB0, axisDca}}); + registry.add("hImpParProngSqSumRecSig", "B^{0} candidates (matched);#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate impact parameter product;entries", {HistType::kTH2F, {axisPtB0, axisImpParProngSqSum}}); + } + // background if (fillBackground) { registry.add("hMassRecBg", "B^{0} candidates (unmatched);#it{p}_{T}(B^{0}) (GeV/#it{c});#it{M} (D#pi) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {axisPtB0, axisMassB0}}); registry.add("hDecLengthRecBg", "B^{0} candidates (unmatched);#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate decay length (cm);entries", {HistType::kTH2F, {axisPtB0, axisDecayLength}}); registry.add("hDecLengthXyRecBg", "B^{0} candidates (unmatched);#it{p}_{T}(B^{0}) (GeV/#it{c});decay length XY (cm);entries", {HistType::kTH2F, {axisPtB0, axisDecayLength}}); registry.add("hNormDecLengthXyRecBg", "B^{0} candidates (unmatched);#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate norm. decay length XY (cm);entries", {HistType::kTH2F, {axisPtB0, axisNormDecayLength}}); - registry.add("hDcaProng0RecBg", "B^{0} candidates (unmatched);#it{p}_{T}(B^{0}) (GeV/#it{c});prong 0 (D^{#minus}) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {axisPtB0, axisDca}}); + registry.add("hDcaProng0RecBg", Form("B^{0} candidates (unmatched);#it{p}_{T}(B^{0}) (GeV/#it{c});prong 0 (%s) DCAxy to prim. vertex (cm);entries", dMesSpecie.c_str()), {HistType::kTH2F, {axisPtB0, axisDca}}); registry.add("hDcaProng1RecBg", "B^{0} candidates (unmatched);#it{p}_{T}(B^{0}) (GeV/#it{c});prong 1 (#pi^{#plus}) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {axisPtB0, axisDca}}); - registry.add("hPtProng0RecBg", "B^{0} candidates (unmatched);#it{p}_{T}(B^{0}) (GeV/#it{c});#it{p}_{T}(D^{#minus}) (GeV/#it{c});entries", {HistType::kTH2F, {axisPtB0, axisPtDminus}}); - registry.add("hPtProng1RecBg", "B^{0} candidates (unmatched);#it{p}_{T}(B^{0}) (GeV/#it{c});#it{p}_{T}(#pi^{#plus}) (GeV/#it{c});entries", {HistType::kTH2F, {axisPtB0, axisPtPi}}); registry.add("hCospRecBg", "B^{0} candidates (unmatched);#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate cos(#vartheta_{P});entries", {HistType::kTH2F, {axisPtB0, axisCosp}}); registry.add("hCospXyRecBg", "B^{0} candidates (unmatched);#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate cos(#vartheta_{P}^{XY});entries", {HistType::kTH2F, {axisPtB0, axisCosp}}); registry.add("hEtaRecBg", "B^{0} candidates (unmatched);#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate #it{#eta};entries", {HistType::kTH2F, {axisPtB0, axisEta}}); registry.add("hRapidityRecBg", "B^{0} candidates (unmatched);#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate #it{y};entries", {HistType::kTH2F, {axisPtB0, axisEta}}); - registry.add("hImpParProdRecBg", "B^{0} candidates (unmatched);#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate impact parameter product;entries", {HistType::kTH2F, {axisPtB0, axisImpParProd}}); - registry.add("hInvMassDRecBg", "B^{0} candidates (unmatched);#it{p}_{T}(D^{#minus}) (GeV/#it{c});prong0, #it{M}(K#pi) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {axisPtDminus, axisMassDminus}}); - registry.add("hDecLengthDRecBg", "B^{0} candidates (unmatched);#it{p}_{T}(D^{#minus}) (GeV/#it{c});D^{#minus} candidate decay length (cm);entries", {HistType::kTH2F, {axisPtDminus, axisDecayLength}}); - registry.add("hDecLengthXyDRecBg", "B^{0} candidates (unmatched);#it{p}_{T}(D^{#minus}) (GeV/#it{c});decay length XY (cm);entries", {HistType::kTH2F, {axisPtDminus, axisDecayLength}}); - registry.add("hCospDRecBg", "B^{0} candidates (unmatched);#it{p}_{T}(D^{#minus}) (GeV/#it{c});D^{#minus} candidate cos(#vartheta_{P});entries", {HistType::kTH2F, {axisPtDminus, axisCosp}}); - registry.add("hCospXyDRecBg", "B^{0} candidates (unmatched);#it{p}_{T}(D^{#minus}) (GeV/#it{c});D^{#minus} candidate cos(#vartheta_{P}^{XY});entries", {HistType::kTH2F, {axisPtDminus, axisCosp}}); + registry.add("hInvMassDRecBg", Form("B^{0} candidates (unmatched);#it{p}_{T}(%s) (GeV/#it{c});prong0, #it{M}(K#pi) (GeV/#it{c}^{2});entries", dMesSpecie.c_str()), {HistType::kTH2F, {axisPtDminus, axisMass}}); + registry.add("hDecLengthDRecBg", Form("B^{0} candidates (unmatched);#it{p}_{T}(%s) (GeV/#it{c});%s candidate decay length (cm);entries", dMesSpecie.c_str(), dMesSpecie.c_str()), {HistType::kTH2F, {axisPtDminus, axisDecayLength}}); + registry.add("hDecLengthXyDRecBg", Form("B^{0} candidates (unmatched);#it{p}_{T}(%s) (GeV/#it{c});decay length XY (cm);entries", dMesSpecie.c_str()), {HistType::kTH2F, {axisPtDminus, axisDecayLength}}); + registry.add("hCospDRecBg", Form("B^{0} candidates (unmatched);#it{p}_{T}(%s) (GeV/#it{c});%s candidate cos(#vartheta_{P});entries", dMesSpecie.c_str(), dMesSpecie.c_str()), {HistType::kTH2F, {axisPtDminus, axisCosp}}); + registry.add("hCospXyDRecBg", Form("B^{0} candidates (unmatched);#it{p}_{T}(%s) (GeV/#it{c});%s candidate cos(#vartheta_{P}^{XY});entries", dMesSpecie.c_str(), dMesSpecie.c_str()), {HistType::kTH2F, {axisPtDminus, axisCosp}}); + + if ((std::accumulate(processFuncDplusPi.begin(), processFuncDplusPi.end(), 0)) > 0) { + registry.add("hPtProng0RecBg", Form("B^{0} candidates (unmatched);#it{p}_{T}(B^{0}) (GeV/#it{c});#it{p}_{T}(%s) (GeV/#it{c});entries", dMesSpecie.c_str()), {HistType::kTH2F, {axisPtB0, axisPtDminus}}); + registry.add("hPtProng1RecBg", "B^{0} candidates (unmatched);#it{p}_{T}(B^{0}) (GeV/#it{c});#it{p}_{T}(#pi^{#plus}) (GeV/#it{c});entries", {HistType::kTH2F, {axisPtB0, axisPtPi}}); + registry.add("hImpParProdRecBg", "B^{0} candidates (unmatched);#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate impact parameter product;entries", {HistType::kTH2F, {axisPtB0, axisImpParProd}}); + } else { + registry.add("hPtProngD0RecBg", Form("B^{0} candidates (unmatched);#it{p}_{T}(B^{0}) (GeV/#it{c});#it{p}_{T}(%s) (GeV/#it{c});entries", dMesSpecie.c_str()), {HistType::kTH2F, {axisPtB0, axisPtDminus}}); + registry.add("hPtProngSoftPiRecBg", "B^{0} candidates (unmatched);#it{p}_{T}(B^{0}) (GeV/#it{c});#it{p}_{T}(#pi^{#plus}) (GeV/#it{c});entries", {HistType::kTH2F, {axisPtB0, axisPtSoftPi}}); + registry.add("hPtProngBachPiRecBg", "B^{0} candidates (unmatched);#it{p}_{T}(B^{0}) (GeV/#it{c});#it{p}_{T}(#pi^{#plus}) (GeV/#it{c});entries", {HistType::kTH2F, {axisPtB0, axisPtPi}}); + registry.add("hImpParProngSqSumRecBg", "B^{0} candidates (unmatched);#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate impact parameter product;entries", {HistType::kTH2F, {axisPtB0, axisImpParProngSqSum}}); + registry.add("hDcaProng2RecBg", "B^{0} candidates (unmatched);#it{p}_{T}(B^{0}) (GeV/#it{c});prong 2 (#pi^{#plus}) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {axisPtB0, axisDca}}); + } } // MC checks - if (doprocessMcWithDecayTypeCheck || doprocessMcWithB0MlAndDecayTypeCheck || doprocessMcWithDmesMlAndDecayTypeCheck) { + if (doprocessMcDplusPiWithDecayTypeCheck || doprocessMcDplusPiWithB0MlAndDecayTypeCheck || doprocessMcDplusPiWithDmesMlAndDecayTypeCheck) { constexpr uint8_t kNBinsDecayTypeMc = hf_cand_b0::DecayTypeMc::NDecayTypeMc; TString labels[kNBinsDecayTypeMc]; - labels[hf_cand_b0::DecayTypeMc::B0ToDplusPiToPiKPiPi] = "B^{0} #rightarrow (D^{#minus} #rightarrow #pi^{#minus} K^{#plus} #pi^{#minus}) #pi^{#plus}"; - labels[hf_cand_b0::DecayTypeMc::B0ToDsPiToKKPiPi] = "B^{0} #rightarrow (D^{#minus}_{s} #rightarrow K^{#minus} K^{#plus} #pi^{#minus}) #pi^{#plus}"; - labels[hf_cand_b0::DecayTypeMc::BsToDsPiToKKPiPi] = "B_{s}^{0} #rightarrow (D^{#minus}_{s} #rightarrow K^{#minus} K^{#plus} #pi^{#minus}) #pi^{#plus}"; - labels[hf_cand_b0::DecayTypeMc::B0ToDplusKToPiKPiK] = "B^{0} #rightarrow (D^{#minus} #rightarrow #pi^{#minus} K^{#plus} #pi^{#minus}) K^{#plus}"; + labels[hf_cand_b0::DecayTypeMc::B0ToDplusPiToPiKPiPi] = Form("B^{0} #rightarrow (%s #rightarrow #pi^{#minus} K^{#plus} #pi^{#minus}) #pi^{#plus}", dMesSpecie.c_str()); + labels[hf_cand_b0::DecayTypeMc::B0ToDsPiToKKPiPi] = Form("B^{0} #rightarrow (%s_{s} #rightarrow K^{#minus} K^{#plus} #pi^{#minus}) #pi^{#plus}", dMesSpecie.c_str()); + labels[hf_cand_b0::DecayTypeMc::BsToDsPiToKKPiPi] = Form("B_{s}^{0} #rightarrow (%s_{s} #rightarrow K^{#minus} K^{#plus} #pi^{#minus}) #pi^{#plus}", dMesSpecie.c_str()); + labels[hf_cand_b0::DecayTypeMc::B0ToDplusKToPiKPiK] = Form("B^{0} #rightarrow (%s #rightarrow #pi^{#minus} K^{#plus} #pi^{#minus}) K^{#plus}", dMesSpecie.c_str()); labels[hf_cand_b0::DecayTypeMc::PartlyRecoDecay] = "Partly reconstructed decay channel"; labels[hf_cand_b0::DecayTypeMc::OtherDecay] = "Other decays"; static const AxisSpec axisDecayType = {kNBinsDecayTypeMc, 0.5, kNBinsDecayTypeMc + 0.5, ""}; @@ -336,18 +392,18 @@ struct HfTaskB0Reduced { } } // ML scores of D- daughter - if (doprocessMcWithDmesMl || doprocessMcWithDmesMlAndDecayTypeCheck) { + if (doprocessMcDplusPiWithDmesMl || doprocessMcDplusPiWithDmesMlAndDecayTypeCheck || doprocessMcDstarPiWithDmesMl) { // signal - registry.add("hMlScoreBkgDRecSig", "B^{0} candidates (matched);#it{p}_{T}(D^{#minus}) (GeV/#it{c});prong0, D^{#minus} ML background score;entries", {HistType::kTH2F, {axisPtDminus, axisMlScore}}); - registry.add("hMlScorePromptDRecSig", "B^{0} candidates (matched);#it{p}_{T}(D^{#minus}) (GeV/#it{c});prong0, D^{#minus} ML prompt score;entries", {HistType::kTH2F, {axisPtDminus, axisMlScore}}); - registry.add("hMlScoreNonPromptDRecSig", "B^{0} candidates (matched);#it{p}_{T}(D^{#minus}) (GeV/#it{c});prong0, D^{#minus} ML nonprompt score;entries", {HistType::kTH2F, {axisPtDminus, axisMlScore}}); + registry.add("hMlScoreBkgDRecSig", Form("B^{0} candidates (matched);#it{p}_{T}(%s) (GeV/#it{c});prong0, %s ML background score;entries", dMesSpecie.c_str(), dMesSpecie.c_str()), {HistType::kTH2F, {axisPtDminus, axisMlScore}}); + registry.add("hMlScorePromptDRecSig", Form("B^{0} candidates (matched);#it{p}_{T}(%s) (GeV/#it{c});prong0, %s ML prompt score;entries", dMesSpecie.c_str(), dMesSpecie.c_str()), {HistType::kTH2F, {axisPtDminus, axisMlScore}}); + registry.add("hMlScoreNonPromptDRecSig", Form("B^{0} candidates (matched);#it{p}_{T}(%s) (GeV/#it{c});prong0, %s ML nonprompt score;entries", dMesSpecie.c_str(), dMesSpecie.c_str()), {HistType::kTH2F, {axisPtDminus, axisMlScore}}); // background - registry.add("hMlScoreBkgDRecBg", "B^{0} candidates (unmatched);#it{p}_{T}(D^{#minus}) (GeV/#it{c});prong0, D^{#minus} ML background score;entries", {HistType::kTH2F, {axisPtDminus, axisMlScore}}); - registry.add("hMlScorePromptDRecBg", "B^{0} candidates (unmatched);#it{p}_{T}(D^{#minus}) (GeV/#it{c});prong0, D^{#minus} ML prompt score;entries", {HistType::kTH2F, {axisPtDminus, axisMlScore}}); - registry.add("hMlScoreNonPromptDRecBg", "B^{0} candidates (unmatched);#it{p}_{T}(D^{#minus}) (GeV/#it{c});prong0, D^{#minus} ML nonprompt score;entries", {HistType::kTH2F, {axisPtDminus, axisMlScore}}); + registry.add("hMlScoreBkgDRecBg", Form("B^{0} candidates (unmatched);#it{p}_{T}(%s) (GeV/#it{c});prong0, %s ML background score;entries", dMesSpecie.c_str(), dMesSpecie.c_str()), {HistType::kTH2F, {axisPtDminus, axisMlScore}}); + registry.add("hMlScorePromptDRecBg", Form("B^{0} candidates (unmatched);#it{p}_{T}(%s) (GeV/#it{c});prong0, %s ML prompt score;entries", dMesSpecie.c_str(), dMesSpecie.c_str()), {HistType::kTH2F, {axisPtDminus, axisMlScore}}); + registry.add("hMlScoreNonPromptDRecBg", Form("B^{0} candidates (unmatched);#it{p}_{T}(%s) (GeV/#it{c});prong0, %s ML nonprompt score;entries", dMesSpecie.c_str(), dMesSpecie.c_str()), {HistType::kTH2F, {axisPtDminus, axisMlScore}}); } // ML scores of B0 candidate - if (doprocessMcWithB0Ml || doprocessMcWithB0MlAndDecayTypeCheck) { + if (doprocessMcDplusPiWithB0Ml || doprocessMcDplusPiWithB0MlAndDecayTypeCheck) { // signal registry.add("hMlScoreSigB0RecSig", "B^{0} candidates (matched);#it{p}_{T}(B^{0}) (GeV/#it{c});prong0, B^{0} ML signal score;entries", {HistType::kTH2F, {axisPtB0, axisMlScore}}); // background @@ -360,15 +416,15 @@ struct HfTaskB0Reduced { registry.add("hPtYWithProngsInAccepanceGenSig", "B^{0} particles (generated-daughters in acceptance);#it{p}_{T}(B^{0}) (GeV/#it{c});#it{y}(B^{0})", {HistType::kTHnSparseF, {axisPtB0, axisEta}}); // reco sparses - if (!(doprocessDataWithDmesMl || doprocessDataWithB0Ml)) { - registry.add("hMassPtCutVarsRecSig", "B^{0} candidates (matched);#it{M} (D#pi) (GeV/#it{c}^{2});#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate decay length (cm);B^{0} candidate norm. decay length XY (cm);B^{0} candidate impact parameter product (cm);B^{0} candidate cos(#vartheta_{P});#it{M} (K#pi) (GeV/#it{c}^{2});#it{p}_{T}(D^{#minus}) (GeV/#it{c});D^{#minus} candidate decay length (cm);D^{#minus} candidate cos(#vartheta_{P})", {HistType::kTHnSparseF, {axisMassB0, axisPtB0, axisDecayLength, axisNormDecayLength, axisImpParProd, axisCosp, axisMassDminus, axisPtDminus, axisDecayLength, axisCosp}}); + if (!(doprocessDataDplusPiWithDmesMl || doprocessDataDplusPiWithB0Ml || doprocessDataDstarPiWithDmesMl)) { + registry.add("hMassPtCutVarsRecSig", Form("B^{0} candidates (matched);#it{M} (D#pi) (GeV/#it{c}^{2});#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate decay length (cm);B^{0} candidate norm. decay length XY (cm);B^{0} candidate impact parameter product (cm);B^{0} candidate cos(#vartheta_{P});#it{M} (K#pi) (GeV/#it{c}^{2});#it{p}_{T}(%s) (GeV/#it{c});%s candidate decay length (cm);%s candidate cos(#vartheta_{P})", dMesSpecie.c_str(), dMesSpecie.c_str(), dMesSpecie.c_str()), {HistType::kTHnSparseF, {axisMassB0, axisPtB0, axisDecayLength, axisNormDecayLength, axisImpParProd, axisCosp, axisMass, axisPtDminus, axisDecayLength, axisCosp}}); if (fillBackground) { - registry.add("hMassPtCutVarsRecBg", "B^{0} candidates (unmatched);#it{M} (D#pi) (GeV/#it{c}^{2});#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate decay length (cm);B^{0} candidate norm. decay length XY (cm);B^{0} candidate impact parameter product (cm);B^{0} candidate cos(#vartheta_{P});#it{M} (K#pi) (GeV/#it{c}^{2});#it{p}_{T}(D^{#minus}) (GeV/#it{c});D^{#minus} candidate decay length (cm);D^{#minus} candidate cos(#vartheta_{P})", {HistType::kTHnSparseF, {axisMassB0, axisPtB0, axisDecayLength, axisNormDecayLength, axisImpParProd, axisCosp, axisMassDminus, axisPtDminus, axisDecayLength, axisCosp}}); + registry.add("hMassPtCutVarsRecBg", Form("B^{0} candidates (unmatched);#it{M} (D#pi) (GeV/#it{c}^{2});#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate decay length (cm);B^{0} candidate norm. decay length XY (cm);B^{0} candidate impact parameter product (cm);B^{0} candidate cos(#vartheta_{P});#it{M} (K#pi) (GeV/#it{c}^{2});#it{p}_{T}(%s) (GeV/#it{c});%s candidate decay length (cm);%s candidate cos(#vartheta_{P})", dMesSpecie.c_str(), dMesSpecie.c_str(), dMesSpecie.c_str()), {HistType::kTHnSparseF, {axisMassB0, axisPtB0, axisDecayLength, axisNormDecayLength, axisImpParProd, axisCosp, axisMass, axisPtDminus, axisDecayLength, axisCosp}}); } } else { - registry.add("hMassPtCutVarsRecSig", "B^{0} candidates (matched);#it{M} (D#pi) (GeV/#it{c}^{2});#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate decay length (cm);B^{0} candidate norm. decay length XY (cm);B^{0} candidate impact parameter product (cm);B^{0} candidate cos(#vartheta_{P});#it{M} (K#pi) (GeV/#it{c}^{2});#it{p}_{T}(D^{#minus}) (GeV/#it{c});D^{#minus} candidate ML score bkg;D^{#minus} candidate ML score nonprompt", {HistType::kTHnSparseF, {axisMassB0, axisPtB0, axisDecayLength, axisNormDecayLength, axisImpParProd, axisCosp, axisMassDminus, axisPtDminus, axisMlScore, axisMlScore}}); + registry.add("hMassPtCutVarsRecSig", Form("B^{0} candidates (matched);#it{M} (D#pi) (GeV/#it{c}^{2});#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate decay length (cm);B^{0} candidate norm. decay length XY (cm);B^{0} candidate impact parameter product (cm);B^{0} candidate cos(#vartheta_{P});#it{M} (K#pi) (GeV/#it{c}^{2});#it{p}_{T}(%s) (GeV/#it{c});%s candidate ML score bkg;%s candidate ML score nonprompt", dMesSpecie.c_str(), dMesSpecie.c_str(), dMesSpecie.c_str()), {HistType::kTHnSparseF, {axisMassB0, axisPtB0, axisDecayLength, axisNormDecayLength, axisImpParProd, axisCosp, axisMass, axisPtDminus, axisMlScore, axisMlScore}}); if (fillBackground) { - registry.add("hMassPtCutVarsRecBg", "B^{0} candidates (unmatched);#it{M} (D#pi) (GeV/#it{c}^{2});#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate decay length (cm);B^{0} candidate norm. decay length XY (cm);B^{0} candidate impact parameter product (cm);B^{0} candidate cos(#vartheta_{P});#it{M} (K#pi) (GeV/#it{c}^{2});#it{p}_{T}(D^{#minus}) (GeV/#it{c});D^{#minus} candidate ML score bkg;D^{#minus} candidate ML score nonprompt", {HistType::kTHnSparseF, {axisMassB0, axisPtB0, axisDecayLength, axisNormDecayLength, axisImpParProd, axisCosp, axisMassDminus, axisPtDminus, axisMlScore, axisMlScore}}); + registry.add("hMassPtCutVarsRecBg", Form("B^{0} candidates (unmatched);#it{M} (D#pi) (GeV/#it{c}^{2});#it{p}_{T}(B^{0}) (GeV/#it{c});B^{0} candidate decay length (cm);B^{0} candidate norm. decay length XY (cm);B^{0} candidate impact parameter product (cm);B^{0} candidate cos(#vartheta_{P});#it{M} (K#pi) (GeV/#it{c}^{2});#it{p}_{T}(%s) (GeV/#it{c});%s candidate ML score bkg;%s candidate ML score nonprompt", dMesSpecie.c_str(), dMesSpecie.c_str(), dMesSpecie.c_str()), {HistType::kTHnSparseF, {axisMassB0, axisPtB0, axisDecayLength, axisNormDecayLength, axisImpParProd, axisCosp, axisMass, axisPtDminus, axisMlScore, axisMlScore}}); } } } @@ -385,6 +441,244 @@ struct HfTaskB0Reduced { return std::abs(etaProng) <= etaTrackMax && ptProng >= ptTrackMin; } + /// Fill candidate information at reconstruction level + /// \param doMc is the flag to enable the filling with MC information + /// \param withDecayTypeCheck is the flag to enable MC with decay type check + /// \param withDmesMl is the flag to enable the filling with ML scores for the D- daughter + /// \param withB0Ml is the flag to enable the filling with ML scores for the B0 candidate + /// \param candidate is the B0 candidate + /// \param candidatesD is the table with D- candidates + template + void fillCandDStarPi(Cand const& candidate, + SoftPions const& softPions, + CandsDmes const&) + { + auto ptCandB0 = candidate.pt(); + auto invMassB0 = hfHelper.invMassB0ToDPi(candidate); + auto candD = candidate.template prongD0_as(); + auto ptD = candidate.ptProng0(); + auto invMassD = candD.invMassHypo0(); + auto softPi = softPions.rawIteratorAt(candD.globalIndex()); + std::array posPv{candidate.posX(), candidate.posY(), candidate.posZ()}; + std::array posSvD{candD.xSecondaryVertex(), candD.ySecondaryVertex(), candD.zSecondaryVertex()}; + std::array momD{candD.pVector()}; + auto cospD = RecoDecay::cpa(posPv, posSvD, momD); + auto cospXyD = RecoDecay::cpaXY(posPv, posSvD, momD); + auto decLenD = RecoDecay::distance(posPv, posSvD); + auto decLenXyD = RecoDecay::distanceXY(posPv, posSvD); + + int8_t flagMcMatchRec = 0; + int8_t flagWrongCollision = 0; + bool isSignal = false; + if constexpr (doMc) { + flagMcMatchRec = candidate.flagMcMatchRec(); + flagWrongCollision = candidate.flagWrongCollision(); + isSignal = TESTBIT(std::abs(flagMcMatchRec), hf_cand_b0::DecayTypeMc::B0ToDstarPiToD0PiPiToKPiPiPi); + } + + if (fillHistograms) { + if constexpr (doMc) { + if (isSignal) { + registry.fill(HIST("hMassRecSig"), ptCandB0, hfHelper.invMassB0ToDPi(candidate)); + registry.fill(HIST("hPtProngD0RecSig"), ptCandB0, candidate.ptProng0()); + registry.fill(HIST("hPtProngSoftPiRecSig"), ptCandB0, candidate.ptProng1()); + registry.fill(HIST("hPtProngBachPiRecSig"), ptCandB0, candidate.ptProng2()); + registry.fill(HIST("hImpParProngSqSumRecSig"), ptCandB0, candidate.impactParameterProngSqSum()); + registry.fill(HIST("hDecLengthRecSig"), ptCandB0, candidate.decayLength()); + registry.fill(HIST("hDecLengthXyRecSig"), ptCandB0, candidate.decayLengthXY()); + registry.fill(HIST("hNormDecLengthXyRecSig"), ptCandB0, candidate.decayLengthXY() / candidate.errorDecayLengthXY()); + registry.fill(HIST("hDcaProng0RecSig"), ptCandB0, candidate.impactParameter0()); + registry.fill(HIST("hDcaProng1RecSig"), ptCandB0, candidate.impactParameter1()); + registry.fill(HIST("hDcaProng2RecSig"), ptCandB0, candidate.impactParameter2()); + registry.fill(HIST("hCospRecSig"), ptCandB0, candidate.cpa()); + registry.fill(HIST("hCospXyRecSig"), ptCandB0, candidate.cpaXY()); + registry.fill(HIST("hEtaRecSig"), ptCandB0, candidate.eta()); + registry.fill(HIST("hRapidityRecSig"), ptCandB0, hfHelper.yB0(candidate)); + registry.fill(HIST("hInvMassDRecSig"), ptD, invMassD); + registry.fill(HIST("hDecLengthDRecSig"), ptD, decLenD); + registry.fill(HIST("hDecLengthXyDRecSig"), ptD, decLenXyD); + registry.fill(HIST("hCospDRecSig"), ptD, cospD); + registry.fill(HIST("hCospXyDRecSig"), ptD, cospXyD); + if constexpr (withDmesMl) { + registry.fill(HIST("hMlScoreBkgDRecSig"), ptD, candidate.prong0MlScoreBkg()); + registry.fill(HIST("hMlScorePromptDRecSig"), ptD, candidate.prong0MlScorePrompt()); + registry.fill(HIST("hMlScoreNonPromptDRecSig"), ptD, candidate.prong0MlScoreNonprompt()); + } + } else if (fillBackground) { + registry.fill(HIST("hMassRecBg"), ptCandB0, hfHelper.invMassB0ToDPi(candidate)); + registry.fill(HIST("hPtProngD0RecBg"), ptCandB0, candidate.ptProng0()); + registry.fill(HIST("hPtProngSoftPiRecBg"), ptCandB0, candidate.ptProng1()); + registry.fill(HIST("hPtProngBachPiRecBg"), ptCandB0, candidate.ptProng2()); + registry.fill(HIST("hImpParProngSqSumRecBg"), ptCandB0, candidate.impactParameterProngSqSum()); + registry.fill(HIST("hDecLengthRecBg"), ptCandB0, candidate.decayLength()); + registry.fill(HIST("hDecLengthXyRecBg"), ptCandB0, candidate.decayLengthXY()); + registry.fill(HIST("hNormDecLengthXyRecBg"), ptCandB0, candidate.decayLengthXY() / candidate.errorDecayLengthXY()); + registry.fill(HIST("hDcaProng0RecBg"), ptCandB0, candidate.impactParameter0()); + registry.fill(HIST("hDcaProng1RecBg"), ptCandB0, candidate.impactParameter1()); + registry.fill(HIST("hDcaProng2RecBg"), ptCandB0, candidate.impactParameter2()); + registry.fill(HIST("hCospRecBg"), ptCandB0, candidate.cpa()); + registry.fill(HIST("hCospXyRecBg"), ptCandB0, candidate.cpaXY()); + registry.fill(HIST("hEtaRecBg"), ptCandB0, candidate.eta()); + registry.fill(HIST("hRapidityRecBg"), ptCandB0, hfHelper.yB0(candidate)); + registry.fill(HIST("hInvMassDRecBg"), ptD, invMassD); + registry.fill(HIST("hDecLengthDRecBg"), ptD, decLenD); + registry.fill(HIST("hDecLengthXyDRecBg"), ptD, decLenXyD); + registry.fill(HIST("hCospDRecBg"), ptD, cospD); + registry.fill(HIST("hCospXyDRecBg"), ptD, cospXyD); + if constexpr (withDmesMl) { + registry.fill(HIST("hMlScoreBkgDRecBg"), ptD, candidate.prong0MlScoreBkg()); + registry.fill(HIST("hMlScorePromptDRecBg"), ptD, candidate.prong0MlScorePrompt()); + registry.fill(HIST("hMlScoreNonPromptDRecBg"), ptD, candidate.prong0MlScoreNonprompt()); + } + } + } else { + registry.fill(HIST("hMass"), ptCandB0, invMassB0); + registry.fill(HIST("hPtProngD0"), ptCandB0, candidate.ptProng0()); + registry.fill(HIST("hPtProngSoftPi"), ptCandB0, candidate.ptProng1()); + registry.fill(HIST("hPtProngBachPi"), ptCandB0, candidate.ptProng2()); + registry.fill(HIST("hDecLength"), ptCandB0, candidate.decayLength()); + registry.fill(HIST("hDecLengthXy"), ptCandB0, candidate.decayLengthXY()); + registry.fill(HIST("hNormDecLengthXy"), ptCandB0, candidate.decayLengthXY() / candidate.errorDecayLengthXY()); + registry.fill(HIST("hImpParProngSqSum"), ptCandB0, candidate.impactParameterProngSqSum()); + registry.fill(HIST("hDcaProng0"), ptCandB0, candidate.impactParameter0()); + registry.fill(HIST("hDcaProng1"), ptCandB0, candidate.impactParameter1()); + registry.fill(HIST("hDcaProng2"), ptCandB0, candidate.impactParameter2()); + registry.fill(HIST("hCosp"), ptCandB0, candidate.cpa()); + registry.fill(HIST("hCospXy"), ptCandB0, candidate.cpaXY()); + registry.fill(HIST("hEta"), ptCandB0, candidate.eta()); + registry.fill(HIST("hRapidity"), ptCandB0, hfHelper.yB0(candidate)); + registry.fill(HIST("hInvMassD"), ptD, invMassD); + registry.fill(HIST("hDecLengthD"), ptD, decLenD); + registry.fill(HIST("hDecLengthXyD"), ptD, decLenXyD); + registry.fill(HIST("hCospD"), ptD, cospD); + registry.fill(HIST("hCospXyD"), ptD, cospXyD); + + if constexpr (withDmesMl) { + registry.fill(HIST("hMlScoreBkgD"), ptD, candidate.prong0MlScoreBkg()); + registry.fill(HIST("hMlScorePromptD"), ptD, candidate.prong0MlScorePrompt()); + registry.fill(HIST("hMlScoreNonPromptD"), ptD, candidate.prong0MlScoreNonprompt()); + } + } + } + if (fillSparses) { + if constexpr (doMc) { + if (isSignal) { + if constexpr (withDmesMl) { + registry.fill(HIST("hMassPtCutVarsRecSig"), invMassB0, ptCandB0, candidate.decayLength(), candidate.decayLengthXY() / candidate.errorDecayLengthXY(), candidate.impactParameterProngSqSum(), candidate.cpa(), invMassD, ptD, candidate.prong0MlScoreBkg(), candidate.prong0MlScoreNonprompt()); + } else { + registry.fill(HIST("hMassPtCutVarsRecSig"), invMassB0, ptCandB0, candidate.decayLength(), candidate.decayLengthXY() / candidate.errorDecayLengthXY(), candidate.impactParameterProngSqSum(), candidate.cpa(), invMassD, ptD, decLenD, cospD); + } + } else if (fillBackground) { + if constexpr (withDmesMl) { + registry.fill(HIST("hMassPtCutVarsRecBg"), invMassB0, ptCandB0, candidate.decayLength(), candidate.decayLengthXY() / candidate.errorDecayLengthXY(), candidate.impactParameterProngSqSum(), candidate.cpa(), invMassD, ptD, candidate.prong0MlScoreBkg(), candidate.prong0MlScoreNonprompt()); + } else { + registry.fill(HIST("hMassPtCutVarsRecBg"), invMassB0, ptCandB0, candidate.decayLength(), candidate.decayLengthXY() / candidate.errorDecayLengthXY(), candidate.impactParameterProngSqSum(), candidate.cpa(), invMassD, ptD, decLenD, cospD); + } + } + } else { + if constexpr (withDmesMl) { + registry.fill(HIST("hMassPtCutVars"), invMassB0, ptCandB0, candidate.decayLength(), candidate.decayLengthXY() / candidate.errorDecayLengthXY(), candidate.impactParameterProngSqSum(), candidate.cpa(), invMassD, ptD, candidate.prong0MlScoreBkg(), candidate.prong0MlScoreNonprompt()); + } else { + registry.fill(HIST("hMassPtCutVars"), invMassB0, ptCandB0, candidate.decayLength(), candidate.decayLengthXY() / candidate.errorDecayLengthXY(), candidate.impactParameterProngSqSum(), candidate.cpa(), invMassD, ptD, decLenD, cospD); + } + } + } + if (fillTree) { + float pseudoRndm = ptD * 1000. - static_cast(ptD * 1000); + if (flagMcMatchRec != 0 || (((doMc && fillBackground) || !doMc) && (ptCandB0 >= ptMaxForDownSample || pseudoRndm < downSampleBkgFactor))) { + float prong0MlScoreBkg = -1.; + float prong0MlScorePrompt = -1.; + float prong0MlScoreNonprompt = -1.; + float candidateMlScoreSig = -1; + if constexpr (withDmesMl) { + prong0MlScoreBkg = candidate.prong0MlScoreBkg(); + prong0MlScorePrompt = candidate.prong0MlScorePrompt(); + prong0MlScoreNonprompt = candidate.prong0MlScoreNonprompt(); + } + auto prongBachPi = candidate.template prongBachPi_as(); + + float ptMother = -1.; + if constexpr (doMc) { + ptMother = candidate.ptMother(); + } + + hfRedCandB0Lite( + // B-meson features + invMassB0, + ptCandB0, + candidate.eta(), + candidate.phi(), + hfHelper.yB0(candidate), + candidate.cpa(), + candidate.cpaXY(), + candidate.chi2PCA(), + candidate.decayLength(), + candidate.decayLengthXY(), + candidate.decayLengthNormalised(), + candidate.decayLengthXYNormalised(), + candidate.impactParameterProngSqSum(), + candidate.maxNormalisedDeltaIP(), + candidateMlScoreSig, + candidate.isSelB0ToDPi(), + // D-meson features + invMassD, + ptD, + decLenD, + decLenXyD, + candidate.impactParameter0(), + candD.ptProngMin(), + candD.absEtaProngMin(), + candD.itsNClsProngMin(), + candD.tpcNClsCrossedRowsProngMin(), + candD.tpcChi2NClProngMax(), + candD.tpcNSigmaPiProng0(), + candD.tofNSigmaPiProng0(), + candD.tpcTofNSigmaPiProng0(), + candD.tpcNSigmaKaProng1(), + candD.tofNSigmaKaProng1(), + candD.tpcTofNSigmaKaProng1(), + softPi.tpcNSigmaPiSoftPi(), + softPi.tofNSigmaPiSoftPi(), + softPi.tpcTofNSigmaPiSoftPi(), + prong0MlScoreBkg, + prong0MlScorePrompt, + prong0MlScoreNonprompt, + // pion features + candidate.ptProng1(), + std::abs(RecoDecay::eta(prongBachPi.pVector())), + prongBachPi.itsNCls(), + prongBachPi.tpcNClsCrossedRows(), + prongBachPi.tpcChi2NCl(), + candidate.impactParameter1(), + prongBachPi.tpcNSigmaPi(), + prongBachPi.tofNSigmaPi(), + prongBachPi.tpcTofNSigmaPi(), + // MC truth + flagMcMatchRec, + isSignal, + flagWrongCollision, + ptMother); + + if constexpr (withDecayTypeCheck) { + hfRedB0McCheck( + flagMcMatchRec, + flagWrongCollision, + invMassD, + ptD, + invMassB0, + ptCandB0, + candidateMlScoreSig, + candidate.pdgCodeBeautyMother(), + candidate.pdgCodeCharmMother(), + candidate.pdgCodeProng0(), + candidate.pdgCodeProng1(), + candidate.pdgCodeProng2(), + candidate.pdgCodeProng3()); + } + } + } + } + /// Fill candidate information at reconstruction level /// \param doMc is the flag to enable the filling with MC information /// \param withDecayTypeCheck is the flag to enable MC with decay type check @@ -558,7 +852,7 @@ struct HfTaskB0Reduced { if constexpr (withB0Ml) { candidateMlScoreSig = candidate.mlProbB0ToDPi(); } - auto prong1 = candidate.template prong1_as(); + auto prong1 = candidate.template prong1_as(); float ptMother = -1.; if constexpr (doMc) { @@ -681,9 +975,9 @@ struct HfTaskB0Reduced { } // Process functions - void processData(soa::Filtered> const& candidates, - CandsDplus const& candidatesD, - TracksPion const&) + void processDataDplusPi(soa::Filtered> const& candidates, + CandsDplus const& candidatesD, + TracksBachPions const&) { for (const auto& candidate : candidates) { if (yCandRecoMax >= 0. && std::abs(hfHelper.yB0(candidate)) > yCandRecoMax) { @@ -691,12 +985,12 @@ struct HfTaskB0Reduced { } fillCand(candidate, candidatesD); } // candidate loop - } // processData - PROCESS_SWITCH(HfTaskB0Reduced, processData, "Process data without ML scores for B0 and D daughter", true); + } // processDataDplusPi + PROCESS_SWITCH(HfTaskB0Reduced, processDataDplusPi, "Process data without ML scores for B0 and Dplus daughter", true); - void processDataWithDmesMl(soa::Filtered> const& candidates, - CandsDplus const& candidatesD, - TracksPion const&) + void processDataDplusPiWithDmesMl(soa::Filtered> const& candidates, + CandsDplus const& candidatesD, + TracksBachPions const&) { for (const auto& candidate : candidates) { if (yCandRecoMax >= 0. && std::abs(hfHelper.yB0(candidate)) > yCandRecoMax) { @@ -704,12 +998,12 @@ struct HfTaskB0Reduced { } fillCand(candidate, candidatesD); } // candidate loop - } // processDataWithDmesMl - PROCESS_SWITCH(HfTaskB0Reduced, processDataWithDmesMl, "Process data with(out) ML scores for D daughter (B0)", false); + } // processDataDplusPiWithDmesMl + PROCESS_SWITCH(HfTaskB0Reduced, processDataDplusPiWithDmesMl, "Process data with(out) ML scores for Dplus daughter (B0)", false); - void processDataWithB0Ml(soa::Filtered> const& candidates, - CandsDplus const& candidatesD, - TracksPion const&) + void processDataDplusPiWithB0Ml(soa::Filtered> const& candidates, + CandsDplus const& candidatesD, + TracksBachPions const&) { for (const auto& candidate : candidates) { if (yCandRecoMax >= 0. && std::abs(hfHelper.yB0(candidate)) > yCandRecoMax) { @@ -717,13 +1011,42 @@ struct HfTaskB0Reduced { } fillCand(candidate, candidatesD); } // candidate loop - } // processDataWithB0Ml - PROCESS_SWITCH(HfTaskB0Reduced, processDataWithB0Ml, "Process data with(out) ML scores for B0 (D daughter)", false); + } // processDataDplusPiWithB0Ml + PROCESS_SWITCH(HfTaskB0Reduced, processDataDplusPiWithB0Ml, "Process data with(out) ML scores for B0 (Dplus daughter)", false); + + // Process functions + void processDataDstarPi(soa::Filtered> const& candidates, + CandsDstar const& candidatesD, + TracksSoftPions const& softPions, + TracksBachPions const&) + { + for (const auto& candidate : candidates) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yB0(candidate)) > yCandRecoMax) { + continue; + } + fillCandDStarPi(candidate, softPions, candidatesD); + } // candidate loop + } // processDataDstarPi + PROCESS_SWITCH(HfTaskB0Reduced, processDataDstarPi, "Process data without ML scores for B0 and Dstar daughter", false); + + void processDataDstarPiWithDmesMl(soa::Filtered> const& candidates, + CandsDstar const& candidatesD, + TracksSoftPions const& softPions, + TracksBachPions const&) + { + for (const auto& candidate : candidates) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yB0(candidate)) > yCandRecoMax) { + continue; + } + fillCandDStarPi(candidate, softPions, candidatesD); + } // candidate loop + } // processDataDstarPiWithDmesMl + PROCESS_SWITCH(HfTaskB0Reduced, processDataDstarPiWithDmesMl, "Process data with(out) ML scores for Dstar daughter (B0)", false); - void processMc(soa::Filtered> const& candidates, - aod::HfMcGenRedB0s const& mcParticles, - CandsDplus const& candidatesD, - TracksPion const&) + void processMcDplusPi(soa::Filtered> const& candidates, + aod::HfMcGenRedB0s const& mcParticles, + CandsDplus const& candidatesD, + TracksBachPions const&) { // MC rec for (const auto& candidate : candidates) { @@ -737,13 +1060,13 @@ struct HfTaskB0Reduced { for (const auto& particle : mcParticles) { fillCandMcGen(particle); } // gen - } // processMc - PROCESS_SWITCH(HfTaskB0Reduced, processMc, "Process MC without ML scores for B0 and D daughter", false); + } // processMcDplusPi + PROCESS_SWITCH(HfTaskB0Reduced, processMcDplusPi, "Process MC without ML scores for B0 and Dplus daughter", false); - void processMcWithDecayTypeCheck(soa::Filtered> const& candidates, - aod::HfMcGenRedB0s const& mcParticles, - CandsDplus const& candidatesD, - TracksPion const&) + void processMcDplusPiWithDecayTypeCheck(soa::Filtered> const& candidates, + aod::HfMcGenRedB0s const& mcParticles, + CandsDplus const& candidatesD, + TracksBachPions const&) { // MC rec for (const auto& candidate : candidates) { @@ -757,13 +1080,13 @@ struct HfTaskB0Reduced { for (const auto& particle : mcParticles) { fillCandMcGen(particle); } // gen - } // processMc - PROCESS_SWITCH(HfTaskB0Reduced, processMcWithDecayTypeCheck, "Process MC with decay type check and without ML scores for B0 and D daughter", false); + } // processMcDplusPi + PROCESS_SWITCH(HfTaskB0Reduced, processMcDplusPiWithDecayTypeCheck, "Process MC with decay type check and without ML scores for B0 and Dplus daughter", false); - void processMcWithDmesMl(soa::Filtered> const& candidates, - aod::HfMcGenRedB0s const& mcParticles, - CandsDplus const& candidatesD, - TracksPion const&) + void processMcDplusPiWithDmesMl(soa::Filtered> const& candidates, + aod::HfMcGenRedB0s const& mcParticles, + CandsDplus const& candidatesD, + TracksBachPions const&) { // MC rec for (const auto& candidate : candidates) { @@ -777,13 +1100,13 @@ struct HfTaskB0Reduced { for (const auto& particle : mcParticles) { fillCandMcGen(particle); } // gen - } // processMcWithDmesMl - PROCESS_SWITCH(HfTaskB0Reduced, processMcWithDmesMl, "Process MC with(out) ML scores for D daughter (B0)", false); + } // processMcDplusPiWithDmesMl + PROCESS_SWITCH(HfTaskB0Reduced, processMcDplusPiWithDmesMl, "Process MC with(out) ML scores for Dplus daughter (B0)", false); - void processMcWithDmesMlAndDecayTypeCheck(soa::Filtered> const& candidates, - aod::HfMcGenRedB0s const& mcParticles, - CandsDplus const& candidatesD, - TracksPion const&) + void processMcDplusPiWithDmesMlAndDecayTypeCheck(soa::Filtered> const& candidates, + aod::HfMcGenRedB0s const& mcParticles, + CandsDplus const& candidatesD, + TracksBachPions const&) { // MC rec for (const auto& candidate : candidates) { @@ -797,13 +1120,13 @@ struct HfTaskB0Reduced { for (const auto& particle : mcParticles) { fillCandMcGen(particle); } // gen - } // processMc - PROCESS_SWITCH(HfTaskB0Reduced, processMcWithDmesMlAndDecayTypeCheck, "Process MC with decay type check and with(out) ML scores for B0 (D daughter)", false); + } // processMcDplusPi + PROCESS_SWITCH(HfTaskB0Reduced, processMcDplusPiWithDmesMlAndDecayTypeCheck, "Process MC with decay type check and with(out) ML scores for B0 (Dplus daughter)", false); - void processMcWithB0Ml(soa::Filtered> const& candidates, - aod::HfMcGenRedB0s const& mcParticles, - CandsDplus const& candidatesD, - TracksPion const&) + void processMcDplusPiWithB0Ml(soa::Filtered> const& candidates, + aod::HfMcGenRedB0s const& mcParticles, + CandsDplus const& candidatesD, + TracksBachPions const&) { // MC rec for (const auto& candidate : candidates) { @@ -817,13 +1140,13 @@ struct HfTaskB0Reduced { for (const auto& particle : mcParticles) { fillCandMcGen(particle); } // gen - } // processMcWithB0Ml - PROCESS_SWITCH(HfTaskB0Reduced, processMcWithB0Ml, "Process MC with(out) ML scores for B0 (D daughter)", false); + } // processMcDplusPiWithB0Ml + PROCESS_SWITCH(HfTaskB0Reduced, processMcDplusPiWithB0Ml, "Process MC with(out) ML scores for B0 (Dplus daughter)", false); - void processMcWithB0MlAndDecayTypeCheck(soa::Filtered> const& candidates, - aod::HfMcGenRedB0s const& mcParticles, - CandsDplus const& candidatesD, - TracksPion const&) + void processMcDplusPiWithB0MlAndDecayTypeCheck(soa::Filtered> const& candidates, + aod::HfMcGenRedB0s const& mcParticles, + CandsDplus const& candidatesD, + TracksBachPions const&) { // MC rec for (const auto& candidate : candidates) { @@ -837,8 +1160,51 @@ struct HfTaskB0Reduced { for (const auto& particle : mcParticles) { fillCandMcGen(particle); } // gen - } // processMc - PROCESS_SWITCH(HfTaskB0Reduced, processMcWithB0MlAndDecayTypeCheck, "Process MC with decay type check and with(out) ML scores for B0 (D daughter)", false); + } // processMcDplusPi + PROCESS_SWITCH(HfTaskB0Reduced, processMcDplusPiWithB0MlAndDecayTypeCheck, "Process MC with decay type check and with(out) ML scores for B0 (Dplus daughter)", false); + + void processMcDstarPi(soa::Filtered> const& candidates, + aod::HfMcGenRedB0s const& mcParticles, + CandsDstar const& candidatesD, + TracksSoftPions const& softPions, + TracksBachPions const&) + { + // MC rec + for (const auto& candidate : candidates) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yB0(candidate)) > yCandRecoMax) { + continue; + } + fillCandDStarPi(candidate, softPions, candidatesD); + } // rec + + // MC gen. level + for (const auto& particle : mcParticles) { + fillCandMcGen(particle); + } // gen + } // processMcDstarPi + PROCESS_SWITCH(HfTaskB0Reduced, processMcDstarPi, "Process MC without ML scores for B0 and Dstar daughter", false); + + void processMcDstarPiWithDmesMl(soa::Filtered> const& candidates, + aod::HfMcGenRedB0s const& mcParticles, + CandsDstar const& candidatesD, + TracksSoftPions const& softPions, + TracksBachPions const&) + { + // MC rec + for (const auto& candidate : candidates) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yB0(candidate)) > yCandRecoMax) { + continue; + } + fillCandDStarPi(candidate, softPions, candidatesD); + } // rec + + // MC gen. level + for (const auto& particle : mcParticles) { + fillCandMcGen(particle); + } // gen + } // processMcDstarPiWithDmesMl + PROCESS_SWITCH(HfTaskB0Reduced, processMcDstarPiWithDmesMl, "Process MC with(out) ML scores for Dstar daughter (B0)", false); + }; // struct WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGHF/D2H/Utils/utilsRedDataFormat.h b/PWGHF/D2H/Utils/utilsRedDataFormat.h index 4e4bc2b9b3c..f5115e59ac0 100644 --- a/PWGHF/D2H/Utils/utilsRedDataFormat.h +++ b/PWGHF/D2H/Utils/utilsRedDataFormat.h @@ -82,6 +82,30 @@ float getTpcTofNSigmaPi1(const T1& prong1) return defaultNSigma; } +/// Helper function to retrive PID information of bachelor pion from b-hadron decay +/// \param prongSoftPi soft pion track +template +float getTpcTofNSigmaSoftPi(const T1& prongSoftPi) +{ + float defaultNSigma = -999.f; // -999.f is the default value set in TPCPIDResponse.h and PIDTOF.h + + bool hasTpc = prongSoftPi.hasTPC(); + bool hasTof = prongSoftPi.hasTOF(); + + if (hasTpc && hasTof) { + float tpcNSigma = prongSoftPi.tpcNSigmaPiSoftPi(); + float tofNSigma = prongSoftPi.tofNSigmaPiSoftPi(); + return std::sqrt(.5f * tpcNSigma * tpcNSigma + .5f * tofNSigma * tofNSigma); + } + if (hasTpc) { + return std::abs(prongSoftPi.tpcNSigmaPiSoftPi()); + } + if (hasTof) { + return std::abs(prongSoftPi.tofNSigmaPiSoftPi()); + } + return defaultNSigma; +} + /// Helper function to retrive PID information of bachelor kaon from b-hadron decay /// \param prong1 kaon track from reduced data format, aod::HfRedBachProng0Tracks /// \return the combined TPC and TOF n-sigma for kaon diff --git a/PWGHF/DataModel/CandidateReconstructionTables.h b/PWGHF/DataModel/CandidateReconstructionTables.h index 8af9f18162d..e334574f894 100644 --- a/PWGHF/DataModel/CandidateReconstructionTables.h +++ b/PWGHF/DataModel/CandidateReconstructionTables.h @@ -2237,6 +2237,40 @@ DECLARE_SOA_TABLE(HfCandB0Base, "AOD", "HFCANDB0BASE", hf_cand::E, hf_cand::E2); +DECLARE_SOA_TABLE(HfCandB0DStar, "AOD", "HFCANDB0DSTAR", + // general columns + HFCAND_COLUMNS, + /* prong 2 */ hf_cand::ImpactParameterNormalised2, + hf_cand::PtProng2, + hf_cand::Pt2Prong2, + hf_cand::PVectorProng2, + // 3-prong specific columns + hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, + hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1, + hf_cand::PxProng2, hf_cand::PyProng2, hf_cand::PzProng2, + hf_cand::ImpactParameter0, hf_cand::ImpactParameter1, hf_cand::ImpactParameter2, + hf_cand::ErrorImpactParameter0, hf_cand::ErrorImpactParameter1, hf_cand::ErrorImpactParameter2, + /* dynamic columns */ + hf_cand_3prong::M, + hf_cand_3prong::M2, + hf_cand_3prong::ImpactParameterProngSqSum, + /* dynamic columns that use candidate momentum components */ + hf_cand::Pt, + hf_cand::Pt2, + hf_cand::P, + hf_cand::P2, + hf_cand::PVector, + hf_cand::Cpa, + hf_cand::CpaXY, + hf_cand::Ct, + hf_cand::ImpactParameterXY, + hf_cand_3prong::MaxNormalisedDeltaIP, + hf_cand::Eta, + hf_cand::Phi, + hf_cand::Y, + hf_cand::E, + hf_cand::E2); + // extended table with expression columns that can be used as arguments of dynamic columns DECLARE_SOA_EXTENDED_TABLE_USER(HfCandB0Ext, HfCandB0Base, "HFCANDB0EXT", hf_cand_2prong::Px, hf_cand_2prong::Py, hf_cand_2prong::Pz); @@ -2246,6 +2280,10 @@ DECLARE_SOA_TABLE(HfCandB0Prongs, "AOD", "HFCANDB0PRONGS", using HfCandB0 = soa::Join; +// extended table with expression columns that can be used as arguments of dynamic columns +DECLARE_SOA_EXTENDED_TABLE_USER(HfCandB0DStExt, HfCandB0DStar, "HFCANDB0DSTEXT", + hf_cand_3prong::Px, hf_cand_3prong::Py, hf_cand_3prong::Pz); + // table with results of reconstruction level MC matching DECLARE_SOA_TABLE(HfCandB0McRec, "AOD", "HFCANDB0MCREC", hf_cand_b0::FlagMcMatchRec, @@ -2678,7 +2716,11 @@ DECLARE_SOA_DYNAMIC_COLUMN(NormalisedImpParamZSoftPi, normalisedImpParamZSoftPi, DECLARE_SOA_COLUMN(PxSoftPi, pxSoftPi, float); DECLARE_SOA_COLUMN(PySoftPi, pySoftPi, float); DECLARE_SOA_COLUMN(PzSoftPi, pzSoftPi, float); +DECLARE_SOA_COLUMN(DcaYSoftPi, dcaYSoftPi, float); +DECLARE_SOA_COLUMN(SigmaYSoftPi, sigmaYSoftPi, float); DECLARE_SOA_COLUMN(SignSoftPi, signSoftPi, int8_t); +DECLARE_SOA_COLUMN(TPCNSigmaPiSoftPi, tpcNSigmaPiSoftPi, float); //! NsigmaTPCPi for soft pi, o2-linter: disable=name/o2-column (written to disk) +DECLARE_SOA_COLUMN(TOFNSigmaPiSoftPi, tofNSigmaPiSoftPi, float); //! NsigmaTOFPi for soft pi, o2-linter: disable=name/o2-column (written to disk) // Dstar momenta DECLARE_SOA_EXPRESSION_COLUMN(PxDstar, pxDstar, float, 1.f * aod::hf_cand::pxProng0 + 1.f * aod::hf_cand::pxProng1 + 1.f * aod::hf_cand_dstar::pxSoftPi); DECLARE_SOA_EXPRESSION_COLUMN(PyDstar, pyDstar, float, 1.f * aod::hf_cand::pyProng0 + 1.f * aod::hf_cand::pyProng1 + 1.f * aod::hf_cand_dstar::pySoftPi); @@ -2694,7 +2736,8 @@ DECLARE_SOA_DYNAMIC_COLUMN(InvMassAntiDstar, invMassAntiDstar, DECLARE_SOA_DYNAMIC_COLUMN(PtSoftPi, ptSoftPi, [](float pxSoftPi, float pySoftPi) -> float { return RecoDecay::pt(pxSoftPi, pySoftPi); }); DECLARE_SOA_DYNAMIC_COLUMN(PVecSoftPi, pVecSoftPi, [](float px, float py, float pz) -> std::array { return std::array{px, py, pz}; }); - +DECLARE_SOA_DYNAMIC_COLUMN(TPCTOFNSigmaPiSoftPi, tpcTofNSigmaPiSoftPi, //! Combination of NsigmaTPC and NsigmaTOF, o2-linter: disable=name/o2-column (written to disk) + [](float tpcNSigmaPiSoftPi, float TOFNSigmaPiSoftPi) -> float { return pid_tpc_tof_utils::combineNSigma(tpcNSigmaPiSoftPi, TOFNSigmaPiSoftPi); }); // MC matching result: DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); //! reconstruction level DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); //! generator level diff --git a/PWGHF/TableProducer/candidateSelectorDstarToD0Pi.cxx b/PWGHF/TableProducer/candidateSelectorDstarToD0Pi.cxx index dbc06282ce0..bd3cb47b28f 100644 --- a/PWGHF/TableProducer/candidateSelectorDstarToD0Pi.cxx +++ b/PWGHF/TableProducer/candidateSelectorDstarToD0Pi.cxx @@ -16,7 +16,6 @@ /// \author Fabrizio Grosa , CERN #include "PWGHF/Core/HfHelper.h" -#include "PWGHF/Core/HfMlResponseD0ToKPi.h" #include "PWGHF/Core/HfMlResponseDstarToD0Pi.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h"