diff --git a/PWGHF/D2H/Tasks/taskD0.cxx b/PWGHF/D2H/Tasks/taskD0.cxx index 219142f3d78..45e20eea651 100644 --- a/PWGHF/D2H/Tasks/taskD0.cxx +++ b/PWGHF/D2H/Tasks/taskD0.cxx @@ -605,100 +605,95 @@ struct HfTaskD0 { const auto& zdc = bcForUPC.zdc(); zdcEnergyZNA = zdc.energyCommonZNA(); zdcEnergyZNC = zdc.energyCommonZNC(); - } - - // Fill QA histograms using the UPC BC for both FIT and ZDC - if (hasZdc) { - registry.fill(HIST("Data/fitInfo/ampFT0A_vs_ampFT0C"), fitInfo.ampFT0A, fitInfo.ampFT0C); registry.fill(HIST("Data/zdc/energyZNA_vs_energyZNC"), zdcEnergyZNA, zdcEnergyZNC); - registry.fill(HIST("Data/hUpcGapAfterSelection"), gap); } - if (hf_upc::isSingleSidedGap(gap)) { - const auto thisCollId = collision.globalIndex(); - const auto& groupedD0Candidates = candidates.sliceBy(candD0PerCollision, thisCollId); + registry.fill(HIST("Data/fitInfo/ampFT0A_vs_ampFT0C"), fitInfo.ampFT0A, fitInfo.ampFT0C); + registry.fill(HIST("Data/hUpcGapAfterSelection"), gap); - // Calculate occupancy and interaction rate if needed - float occ{-1.f}; - float ir{-1.f}; - if (storeOccupancyAndIR && occEstimator != OccupancyEstimator::None) { - occ = o2::hf_occupancy::getOccupancyColl(collision, occEstimator); - ir = mRateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), irSource, true) * 1.e-3; // kHz + const auto thisCollId = collision.globalIndex(); + const auto& groupedD0Candidates = candidates.sliceBy(candD0PerCollision, thisCollId); + + // Calculate occupancy and interaction rate if needed + float occ{-1.f}; + float ir{-1.f}; + if (storeOccupancyAndIR && occEstimator != OccupancyEstimator::None) { + occ = o2::hf_occupancy::getOccupancyColl(collision, occEstimator); + ir = mRateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), irSource, true) * 1.e-3; // kHz + } + + for (const auto& candidate : groupedD0Candidates) { + if (yCandRecoMax >= 0. && std::abs(HfHelper::yD0(candidate)) > yCandRecoMax) { + continue; } - for (const auto& candidate : groupedD0Candidates) { - if (yCandRecoMax >= 0. && std::abs(HfHelper::yD0(candidate)) > yCandRecoMax) { - continue; - } + const float massD0 = HfHelper::invMassD0ToPiK(candidate); + const float massD0bar = HfHelper::invMassD0barToKPi(candidate); + const auto ptCandidate = candidate.pt(); - const float massD0 = HfHelper::invMassD0ToPiK(candidate); - const float massD0bar = HfHelper::invMassD0barToKPi(candidate); - const auto ptCandidate = candidate.pt(); + if (candidate.isSelD0() >= selectionFlagD0) { + registry.fill(HIST("hMass"), massD0, ptCandidate); + registry.fill(HIST("hMassFinerBinning"), massD0, ptCandidate); + registry.fill(HIST("hMassVsPhi"), massD0, ptCandidate, candidate.phi()); + } + if (candidate.isSelD0bar() >= selectionFlagD0bar) { + registry.fill(HIST("hMass"), massD0bar, ptCandidate); + registry.fill(HIST("hMassFinerBinning"), massD0bar, ptCandidate); + registry.fill(HIST("hMassVsPhi"), massD0bar, ptCandidate, candidate.phi()); + } - if (candidate.isSelD0() >= selectionFlagD0) { - registry.fill(HIST("hMass"), massD0, ptCandidate); - registry.fill(HIST("hMassFinerBinning"), massD0, ptCandidate); - registry.fill(HIST("hMassVsPhi"), massD0, ptCandidate, candidate.phi()); + // Fill THnSparse with structure matching histogram axes: [mass, pt, (mlScores if FillMl), rapidity, d0Type, (cent if storeCentrality), (occ, ir if storeOccupancyAndIR), gapType, FT0A, FT0C, FV0A, FDDA, FDDC, ZNA, ZNC] + auto fillTHnData = [&](float mass, int d0Type) { + // Pre-calculate vector size to avoid reallocations + constexpr int NAxesBase = 12; // mass, pt, rapidity, d0Type, gapType, FT0A, FT0C, FV0A, FDDA, FDDC, ZNA, ZNC + constexpr int NAxesMl = FillMl ? 3 : 0; // 3 ML scores if FillMl + int const nAxesCent = storeCentrality ? 1 : 0; // centrality if storeCentrality + int const nAxesOccIR = storeOccupancyAndIR ? 2 : 0; // occupancy and IR if storeOccupancyAndIR + int const nAxesTotal = NAxesBase + NAxesMl + nAxesCent + nAxesOccIR; + + std::vector valuesToFill; + valuesToFill.reserve(nAxesTotal); + + // Fill values in order matching histogram axes + valuesToFill.push_back(static_cast(mass)); + valuesToFill.push_back(static_cast(ptCandidate)); + if constexpr (FillMl) { + valuesToFill.push_back(candidate.mlProbD0()[0]); + valuesToFill.push_back(candidate.mlProbD0()[1]); + valuesToFill.push_back(candidate.mlProbD0()[2]); } - if (candidate.isSelD0bar() >= selectionFlagD0bar) { - registry.fill(HIST("hMass"), massD0bar, ptCandidate); - registry.fill(HIST("hMassFinerBinning"), massD0bar, ptCandidate); - registry.fill(HIST("hMassVsPhi"), massD0bar, ptCandidate, candidate.phi()); + valuesToFill.push_back(static_cast(HfHelper::yD0(candidate))); + valuesToFill.push_back(static_cast(d0Type)); + if (storeCentrality) { + valuesToFill.push_back(centrality); } - - // Fill THnSparse with structure matching histogram axes: [mass, pt, (mlScores if FillMl), rapidity, d0Type, (cent if storeCentrality), (occ, ir if storeOccupancyAndIR), gapType, FT0A, FT0C, FV0A, FDDA, FDDC, ZNA, ZNC] - auto fillTHnData = [&](float mass, int d0Type) { - // Pre-calculate vector size to avoid reallocations - constexpr int NAxesBase = 12; // mass, pt, rapidity, d0Type, gapType, FT0A, FT0C, FV0A, FDDA, FDDC, ZNA, ZNC - constexpr int NAxesMl = FillMl ? 3 : 0; // 3 ML scores if FillMl - int const nAxesCent = storeCentrality ? 1 : 0; // centrality if storeCentrality - int const nAxesOccIR = storeOccupancyAndIR ? 2 : 0; // occupancy and IR if storeOccupancyAndIR - int const nAxesTotal = NAxesBase + NAxesMl + nAxesCent + nAxesOccIR; - - std::vector valuesToFill; - valuesToFill.reserve(nAxesTotal); - - // Fill values in order matching histogram axes - valuesToFill.push_back(static_cast(mass)); - valuesToFill.push_back(static_cast(ptCandidate)); - if constexpr (FillMl) { - valuesToFill.push_back(candidate.mlProbD0()[0]); - valuesToFill.push_back(candidate.mlProbD0()[1]); - valuesToFill.push_back(candidate.mlProbD0()[2]); - } - valuesToFill.push_back(static_cast(HfHelper::yD0(candidate))); - valuesToFill.push_back(static_cast(d0Type)); - if (storeCentrality) { - valuesToFill.push_back(centrality); - } - if (storeOccupancyAndIR) { - valuesToFill.push_back(occ); - valuesToFill.push_back(ir); - } - valuesToFill.push_back(static_cast(gap)); - valuesToFill.push_back(static_cast(fitInfo.ampFT0A)); - valuesToFill.push_back(static_cast(fitInfo.ampFT0C)); - valuesToFill.push_back(static_cast(fitInfo.ampFV0A)); - valuesToFill.push_back(static_cast(fitInfo.ampFDDA)); - valuesToFill.push_back(static_cast(fitInfo.ampFDDC)); - valuesToFill.push_back(static_cast(zdcEnergyZNA)); - valuesToFill.push_back(static_cast(zdcEnergyZNC)); - - if constexpr (FillMl) { - registry.get(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type"))->Fill(valuesToFill.data()); - } else { - registry.get(HIST("hMassVsPtVsPtBVsYVsOriginVsD0Type"))->Fill(valuesToFill.data()); - } - }; - - if (candidate.isSelD0() >= selectionFlagD0) { - fillTHnData(massD0, SigD0); - fillTHnData(massD0, candidate.isSelD0bar() ? ReflectedD0 : PureSigD0); + if (storeOccupancyAndIR) { + valuesToFill.push_back(occ); + valuesToFill.push_back(ir); } - if (candidate.isSelD0bar() >= selectionFlagD0bar) { - fillTHnData(massD0bar, SigD0bar); - fillTHnData(massD0bar, candidate.isSelD0() ? ReflectedD0bar : PureSigD0bar); + valuesToFill.push_back(static_cast(gap)); + valuesToFill.push_back(static_cast(fitInfo.ampFT0A)); + valuesToFill.push_back(static_cast(fitInfo.ampFT0C)); + valuesToFill.push_back(static_cast(fitInfo.ampFV0A)); + valuesToFill.push_back(static_cast(fitInfo.ampFDDA)); + valuesToFill.push_back(static_cast(fitInfo.ampFDDC)); + valuesToFill.push_back(static_cast(zdcEnergyZNA)); + valuesToFill.push_back(static_cast(zdcEnergyZNC)); + + if constexpr (FillMl) { + registry.get(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type"))->Fill(valuesToFill.data()); + } else { + registry.get(HIST("hMassVsPtVsPtBVsYVsOriginVsD0Type"))->Fill(valuesToFill.data()); } + }; + + if (candidate.isSelD0() >= selectionFlagD0) { + fillTHnData(massD0, SigD0); + fillTHnData(massD0, candidate.isSelD0bar() ? ReflectedD0 : PureSigD0); + } + if (candidate.isSelD0bar() >= selectionFlagD0bar) { + fillTHnData(massD0bar, SigD0bar); + fillTHnData(massD0bar, candidate.isSelD0() ? ReflectedD0bar : PureSigD0bar); } } } diff --git a/PWGHF/D2H/Tasks/taskDplus.cxx b/PWGHF/D2H/Tasks/taskDplus.cxx index 2e3ceec0884..b09e705d3ab 100644 --- a/PWGHF/D2H/Tasks/taskDplus.cxx +++ b/PWGHF/D2H/Tasks/taskDplus.cxx @@ -213,7 +213,7 @@ struct HfTaskDplus { registry.add("hPtVsYGenPrompt", "MC particles (matched, prompt);#it{p}_{T}^{gen.}; #it{y}", {HistType::kTH2F, {{vbins, "#it{p}_{T} (GeV/#it{c})"}, {100, -5., 5.}}}); registry.add("hPtVsYGenNonPrompt", "MC particles (matched, non-prompt);#it{p}_{T}^{gen.}; #it{y}", {HistType::kTH2F, {{vbins, "#it{p}_{T} (GeV/#it{c})"}, {100, -5., 5.}}}); - if (doprocessDataWithMl || doprocessData || doprocessDataWithMlWithUpc) { + if (doprocessDataWithMl || doprocessData || doprocessDataWithMlWithUpc || doprocessDataWithUpc) { std::vector axes = {thnAxisMass, thnAxisPt}; if (doprocessDataWithMl || doprocessDataWithMlWithUpc) { @@ -742,81 +742,75 @@ struct HfTaskDplus { const auto& zdc = bcForUPC.zdc(); zdcEnergyZNA = zdc.energyCommonZNA(); zdcEnergyZNC = zdc.energyCommonZNC(); - } - - // Fill QA histograms using the UPC BC for both FIT and ZDC - if (hasZdc) { - registry.fill(HIST("Data/fitInfo/ampFT0A_vs_ampFT0C"), fitInfo.ampFT0A, fitInfo.ampFT0C); registry.fill(HIST("Data/zdc/energyZNA_vs_energyZNC"), zdcEnergyZNA, zdcEnergyZNC); - registry.fill(HIST("Data/hUpcGapAfterSelection"), gap); } + registry.fill(HIST("Data/fitInfo/ampFT0A_vs_ampFT0C"), fitInfo.ampFT0A, fitInfo.ampFT0C); + registry.fill(HIST("Data/hUpcGapAfterSelection"), gap); - if (hf_upc::isSingleSidedGap(gap)) { - const auto thisCollId = collision.globalIndex(); - const auto& groupedDplusCandidates = candidates.sliceBy(candDplusPerCollision, thisCollId); + const auto thisCollId = collision.globalIndex(); + const auto& groupedDplusCandidates = candidates.sliceBy(candDplusPerCollision, thisCollId); - float cent{-1.f}; - float occ{-1.f}; - float ir{-1.f}; - if (storeOccupancy && occEstimator != OccupancyEstimator::None) { - occ = o2::hf_occupancy::getOccupancyColl(collision, occEstimator); + float cent{-1.f}; + float occ{-1.f}; + float ir{-1.f}; + if (storeOccupancy && occEstimator != OccupancyEstimator::None) { + occ = o2::hf_occupancy::getOccupancyColl(collision, occEstimator); + } + if (storeIR) { + ir = mRateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), irSource, true) * 1.e-3; // kHz + } + static constexpr auto HSparseMass = HIST("hSparseMass"); + // Lambda function to fill THn - handles both ML and non-ML cases + auto fillTHnData = [&](const auto& candidate) { + // Pre-calculate vector size to avoid reallocations + constexpr int NAxesBase = 10; // mass, pt, gapType, FT0A, FT0C, FV0A, FDDA, FDDC, ZNA, ZNC + constexpr int NAxesMl = FillMl ? 3 : 0; // 3 ML scores if FillMl + int const nAxesCent = storeCentrality ? 1 : 0; // centrality if storeCentrality + int const nAxesOcc = storeOccupancy ? 1 : 0; // occupancy if storeOccupancy + int const nAxesIR = storeIR ? 1 : 0; // IR if storeIR + int const nAxesTotal = NAxesBase + NAxesMl + nAxesCent + nAxesOcc + nAxesIR; + + std::vector valuesToFill; + valuesToFill.reserve(nAxesTotal); + + // Fill values in order matching histogram axes + valuesToFill.push_back(HfHelper::invMassDplusToPiKPi(candidate)); + valuesToFill.push_back(static_cast(candidate.pt())); + if constexpr (FillMl) { + std::vector outputMl = {-999., -999., -999.}; + for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { + outputMl[iclass] = candidate.mlProbDplusToPiKPi()[classMl->at(iclass)]; + } + valuesToFill.push_back(outputMl[0]); + valuesToFill.push_back(outputMl[1]); + valuesToFill.push_back(outputMl[2]); + } + if (storeCentrality) { + valuesToFill.push_back(cent); + } + if (storeOccupancy) { + valuesToFill.push_back(occ); } if (storeIR) { - ir = mRateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), irSource, true) * 1.e-3; // kHz + valuesToFill.push_back(ir); } - static constexpr auto HSparseMass = HIST("hSparseMass"); - // Lambda function to fill THn - handles both ML and non-ML cases - auto fillTHnData = [&](const auto& candidate) { - // Pre-calculate vector size to avoid reallocations - constexpr int NAxesBase = 10; // mass, pt, gapType, FT0A, FT0C, FV0A, FDDA, FDDC, ZNA, ZNC - constexpr int NAxesMl = FillMl ? 3 : 0; // 3 ML scores if FillMl - int const nAxesCent = storeCentrality ? 1 : 0; // centrality if storeCentrality - int const nAxesOcc = storeOccupancy ? 1 : 0; // occupancy if storeOccupancy - int const nAxesIR = storeIR ? 1 : 0; // IR if storeIR - int const nAxesTotal = NAxesBase + NAxesMl + nAxesCent + nAxesOcc + nAxesIR; - - std::vector valuesToFill; - valuesToFill.reserve(nAxesTotal); - - // Fill values in order matching histogram axes - valuesToFill.push_back(HfHelper::invMassDplusToPiKPi(candidate)); - valuesToFill.push_back(static_cast(candidate.pt())); - if constexpr (FillMl) { - std::vector outputMl = {-999., -999., -999.}; - for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { - outputMl[iclass] = candidate.mlProbDplusToPiKPi()[classMl->at(iclass)]; - } - valuesToFill.push_back(outputMl[0]); - valuesToFill.push_back(outputMl[1]); - valuesToFill.push_back(outputMl[2]); - } - if (storeCentrality) { - valuesToFill.push_back(cent); - } - if (storeOccupancy) { - valuesToFill.push_back(occ); - } - if (storeIR) { - valuesToFill.push_back(ir); - } - valuesToFill.push_back(static_cast(gap)); - valuesToFill.push_back(static_cast(fitInfo.ampFT0A)); - valuesToFill.push_back(static_cast(fitInfo.ampFT0C)); - valuesToFill.push_back(static_cast(fitInfo.ampFV0A)); - valuesToFill.push_back(static_cast(fitInfo.ampFDDA)); - valuesToFill.push_back(static_cast(fitInfo.ampFDDC)); - valuesToFill.push_back(static_cast(zdcEnergyZNA)); - valuesToFill.push_back(static_cast(zdcEnergyZNC)); - registry.get(HSparseMass)->Fill(valuesToFill.data()); - }; - - for (const auto& candidate : groupedDplusCandidates) { - if ((yCandRecoMax >= 0. && std::abs(HfHelper::yDplus(candidate)) > yCandRecoMax)) { - continue; - } - fillHisto(candidate); - fillTHnData(candidate); + valuesToFill.push_back(static_cast(gap)); + valuesToFill.push_back(static_cast(fitInfo.ampFT0A)); + valuesToFill.push_back(static_cast(fitInfo.ampFT0C)); + valuesToFill.push_back(static_cast(fitInfo.ampFV0A)); + valuesToFill.push_back(static_cast(fitInfo.ampFDDA)); + valuesToFill.push_back(static_cast(fitInfo.ampFDDC)); + valuesToFill.push_back(static_cast(zdcEnergyZNA)); + valuesToFill.push_back(static_cast(zdcEnergyZNC)); + registry.get(HSparseMass)->Fill(valuesToFill.data()); + }; + + for (const auto& candidate : groupedDplusCandidates) { + if ((yCandRecoMax >= 0. && std::abs(HfHelper::yDplus(candidate)) > yCandRecoMax)) { + continue; } + fillHisto(candidate); + fillTHnData(candidate); } } } diff --git a/PWGHF/Utils/utilsUpcHf.h b/PWGHF/Utils/utilsUpcHf.h index 45190185c74..436afc34710 100644 --- a/PWGHF/Utils/utilsUpcHf.h +++ b/PWGHF/Utils/utilsUpcHf.h @@ -111,15 +111,15 @@ inline auto determineGapType(TCollision const& collision, thresholds.ft0aThreshold.value, thresholds.ft0cThreshold.value); } - +/* /// \brief Check if the gap type is a single-sided gap (SingleGapA or SingleGapC) /// \param gap TrueGap enum value /// \return true if single-sided gap, false otherwise constexpr bool isSingleSidedGap(int gap) noexcept { - return (gap == TrueGap::SingleGapA || gap == TrueGap::SingleGapC); + return (gap == TrueGap::SingleGapA || gap == TrueGap::SingleGapC || gap == TrueGap::DoubleGap || gap == TrueGap::BadDoubleGap || gap == TrueGap::TrkOutOfRange || gap == TrueGap::NoUpc); } - +*/ /// \brief Get gap type name as string /// \param gap TrueGap enum value /// \return String representation of gap type