From a76b9c13e44e4fd050fdcb295b09b796e97faafa Mon Sep 17 00:00:00 2001 From: Fabrizio Grosa Date: Thu, 7 Dec 2023 10:15:33 +0100 Subject: [PATCH 01/10] PWGHF: add possibility to use ML scores of D- mesons and improve B0 task --- PWGHF/Core/HfHelper.h | 29 + PWGHF/D2H/DataModel/ReducedDataModel.h | 11 +- .../candidateCreatorB0Reduced.cxx | 261 ++++---- .../candidateSelectorB0ToDPiReduced.cxx | 70 ++- PWGHF/D2H/Tasks/taskB0Reduced.cxx | 556 ++++++++++++------ 5 files changed, 636 insertions(+), 291 deletions(-) diff --git a/PWGHF/Core/HfHelper.h b/PWGHF/Core/HfHelper.h index 4b258566417..8bbca1fa659 100644 --- a/PWGHF/Core/HfHelper.h +++ b/PWGHF/Core/HfHelper.h @@ -890,6 +890,35 @@ class HfHelper return true; } + /// Apply selection on ML scores for charm-hadron daughter in b-hadron decays (common for all the beauty channels) + /// \param candB b-hadron candidates + /// \param cuts ML score selection per bin of charm-hadron pT + /// \param binsPtC pT bin limits of charm hadron + /// \return true if b-hadron candidate passes all selections + template + bool selectionDmesMlScoresForB(const T1& candB, const T2& cuts, const T3& binsPtC) + { + auto ptC = RecoDecay::pt(candB.pxProng0(), candB.pyProng0()); // the first daughter is the charm hadron + int pTBin = o2::analysis::findBin(binsPtC, ptC); + if (pTBin == -1) { + return false; + } + + if (candB.prong0MlScoreBkg() > cuts->get(pTBin, "ML score charm bkg")) { + return false; + } + + if (candB.prong0MlScorePrompt() > cuts->get(pTBin, "ML score charm prompt")) { // we want non-prompt for beauty + return false; + } + + if (candB.prong0MlScoreNonprompt() < cuts->get(pTBin, "ML score charm nonprompt")) { // we want non-prompt for beauty + return false; + } + + return true; + } + private: }; diff --git a/PWGHF/D2H/DataModel/ReducedDataModel.h b/PWGHF/D2H/DataModel/ReducedDataModel.h index 35a58606074..fd0a9f3b1f1 100644 --- a/PWGHF/D2H/DataModel/ReducedDataModel.h +++ b/PWGHF/D2H/DataModel/ReducedDataModel.h @@ -207,11 +207,20 @@ 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_COLUMN(Prong0MlScoreBkg, prong0MlScoreBkg, float); //! Bkg ML score of the D daughter +DECLARE_SOA_COLUMN(Prong0MlScorePrompt, prong0MlScorePrompt, float); //! Prompt ML score of the D daughter +DECLARE_SOA_COLUMN(Prong0MlScoreNonprompt, prong0MlScoreNonprompt, float); //! Nonprompt ML score of the D daughter } // namespace hf_cand_b0_reduced -DECLARE_SOA_TABLE(HfRedB0Prongs, "AOD", "HFREDB0PRONG", +DECLARE_SOA_TABLE(HfRedB0Prongs, "AOD", "HFREDB0PRONG", //! Table with B0 daughter indices hf_cand_b0_reduced::Prong0Id, hf_cand_b0_reduced::Prong1Id); +DECLARE_SOA_TABLE(HfRedB0DpMls, "AOD", "HFREDB0DPML", //! Table with ML scores for the D+ daughter + hf_cand_b0_reduced::Prong0MlScoreBkg, + hf_cand_b0_reduced::Prong0MlScorePrompt, + hf_cand_b0_reduced::Prong0MlScoreNonprompt, + o2::soa::Marker<1>); + using HfRedCandB0 = soa::Join; namespace hf_cand_bplus_reduced diff --git a/PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx index fb5c9184f40..01789eb694f 100644 --- a/PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx @@ -13,6 +13,7 @@ /// \brief Reconstruction of B0 candidates /// /// \author Alexandre Bigot , IPHC Strasbourg +/// \author Fabrizio Grosa , CERN #include "CommonConstants/PhysicsConstants.h" #include "DCAFitter/DCAFitterN.h" @@ -34,37 +35,44 @@ using namespace o2::framework::expressions; /// Reconstruction of B0 candidates struct HfCandidateCreatorB0Reduced { - Produces rowCandidateBase; // table defined in CandidateReconstructionTables.h - Produces rowCandidateProngs; // table defined in ReducedDataModel.h + Produces rowCandidateBase; // table defined in CandidateReconstructionTables.h + Produces rowCandidateProngs; // table defined in ReducedDataModel.h + Produces rowCandidateDmesMlScores; // table defined in ReducedDataModel.h // vertexing Configurable propagateToPCA{"propagateToPCA", true, "create tracks version propagated to PCA"}; Configurable useAbsDCA{"useAbsDCA", true, "Minimise abs. distance rather than chi2"}; Configurable useWeightedFinalPCA{"useWeightedFinalPCA", false, "Recalculate vertex position using track covariances, effective only if useAbsDCA is true"}; - Configurable maxR{"maxR", 200., "reject PCA's above this radius"}; - Configurable maxDZIni{"maxDZIni", 4., "reject (if>0) PCA candidate if tracks DZ exceeds threshold"}; - Configurable minParamChange{"minParamChange", 1.e-3, "stop iterations if largest change of any B0 is smaller than this"}; - Configurable minRelChi2Change{"minRelChi2Change", 0.9, "stop iterations is chi2/chi2old > this"}; + Configurable maxR{"maxR", 200., "reject PCA's above this radius"}; + Configurable maxDZIni{"maxDZIni", 4., "reject (if>0) PCA candidate if tracks DZ exceeds threshold"}; + Configurable minParamChange{"minParamChange", 1.e-3, "stop iterations if largest change of any B0 is smaller than this"}; + Configurable minRelChi2Change{"minRelChi2Change", 0.9, "stop iterations is chi2/chi2old > this"}; // selection - Configurable invMassWindowDPiTolerance{"invMassWindowDPiTolerance", 0.01, "invariant-mass window tolerance for DPi pair preselections (GeV/c2)"}; + Configurable invMassWindowDPiTolerance{"invMassWindowDPiTolerance", 0.01, "invariant-mass window tolerance for DPi pair preselections (GeV/c2)"}; // variable that will store the value of invMassWindowDPi (defined in dataCreatorDplusPiReduced.cxx) float myInvMassWindowDPi{1.}; - double massPi{0.}; - double massD{0.}; - double massB0{0.}; - double bz{0.}; + float massPi{0.}; + float massD{0.}; + float massB0{0.}; + float bz{0.}; // Fitter for B vertex (2-prong vertex filter) o2::vertexing::DCAFitterN<2> df2; Preslice> candsDPerCollision = hf_track_index_reduced::hfRedCollisionId; + Preslice> candsDWithMlPerCollision = hf_track_index_reduced::hfRedCollisionId; Preslice> tracksPionPerCollision = hf_track_index_reduced::hfRedCollisionId; HistogramRegistry registry{"registry"}; void init(InitContext const&) { + std::array doprocess{doprocessData, doprocessDataWithDmesMl}; + if ((std::accumulate(doprocess.begin(), doprocess.end(), 0)) != 1) { + LOGP(fatal, "Only one process function for data should be enabled at a time."); + } + // 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.}}}); 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}}}); @@ -86,11 +94,106 @@ struct HfCandidateCreatorB0Reduced { df2.setWeightedFinalPCA(useWeightedFinalPCA); } - void process(aod::HfRedCollisions const& collisions, - soa::Join const& candsD, - soa::Join const& tracksPion, - aod::HfOrigColCounts const& collisionsCounter, - aod::HfCandB0Configs const& configs) + /// 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 runCandidateCreation(aod::HfRedCollisions::iterator const& collision, + Cands const& candsDThisColl, + 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(); + df2.setBz(bz); + + for (const auto& candD : candsDThisColl) { + auto trackParCovD = getTrackParCov(candD); + std::array pVecD = {candD.px(), candD.py(), candD.pz()}; + + for (const auto& trackPion : tracksPionThisCollision) { + // this track is among daughters + if (trackPion.trackId() == candD.prong0Id() || trackPion.trackId() == candD.prong1Id() || trackPion.trackId() == candD.prong2Id()) { + continue; + } + + auto trackParCovPi = getTrackParCov(trackPion); + std::array pVecPion = {trackPion.px(), trackPion.py(), trackPion.pz()}; + + // compute invariant mass square and apply selection + auto invMass2DPi = RecoDecay::m2(std::array{pVecD, pVecPion}, std::array{massD, massPi}); + if ((invMass2DPi < invMass2DPiMin) || (invMass2DPi > invMass2DPiMax)) { + continue; + } + // --------------------------------- + // reconstruct the 2-prong B0 vertex + if (df2.process(trackParCovD, trackParCovPi) == 0) { + continue; + } + // DPi passed B0 reconstruction + + // calculate relevant properties + const auto& secondaryVertexB0 = df2.getPCACandidate(); + auto chi2PCA = df2.getChi2AtPCACandidate(); + auto covMatrixPCA = df2.calcPCACovMatrixFlat(); + registry.fill(HIST("hCovSVXX"), covMatrixPCA[0]); + registry.fill(HIST("hCovPVXX"), covMatrixPV[0]); + + // propagate D and Pi to the B0 vertex + df2.propagateTracksToVertex(); + // track.getPxPyPzGlo(pVec) modifies pVec of track + df2.getTrack(0).getPxPyPzGlo(pVecD); // momentum of D at the B0 vertex + df2.getTrack(1).getPxPyPzGlo(pVecPion); // 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 dcaPion; + trackParCovD.propagateToDCA(primaryVertex, bz, &dcaD); + trackParCovPi.propagateToDCA(primaryVertex, bz, &dcaPion); + + // 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: + rowCandidateBase(collision.globalIndex(), + collision.posX(), collision.posY(), collision.posZ(), + secondaryVertexB0[0], secondaryVertexB0[1], secondaryVertexB0[2], + errorDecayLength, errorDecayLengthXY, + chi2PCA, + pVecD[0], pVecD[1], pVecD[2], + pVecPion[0], pVecPion[1], pVecPion[2], + dcaD.getY(), dcaPion.getY(), + std::sqrt(dcaD.getSigmaY2()), std::sqrt(dcaPion.getSigmaY2()), + BIT(hf_cand_b0::DecayType::B0ToDPi)); + + rowCandidateProngs(candD.globalIndex(), trackPion.globalIndex()); + + if constexpr (withDmesMl) { + rowCandidateDmesMlScores(candD.mlScoreBkg(), candD.mlScorePrompt(), candD.mlScoreNonprompt()); + } + } // pi loop + } // D loop + } + + void processData(aod::HfRedCollisions 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) { @@ -98,104 +201,62 @@ 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 - double invMass2DPiMin = (massB0 - myInvMassWindowDPi + invMassWindowDPiTolerance) * (massB0 - myInvMassWindowDPi + invMassWindowDPiTolerance); - double invMass2DPiMax = (massB0 + myInvMassWindowDPi - invMassWindowDPiTolerance) * (massB0 + myInvMassWindowDPi - invMassWindowDPiTolerance); + float invMass2DPiMin = (massB0 - myInvMassWindowDPi + invMassWindowDPiTolerance) * (massB0 - myInvMassWindowDPi + invMassWindowDPiTolerance); + float invMass2DPiMax = (massB0 + myInvMassWindowDPi - invMassWindowDPiTolerance) * (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 primaryVertex = getPrimaryVertex(collision); - auto covMatrixPV = primaryVertex.getCov(); - + auto candsDThisColl = candsD.sliceBy(candsDPerCollision, thisCollId); + auto tracksPionThisCollision = tracksPion.sliceBy(tracksPionPerCollision, thisCollId); + runCandidateCreation(collision, candsDThisColl, tracksPionThisCollision, invMass2DPiMin, invMass2DPiMax); if (ncol % 10000 == 0) { - LOG(debug) << ncol << " collisions parsed"; + LOGP(debug, "collisions parsed {}", ncol); } ncol++; + } + } // processData - // Set the magnetic field from ccdb - bz = collision.bz(); - df2.setBz(bz); + PROCESS_SWITCH(HfCandidateCreatorB0Reduced, processData, "Process data without any ML score", true); + void processDataWithDmesMl(aod::HfRedCollisions 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) { + 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 = (massB0 - myInvMassWindowDPi + invMassWindowDPiTolerance) * (massB0 - myInvMassWindowDPi + invMassWindowDPiTolerance); + float invMass2DPiMax = (massB0 + myInvMassWindowDPi - invMassWindowDPiTolerance) * (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(candsDPerCollision, thisCollId); - for (const auto& candD : candsDThisColl) { - auto trackParCovD = getTrackParCov(candD); - std::array pVecD = {candD.px(), candD.py(), candD.pz()}; - - auto tracksPionThisCollision = tracksPion.sliceBy(tracksPionPerCollision, thisCollId); - for (const auto& trackPion : tracksPionThisCollision) { - // this track is among daughters - if (trackPion.trackId() == candD.prong0Id() || trackPion.trackId() == candD.prong1Id() || trackPion.trackId() == candD.prong2Id()) { - continue; - } - - auto trackParCovPi = getTrackParCov(trackPion); - std::array pVecPion = {trackPion.px(), trackPion.py(), trackPion.pz()}; - - // compute invariant mass square and apply selection - auto invMass2DPi = RecoDecay::m2(std::array{pVecD, pVecPion}, std::array{massD, massPi}); - if ((invMass2DPi < invMass2DPiMin) || (invMass2DPi > invMass2DPiMax)) { - continue; - } - // --------------------------------- - // reconstruct the 2-prong B0 vertex - if (df2.process(trackParCovD, trackParCovPi) == 0) { - continue; - } - // DPi passed B0 reconstruction - - // calculate relevant properties - const auto& secondaryVertexB0 = df2.getPCACandidate(); - auto chi2PCA = df2.getChi2AtPCACandidate(); - auto covMatrixPCA = df2.calcPCACovMatrixFlat(); - registry.fill(HIST("hCovSVXX"), covMatrixPCA[0]); - registry.fill(HIST("hCovPVXX"), covMatrixPV[0]); - - // propagate D and Pi to the B0 vertex - df2.propagateTracksToVertex(); - // track.getPxPyPzGlo(pVec) modifies pVec of track - df2.getTrack(0).getPxPyPzGlo(pVecD); // momentum of D at the B0 vertex - df2.getTrack(1).getPxPyPzGlo(pVecPion); // 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 dcaPion; - trackParCovD.propagateToDCA(primaryVertex, bz, &dcaD); - trackParCovPi.propagateToDCA(primaryVertex, bz, &dcaPion); - - // get uncertainty of the decay length - double 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.)); - - int hfFlag = BIT(hf_cand_b0::DecayType::B0ToDPi); - - // fill the candidate table for the B0 here: - rowCandidateBase(thisCollId, - collision.posX(), collision.posY(), collision.posZ(), - secondaryVertexB0[0], secondaryVertexB0[1], secondaryVertexB0[2], - errorDecayLength, errorDecayLengthXY, - chi2PCA, - pVecD[0], pVecD[1], pVecD[2], - pVecPion[0], pVecPion[1], pVecPion[2], - dcaD.getY(), dcaPion.getY(), - std::sqrt(dcaD.getSigmaY2()), std::sqrt(dcaPion.getSigmaY2()), - hfFlag); - - rowCandidateProngs(candD.globalIndex(), trackPion.globalIndex()); - } // pi loop - } // D loop - } // collision loop - } // process -}; // struct + auto tracksPionThisCollision = tracksPion.sliceBy(tracksPionPerCollision, thisCollId); + runCandidateCreation(collision, candsDThisColl, tracksPionThisCollision, invMass2DPiMin, invMass2DPiMax); + if (ncol % 10000 == 0) { + LOGP(debug, "collisions parsed {}", ncol); + } + ncol++; + } + } // processDataWithDmesMl + + 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 { diff --git a/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx b/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx index 4b88fcdaa98..00effa6ecad 100644 --- a/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx @@ -13,6 +13,7 @@ /// \brief B0 → D- π+ candidate selector /// /// \author Alexandre Bigot , IPHC Strasbourg +/// \author Fabrizio Grosa , CERN #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" @@ -33,24 +34,27 @@ using namespace o2::analysis; struct HfCandidateSelectorB0ToDPiReduced { Produces hfSelB0ToDPiCandidate; // table defined in CandidateSelectionTables.h - Configurable ptCandMin{"ptCandMin", 0., "Lower bound of candidate pT"}; - Configurable ptCandMax{"ptCandMax", 50., "Upper bound of candidate pT"}; + Configurable ptCandMin{"ptCandMin", 0., "Lower bound of candidate pT"}; + Configurable ptCandMax{"ptCandMax", 50., "Upper bound of candidate pT"}; // Enable PID Configurable usePid{"usePid", true, "Switch for PID selection at track level"}; Configurable acceptPIDNotApplicable{"acceptPIDNotApplicable", true, "Switch to accept Status::NotApplicable [(NotApplicable for one detector) and (NotApplicable or Conditional for the other)] in PID selection"}; // TPC PID - Configurable ptPidTpcMin{"ptPidTpcMin", 0.15, "Lower bound of track pT for TPC PID"}; - Configurable ptPidTpcMax{"ptPidTpcMax", 20., "Upper bound of track pT for TPC PID"}; - Configurable nSigmaTpcMax{"nSigmaTpcMax", 5., "Nsigma cut on TPC only"}; - Configurable nSigmaTpcCombinedMax{"nSigmaTpcCombinedMax", 5., "Nsigma cut on TPC combined with TOF"}; + Configurable ptPidTpcMin{"ptPidTpcMin", 0.15, "Lower bound of track pT for TPC PID"}; + Configurable ptPidTpcMax{"ptPidTpcMax", 20., "Upper bound of track pT for TPC PID"}; + Configurable nSigmaTpcMax{"nSigmaTpcMax", 5., "Nsigma cut on TPC only"}; + Configurable nSigmaTpcCombinedMax{"nSigmaTpcCombinedMax", 5., "Nsigma cut on TPC combined with TOF"}; // TOF PID - Configurable ptPidTofMin{"ptPidTofMin", 0.15, "Lower bound of track pT for TOF PID"}; - Configurable ptPidTofMax{"ptPidTofMax", 20., "Upper bound of track pT for TOF PID"}; - Configurable nSigmaTofMax{"nSigmaTofMax", 5., "Nsigma cut on TOF only"}; - Configurable nSigmaTofCombinedMax{"nSigmaTofCombinedMax", 5., "Nsigma cut on TOF combined with TPC"}; + Configurable ptPidTofMin{"ptPidTofMin", 0.15, "Lower bound of track pT for TOF PID"}; + Configurable ptPidTofMax{"ptPidTofMax", 20., "Upper bound of track pT for TOF PID"}; + Configurable nSigmaTofMax{"nSigmaTofMax", 5., "Nsigma cut on TOF only"}; + Configurable nSigmaTofCombinedMax{"nSigmaTofCombinedMax", 5., "Nsigma cut on TOF combined with TPC"}; // topological cuts Configurable> binsPt{"binsPt", std::vector{hf_cuts_b0_to_d_pi::vecBinsPt}, "pT bin limits"}; Configurable> cuts{"cuts", {hf_cuts_b0_to_d_pi::cuts[0], hf_cuts_b0_to_d_pi::nBinsPt, hf_cuts_b0_to_d_pi::nCutVars, hf_cuts_b0_to_d_pi::labelsPt, hf_cuts_b0_to_d_pi::labelsCutVar}, "B0 candidate selection per pT bin"}; + // D-meson ML cuts + Configurable> binsPtDmesMl{"binsPtDmesMl", std::vector{hf_cuts_ml::vecBinsPt}, "D-meson pT bin limits for ML cuts"}; + Configurable> cutsDmesMl{"cutsDmesMl", {hf_cuts_ml::cuts[0], hf_cuts_ml::nBinsPt, hf_cuts_ml::nCutScores, hf_cuts_ml::labelsPt, hf_cuts_ml::labelsCutScore}, "D-meson ML cuts per pT bin"}; // QA switch Configurable activateQA{"activateQA", false, "Flag to enable QA histogram"}; @@ -68,6 +72,11 @@ struct HfCandidateSelectorB0ToDPiReduced { void init(InitContext const& initContext) { + std::array doprocess{doprocessSelection, doprocessSelectionWithDmesMl}; + if ((std::accumulate(doprocess.begin(), doprocess.end(), 0)) != 1) { + LOGP(fatal, "Only one process function for data should be enabled at a time."); + } + if (usePid) { selectorPion.setRangePtTpc(ptPidTpcMin, ptPidTpcMax); selectorPion.setRangeNSigmaTpc(-nSigmaTpcMax, nSigmaTpcMax); @@ -92,9 +101,15 @@ struct HfCandidateSelectorB0ToDPiReduced { } } - void process(HfRedCandB0 const& hfCandsB0, - TracksPion const&, - HfCandB0Configs const& configs) + /// 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 + /// \param pionTracks pion tracks + /// \param configs config inherited from the Dpi data creator + template + void runSelection(Cands const& hfCandsB0, + TracksPion const& pionTracks, + HfCandB0Configs const& configs) { // get DplusPi creator configurable for (const auto& config : configs) { @@ -134,6 +149,15 @@ struct HfCandidateSelectorB0ToDPiReduced { // LOGF(info, "B0 candidate selection failed at topology selection"); continue; } + + if constexpr (withDmesMl) { // we include it in the topological selections + if (!hfHelper.selectionDmesMlScoresForB(hfCandB0, cutsDmesMl, binsPtDmesMl)) { + hfSelB0ToDPiCandidate(statusB0ToDPi); + // LOGF(info, "B0 candidate selection failed at D-meson ML selection"); + continue; + } + } + SETBIT(statusB0ToDPi, SelectionStep::RecoTopol); // RecoTopol = 1 --> statusB0ToDPi = 3 if (activateQA) { registry.fill(HIST("hSelections"), 2 + SelectionStep::RecoTopol, ptCandB0); @@ -146,7 +170,7 @@ struct HfCandidateSelectorB0ToDPiReduced { } // track-level PID selection if (usePid) { - auto trackPi = hfCandB0.prong1_as(); + auto trackPi = hfCandB0.template prong1_as(); int pidTrackPi = selectorPion.statusTpcAndTof(trackPi); if (!hfHelper.selectionB0ToDPiPid(pidTrackPi, acceptPIDNotApplicable.value)) { // LOGF(info, "B0 candidate selection failed at PID selection"); @@ -162,6 +186,24 @@ struct HfCandidateSelectorB0ToDPiReduced { // LOGF(info, "B0 candidate selection passed all selections"); } } + + void processSelection(HfRedCandB0 const& hfCandsB0, + TracksPion const& pionTracks, + HfCandB0Configs const& configs) + { + runSelection(hfCandsB0, pionTracks, configs); + } // processSelection + + PROCESS_SWITCH(HfCandidateSelectorB0ToDPiReduced, processSelection, "Process selection without ML scores of D mesons", true); + + void processSelectionWithDmesMl(soa::Join const& hfCandsB0, + TracksPion const& pionTracks, + HfCandB0Configs const& configs) + { + runSelection(hfCandsB0, pionTracks, configs); + } // processSelectionWithDmesMl + + PROCESS_SWITCH(HfCandidateSelectorB0ToDPiReduced, processSelectionWithDmesMl, "Process selection with ML scores of D mesons", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGHF/D2H/Tasks/taskB0Reduced.cxx b/PWGHF/D2H/Tasks/taskB0Reduced.cxx index d316b0c0ca4..833baf17707 100644 --- a/PWGHF/D2H/Tasks/taskB0Reduced.cxx +++ b/PWGHF/D2H/Tasks/taskB0Reduced.cxx @@ -13,6 +13,7 @@ /// \brief B0 → D- π+ → (π- K+ π-) π+ analysis task /// /// \author Alexandre Bigot , IPHC Strasbourg +/// \author Fabrizio Grosa , CERN #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" @@ -34,89 +35,168 @@ using namespace o2::framework::expressions; /// B0 analysis task struct HfTaskB0Reduced { Configurable selectionFlagB0{"selectionFlagB0", 1, "Selection Flag for B0"}; - Configurable yCandGenMax{"yCandGenMax", 0.5, "max. gen particle rapidity"}; - Configurable yCandRecoMax{"yCandRecoMax", 0.8, "max. cand. rapidity"}; + Configurable yCandGenMax{"yCandGenMax", 0.5, "max. gen particle rapidity"}; + Configurable yCandRecoMax{"yCandRecoMax", 0.8, "max. cand. rapidity"}; Configurable etaTrackMax{"etaTrackMax", 0.8, "max. track pseudo-rapidity"}; Configurable ptTrackMin{"ptTrackMin", 0.1, "min. track transverse momentum"}; - Configurable> binsPt{"binsPt", std::vector{hf_cuts_b0_to_d_pi::vecBinsPt}, "pT bin limits"}; + Configurable fillHistograms{"fillHistograms", true, "Flag to enable histogram filling"}; + Configurable fillSparses{"fillSparses", false, "Flag to enable sparse filling"}; + Configurable fillBackground{"fillBackground", false, "Flag to enable filling of background histograms/sparses (only MC)"}; HfHelper hfHelper; Filter filterSelectCandidates = (aod::hf_sel_candidate_b0::isSelB0ToDPi >= selectionFlagB0); - HistogramRegistry registry{ - "registry", - {{"hPtProng0", "B0 candidates;prong 0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{1000, 0., 50.}}}}, - {"hPtProng1", "B0 candidates;prong 1 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 10.}}}}, - {"hPtCand", "B0 candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{1000, 0., 50.}}}}}}; + HistogramRegistry registry{"registry"}; void init(InitContext&) { - registry.add("hMass", "B^{0} candidates;inv. mass D^{#minus}#pi^{#plus} (GeV/#it{c}^{2});#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {{300, 4.5, 6.0}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hDecLength", "B^{0} candidates;decay length (cm);entries", {HistType::kTH2F, {{200, 0., 0.4}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hDecLengthXY", "B^{0} candidates;decay length xy (cm);entries", {HistType::kTH2F, {{200, 0., 0.4}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hd0Prong0", "B^{0} candidates;prong 0 (D^{#minus}) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {{100, -0.05, 0.05}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hd0Prong1", "B^{0} candidates;prong 1 (#pi^{#plus}) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {{100, -0.05, 0.05}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hCPA", "B^{0} candidates;B^{0} candidate cosine of pointing angle;entries", {HistType::kTH2F, {{110, -1.1, 1.1}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hEta", "B^{0} candidates;B^{0} candidate #it{#eta};entries", {HistType::kTH2F, {{100, -2., 2.}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hRapidity", "B^{0} candidates;B^{0} candidate #it{y};entries", {HistType::kTH2F, {{100, -2., 2.}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hImpParErr", "B^{0} candidates;B^{0} candidate impact parameter error (cm);entries", {HistType::kTH2F, {{100, -1., 1.}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hDecLenErr", "B^{0} candidates;B^{0} candidate decay length error (cm);entries", {HistType::kTH2F, {{100, 0., 1.}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hDecLenXYErr", "B^{0} candidates;B^{0} candidate decay length xy error (cm);entries", {HistType::kTH2F, {{100, 0., 1.}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hIPProd", "B^{0} candidates;B^{0} candidate impact parameter product;entries", {HistType::kTH2F, {{100, -0.5, 0.5}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hInvMassD", "B^{0} candidates;prong0, D^{#minus} inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{350, 1.7, 2.05}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - - registry.add("hEtaGen", "MC particles (generated);B^{0} candidate #it{#eta}^{gen};entries", {HistType::kTH2F, {{100, -2., 2.}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hYGen", "MC particles (generated);B^{0} candidate #it{y}^{gen};entries", {HistType::kTH2F, {{100, -2., 2.}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hEtaGenWithProngsInAcceptance", "MC particles (generated-daughters in acceptance);B^{0} candidate #it{#eta}^{gen};entries", {HistType::kTH2F, {{100, -2., 2.}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hYGenWithProngsInAcceptance", "MC particles (generated-daughters in acceptance);B^{0} candidate #it{y}^{gen};entries", {HistType::kTH2F, {{100, -2., 2.}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hPtProng0Gen", "MC particles (generated);prong 0 (D^{#minus}) #it{p}_{T}^{gen} (GeV/#it{c});entries", {HistType::kTH2F, {{100, 0., 10.}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hPtProng1Gen", "MC particles (generated);prong 1 (#pi^{-}) #it{p}_{T}^{gen} (GeV/#it{c});entries", {HistType::kTH2F, {{100, 0., 10.}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hYProng0Gen", "MC particles (generated);prong 0 (D^{#minus}) #it{y}^{gen};entries", {HistType::kTH2F, {{100, -2, 2}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hYProng1Gen", "MC particles (generated);prong 1 (#pi^{-}) #it{y}^{gen};entries", {HistType::kTH2F, {{100, -2, 2}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hEtaProng0Gen", "MC particles (generated);prong 0 (B^{0}) #it{#eta}^{gen};entries", {HistType::kTH2F, {{100, -2, 2}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hEtaProng1Gen", "MC particles (generated);prong 1 (#pi^{-}) #it{#eta}^{gen};entries", {HistType::kTH2F, {{100, -2, 2}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hCPARecSig", "B^{0} candidates (matched);B^{0} candidate cosine of pointing angle;entries", {HistType::kTH2F, {{220, 0., 1.1}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hCPARecBg", "B^{0} candidates (unmatched);B^{0} candidate cosine of pointing angle;entries", {HistType::kTH2F, {{220, 0., 1.1}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hCPAxyRecSig", "B^{0} candidates (matched);B^{0} candidate CPAxy;entries", {HistType::kTH2F, {{220, 0., 1.1}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hCPAxyRecBg", "B^{0} candidates (unmatched);B^{0} candidate CPAxy;entries", {HistType::kTH2F, {{220, 0., 1.1}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hCPADRecSig", "B^{0} candidates (matched);prong 0 (D^{#minus}) cosine of pointing angle;entries", {HistType::kTH2F, {{220, 0., 1.1}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hCPADRecBg", "B^{0} candidates (unmatched);prong 0 (D^{#minus}) cosine of pointing angle;entries", {HistType::kTH2F, {{220, 0., 1.1}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hEtaRecSig", "B^{0} candidates (matched);B^{0} candidate #it{#eta};entries", {HistType::kTH2F, {{100, -2., 2.}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hEtaRecBg", "B^{0} candidates (unmatched);B^{0} candidate #it{#eta};entries", {HistType::kTH2F, {{100, -2., 2.}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hRapidityRecSig", "B^{0} candidates (matched);B^{0} candidate #it{y};entries", {HistType::kTH2F, {{100, -2., 2.}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hRapidityRecBg", "B^{0} candidates (unmatched);B^{0} candidate #it{#y};entries", {HistType::kTH2F, {{100, -2., 2.}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - - registry.add("hPtProng0RecSig", "B^{0} candidates (matched);prong 0 (D^{#minus}) #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH2F, {{100, 0., 10.}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hPtProng1RecSig", "B^{0} candidates (matched);prong 1 (#pi^{#minus}) #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH2F, {{100, 0., 10.}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hPtProng0RecBg", "B^{0} candidates (unmatched);prong 0 (D^{#minus}) #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH2F, {{100, 0., 10.}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hPtProng1RecBg", "B^{0} candidates (unmatched);prong 1 (#pi^{#minus}) #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH2F, {{100, 0., 10.}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hMassRecSig", "B^{0} candidates (matched);inv. mass D^{#minus}#pi^{+} (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{300, 4.0, 7.00}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hMassRecBg", "B^{0} candidates (unmatched);inv. mass D^{#minus}#pi^{+} (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{300, 4.0, 7.0}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hd0Prong0RecSig", "B^{0} candidates (matched);prong 0 (D^{#minus}}) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {{200, -0.05, 0.05}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hd0Prong1RecSig", "B^{0} candidates (matched);prong 1 (#pi^{#minus}) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {{200, -0.05, 0.05}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hd0Prong0RecBg", "B^{0} candidates (unmatched);prong 0 (D^{#minus}) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {{200, -0.05, 0.05}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hd0Prong1RecBg", "B^{0} candidates (unmatched);prong 1 (#pi^{#minus}) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {{200, -0.05, 0.05}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hDecLengthRecSig", "B^{0} candidates (matched);B^{0} candidate decay length (cm);entries", {HistType::kTH2F, {{100, 0., 0.5}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hDecLengthXYRecSig", "B^{0} candidates (matched);B^{0} candidate decay length xy (cm);entries", {HistType::kTH2F, {{100, 0., 0.5}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hDecLengthRecBg", "B^{0} candidates (unmatched);B^{0} candidate decay length (cm);entries", {HistType::kTH2F, {{100, 0., 0.5}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hDecLengthXYRecBg", "B^{0} candidates (unmatched);B^{0} candidate decay length xy(cm);entries", {HistType::kTH2F, {{100, 0., 0.5}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hDecLengthDRecSig", "B^{0} candidates (matched);B^{0} candidate decay length (cm);entries", {HistType::kTH2F, {{100, 0., 0.5}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hDecLengthDRecBg", "B^{0} candidates (unmatched);B^{0} candidate decay length (cm);entries", {HistType::kTH2F, {{100, 0., 0.5}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hDecLengthNormRecSig", "B^{0} candidates (matched);B^{0} candidate decay length (cm);entries", {HistType::kTH2F, {{100, 0., 0.5}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hDecLengthNormRecBg", "B^{0} candidates (unmatched);B^{0} candidate decay length (cm);entries", {HistType::kTH2F, {{100, 0., 0.5}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hImpParProdB0RecSig", "B^{0} candidates (matched);B^{0} candidate impact parameter product ;entries", {HistType::kTH2F, {{100, -0.01, 0.01}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hImpParProdB0RecBg", "B^{0} candidates (unmatched);B^{0} candidate impact parameter product ;entries", {HistType::kTH2F, {{100, -0.01, 0.01}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - - registry.add("hChi2PCARecSig", "B^{0} candidates (matched);sum of distances of the secondary vertex to its prongs;entries", {HistType::kTH2F, {{240, -0.01, 0.1}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hChi2PCARecBg", "B^{0} candidates (unmatched);sum of distances of the secondary vertex to its prongs;entries", {HistType::kTH2F, {{240, -0.01, 0.1}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - - registry.add("hPtRecSig", "B0 candidates (matched);candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{300, 0., 30.}}}); - registry.add("hPtRecBg", "B0 candidates (unmatched);candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{300, 0., 30.}}}); - registry.add("hPtGenSig", "B0 candidates (gen+rec);candidate #it{p}_{T}^{gen.} (GeV/#it{c});entries", {HistType::kTH1F, {{300, 0., 10.}}}); - registry.add("hPtGen", "MC particles (generated);candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{300, 0., 30.}}}); - registry.add("hPtGenWithRapidityBelowHalf", "MC particles (generated - |#it{y}^{gen}|<0.5);candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{300, 0., 30.}}}); - registry.add("hPtGenWithProngsInAcceptance", "MC particles (generated-daughters in acceptance);candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{300, 0., 30.}}}); + std::array processFuncData{doprocessData, doprocessDataWithDmesMl}; + 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, doprocessMcWithDmesMl}; + if ((std::accumulate(processFuncMc.begin(), processFuncMc.end(), 0)) > 1) { + LOGP(fatal, "Only one process function for MC can be enabled at a time."); + } + + 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 axisDecayLength{200, 0.f, 0.4f}; + const AxisSpec axisNormDecayLength{100, 0.f, 50.f}; + const AxisSpec axisDca{100, -0.05f, 0.05f}; + const AxisSpec axisCosp{110, 0.f, 1.1f}; + 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 axisPtB0{100, 0.f, 50.f}; + const AxisSpec axisPtDminus{100, 0.f, 50.f}; + const AxisSpec axisPtPi{100, 0.f, 10.f}; + + if (doprocessData || doprocessDataWithDmesMl) { + 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("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}}); + + // 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 (fillSparses) { + if (!doprocessDataWithDmesMl) { + 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}}); + } 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 (doprocessMc || doprocessMcWithDmesMl) { + 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("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("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("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 + // signal + registry.add("hMassRecSig", "B^{0} candidates (matched);#it{p}_{T}(B^{0}) (GeV/#it{c});#it{M} (D#pi) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {axisPtB0, axisMassB0}}); + 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("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}}); + // 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("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}}); + } + + // ML scores of D- daughter + if (doprocessMcWithDmesMl) { + // 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}}); + // 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}}); + } + } + if (fillSparses) { + // gen sparses + registry.add("hPtYGenSig", "B^{0} particles (generated);#it{p}_{T}(B^{0}) (GeV/#it{c});#it{y}(B^{0})", {HistType::kTHnSparseF, {axisPtB0, axisEta}}); + 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) { + 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 (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}}); + } + } 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}}); + 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}}); + } + } + } + } } /// Selection of B0 daughter in geometrical acceptance @@ -129,8 +209,191 @@ struct HfTaskB0Reduced { return std::abs(etaProng) <= etaTrackMax && ptProng >= ptTrackMin; } - void process(soa::Filtered> const& candidates, - aod::HfRed3Prongs const&) + /// Fill candidate histograms (reco no MC truth) + /// \param withDmesMl is the flag to enable the filling of hisgorams with ML scores for the D- daughter + /// \param candidate is the B0 candidate + /// \param candidatesD is the table with D- candidates + template + void fillCand(Cand const& candidate, + aod::HfRed3Prongs const& candidatesD) + { + auto ptCandB0 = candidate.pt(); + auto invMassB0 = hfHelper.invMassB0ToDPi(candidate); + auto candD = candidate.template prong0_as(); + auto ptD = RecoDecay::pt(candD.px(), candD.py()); + std::array posPv{candidate.posX(), candidate.posY(), candidate.posZ()}; + std::array posSvD{candD.xSecondaryVertex(), candD.ySecondaryVertex(), candD.zSecondaryVertex()}; + std::array momD{candD.px(), candD.py(), candD.pz()}; + 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); + + if (fillHistograms) { + registry.fill(HIST("hMass"), ptCandB0, invMassB0); + registry.fill(HIST("hPtProng0"), ptCandB0, candidate.ptProng0()); + registry.fill(HIST("hPtProng1"), ptCandB0, candidate.ptProng1()); + registry.fill(HIST("hImpParProd"), ptCandB0, candidate.impactParameterProduct()); + 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("hDcaProng0"), ptCandB0, candidate.impactParameter0()); + registry.fill(HIST("hDcaProng1"), ptCandB0, candidate.impactParameter1()); + 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, candD.invMass()); + 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 (withDmesMl) { + registry.fill(HIST("hMassPtCutVars"), invMassB0, ptCandB0, candidate.decayLength(), candidate.decayLengthXY() / candidate.errorDecayLengthXY(), candidate.impactParameterProduct(), candidate.cpa(), candD.invMass(), ptD, candidate.prong0MlScoreBkg(), candidate.prong0MlScoreNonprompt()); + } else { + registry.fill(HIST("hMassPtCutVars"), invMassB0, ptCandB0, candidate.decayLength(), candidate.decayLengthXY() / candidate.errorDecayLengthXY(), candidate.impactParameterProduct(), candidate.cpa(), candD.invMass(), ptD, decLenD, cospD); + } + } + } + + /// Fill candidate histograms (reco MC truth) + /// \param withDmesMl is the flag to enable the filling of hisgorams with ML scores for the D- daughter + /// \param candidate is the B0 candidate + /// \param candidatesD is the table with D- candidates + template + void fillCandMcReco(Cand const& candidate, + aod::HfRed3Prongs const& candidatesD) + { + auto ptCandB0 = candidate.pt(); + auto invMassB0 = hfHelper.invMassB0ToDPi(candidate); + auto candD = candidate.template prong0_as(); + auto ptD = RecoDecay::pt(candD.px(), candD.py()); + std::array posPv{candidate.posX(), candidate.posY(), candidate.posZ()}; + std::array posSvD{candD.xSecondaryVertex(), candD.ySecondaryVertex(), candD.zSecondaryVertex()}; + std::array momD{candD.px(), candD.py(), candD.pz()}; + 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); + + bool isSignal = TESTBIT(std::abs(candidate.flagMcMatchRec()), hf_cand_b0::DecayType::B0ToDPi); + if (fillHistograms) { + if (isSignal) { + registry.fill(HIST("hMassRecSig"), ptCandB0, hfHelper.invMassB0ToDPi(candidate)); + registry.fill(HIST("hPtProng0RecSig"), ptCandB0, candidate.ptProng0()); + registry.fill(HIST("hPtProng1RecSig"), ptCandB0, candidate.ptProng1()); + registry.fill(HIST("hImpParProdRecSig"), ptCandB0, candidate.impactParameterProduct()); + 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("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, candD.invMass()); + 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("hPtProng0RecBg"), ptCandB0, candidate.ptProng0()); + registry.fill(HIST("hPtProng1RecBg"), ptCandB0, candidate.ptProng1()); + registry.fill(HIST("hImpParProdRecBg"), ptCandB0, candidate.impactParameterProduct()); + 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("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, candD.invMass()); + 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()); + } + } + } + if (fillSparses) { + if (isSignal) { + if constexpr (withDmesMl) { + registry.fill(HIST("hMassPtCutVarsRecSig"), invMassB0, ptCandB0, candidate.decayLength(), candidate.decayLengthXY() / candidate.errorDecayLengthXY(), candidate.impactParameterProduct(), candidate.cpa(), candD.invMass(), ptD, candidate.prong0MlScoreBkg(), candidate.prong0MlScoreNonprompt()); + } else { + registry.fill(HIST("hMassPtCutVarsRecSig"), invMassB0, ptCandB0, candidate.decayLength(), candidate.decayLengthXY() / candidate.errorDecayLengthXY(), candidate.impactParameterProduct(), candidate.cpa(), candD.invMass(), ptD, decLenD, cospD); + } + } else if (fillBackground) { + if constexpr (withDmesMl) { + registry.fill(HIST("hMassPtCutVarsRecBg"), invMassB0, ptCandB0, candidate.decayLength(), candidate.decayLengthXY() / candidate.errorDecayLengthXY(), candidate.impactParameterProduct(), candidate.cpa(), candD.invMass(), ptD, candidate.prong0MlScoreBkg(), candidate.prong0MlScoreNonprompt()); + } else { + registry.fill(HIST("hMassPtCutVarsRecBg"), invMassB0, ptCandB0, candidate.decayLength(), candidate.decayLengthXY() / candidate.errorDecayLengthXY(), candidate.impactParameterProduct(), candidate.cpa(), candD.invMass(), ptD, decLenD, cospD); + } + } + } + } + + /// Fill particle histograms (gen MC truth) + void fillCandMcGen(aod::HfMcGenRedB0s::iterator const& particle) + { + auto ptParticle = particle.ptTrack(); + auto yParticle = particle.yTrack(); + auto etaParticle = particle.etaTrack(); + if (yCandGenMax >= 0. && std::abs(yParticle) > yCandGenMax) { + return; + } + std::array ptProngs = {particle.ptProng0(), particle.ptProng1()}; + std::array yProngs = {particle.yProng0(), particle.yProng1()}; + std::array etaProngs = {particle.etaProng0(), particle.etaProng1()}; + bool prongsInAcc = isProngInAcceptance(etaProngs[0], ptProngs[0]) && isProngInAcceptance(etaProngs[1], ptProngs[1]); + + if (fillHistograms) { + registry.fill(HIST("hPtProng0Gen"), ptParticle, ptProngs[0]); + registry.fill(HIST("hPtProng1Gen"), ptParticle, ptProngs[1]); + registry.fill(HIST("hYProng0Gen"), ptParticle, yProngs[0]); + registry.fill(HIST("hYProng1Gen"), ptParticle, yProngs[1]); + registry.fill(HIST("hEtaProng0Gen"), ptParticle, etaProngs[0]); + registry.fill(HIST("hEtaProng1Gen"), ptParticle, etaProngs[1]); + + registry.fill(HIST("hYGen"), ptParticle, yParticle); + registry.fill(HIST("hEtaGen"), ptParticle, etaParticle); + + // generated B0 with daughters in geometrical acceptance + if (prongsInAcc) { + registry.fill(HIST("hYGenWithProngsInAcceptance"), ptParticle, yParticle); + } + } + if (fillSparses) { + registry.fill(HIST("hPtYGenSig"), ptParticle, yParticle); + if (prongsInAcc) { + registry.fill(HIST("hPtYWithProngsInAccepanceGenSig"), ptParticle, yParticle); + } + } + } + + // Process functions + void processData(soa::Filtered> const& candidates, + aod::HfRed3Prongs const& candidatesD) { for (const auto& candidate : candidates) { if (!TESTBIT(candidate.hfflag(), hf_cand_b0::DecayType::B0ToDPi)) { @@ -139,34 +402,31 @@ struct HfTaskB0Reduced { if (yCandRecoMax >= 0. && std::abs(hfHelper.yB0(candidate)) > yCandRecoMax) { continue; } + fillCand(candidate, candidatesD); + } // candidate loop + } // processData - auto ptCandB0 = candidate.pt(); - auto candD = candidate.prong0_as(); - - registry.fill(HIST("hMass"), hfHelper.invMassB0ToDPi(candidate), ptCandB0); - registry.fill(HIST("hPtCand"), ptCandB0); - registry.fill(HIST("hPtProng0"), candidate.ptProng0()); - registry.fill(HIST("hPtProng1"), candidate.ptProng1()); - registry.fill(HIST("hIPProd"), candidate.impactParameterProduct(), ptCandB0); - registry.fill(HIST("hDecLength"), candidate.decayLength(), ptCandB0); - registry.fill(HIST("hDecLengthXY"), candidate.decayLengthXY(), ptCandB0); - registry.fill(HIST("hd0Prong0"), candidate.impactParameter0(), ptCandB0); - registry.fill(HIST("hd0Prong1"), candidate.impactParameter1(), ptCandB0); - registry.fill(HIST("hCPA"), candidate.cpa(), ptCandB0); - registry.fill(HIST("hEta"), candidate.eta(), ptCandB0); - registry.fill(HIST("hRapidity"), hfHelper.yB0(candidate), ptCandB0); - registry.fill(HIST("hImpParErr"), candidate.errorImpactParameter0(), ptCandB0); - registry.fill(HIST("hImpParErr"), candidate.errorImpactParameter1(), ptCandB0); - registry.fill(HIST("hDecLenErr"), candidate.errorDecayLength(), ptCandB0); - registry.fill(HIST("hDecLenXYErr"), candidate.errorDecayLengthXY(), ptCandB0); - registry.fill(HIST("hInvMassD"), candD.invMass(), ptCandB0); + PROCESS_SWITCH(HfTaskB0Reduced, processData, "Process data without ML scores for D daughter", true); + + void processDataWithDmesMl(soa::Filtered> const& candidates, + aod::HfRed3Prongs const& candidatesD) + { + for (const auto& candidate : candidates) { + if (!TESTBIT(candidate.hfflag(), hf_cand_b0::DecayType::B0ToDPi)) { + continue; + } + if (yCandRecoMax >= 0. && std::abs(hfHelper.yB0(candidate)) > yCandRecoMax) { + continue; + } + fillCand(candidate, candidatesD); } // candidate loop - } // process + } // processDataWithDmesMl + + PROCESS_SWITCH(HfTaskB0Reduced, processDataWithDmesMl, "Process data with ML scores for D daughter", false); - /// B0 MC analysis and fill histograms void processMc(soa::Join const& candidates, aod::HfMcGenRedB0s const& mcParticles, - aod::HfRed3Prongs const&) + aod::HfRed3Prongs const& candidatesD) { // MC rec for (const auto& candidate : candidates) { @@ -176,93 +436,37 @@ struct HfTaskB0Reduced { if (yCandRecoMax >= 0. && std::abs(hfHelper.yB0(candidate)) > yCandRecoMax) { continue; } - - auto ptCandB0 = candidate.pt(); - auto candD = candidate.prong0_as(); - std::array posPv{candidate.posX(), candidate.posY(), candidate.posZ()}; - std::array posSvD{candD.xSecondaryVertex(), candD.ySecondaryVertex(), candD.zSecondaryVertex()}; - std::array momD{candD.px(), candD.py(), candD.pz()}; - auto cospD = RecoDecay::cpa(posPv, posSvD, momD); - auto decLenD = RecoDecay::distance(posPv, posSvD); - - if (TESTBIT(std::abs(candidate.flagMcMatchRec()), hf_cand_b0::DecayType::B0ToDPi)) { - registry.fill(HIST("hPtGenSig"), candidate.ptMother()); - registry.fill(HIST("hPtRecSig"), ptCandB0); - registry.fill(HIST("hCPARecSig"), candidate.cpa(), ptCandB0); - registry.fill(HIST("hCPAxyRecSig"), candidate.cpaXY(), ptCandB0); - registry.fill(HIST("hEtaRecSig"), candidate.eta(), ptCandB0); - registry.fill(HIST("hRapidityRecSig"), hfHelper.yB0(candidate), ptCandB0); - registry.fill(HIST("hDecLengthRecSig"), candidate.decayLength(), ptCandB0); - registry.fill(HIST("hDecLengthXYRecSig"), candidate.decayLengthXY(), ptCandB0); - registry.fill(HIST("hMassRecSig"), hfHelper.invMassB0ToDPi(candidate), ptCandB0); - registry.fill(HIST("hd0Prong0RecSig"), candidate.impactParameter0(), ptCandB0); - registry.fill(HIST("hd0Prong1RecSig"), candidate.impactParameter1(), ptCandB0); - registry.fill(HIST("hPtProng0RecSig"), candidate.ptProng0(), ptCandB0); - registry.fill(HIST("hPtProng1RecSig"), candidate.ptProng1(), ptCandB0); - registry.fill(HIST("hImpParProdB0RecSig"), candidate.impactParameterProduct(), ptCandB0); - registry.fill(HIST("hDecLengthNormRecSig"), candidate.decayLengthXYNormalised(), ptCandB0); - registry.fill(HIST("hCPADRecSig"), cospD, ptCandB0); - registry.fill(HIST("hDecLengthDRecSig"), decLenD, ptCandB0); - registry.fill(HIST("hChi2PCARecSig"), candidate.chi2PCA(), ptCandB0); - } else { - registry.fill(HIST("hPtRecBg"), ptCandB0); - registry.fill(HIST("hCPARecBg"), candidate.cpa(), ptCandB0); - registry.fill(HIST("hCPAxyRecBg"), candidate.cpaXY(), ptCandB0); - registry.fill(HIST("hEtaRecBg"), candidate.eta(), ptCandB0); - registry.fill(HIST("hRapidityRecBg"), hfHelper.yB0(candidate), ptCandB0); - registry.fill(HIST("hDecLengthRecBg"), candidate.decayLength(), ptCandB0); - registry.fill(HIST("hDecLengthXYRecBg"), candidate.decayLengthXY(), ptCandB0); - registry.fill(HIST("hMassRecBg"), hfHelper.invMassB0ToDPi(candidate), ptCandB0); - registry.fill(HIST("hd0Prong0RecBg"), candidate.impactParameter0(), ptCandB0); - registry.fill(HIST("hd0Prong1RecBg"), candidate.impactParameter1(), ptCandB0); - registry.fill(HIST("hPtProng0RecBg"), candidate.ptProng0(), ptCandB0); - registry.fill(HIST("hPtProng1RecBg"), candidate.ptProng1(), ptCandB0); - registry.fill(HIST("hImpParProdB0RecBg"), candidate.impactParameterProduct(), ptCandB0); - registry.fill(HIST("hDecLengthNormRecBg"), candidate.decayLengthXYNormalised(), ptCandB0); - registry.fill(HIST("hCPADRecBg"), cospD, ptCandB0); - registry.fill(HIST("hDecLengthDRecBg"), decLenD, ptCandB0); - registry.fill(HIST("hChi2PCARecBg"), candidate.chi2PCA(), ptCandB0); - } + fillCandMcReco(candidate, candidatesD); } // rec // MC gen. level for (const auto& particle : mcParticles) { - auto ptParticle = particle.ptTrack(); - auto yParticle = particle.yTrack(); - auto etaParticle = particle.etaTrack(); - if (yCandGenMax >= 0. && std::abs(yParticle) > yCandGenMax) { + fillCandMcGen(particle); + } // gen + } // processMc + PROCESS_SWITCH(HfTaskB0Reduced, processMc, "Process MC without ML scores for D daughter", false); + + void processMcWithDmesMl(soa::Join const& candidates, + aod::HfMcGenRedB0s const& mcParticles, + aod::HfRed3Prongs const& candidatesD) + { + // MC rec + for (const auto& candidate : candidates) { + if (!TESTBIT(candidate.hfflag(), hf_cand_b0::DecayType::B0ToDPi)) { continue; } - - std::array ptProngs = {particle.ptProng0(), particle.ptProng1()}; - std::array yProngs = {particle.yProng0(), particle.yProng1()}; - std::array etaProngs = {particle.etaProng0(), particle.etaProng1()}; - - registry.fill(HIST("hPtProng0Gen"), ptProngs[0], ptParticle); - registry.fill(HIST("hPtProng1Gen"), ptProngs[1], ptParticle); - registry.fill(HIST("hYProng0Gen"), yProngs[0], ptParticle); - registry.fill(HIST("hYProng1Gen"), yProngs[1], ptParticle); - registry.fill(HIST("hEtaProng0Gen"), etaProngs[0], ptParticle); - registry.fill(HIST("hEtaProng1Gen"), etaProngs[1], ptParticle); - - registry.fill(HIST("hPtGen"), ptParticle); - registry.fill(HIST("hYGen"), yParticle, ptParticle); - registry.fill(HIST("hEtaGen"), etaParticle, ptParticle); - - // generated B0 with |y|<0.5 - if (std::abs(yParticle) < 0.5) { - registry.fill(HIST("hPtGenWithRapidityBelowHalf"), ptParticle); + if (yCandRecoMax >= 0. && std::abs(hfHelper.yB0(candidate)) > yCandRecoMax) { + continue; } + fillCandMcReco(candidate, candidatesD); + } // rec - // generated B0 with daughters in geometrical acceptance - if (isProngInAcceptance(etaProngs[0], ptProngs[0]) && isProngInAcceptance(etaProngs[1], ptProngs[1])) { - registry.fill(HIST("hPtGenWithProngsInAcceptance"), ptParticle); - registry.fill(HIST("hYGenWithProngsInAcceptance"), yParticle, ptParticle); - registry.fill(HIST("hEtaGenWithProngsInAcceptance"), etaParticle, ptParticle); - } + // MC gen. level + for (const auto& particle : mcParticles) { + fillCandMcGen(particle); } // gen - } // process - PROCESS_SWITCH(HfTaskB0Reduced, processMc, "Process MC", false); + } // processMcWithDmesMl + PROCESS_SWITCH(HfTaskB0Reduced, processMcWithDmesMl, "Process MC with ML scores for D daughter", false); }; // struct WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From 7a4b2874cc288e5f0c3cf73fcddf7b4f05d9d51b Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Thu, 7 Dec 2023 09:19:29 +0000 Subject: [PATCH 02/10] Please consider the following formatting changes --- PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx | 4 ++-- .../TableProducer/candidateSelectorB0ToDPiReduced.cxx | 6 +++--- PWGHF/D2H/Tasks/taskB0Reduced.cxx | 10 +++++----- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx index 01789eb694f..844945d399d 100644 --- a/PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx @@ -101,7 +101,7 @@ struct HfCandidateCreatorB0Reduced { /// \param tracksPionThisCollision pion tracks in this collision /// \param invMass2DPiMin minimum B0 invariant-mass /// \param invMass2DPiMax maximum B0 invariant-mass - template + template void runCandidateCreation(aod::HfRedCollisions::iterator const& collision, Cands const& candsDThisColl, Pions const& tracksPionThisCollision, @@ -256,7 +256,7 @@ struct HfCandidateCreatorB0Reduced { } // processDataWithDmesMl PROCESS_SWITCH(HfCandidateCreatorB0Reduced, processDataWithDmesMl, "Process data with ML scores of D mesons", false); -}; // struct +}; // struct /// Extends the table base with expression columns and performs MC matching. struct HfCandidateCreatorB0ReducedExpressions { diff --git a/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx b/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx index 00effa6ecad..262ef26aca5 100644 --- a/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx @@ -103,10 +103,10 @@ struct HfCandidateSelectorB0ToDPiReduced { /// 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 + /// \param hfCandsB0 B0 candidates /// \param pionTracks pion tracks /// \param configs config inherited from the Dpi data creator - template + template void runSelection(Cands const& hfCandsB0, TracksPion const& pionTracks, HfCandB0Configs const& configs) @@ -157,7 +157,7 @@ struct HfCandidateSelectorB0ToDPiReduced { continue; } } - + SETBIT(statusB0ToDPi, SelectionStep::RecoTopol); // RecoTopol = 1 --> statusB0ToDPi = 3 if (activateQA) { registry.fill(HIST("hSelections"), 2 + SelectionStep::RecoTopol, ptCandB0); diff --git a/PWGHF/D2H/Tasks/taskB0Reduced.cxx b/PWGHF/D2H/Tasks/taskB0Reduced.cxx index 833baf17707..d1c69d61b33 100644 --- a/PWGHF/D2H/Tasks/taskB0Reduced.cxx +++ b/PWGHF/D2H/Tasks/taskB0Reduced.cxx @@ -213,7 +213,7 @@ struct HfTaskB0Reduced { /// \param withDmesMl is the flag to enable the filling of hisgorams with ML scores for the D- daughter /// \param candidate is the B0 candidate /// \param candidatesD is the table with D- candidates - template + template void fillCand(Cand const& candidate, aod::HfRed3Prongs const& candidatesD) { @@ -268,7 +268,7 @@ struct HfTaskB0Reduced { /// \param withDmesMl is the flag to enable the filling of hisgorams with ML scores for the D- daughter /// \param candidate is the B0 candidate /// \param candidatesD is the table with D- candidates - template + template void fillCandMcReco(Cand const& candidate, aod::HfRed3Prongs const& candidatesD) { @@ -309,7 +309,7 @@ struct HfTaskB0Reduced { 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("hPtProng0RecBg"), ptCandB0, candidate.ptProng0()); @@ -333,7 +333,7 @@ struct HfTaskB0Reduced { registry.fill(HIST("hMlScoreBkgDRecBg"), ptD, candidate.prong0MlScoreBkg()); registry.fill(HIST("hMlScorePromptDRecBg"), ptD, candidate.prong0MlScorePrompt()); registry.fill(HIST("hMlScoreNonPromptDRecBg"), ptD, candidate.prong0MlScoreNonprompt()); - } + } } } if (fillSparses) { @@ -347,7 +347,7 @@ struct HfTaskB0Reduced { if constexpr (withDmesMl) { registry.fill(HIST("hMassPtCutVarsRecBg"), invMassB0, ptCandB0, candidate.decayLength(), candidate.decayLengthXY() / candidate.errorDecayLengthXY(), candidate.impactParameterProduct(), candidate.cpa(), candD.invMass(), ptD, candidate.prong0MlScoreBkg(), candidate.prong0MlScoreNonprompt()); } else { - registry.fill(HIST("hMassPtCutVarsRecBg"), invMassB0, ptCandB0, candidate.decayLength(), candidate.decayLengthXY() / candidate.errorDecayLengthXY(), candidate.impactParameterProduct(), candidate.cpa(), candD.invMass(), ptD, decLenD, cospD); + registry.fill(HIST("hMassPtCutVarsRecBg"), invMassB0, ptCandB0, candidate.decayLength(), candidate.decayLengthXY() / candidate.errorDecayLengthXY(), candidate.impactParameterProduct(), candidate.cpa(), candD.invMass(), ptD, decLenD, cospD); } } } From 81d94e755c233bd37cbe0132e9bc7a52001a3022 Mon Sep 17 00:00:00 2001 From: Alexandre Bigot Date: Fri, 8 Dec 2023 18:33:28 +0100 Subject: [PATCH 03/10] Implement a Tree creator inside B0 reduced selector --- PWGHF/D2H/DataModel/ReducedDataModel.h | 46 ++++++ .../candidateSelectorB0ToDPiReduced.cxx | 139 ++++++++++++++++-- 2 files changed, 174 insertions(+), 11 deletions(-) diff --git a/PWGHF/D2H/DataModel/ReducedDataModel.h b/PWGHF/D2H/DataModel/ReducedDataModel.h index fd0a9f3b1f1..5358b4f1699 100644 --- a/PWGHF/D2H/DataModel/ReducedDataModel.h +++ b/PWGHF/D2H/DataModel/ReducedDataModel.h @@ -210,6 +210,25 @@ DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, HfRedTrackBases, "_1"); //! P 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 +DECLARE_SOA_COLUMN(PtProng0, ptProng0, float); //! Transverse momentum of prong0 (GeV/c) +DECLARE_SOA_COLUMN(PtProng1, ptProng1, float); //! Transverse momentum of prong1 (GeV/c) +DECLARE_SOA_COLUMN(CandidateSelFlag, candidateSelFlag, uint8_t); //! Selection flag of candidate (output of candidateSelector) +DECLARE_SOA_COLUMN(M, m, float); //! Invariant mass of candidate (GeV/c2) +DECLARE_SOA_COLUMN(Pt, pt, float); //! Transverse momentum of candidate (GeV/c) +DECLARE_SOA_COLUMN(P, p, float); //! Momentum of candidate (GeV/c) +DECLARE_SOA_COLUMN(Y, y, float); //! Rapidity of candidate +DECLARE_SOA_COLUMN(Eta, eta, float); //! Pseudorapidity of candidate +DECLARE_SOA_COLUMN(Phi, phi, float); //! Azimuth angle of candidate +DECLARE_SOA_COLUMN(E, e, float); //! Energy of candidate (GeV) +DECLARE_SOA_COLUMN(NSigTpcPi1, nSigTpcPi1, float); //! TPC Nsigma separation for prong1 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTofPi1, nSigTofPi1, float); //! TOF Nsigma separation for prong1 with pion mass hypothesis +DECLARE_SOA_COLUMN(DecayLength, decayLength, float); //! Decay length of candidate (cm) +DECLARE_SOA_COLUMN(DecayLengthXY, decayLengthXY, float); //! Transverse decay length of candidate (cm) +DECLARE_SOA_COLUMN(DecayLengthNormalised, decayLengthNormalised, float); //! Normalised decay length of candidate +DECLARE_SOA_COLUMN(DecayLengthXYNormalised, decayLengthXYNormalised, float); //! Normalised transverse decay length of candidate +DECLARE_SOA_COLUMN(Cpa, cpa, float); //! Cosine pointing angle of candidate +DECLARE_SOA_COLUMN(CpaXY, cpaXY, float); //! Cosine pointing angle of candidate in transverse plane +DECLARE_SOA_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, float); //! Maximum normalized difference between measured and expected impact parameter of candidate prongs } // namespace hf_cand_b0_reduced DECLARE_SOA_TABLE(HfRedB0Prongs, "AOD", "HFREDB0PRONG", //! Table with B0 daughter indices @@ -221,6 +240,33 @@ DECLARE_SOA_TABLE(HfRedB0DpMls, "AOD", "HFREDB0DPML", //! Table with ML scores f hf_cand_b0_reduced::Prong0MlScoreNonprompt, o2::soa::Marker<1>); +DECLARE_SOA_TABLE(HfRedCandB0Lites, "AOD", "HFREDCANDB0LITE", //! Table with some B0 properties + hf_cand::Chi2PCA, + hf_cand_b0_reduced::DecayLength, + hf_cand_b0_reduced::DecayLengthXY, + hf_cand_b0_reduced::DecayLengthNormalised, + hf_cand_b0_reduced::DecayLengthXYNormalised, + hf_cand_b0_reduced::PtProng0, + hf_cand_b0_reduced::PtProng1, + hf_cand::ImpactParameter0, + hf_cand::ImpactParameter1, + hf_cand_b0_reduced::NSigTpcPi1, + hf_cand_b0_reduced::NSigTofPi1, + hf_cand_b0_reduced::Prong0MlScoreBkg, + hf_cand_b0_reduced::Prong0MlScorePrompt, + hf_cand_b0_reduced::Prong0MlScoreNonprompt, + hf_cand_b0_reduced::CandidateSelFlag, + hf_cand_b0_reduced::M, + hf_cand_b0_reduced::Pt, + hf_cand_b0_reduced::Cpa, + hf_cand_b0_reduced::CpaXY, + hf_cand_b0_reduced::MaxNormalisedDeltaIP, + hf_cand_b0_reduced::Eta, + hf_cand_b0_reduced::Phi, + hf_cand_b0_reduced::Y, + hf_cand_3prong::FlagMcMatchRec, + hf_cand_3prong::OriginMcRec); + using HfRedCandB0 = soa::Join; namespace hf_cand_bplus_reduced diff --git a/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx b/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx index 262ef26aca5..58489bbe25a 100644 --- a/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx @@ -33,6 +33,7 @@ using namespace o2::analysis; struct HfCandidateSelectorB0ToDPiReduced { Produces hfSelB0ToDPiCandidate; // table defined in CandidateSelectionTables.h + Produces hfRedCandB0Lite; Configurable ptCandMin{"ptCandMin", 0., "Lower bound of candidate pT"}; Configurable ptCandMax{"ptCandMax", 50., "Upper bound of candidate pT"}; @@ -57,6 +58,13 @@ struct HfCandidateSelectorB0ToDPiReduced { Configurable> cutsDmesMl{"cutsDmesMl", {hf_cuts_ml::cuts[0], hf_cuts_ml::nBinsPt, hf_cuts_ml::nCutScores, hf_cuts_ml::labelsPt, hf_cuts_ml::labelsCutScore}, "D-meson ML cuts per pT bin"}; // QA switch Configurable activateQA{"activateQA", false, "Flag to enable QA histogram"}; + // parameters for TTree filling + Configurable fillTree{"fillTree", false, "Switch to fill lite table with candidate properties"}; + Configurable fillingFlagB0{"fillingFlagB0", 1, "Tree filling flag for B0"}; + Configurable fillOnlySignal{"fillOnlySignal", false, "Flag to fill derived tables with signal for ML trainings"}; + Configurable fillOnlyBackground{"fillOnlyBackground", false, "Flag to fill derived tables with background for ML trainings"}; + Configurable downSampleBkgFactor{"downSampleBkgFactor", 1., "Fraction of background candidates to keep for ML trainings"}; + Configurable ptMaxForDownSample{"ptMaxForDownSample", 10., "Maximum pt for the application of the downsampling factor"}; // check if selectionFlagD (defined in dataCreatorDplusPiReduced.cxx) and usePid configurables are in sync bool selectionFlagDAndUsePidInSync = true; @@ -72,7 +80,7 @@ struct HfCandidateSelectorB0ToDPiReduced { void init(InitContext const& initContext) { - std::array doprocess{doprocessSelection, doprocessSelectionWithDmesMl}; + std::array doprocess{doprocessDataSelection, doprocessDataSelectionWithDmesMl, doprocessMcSelection, doprocessMcSelectionWithDmesMl}; if ((std::accumulate(doprocess.begin(), doprocess.end(), 0)) != 1) { LOGP(fatal, "Only one process function for data should be enabled at a time."); } @@ -101,12 +109,83 @@ struct HfCandidateSelectorB0ToDPiReduced { } } + /// Function to fill B0 candidate lite table + /// \param doMc is the flag to use the table with MC information + /// \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 candidate B0 candidates + /// \param selectionFlag selection flag of B0 candidates + template + void fillCandidateLiteTable(const T& candidate, const U& selectionFlag) + { + if (selectionFlag < fillingFlagB0) { + return; + } + int8_t flagMc{0}; + int8_t originMc{0}; + if constexpr (doMc) { + flagMc = candidate.flagMcMatchRec(); + if (flagMc != 0) { + originMc = 1; + } + } + if (fillOnlySignal && flagMc == 0) { + return; + } + if (fillOnlyBackground) { + if (flagMc != 0) { + return; + } + float pseudoRndm = candidate.ptProng1() * 1000. - (int64_t)(candidate.ptProng1() * 1000); + if (candidate.pt() < ptMaxForDownSample && pseudoRndm >= downSampleBkgFactor) { + return; + } + } + float prong0MlScoreBkg = -1.; + float prong0MlScorePrompt = -1.; + float prong0MlScoreNonprompt = -1.; + if constexpr (withDmesMl) { + prong0MlScoreBkg = candidate.prong0MlScoreBkg(); + prong0MlScorePrompt = candidate.prong0MlScorePrompt(); + prong0MlScoreNonprompt = candidate.prong0MlScoreNonprompt(); + } + + auto prong1 = candidate.template prong1_as(); + + hfRedCandB0Lite( + candidate.chi2PCA(), + candidate.decayLength(), + candidate.decayLengthXY(), + candidate.decayLengthNormalised(), + candidate.decayLengthXYNormalised(), + candidate.ptProng0(), + candidate.ptProng1(), + candidate.impactParameter0(), + candidate.impactParameter1(), + prong1.tpcNSigmaPi(), + prong1.tofNSigmaPi(), + prong0MlScoreBkg, + prong0MlScorePrompt, + prong0MlScoreNonprompt, + selectionFlag, + hfHelper.invMassB0ToDPi(candidate), + candidate.pt(), + candidate.cpa(), + candidate.cpaXY(), + candidate.maxNormalisedDeltaIP(), + candidate.eta(), + candidate.phi(), + hfHelper.yB0(candidate), + flagMc, + originMc); + } + /// Main function to perform B0 candidate creation + /// \param doMc is the flag to use the table with MC information /// \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 /// \param pionTracks pion tracks /// \param configs config inherited from the Dpi data creator - template + template void runSelection(Cands const& hfCandsB0, TracksPion const& pionTracks, HfCandB0Configs const& configs) @@ -125,8 +204,10 @@ struct HfCandidateSelectorB0ToDPiReduced { } } + hfRedCandB0Lite.reserve(hfCandsB0.size()); + for (const auto& hfCandB0 : hfCandsB0) { - int statusB0ToDPi = 0; + uint8_t statusB0ToDPi = 0; auto ptCandB0 = hfCandB0.pt(); // check if flagged as B0 → D π @@ -135,6 +216,9 @@ struct HfCandidateSelectorB0ToDPiReduced { if (activateQA) { registry.fill(HIST("hSelections"), 1, ptCandB0); } + if (fillTree) { + fillCandidateLiteTable(hfCandB0, statusB0ToDPi); + } // LOGF(info, "B0 candidate selection failed at hfflag check"); continue; } @@ -146,6 +230,9 @@ struct HfCandidateSelectorB0ToDPiReduced { // topological cuts if (!hfHelper.selectionB0ToDPiTopol(hfCandB0, cuts, binsPt)) { hfSelB0ToDPiCandidate(statusB0ToDPi); + if (fillTree) { + fillCandidateLiteTable(hfCandB0, statusB0ToDPi); + } // LOGF(info, "B0 candidate selection failed at topology selection"); continue; } @@ -153,6 +240,9 @@ struct HfCandidateSelectorB0ToDPiReduced { if constexpr (withDmesMl) { // we include it in the topological selections if (!hfHelper.selectionDmesMlScoresForB(hfCandB0, cutsDmesMl, binsPtDmesMl)) { hfSelB0ToDPiCandidate(statusB0ToDPi); + if (fillTree) { + fillCandidateLiteTable(hfCandB0, statusB0ToDPi); + } // LOGF(info, "B0 candidate selection failed at D-meson ML selection"); continue; } @@ -166,6 +256,9 @@ struct HfCandidateSelectorB0ToDPiReduced { // checking if selectionFlagD and usePid are in sync if (!selectionFlagDAndUsePidInSync) { hfSelB0ToDPiCandidate(statusB0ToDPi); + if (fillTree) { + fillCandidateLiteTable(hfCandB0, statusB0ToDPi); + } continue; } // track-level PID selection @@ -175,6 +268,9 @@ struct HfCandidateSelectorB0ToDPiReduced { if (!hfHelper.selectionB0ToDPiPid(pidTrackPi, acceptPIDNotApplicable.value)) { // LOGF(info, "B0 candidate selection failed at PID selection"); hfSelB0ToDPiCandidate(statusB0ToDPi); + if (fillTree) { + fillCandidateLiteTable(hfCandB0, statusB0ToDPi); + } continue; } SETBIT(statusB0ToDPi, SelectionStep::RecoPID); // RecoPID = 2 --> statusB0ToDPi = 7 @@ -183,27 +279,48 @@ struct HfCandidateSelectorB0ToDPiReduced { } } hfSelB0ToDPiCandidate(statusB0ToDPi); + if (fillTree) { + fillCandidateLiteTable(hfCandB0, statusB0ToDPi); + } // LOGF(info, "B0 candidate selection passed all selections"); } } - void processSelection(HfRedCandB0 const& hfCandsB0, + void processDataSelection(HfRedCandB0 const& hfCandsB0, + TracksPion const& pionTracks, + HfCandB0Configs const& configs) + { + runSelection(hfCandsB0, pionTracks, configs); + } // processDataSelection + + PROCESS_SWITCH(HfCandidateSelectorB0ToDPiReduced, processDataSelection, "Process selection without MC info and without ML scores of D mesons", true); + + void processDataSelectionWithDmesMl(soa::Join const& hfCandsB0, + TracksPion const& pionTracks, + HfCandB0Configs const& configs) + { + runSelection(hfCandsB0, pionTracks, configs); + } // processDataSelectionWithDmesMl + + PROCESS_SWITCH(HfCandidateSelectorB0ToDPiReduced, processDataSelectionWithDmesMl, "Process selection without MC info and with ML scores of D mesons", false); + + void processMcSelection(soa::Join const& hfCandsB0, TracksPion const& pionTracks, HfCandB0Configs const& configs) { - runSelection(hfCandsB0, pionTracks, configs); - } // processSelection + runSelection(hfCandsB0, pionTracks, configs); + } // processMcSelection - PROCESS_SWITCH(HfCandidateSelectorB0ToDPiReduced, processSelection, "Process selection without ML scores of D mesons", true); + PROCESS_SWITCH(HfCandidateSelectorB0ToDPiReduced, processMcSelection, "Process selection with MC info and without ML scores of D mesons", false); - void processSelectionWithDmesMl(soa::Join const& hfCandsB0, + void processMcSelectionWithDmesMl(soa::Join const& hfCandsB0, TracksPion const& pionTracks, HfCandB0Configs const& configs) { - runSelection(hfCandsB0, pionTracks, configs); - } // processSelectionWithDmesMl + runSelection(hfCandsB0, pionTracks, configs); + } // processMcSelectionWithDmesMl - PROCESS_SWITCH(HfCandidateSelectorB0ToDPiReduced, processSelectionWithDmesMl, "Process selection with ML scores of D mesons", false); + PROCESS_SWITCH(HfCandidateSelectorB0ToDPiReduced, processMcSelectionWithDmesMl, "Process selection with MC info and with ML scores of D mesons", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From 4a31397f21602802f9f24ca6096d8e092b57a919 Mon Sep 17 00:00:00 2001 From: Alexandre Bigot Date: Fri, 8 Dec 2023 18:37:11 +0100 Subject: [PATCH 04/10] Clang format --- PWGHF/D2H/DataModel/ReducedDataModel.h | 38 +++++++++---------- .../candidateSelectorB0ToDPiReduced.cxx | 16 ++++---- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/PWGHF/D2H/DataModel/ReducedDataModel.h b/PWGHF/D2H/DataModel/ReducedDataModel.h index 5358b4f1699..1e2ae88795b 100644 --- a/PWGHF/D2H/DataModel/ReducedDataModel.h +++ b/PWGHF/D2H/DataModel/ReducedDataModel.h @@ -210,25 +210,25 @@ DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, HfRedTrackBases, "_1"); //! P 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 -DECLARE_SOA_COLUMN(PtProng0, ptProng0, float); //! Transverse momentum of prong0 (GeV/c) -DECLARE_SOA_COLUMN(PtProng1, ptProng1, float); //! Transverse momentum of prong1 (GeV/c) -DECLARE_SOA_COLUMN(CandidateSelFlag, candidateSelFlag, uint8_t); //! Selection flag of candidate (output of candidateSelector) -DECLARE_SOA_COLUMN(M, m, float); //! Invariant mass of candidate (GeV/c2) -DECLARE_SOA_COLUMN(Pt, pt, float); //! Transverse momentum of candidate (GeV/c) -DECLARE_SOA_COLUMN(P, p, float); //! Momentum of candidate (GeV/c) -DECLARE_SOA_COLUMN(Y, y, float); //! Rapidity of candidate -DECLARE_SOA_COLUMN(Eta, eta, float); //! Pseudorapidity of candidate -DECLARE_SOA_COLUMN(Phi, phi, float); //! Azimuth angle of candidate -DECLARE_SOA_COLUMN(E, e, float); //! Energy of candidate (GeV) -DECLARE_SOA_COLUMN(NSigTpcPi1, nSigTpcPi1, float); //! TPC Nsigma separation for prong1 with pion mass hypothesis -DECLARE_SOA_COLUMN(NSigTofPi1, nSigTofPi1, float); //! TOF Nsigma separation for prong1 with pion mass hypothesis -DECLARE_SOA_COLUMN(DecayLength, decayLength, float); //! Decay length of candidate (cm) -DECLARE_SOA_COLUMN(DecayLengthXY, decayLengthXY, float); //! Transverse decay length of candidate (cm) -DECLARE_SOA_COLUMN(DecayLengthNormalised, decayLengthNormalised, float); //! Normalised decay length of candidate -DECLARE_SOA_COLUMN(DecayLengthXYNormalised, decayLengthXYNormalised, float); //! Normalised transverse decay length of candidate -DECLARE_SOA_COLUMN(Cpa, cpa, float); //! Cosine pointing angle of candidate -DECLARE_SOA_COLUMN(CpaXY, cpaXY, float); //! Cosine pointing angle of candidate in transverse plane -DECLARE_SOA_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, float); //! Maximum normalized difference between measured and expected impact parameter of candidate prongs +DECLARE_SOA_COLUMN(PtProng0, ptProng0, float); //! Transverse momentum of prong0 (GeV/c) +DECLARE_SOA_COLUMN(PtProng1, ptProng1, float); //! Transverse momentum of prong1 (GeV/c) +DECLARE_SOA_COLUMN(CandidateSelFlag, candidateSelFlag, uint8_t); //! Selection flag of candidate (output of candidateSelector) +DECLARE_SOA_COLUMN(M, m, float); //! Invariant mass of candidate (GeV/c2) +DECLARE_SOA_COLUMN(Pt, pt, float); //! Transverse momentum of candidate (GeV/c) +DECLARE_SOA_COLUMN(P, p, float); //! Momentum of candidate (GeV/c) +DECLARE_SOA_COLUMN(Y, y, float); //! Rapidity of candidate +DECLARE_SOA_COLUMN(Eta, eta, float); //! Pseudorapidity of candidate +DECLARE_SOA_COLUMN(Phi, phi, float); //! Azimuth angle of candidate +DECLARE_SOA_COLUMN(E, e, float); //! Energy of candidate (GeV) +DECLARE_SOA_COLUMN(NSigTpcPi1, nSigTpcPi1, float); //! TPC Nsigma separation for prong1 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTofPi1, nSigTofPi1, float); //! TOF Nsigma separation for prong1 with pion mass hypothesis +DECLARE_SOA_COLUMN(DecayLength, decayLength, float); //! Decay length of candidate (cm) +DECLARE_SOA_COLUMN(DecayLengthXY, decayLengthXY, float); //! Transverse decay length of candidate (cm) +DECLARE_SOA_COLUMN(DecayLengthNormalised, decayLengthNormalised, float); //! Normalised decay length of candidate +DECLARE_SOA_COLUMN(DecayLengthXYNormalised, decayLengthXYNormalised, float); //! Normalised transverse decay length of candidate +DECLARE_SOA_COLUMN(Cpa, cpa, float); //! Cosine pointing angle of candidate +DECLARE_SOA_COLUMN(CpaXY, cpaXY, float); //! Cosine pointing angle of candidate in transverse plane +DECLARE_SOA_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, float); //! Maximum normalized difference between measured and expected impact parameter of candidate prongs } // namespace hf_cand_b0_reduced DECLARE_SOA_TABLE(HfRedB0Prongs, "AOD", "HFREDB0PRONG", //! Table with B0 daughter indices diff --git a/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx b/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx index 58489bbe25a..be747f9c9bc 100644 --- a/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx @@ -287,8 +287,8 @@ struct HfCandidateSelectorB0ToDPiReduced { } void processDataSelection(HfRedCandB0 const& hfCandsB0, - TracksPion const& pionTracks, - HfCandB0Configs const& configs) + TracksPion const& pionTracks, + HfCandB0Configs const& configs) { runSelection(hfCandsB0, pionTracks, configs); } // processDataSelection @@ -296,8 +296,8 @@ struct HfCandidateSelectorB0ToDPiReduced { PROCESS_SWITCH(HfCandidateSelectorB0ToDPiReduced, processDataSelection, "Process selection without MC info and without ML scores of D mesons", true); void processDataSelectionWithDmesMl(soa::Join const& hfCandsB0, - TracksPion const& pionTracks, - HfCandB0Configs const& configs) + TracksPion const& pionTracks, + HfCandB0Configs const& configs) { runSelection(hfCandsB0, pionTracks, configs); } // processDataSelectionWithDmesMl @@ -305,8 +305,8 @@ struct HfCandidateSelectorB0ToDPiReduced { PROCESS_SWITCH(HfCandidateSelectorB0ToDPiReduced, processDataSelectionWithDmesMl, "Process selection without MC info and with ML scores of D mesons", false); void processMcSelection(soa::Join const& hfCandsB0, - TracksPion const& pionTracks, - HfCandB0Configs const& configs) + TracksPion const& pionTracks, + HfCandB0Configs const& configs) { runSelection(hfCandsB0, pionTracks, configs); } // processMcSelection @@ -314,8 +314,8 @@ struct HfCandidateSelectorB0ToDPiReduced { PROCESS_SWITCH(HfCandidateSelectorB0ToDPiReduced, processMcSelection, "Process selection with MC info and without ML scores of D mesons", false); void processMcSelectionWithDmesMl(soa::Join const& hfCandsB0, - TracksPion const& pionTracks, - HfCandB0Configs const& configs) + TracksPion const& pionTracks, + HfCandB0Configs const& configs) { runSelection(hfCandsB0, pionTracks, configs); } // processMcSelectionWithDmesMl From b67c54e7705bb4b1eb8435cca12cc3e2b1038148 Mon Sep 17 00:00:00 2001 From: Alexandre Bigot Date: Sun, 10 Dec 2023 11:26:52 +0100 Subject: [PATCH 05/10] Move Tree creator from selector to task --- PWGHF/D2H/DataModel/ReducedDataModel.h | 27 --- .../candidateSelectorB0ToDPiReduced.cxx | 147 ++------------- PWGHF/D2H/Tasks/taskB0Reduced.cxx | 176 +++++++++++++++++- 3 files changed, 183 insertions(+), 167 deletions(-) diff --git a/PWGHF/D2H/DataModel/ReducedDataModel.h b/PWGHF/D2H/DataModel/ReducedDataModel.h index 1e2ae88795b..f048df9d495 100644 --- a/PWGHF/D2H/DataModel/ReducedDataModel.h +++ b/PWGHF/D2H/DataModel/ReducedDataModel.h @@ -240,33 +240,6 @@ DECLARE_SOA_TABLE(HfRedB0DpMls, "AOD", "HFREDB0DPML", //! Table with ML scores f hf_cand_b0_reduced::Prong0MlScoreNonprompt, o2::soa::Marker<1>); -DECLARE_SOA_TABLE(HfRedCandB0Lites, "AOD", "HFREDCANDB0LITE", //! Table with some B0 properties - hf_cand::Chi2PCA, - hf_cand_b0_reduced::DecayLength, - hf_cand_b0_reduced::DecayLengthXY, - hf_cand_b0_reduced::DecayLengthNormalised, - hf_cand_b0_reduced::DecayLengthXYNormalised, - hf_cand_b0_reduced::PtProng0, - hf_cand_b0_reduced::PtProng1, - hf_cand::ImpactParameter0, - hf_cand::ImpactParameter1, - hf_cand_b0_reduced::NSigTpcPi1, - hf_cand_b0_reduced::NSigTofPi1, - hf_cand_b0_reduced::Prong0MlScoreBkg, - hf_cand_b0_reduced::Prong0MlScorePrompt, - hf_cand_b0_reduced::Prong0MlScoreNonprompt, - hf_cand_b0_reduced::CandidateSelFlag, - hf_cand_b0_reduced::M, - hf_cand_b0_reduced::Pt, - hf_cand_b0_reduced::Cpa, - hf_cand_b0_reduced::CpaXY, - hf_cand_b0_reduced::MaxNormalisedDeltaIP, - hf_cand_b0_reduced::Eta, - hf_cand_b0_reduced::Phi, - hf_cand_b0_reduced::Y, - hf_cand_3prong::FlagMcMatchRec, - hf_cand_3prong::OriginMcRec); - using HfRedCandB0 = soa::Join; namespace hf_cand_bplus_reduced diff --git a/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx b/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx index be747f9c9bc..262ef26aca5 100644 --- a/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx @@ -33,7 +33,6 @@ using namespace o2::analysis; struct HfCandidateSelectorB0ToDPiReduced { Produces hfSelB0ToDPiCandidate; // table defined in CandidateSelectionTables.h - Produces hfRedCandB0Lite; Configurable ptCandMin{"ptCandMin", 0., "Lower bound of candidate pT"}; Configurable ptCandMax{"ptCandMax", 50., "Upper bound of candidate pT"}; @@ -58,13 +57,6 @@ struct HfCandidateSelectorB0ToDPiReduced { Configurable> cutsDmesMl{"cutsDmesMl", {hf_cuts_ml::cuts[0], hf_cuts_ml::nBinsPt, hf_cuts_ml::nCutScores, hf_cuts_ml::labelsPt, hf_cuts_ml::labelsCutScore}, "D-meson ML cuts per pT bin"}; // QA switch Configurable activateQA{"activateQA", false, "Flag to enable QA histogram"}; - // parameters for TTree filling - Configurable fillTree{"fillTree", false, "Switch to fill lite table with candidate properties"}; - Configurable fillingFlagB0{"fillingFlagB0", 1, "Tree filling flag for B0"}; - Configurable fillOnlySignal{"fillOnlySignal", false, "Flag to fill derived tables with signal for ML trainings"}; - Configurable fillOnlyBackground{"fillOnlyBackground", false, "Flag to fill derived tables with background for ML trainings"}; - Configurable downSampleBkgFactor{"downSampleBkgFactor", 1., "Fraction of background candidates to keep for ML trainings"}; - Configurable ptMaxForDownSample{"ptMaxForDownSample", 10., "Maximum pt for the application of the downsampling factor"}; // check if selectionFlagD (defined in dataCreatorDplusPiReduced.cxx) and usePid configurables are in sync bool selectionFlagDAndUsePidInSync = true; @@ -80,7 +72,7 @@ struct HfCandidateSelectorB0ToDPiReduced { void init(InitContext const& initContext) { - std::array doprocess{doprocessDataSelection, doprocessDataSelectionWithDmesMl, doprocessMcSelection, doprocessMcSelectionWithDmesMl}; + std::array doprocess{doprocessSelection, doprocessSelectionWithDmesMl}; if ((std::accumulate(doprocess.begin(), doprocess.end(), 0)) != 1) { LOGP(fatal, "Only one process function for data should be enabled at a time."); } @@ -109,83 +101,12 @@ struct HfCandidateSelectorB0ToDPiReduced { } } - /// Function to fill B0 candidate lite table - /// \param doMc is the flag to use the table with MC information - /// \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 candidate B0 candidates - /// \param selectionFlag selection flag of B0 candidates - template - void fillCandidateLiteTable(const T& candidate, const U& selectionFlag) - { - if (selectionFlag < fillingFlagB0) { - return; - } - int8_t flagMc{0}; - int8_t originMc{0}; - if constexpr (doMc) { - flagMc = candidate.flagMcMatchRec(); - if (flagMc != 0) { - originMc = 1; - } - } - if (fillOnlySignal && flagMc == 0) { - return; - } - if (fillOnlyBackground) { - if (flagMc != 0) { - return; - } - float pseudoRndm = candidate.ptProng1() * 1000. - (int64_t)(candidate.ptProng1() * 1000); - if (candidate.pt() < ptMaxForDownSample && pseudoRndm >= downSampleBkgFactor) { - return; - } - } - float prong0MlScoreBkg = -1.; - float prong0MlScorePrompt = -1.; - float prong0MlScoreNonprompt = -1.; - if constexpr (withDmesMl) { - prong0MlScoreBkg = candidate.prong0MlScoreBkg(); - prong0MlScorePrompt = candidate.prong0MlScorePrompt(); - prong0MlScoreNonprompt = candidate.prong0MlScoreNonprompt(); - } - - auto prong1 = candidate.template prong1_as(); - - hfRedCandB0Lite( - candidate.chi2PCA(), - candidate.decayLength(), - candidate.decayLengthXY(), - candidate.decayLengthNormalised(), - candidate.decayLengthXYNormalised(), - candidate.ptProng0(), - candidate.ptProng1(), - candidate.impactParameter0(), - candidate.impactParameter1(), - prong1.tpcNSigmaPi(), - prong1.tofNSigmaPi(), - prong0MlScoreBkg, - prong0MlScorePrompt, - prong0MlScoreNonprompt, - selectionFlag, - hfHelper.invMassB0ToDPi(candidate), - candidate.pt(), - candidate.cpa(), - candidate.cpaXY(), - candidate.maxNormalisedDeltaIP(), - candidate.eta(), - candidate.phi(), - hfHelper.yB0(candidate), - flagMc, - originMc); - } - /// Main function to perform B0 candidate creation - /// \param doMc is the flag to use the table with MC information /// \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 /// \param pionTracks pion tracks /// \param configs config inherited from the Dpi data creator - template + template void runSelection(Cands const& hfCandsB0, TracksPion const& pionTracks, HfCandB0Configs const& configs) @@ -204,10 +125,8 @@ struct HfCandidateSelectorB0ToDPiReduced { } } - hfRedCandB0Lite.reserve(hfCandsB0.size()); - for (const auto& hfCandB0 : hfCandsB0) { - uint8_t statusB0ToDPi = 0; + int statusB0ToDPi = 0; auto ptCandB0 = hfCandB0.pt(); // check if flagged as B0 → D π @@ -216,9 +135,6 @@ struct HfCandidateSelectorB0ToDPiReduced { if (activateQA) { registry.fill(HIST("hSelections"), 1, ptCandB0); } - if (fillTree) { - fillCandidateLiteTable(hfCandB0, statusB0ToDPi); - } // LOGF(info, "B0 candidate selection failed at hfflag check"); continue; } @@ -230,9 +146,6 @@ struct HfCandidateSelectorB0ToDPiReduced { // topological cuts if (!hfHelper.selectionB0ToDPiTopol(hfCandB0, cuts, binsPt)) { hfSelB0ToDPiCandidate(statusB0ToDPi); - if (fillTree) { - fillCandidateLiteTable(hfCandB0, statusB0ToDPi); - } // LOGF(info, "B0 candidate selection failed at topology selection"); continue; } @@ -240,9 +153,6 @@ struct HfCandidateSelectorB0ToDPiReduced { if constexpr (withDmesMl) { // we include it in the topological selections if (!hfHelper.selectionDmesMlScoresForB(hfCandB0, cutsDmesMl, binsPtDmesMl)) { hfSelB0ToDPiCandidate(statusB0ToDPi); - if (fillTree) { - fillCandidateLiteTable(hfCandB0, statusB0ToDPi); - } // LOGF(info, "B0 candidate selection failed at D-meson ML selection"); continue; } @@ -256,9 +166,6 @@ struct HfCandidateSelectorB0ToDPiReduced { // checking if selectionFlagD and usePid are in sync if (!selectionFlagDAndUsePidInSync) { hfSelB0ToDPiCandidate(statusB0ToDPi); - if (fillTree) { - fillCandidateLiteTable(hfCandB0, statusB0ToDPi); - } continue; } // track-level PID selection @@ -268,9 +175,6 @@ struct HfCandidateSelectorB0ToDPiReduced { if (!hfHelper.selectionB0ToDPiPid(pidTrackPi, acceptPIDNotApplicable.value)) { // LOGF(info, "B0 candidate selection failed at PID selection"); hfSelB0ToDPiCandidate(statusB0ToDPi); - if (fillTree) { - fillCandidateLiteTable(hfCandB0, statusB0ToDPi); - } continue; } SETBIT(statusB0ToDPi, SelectionStep::RecoPID); // RecoPID = 2 --> statusB0ToDPi = 7 @@ -279,48 +183,27 @@ struct HfCandidateSelectorB0ToDPiReduced { } } hfSelB0ToDPiCandidate(statusB0ToDPi); - if (fillTree) { - fillCandidateLiteTable(hfCandB0, statusB0ToDPi); - } // LOGF(info, "B0 candidate selection passed all selections"); } } - void processDataSelection(HfRedCandB0 const& hfCandsB0, - TracksPion const& pionTracks, - HfCandB0Configs const& configs) - { - runSelection(hfCandsB0, pionTracks, configs); - } // processDataSelection - - PROCESS_SWITCH(HfCandidateSelectorB0ToDPiReduced, processDataSelection, "Process selection without MC info and without ML scores of D mesons", true); - - void processDataSelectionWithDmesMl(soa::Join const& hfCandsB0, - TracksPion const& pionTracks, - HfCandB0Configs const& configs) - { - runSelection(hfCandsB0, pionTracks, configs); - } // processDataSelectionWithDmesMl - - PROCESS_SWITCH(HfCandidateSelectorB0ToDPiReduced, processDataSelectionWithDmesMl, "Process selection without MC info and with ML scores of D mesons", false); - - void processMcSelection(soa::Join const& hfCandsB0, - TracksPion const& pionTracks, - HfCandB0Configs const& configs) + void processSelection(HfRedCandB0 const& hfCandsB0, + TracksPion const& pionTracks, + HfCandB0Configs const& configs) { - runSelection(hfCandsB0, pionTracks, configs); - } // processMcSelection + runSelection(hfCandsB0, pionTracks, configs); + } // processSelection - PROCESS_SWITCH(HfCandidateSelectorB0ToDPiReduced, processMcSelection, "Process selection with MC info and without ML scores of D mesons", false); + PROCESS_SWITCH(HfCandidateSelectorB0ToDPiReduced, processSelection, "Process selection without ML scores of D mesons", true); - void processMcSelectionWithDmesMl(soa::Join const& hfCandsB0, - TracksPion const& pionTracks, - HfCandB0Configs const& configs) + void processSelectionWithDmesMl(soa::Join const& hfCandsB0, + TracksPion const& pionTracks, + HfCandB0Configs const& configs) { - runSelection(hfCandsB0, pionTracks, configs); - } // processMcSelectionWithDmesMl + runSelection(hfCandsB0, pionTracks, configs); + } // processSelectionWithDmesMl - PROCESS_SWITCH(HfCandidateSelectorB0ToDPiReduced, processMcSelectionWithDmesMl, "Process selection with MC info and with ML scores of D mesons", false); + PROCESS_SWITCH(HfCandidateSelectorB0ToDPiReduced, processSelectionWithDmesMl, "Process selection with ML scores of D mesons", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGHF/D2H/Tasks/taskB0Reduced.cxx b/PWGHF/D2H/Tasks/taskB0Reduced.cxx index d1c69d61b33..e320a3945d6 100644 --- a/PWGHF/D2H/Tasks/taskB0Reduced.cxx +++ b/PWGHF/D2H/Tasks/taskB0Reduced.cxx @@ -32,8 +32,40 @@ using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; +namespace o2::aod +{ +DECLARE_SOA_TABLE(HfRedCandB0Lites, "AOD", "HFREDCANDB0LITE", //! Table with some B0 properties + hf_cand::Chi2PCA, + hf_cand_b0_reduced::DecayLength, + hf_cand_b0_reduced::DecayLengthXY, + hf_cand_b0_reduced::DecayLengthNormalised, + hf_cand_b0_reduced::DecayLengthXYNormalised, + hf_cand_b0_reduced::PtProng0, + hf_cand_b0_reduced::PtProng1, + hf_cand::ImpactParameter0, + hf_cand::ImpactParameter1, + hf_cand_b0_reduced::NSigTpcPi1, + hf_cand_b0_reduced::NSigTofPi1, + hf_cand_b0_reduced::Prong0MlScoreBkg, + hf_cand_b0_reduced::Prong0MlScorePrompt, + hf_cand_b0_reduced::Prong0MlScoreNonprompt, + hf_cand_b0_reduced::CandidateSelFlag, + hf_cand_b0_reduced::M, + hf_cand_b0_reduced::Pt, + hf_cand_b0_reduced::Cpa, + hf_cand_b0_reduced::CpaXY, + hf_cand_b0_reduced::MaxNormalisedDeltaIP, + hf_cand_b0_reduced::Eta, + hf_cand_b0_reduced::Phi, + hf_cand_b0_reduced::Y, + hf_cand_3prong::FlagMcMatchRec, + hf_cand_3prong::OriginMcRec); +} // namespace o2::aod + /// B0 analysis task struct HfTaskB0Reduced { + Produces hfRedCandB0Lite; + Configurable selectionFlagB0{"selectionFlagB0", 1, "Selection Flag for B0"}; Configurable yCandGenMax{"yCandGenMax", 0.5, "max. gen particle rapidity"}; Configurable yCandRecoMax{"yCandRecoMax", 0.8, "max. cand. rapidity"}; @@ -41,7 +73,10 @@ struct HfTaskB0Reduced { Configurable ptTrackMin{"ptTrackMin", 0.1, "min. track transverse momentum"}; Configurable fillHistograms{"fillHistograms", true, "Flag to enable histogram filling"}; Configurable fillSparses{"fillSparses", false, "Flag to enable sparse filling"}; - Configurable fillBackground{"fillBackground", false, "Flag to enable filling of background histograms/sparses (only MC)"}; + Configurable fillTree{"fillTree", false, "Flag to enable tree filling"}; + Configurable fillBackground{"fillBackground", false, "Flag to enable filling of background histograms/sparses/tree (only MC)"}; + Configurable downSampleBkgFactor{"downSampleBkgFactor", 1., "Fraction of background candidates to keep for ML trainings"}; + Configurable ptMaxForDownSample{"ptMaxForDownSample", 10., "Maximum pt for the application of the downsampling factor"}; HfHelper hfHelper; @@ -49,6 +84,8 @@ struct HfTaskB0Reduced { HistogramRegistry registry{"registry"}; + using TracksPion = soa::Join; + void init(InitContext&) { std::array processFuncData{doprocessData, doprocessDataWithDmesMl}; @@ -60,6 +97,11 @@ struct HfTaskB0Reduced { LOGP(fatal, "Only one process function for MC can be enabled at a time."); } + if (((doprocessData || doprocessDataWithDmesMl) && fillTree && downSampleBkgFactor >= 1.) || + ((doprocessMc || doprocessMcWithDmesMl) && fillTree && fillBackground && downSampleBkgFactor >= 1.)) { + LOGP(fatal, "Set downSampleBkgFactor below unity when filling tree with background."); + } + const AxisSpec axisMlScore{100, 0.f, 1.f}; const AxisSpec axisMassB0{300, 4.5f, 6.0f}; const AxisSpec axisMassDminus{300, 1.75f, 2.05f}; @@ -262,6 +304,49 @@ struct HfTaskB0Reduced { registry.fill(HIST("hMassPtCutVars"), invMassB0, ptCandB0, candidate.decayLength(), candidate.decayLengthXY() / candidate.errorDecayLengthXY(), candidate.impactParameterProduct(), candidate.cpa(), candD.invMass(), ptD, decLenD, cospD); } } + if (fillTree) { + float pseudoRndm = ptD * 1000. - (int64_t)(ptD * 1000); + if (ptCandB0 >= ptMaxForDownSample || pseudoRndm < downSampleBkgFactor) { + int8_t flag{0}; + int8_t origin{0}; + float prong0MlScoreBkg = -1.; + float prong0MlScorePrompt = -1.; + float prong0MlScoreNonprompt = -1.; + if constexpr (withDmesMl) { + prong0MlScoreBkg = candidate.prong0MlScoreBkg(); + prong0MlScorePrompt = candidate.prong0MlScorePrompt(); + prong0MlScoreNonprompt = candidate.prong0MlScoreNonprompt(); + } + auto prong1 = candidate.template prong1_as(); + + hfRedCandB0Lite( + candidate.chi2PCA(), + candidate.decayLength(), + candidate.decayLengthXY(), + candidate.decayLengthNormalised(), + candidate.decayLengthXYNormalised(), + ptD, + candidate.ptProng1(), + candidate.impactParameter0(), + candidate.impactParameter1(), + prong1.tpcNSigmaPi(), + prong1.tofNSigmaPi(), + prong0MlScoreBkg, + prong0MlScorePrompt, + prong0MlScoreNonprompt, + candidate.isSelB0ToDPi(), + invMassB0, + ptCandB0, + candidate.cpa(), + candidate.cpaXY(), + candidate.maxNormalisedDeltaIP(), + candidate.eta(), + candidate.phi(), + hfHelper.yB0(candidate), + flag, + origin); + } + } } /// Fill candidate histograms (reco MC truth) @@ -284,7 +369,8 @@ struct HfTaskB0Reduced { auto decLenD = RecoDecay::distance(posPv, posSvD); auto decLenXyD = RecoDecay::distanceXY(posPv, posSvD); - bool isSignal = TESTBIT(std::abs(candidate.flagMcMatchRec()), hf_cand_b0::DecayType::B0ToDPi); + int8_t flagMcMatchRec = candidate.flagMcMatchRec(); + bool isSignal = TESTBIT(std::abs(candidate.flagMcMatchRec()), hf_cand_b0::DecayTypeMc::B0ToDplusPiToPiKPiPi); if (fillHistograms) { if (isSignal) { registry.fill(HIST("hMassRecSig"), ptCandB0, hfHelper.invMassB0ToDPi(candidate)); @@ -351,6 +437,76 @@ struct HfTaskB0Reduced { } } } + if (fillTree) { + float prong0MlScoreBkg = -1.; + float prong0MlScorePrompt = -1.; + float prong0MlScoreNonprompt = -1.; + if constexpr (withDmesMl) { + prong0MlScoreBkg = candidate.prong0MlScoreBkg(); + prong0MlScorePrompt = candidate.prong0MlScorePrompt(); + prong0MlScoreNonprompt = candidate.prong0MlScoreNonprompt(); + } + auto prong1 = candidate.template prong1_as(); + + if (isSignal) { + hfRedCandB0Lite( + candidate.chi2PCA(), + candidate.decayLength(), + candidate.decayLengthXY(), + candidate.decayLengthNormalised(), + candidate.decayLengthXYNormalised(), + ptD, + candidate.ptProng1(), + candidate.impactParameter0(), + candidate.impactParameter1(), + prong1.tpcNSigmaPi(), + prong1.tofNSigmaPi(), + prong0MlScoreBkg, + prong0MlScorePrompt, + prong0MlScoreNonprompt, + candidate.isSelB0ToDPi(), + invMassB0, + ptCandB0, + candidate.cpa(), + candidate.cpaXY(), + candidate.maxNormalisedDeltaIP(), + candidate.eta(), + candidate.phi(), + hfHelper.yB0(candidate), + flagMcMatchRec, + isSignal); + } else if (fillBackground) { + float pseudoRndm = ptD * 1000. - (int64_t)(ptD * 1000); + if (ptCandB0 >= ptMaxForDownSample || pseudoRndm < downSampleBkgFactor) { + hfRedCandB0Lite( + candidate.chi2PCA(), + candidate.decayLength(), + candidate.decayLengthXY(), + candidate.decayLengthNormalised(), + candidate.decayLengthXYNormalised(), + ptD, + candidate.ptProng1(), + candidate.impactParameter0(), + candidate.impactParameter1(), + prong1.tpcNSigmaPi(), + prong1.tofNSigmaPi(), + prong0MlScoreBkg, + prong0MlScorePrompt, + prong0MlScoreNonprompt, + candidate.isSelB0ToDPi(), + invMassB0, + ptCandB0, + candidate.cpa(), + candidate.cpaXY(), + candidate.maxNormalisedDeltaIP(), + candidate.eta(), + candidate.phi(), + hfHelper.yB0(candidate), + flagMcMatchRec, + isSignal); + } + } + } } /// Fill particle histograms (gen MC truth) @@ -393,7 +549,8 @@ struct HfTaskB0Reduced { // Process functions void processData(soa::Filtered> const& candidates, - aod::HfRed3Prongs const& candidatesD) + aod::HfRed3Prongs const& candidatesD, + TracksPion const&) { for (const auto& candidate : candidates) { if (!TESTBIT(candidate.hfflag(), hf_cand_b0::DecayType::B0ToDPi)) { @@ -409,7 +566,8 @@ struct HfTaskB0Reduced { PROCESS_SWITCH(HfTaskB0Reduced, processData, "Process data without ML scores for D daughter", true); void processDataWithDmesMl(soa::Filtered> const& candidates, - aod::HfRed3Prongs const& candidatesD) + aod::HfRed3Prongs const& candidatesD, + TracksPion const&) { for (const auto& candidate : candidates) { if (!TESTBIT(candidate.hfflag(), hf_cand_b0::DecayType::B0ToDPi)) { @@ -424,9 +582,10 @@ struct HfTaskB0Reduced { PROCESS_SWITCH(HfTaskB0Reduced, processDataWithDmesMl, "Process data with ML scores for D daughter", false); - void processMc(soa::Join const& candidates, + void processMc(soa::Join const& candidates, aod::HfMcGenRedB0s const& mcParticles, - aod::HfRed3Prongs const& candidatesD) + aod::HfRed3Prongs const& candidatesD, + TracksPion const&) { // MC rec for (const auto& candidate : candidates) { @@ -446,9 +605,10 @@ struct HfTaskB0Reduced { } // processMc PROCESS_SWITCH(HfTaskB0Reduced, processMc, "Process MC without ML scores for D daughter", false); - void processMcWithDmesMl(soa::Join const& candidates, + void processMcWithDmesMl(soa::Join const& candidates, aod::HfMcGenRedB0s const& mcParticles, - aod::HfRed3Prongs const& candidatesD) + aod::HfRed3Prongs const& candidatesD, + TracksPion const&) { // MC rec for (const auto& candidate : candidates) { From 4b1841d728aff474823e2edefa9d5181b6c51e56 Mon Sep 17 00:00:00 2001 From: Alexandre Bigot Date: Sun, 10 Dec 2023 11:37:54 +0100 Subject: [PATCH 06/10] Use column already defined for B0 selection flag + solve MegaLinter error --- PWGHF/D2H/DataModel/ReducedDataModel.h | 39 +++++++++++++------------- PWGHF/D2H/Tasks/taskB0Reduced.cxx | 2 +- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/PWGHF/D2H/DataModel/ReducedDataModel.h b/PWGHF/D2H/DataModel/ReducedDataModel.h index f048df9d495..873876f2ca4 100644 --- a/PWGHF/D2H/DataModel/ReducedDataModel.h +++ b/PWGHF/D2H/DataModel/ReducedDataModel.h @@ -205,26 +205,25 @@ DECLARE_SOA_TABLE(HfRed3ProngsMl, "AOD", "HFRED3PRONGML", //! Table with 3prong // 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_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 -DECLARE_SOA_COLUMN(PtProng0, ptProng0, float); //! Transverse momentum of prong0 (GeV/c) -DECLARE_SOA_COLUMN(PtProng1, ptProng1, float); //! Transverse momentum of prong1 (GeV/c) -DECLARE_SOA_COLUMN(CandidateSelFlag, candidateSelFlag, uint8_t); //! Selection flag of candidate (output of candidateSelector) -DECLARE_SOA_COLUMN(M, m, float); //! Invariant mass of candidate (GeV/c2) -DECLARE_SOA_COLUMN(Pt, pt, float); //! Transverse momentum of candidate (GeV/c) -DECLARE_SOA_COLUMN(P, p, float); //! Momentum of candidate (GeV/c) -DECLARE_SOA_COLUMN(Y, y, float); //! Rapidity of candidate -DECLARE_SOA_COLUMN(Eta, eta, float); //! Pseudorapidity of candidate -DECLARE_SOA_COLUMN(Phi, phi, float); //! Azimuth angle of candidate -DECLARE_SOA_COLUMN(E, e, float); //! Energy of candidate (GeV) -DECLARE_SOA_COLUMN(NSigTpcPi1, nSigTpcPi1, float); //! TPC Nsigma separation for prong1 with pion mass hypothesis -DECLARE_SOA_COLUMN(NSigTofPi1, nSigTofPi1, float); //! TOF Nsigma separation for prong1 with pion mass hypothesis -DECLARE_SOA_COLUMN(DecayLength, decayLength, float); //! Decay length of candidate (cm) -DECLARE_SOA_COLUMN(DecayLengthXY, decayLengthXY, float); //! Transverse decay length of candidate (cm) -DECLARE_SOA_COLUMN(DecayLengthNormalised, decayLengthNormalised, float); //! Normalised decay length of candidate +DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfRed3Prongs, "_0"); //! Prong0 index +DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, HfRedTrackBases, "_1"); //! Prong1 index +DECLARE_SOA_COLUMN(Prong0MlScoreBkg, prong0MlScoreBkg, float); //! Bkg ML score of the D daughter +DECLARE_SOA_COLUMN(Prong0MlScorePrompt, prong0MlScorePrompt, float); //! Prompt ML score of the D daughter +DECLARE_SOA_COLUMN(Prong0MlScoreNonprompt, prong0MlScoreNonprompt, float); //! Nonprompt ML score of the D daughter +DECLARE_SOA_COLUMN(PtProng0, ptProng0, float); //! Transverse momentum of prong0 (GeV/c) +DECLARE_SOA_COLUMN(PtProng1, ptProng1, float); //! Transverse momentum of prong1 (GeV/c) +DECLARE_SOA_COLUMN(M, m, float); //! Invariant mass of candidate (GeV/c2) +DECLARE_SOA_COLUMN(Pt, pt, float); //! Transverse momentum of candidate (GeV/c) +DECLARE_SOA_COLUMN(P, p, float); //! Momentum of candidate (GeV/c) +DECLARE_SOA_COLUMN(Y, y, float); //! Rapidity of candidate +DECLARE_SOA_COLUMN(Eta, eta, float); //! Pseudorapidity of candidate +DECLARE_SOA_COLUMN(Phi, phi, float); //! Azimuth angle of candidate +DECLARE_SOA_COLUMN(E, e, float); //! Energy of candidate (GeV) +DECLARE_SOA_COLUMN(NSigTpcPi1, nSigTpcPi1, float); //! TPC Nsigma separation for prong1 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTofPi1, nSigTofPi1, float); //! TOF Nsigma separation for prong1 with pion mass hypothesis +DECLARE_SOA_COLUMN(DecayLength, decayLength, float); //! Decay length of candidate (cm) +DECLARE_SOA_COLUMN(DecayLengthXY, decayLengthXY, float); //! Transverse decay length of candidate (cm) +DECLARE_SOA_COLUMN(DecayLengthNormalised, decayLengthNormalised, float); //! Normalised decay length of candidate DECLARE_SOA_COLUMN(DecayLengthXYNormalised, decayLengthXYNormalised, float); //! Normalised transverse decay length of candidate DECLARE_SOA_COLUMN(Cpa, cpa, float); //! Cosine pointing angle of candidate DECLARE_SOA_COLUMN(CpaXY, cpaXY, float); //! Cosine pointing angle of candidate in transverse plane diff --git a/PWGHF/D2H/Tasks/taskB0Reduced.cxx b/PWGHF/D2H/Tasks/taskB0Reduced.cxx index e320a3945d6..ddd63870b8d 100644 --- a/PWGHF/D2H/Tasks/taskB0Reduced.cxx +++ b/PWGHF/D2H/Tasks/taskB0Reduced.cxx @@ -49,7 +49,7 @@ DECLARE_SOA_TABLE(HfRedCandB0Lites, "AOD", "HFREDCANDB0LITE", //! Table with som hf_cand_b0_reduced::Prong0MlScoreBkg, hf_cand_b0_reduced::Prong0MlScorePrompt, hf_cand_b0_reduced::Prong0MlScoreNonprompt, - hf_cand_b0_reduced::CandidateSelFlag, + hf_sel_candidate_b0::IsSelB0ToDPi, hf_cand_b0_reduced::M, hf_cand_b0_reduced::Pt, hf_cand_b0_reduced::Cpa, From be53b0f8b564aa518471232858dcf107627fbeaa Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Sun, 10 Dec 2023 10:42:12 +0000 Subject: [PATCH 07/10] MegaLinter fixes --- PWGHF/D2H/DataModel/ReducedDataModel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGHF/D2H/DataModel/ReducedDataModel.h b/PWGHF/D2H/DataModel/ReducedDataModel.h index 873876f2ca4..8014da5a4a6 100644 --- a/PWGHF/D2H/DataModel/ReducedDataModel.h +++ b/PWGHF/D2H/DataModel/ReducedDataModel.h @@ -298,7 +298,7 @@ DECLARE_SOA_TABLE(HfMcGenRedB0s, "AOD", "HFMCGENREDB0", //! Generation-level MC // so we can use them in the B0 part namespace hf_cand_b0_config { -DECLARE_SOA_COLUMN(MySelectionFlagD, mySelectionFlagD, int8_t); //! Flag to filter selected D+ mesons +DECLARE_SOA_COLUMN(MySelectionFlagD, mySelectionFlagD, int8_t); //! Flag to filter selected D+ mesons DECLARE_SOA_COLUMN(MyInvMassWindowDPi, myInvMassWindowDPi, float); //! Half-width of the B0 invariant-mass window in GeV/c2 } // namespace hf_cand_b0_config From 388cb8dd868053304a704c2d0bb4e3c56b8f0376 Mon Sep 17 00:00:00 2001 From: Alexandre Bigot Date: Tue, 12 Dec 2023 11:50:55 +0100 Subject: [PATCH 08/10] Fix bug in Dmeson ML score cut in B0 reduced selector --- PWGHF/Core/SelectorCuts.h | 1 + PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/PWGHF/Core/SelectorCuts.h b/PWGHF/Core/SelectorCuts.h index bc366dffd57..41fac07b5dd 100644 --- a/PWGHF/Core/SelectorCuts.h +++ b/PWGHF/Core/SelectorCuts.h @@ -163,6 +163,7 @@ static const std::vector labelsPt = { // column labels static const std::vector labelsCutScore = {"score class 1", "score class 2", "score class 3"}; +static const std::vector labelsDmesCutScore = {"ML score charm bkg", "ML score charm prompt", "ML score charm nonprompt"}; } // namespace hf_cuts_ml namespace hf_cuts_presel_2prong diff --git a/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx b/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx index 262ef26aca5..0f312fa0c44 100644 --- a/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx @@ -54,7 +54,7 @@ struct HfCandidateSelectorB0ToDPiReduced { Configurable> cuts{"cuts", {hf_cuts_b0_to_d_pi::cuts[0], hf_cuts_b0_to_d_pi::nBinsPt, hf_cuts_b0_to_d_pi::nCutVars, hf_cuts_b0_to_d_pi::labelsPt, hf_cuts_b0_to_d_pi::labelsCutVar}, "B0 candidate selection per pT bin"}; // D-meson ML cuts Configurable> binsPtDmesMl{"binsPtDmesMl", std::vector{hf_cuts_ml::vecBinsPt}, "D-meson pT bin limits for ML cuts"}; - Configurable> cutsDmesMl{"cutsDmesMl", {hf_cuts_ml::cuts[0], hf_cuts_ml::nBinsPt, hf_cuts_ml::nCutScores, hf_cuts_ml::labelsPt, hf_cuts_ml::labelsCutScore}, "D-meson ML cuts per pT bin"}; + Configurable> cutsDmesMl{"cutsDmesMl", {hf_cuts_ml::cuts[0], hf_cuts_ml::nBinsPt, hf_cuts_ml::nCutScores, hf_cuts_ml::labelsPt, hf_cuts_ml::labelsDmesCutScore}, "D-meson ML cuts per pT bin"}; // QA switch Configurable activateQA{"activateQA", false, "Flag to enable QA histogram"}; From 6e914ff3d089c1a04a6f233ceeba16c0d4c3542b Mon Sep 17 00:00:00 2001 From: Alexandre Bigot Date: Tue, 12 Dec 2023 12:34:27 +0100 Subject: [PATCH 09/10] Add Mattia's comments --- PWGHF/D2H/DataModel/ReducedDataModel.h | 18 ------ PWGHF/D2H/Tasks/taskB0Reduced.cxx | 90 ++++++++++++-------------- 2 files changed, 41 insertions(+), 67 deletions(-) diff --git a/PWGHF/D2H/DataModel/ReducedDataModel.h b/PWGHF/D2H/DataModel/ReducedDataModel.h index 8014da5a4a6..7c38e83758c 100644 --- a/PWGHF/D2H/DataModel/ReducedDataModel.h +++ b/PWGHF/D2H/DataModel/ReducedDataModel.h @@ -210,24 +210,6 @@ DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, HfRedTrackBases, "_1"); //! 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 -DECLARE_SOA_COLUMN(PtProng0, ptProng0, float); //! Transverse momentum of prong0 (GeV/c) -DECLARE_SOA_COLUMN(PtProng1, ptProng1, float); //! Transverse momentum of prong1 (GeV/c) -DECLARE_SOA_COLUMN(M, m, float); //! Invariant mass of candidate (GeV/c2) -DECLARE_SOA_COLUMN(Pt, pt, float); //! Transverse momentum of candidate (GeV/c) -DECLARE_SOA_COLUMN(P, p, float); //! Momentum of candidate (GeV/c) -DECLARE_SOA_COLUMN(Y, y, float); //! Rapidity of candidate -DECLARE_SOA_COLUMN(Eta, eta, float); //! Pseudorapidity of candidate -DECLARE_SOA_COLUMN(Phi, phi, float); //! Azimuth angle of candidate -DECLARE_SOA_COLUMN(E, e, float); //! Energy of candidate (GeV) -DECLARE_SOA_COLUMN(NSigTpcPi1, nSigTpcPi1, float); //! TPC Nsigma separation for prong1 with pion mass hypothesis -DECLARE_SOA_COLUMN(NSigTofPi1, nSigTofPi1, float); //! TOF Nsigma separation for prong1 with pion mass hypothesis -DECLARE_SOA_COLUMN(DecayLength, decayLength, float); //! Decay length of candidate (cm) -DECLARE_SOA_COLUMN(DecayLengthXY, decayLengthXY, float); //! Transverse decay length of candidate (cm) -DECLARE_SOA_COLUMN(DecayLengthNormalised, decayLengthNormalised, float); //! Normalised decay length of candidate -DECLARE_SOA_COLUMN(DecayLengthXYNormalised, decayLengthXYNormalised, float); //! Normalised transverse decay length of candidate -DECLARE_SOA_COLUMN(Cpa, cpa, float); //! Cosine pointing angle of candidate -DECLARE_SOA_COLUMN(CpaXY, cpaXY, float); //! Cosine pointing angle of candidate in transverse plane -DECLARE_SOA_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, float); //! Maximum normalized difference between measured and expected impact parameter of candidate prongs } // namespace hf_cand_b0_reduced DECLARE_SOA_TABLE(HfRedB0Prongs, "AOD", "HFREDB0PRONG", //! Table with B0 daughter indices diff --git a/PWGHF/D2H/Tasks/taskB0Reduced.cxx b/PWGHF/D2H/Tasks/taskB0Reduced.cxx index ddd63870b8d..fe08c538e8a 100644 --- a/PWGHF/D2H/Tasks/taskB0Reduced.cxx +++ b/PWGHF/D2H/Tasks/taskB0Reduced.cxx @@ -34,30 +34,52 @@ using namespace o2::framework::expressions; namespace o2::aod { +namespace hf_cand_b0_lite +{ +DECLARE_SOA_COLUMN(PtProng0, ptProng0, float); //! Transverse momentum of prong0 (GeV/c) +DECLARE_SOA_COLUMN(PtProng1, ptProng1, float); //! Transverse momentum of prong1 (GeV/c) +DECLARE_SOA_COLUMN(M, m, float); //! Invariant mass of candidate (GeV/c2) +DECLARE_SOA_COLUMN(Pt, pt, float); //! Transverse momentum of candidate (GeV/c) +DECLARE_SOA_COLUMN(P, p, float); //! Momentum of candidate (GeV/c) +DECLARE_SOA_COLUMN(Y, y, float); //! Rapidity of candidate +DECLARE_SOA_COLUMN(Eta, eta, float); //! Pseudorapidity of candidate +DECLARE_SOA_COLUMN(Phi, phi, float); //! Azimuth angle of candidate +DECLARE_SOA_COLUMN(E, e, float); //! Energy of candidate (GeV) +DECLARE_SOA_COLUMN(NSigTpcPi1, nSigTpcPi1, float); //! TPC Nsigma separation for prong1 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTofPi1, nSigTofPi1, float); //! TOF Nsigma separation for prong1 with pion mass hypothesis +DECLARE_SOA_COLUMN(DecayLength, decayLength, float); //! Decay length of candidate (cm) +DECLARE_SOA_COLUMN(DecayLengthXY, decayLengthXY, float); //! Transverse decay length of candidate (cm) +DECLARE_SOA_COLUMN(DecayLengthNormalised, decayLengthNormalised, float); //! Normalised decay length of candidate +DECLARE_SOA_COLUMN(DecayLengthXYNormalised, decayLengthXYNormalised, float); //! Normalised transverse decay length of candidate +DECLARE_SOA_COLUMN(Cpa, cpa, float); //! Cosine pointing angle of candidate +DECLARE_SOA_COLUMN(CpaXY, cpaXY, float); //! Cosine pointing angle of candidate in transverse plane +DECLARE_SOA_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, float); //! Maximum normalized difference between measured and expected impact parameter of candidate prongs +} // namespace hf_cand_b0_lite + DECLARE_SOA_TABLE(HfRedCandB0Lites, "AOD", "HFREDCANDB0LITE", //! Table with some B0 properties hf_cand::Chi2PCA, - hf_cand_b0_reduced::DecayLength, - hf_cand_b0_reduced::DecayLengthXY, - hf_cand_b0_reduced::DecayLengthNormalised, - hf_cand_b0_reduced::DecayLengthXYNormalised, - hf_cand_b0_reduced::PtProng0, - hf_cand_b0_reduced::PtProng1, + hf_cand_b0_lite::DecayLength, + hf_cand_b0_lite::DecayLengthXY, + hf_cand_b0_lite::DecayLengthNormalised, + hf_cand_b0_lite::DecayLengthXYNormalised, + hf_cand_b0_lite::PtProng0, + hf_cand_b0_lite::PtProng1, hf_cand::ImpactParameter0, hf_cand::ImpactParameter1, - hf_cand_b0_reduced::NSigTpcPi1, - hf_cand_b0_reduced::NSigTofPi1, + hf_cand_b0_lite::NSigTpcPi1, + hf_cand_b0_lite::NSigTofPi1, hf_cand_b0_reduced::Prong0MlScoreBkg, hf_cand_b0_reduced::Prong0MlScorePrompt, hf_cand_b0_reduced::Prong0MlScoreNonprompt, hf_sel_candidate_b0::IsSelB0ToDPi, - hf_cand_b0_reduced::M, - hf_cand_b0_reduced::Pt, - hf_cand_b0_reduced::Cpa, - hf_cand_b0_reduced::CpaXY, - hf_cand_b0_reduced::MaxNormalisedDeltaIP, - hf_cand_b0_reduced::Eta, - hf_cand_b0_reduced::Phi, - hf_cand_b0_reduced::Y, + hf_cand_b0_lite::M, + hf_cand_b0_lite::Pt, + hf_cand_b0_lite::Cpa, + hf_cand_b0_lite::CpaXY, + hf_cand_b0_lite::MaxNormalisedDeltaIP, + hf_cand_b0_lite::Eta, + hf_cand_b0_lite::Phi, + hf_cand_b0_lite::Y, hf_cand_3prong::FlagMcMatchRec, hf_cand_3prong::OriginMcRec); } // namespace o2::aod @@ -370,7 +392,7 @@ struct HfTaskB0Reduced { auto decLenXyD = RecoDecay::distanceXY(posPv, posSvD); int8_t flagMcMatchRec = candidate.flagMcMatchRec(); - bool isSignal = TESTBIT(std::abs(candidate.flagMcMatchRec()), hf_cand_b0::DecayTypeMc::B0ToDplusPiToPiKPiPi); + bool isSignal = TESTBIT(std::abs(flagMcMatchRec), hf_cand_b0::DecayTypeMc::B0ToDplusPiToPiKPiPi); if (fillHistograms) { if (isSignal) { registry.fill(HIST("hMassRecSig"), ptCandB0, hfHelper.invMassB0ToDPi(candidate)); @@ -447,8 +469,8 @@ struct HfTaskB0Reduced { prong0MlScoreNonprompt = candidate.prong0MlScoreNonprompt(); } auto prong1 = candidate.template prong1_as(); - - if (isSignal) { + float pseudoRndm = ptD * 1000. - (int64_t)(ptD * 1000); + if (isSignal || (fillBackground && (ptCandB0 >= ptMaxForDownSample || pseudoRndm < downSampleBkgFactor))) { hfRedCandB0Lite( candidate.chi2PCA(), candidate.decayLength(), @@ -475,36 +497,6 @@ struct HfTaskB0Reduced { hfHelper.yB0(candidate), flagMcMatchRec, isSignal); - } else if (fillBackground) { - float pseudoRndm = ptD * 1000. - (int64_t)(ptD * 1000); - if (ptCandB0 >= ptMaxForDownSample || pseudoRndm < downSampleBkgFactor) { - hfRedCandB0Lite( - candidate.chi2PCA(), - candidate.decayLength(), - candidate.decayLengthXY(), - candidate.decayLengthNormalised(), - candidate.decayLengthXYNormalised(), - ptD, - candidate.ptProng1(), - candidate.impactParameter0(), - candidate.impactParameter1(), - prong1.tpcNSigmaPi(), - prong1.tofNSigmaPi(), - prong0MlScoreBkg, - prong0MlScorePrompt, - prong0MlScoreNonprompt, - candidate.isSelB0ToDPi(), - invMassB0, - ptCandB0, - candidate.cpa(), - candidate.cpaXY(), - candidate.maxNormalisedDeltaIP(), - candidate.eta(), - candidate.phi(), - hfHelper.yB0(candidate), - flagMcMatchRec, - isSignal); - } } } } From d9d6fa99c03e0f67cb002502c70c6775f0833f53 Mon Sep 17 00:00:00 2001 From: Alexandre Bigot Date: Tue, 12 Dec 2023 12:39:18 +0100 Subject: [PATCH 10/10] Clang format --- PWGHF/D2H/DataModel/ReducedDataModel.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/PWGHF/D2H/DataModel/ReducedDataModel.h b/PWGHF/D2H/DataModel/ReducedDataModel.h index 7c38e83758c..3ca7fbb410f 100644 --- a/PWGHF/D2H/DataModel/ReducedDataModel.h +++ b/PWGHF/D2H/DataModel/ReducedDataModel.h @@ -205,11 +205,11 @@ DECLARE_SOA_TABLE(HfRed3ProngsMl, "AOD", "HFRED3PRONGML", //! Table with 3prong // 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_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 +DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfRed3Prongs, "_0"); //! Prong0 index +DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, HfRedTrackBases, "_1"); //! Prong1 index +DECLARE_SOA_COLUMN(Prong0MlScoreBkg, prong0MlScoreBkg, float); //! Bkg ML score of the D daughter +DECLARE_SOA_COLUMN(Prong0MlScorePrompt, prong0MlScorePrompt, float); //! Prompt ML score of the D daughter +DECLARE_SOA_COLUMN(Prong0MlScoreNonprompt, prong0MlScoreNonprompt, float); //! Nonprompt ML score of the D daughter } // namespace hf_cand_b0_reduced DECLARE_SOA_TABLE(HfRedB0Prongs, "AOD", "HFREDB0PRONG", //! Table with B0 daughter indices