Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
159 changes: 77 additions & 82 deletions PWGHF/D2H/Tasks/taskD0.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -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<double> valuesToFill;
valuesToFill.reserve(nAxesTotal);

// Fill values in order matching histogram axes
valuesToFill.push_back(static_cast<double>(mass));
valuesToFill.push_back(static_cast<double>(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<double>(HfHelper::yD0(candidate)));
valuesToFill.push_back(static_cast<double>(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<double> valuesToFill;
valuesToFill.reserve(nAxesTotal);

// Fill values in order matching histogram axes
valuesToFill.push_back(static_cast<double>(mass));
valuesToFill.push_back(static_cast<double>(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<double>(HfHelper::yD0(candidate)));
valuesToFill.push_back(static_cast<double>(d0Type));
if (storeCentrality) {
valuesToFill.push_back(centrality);
}
if (storeOccupancyAndIR) {
valuesToFill.push_back(occ);
valuesToFill.push_back(ir);
}
valuesToFill.push_back(static_cast<double>(gap));
valuesToFill.push_back(static_cast<double>(fitInfo.ampFT0A));
valuesToFill.push_back(static_cast<double>(fitInfo.ampFT0C));
valuesToFill.push_back(static_cast<double>(fitInfo.ampFV0A));
valuesToFill.push_back(static_cast<double>(fitInfo.ampFDDA));
valuesToFill.push_back(static_cast<double>(fitInfo.ampFDDC));
valuesToFill.push_back(static_cast<double>(zdcEnergyZNA));
valuesToFill.push_back(static_cast<double>(zdcEnergyZNC));

if constexpr (FillMl) {
registry.get<THnSparse>(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type"))->Fill(valuesToFill.data());
} else {
registry.get<THnSparse>(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<double>(gap));
valuesToFill.push_back(static_cast<double>(fitInfo.ampFT0A));
valuesToFill.push_back(static_cast<double>(fitInfo.ampFT0C));
valuesToFill.push_back(static_cast<double>(fitInfo.ampFV0A));
valuesToFill.push_back(static_cast<double>(fitInfo.ampFDDA));
valuesToFill.push_back(static_cast<double>(fitInfo.ampFDDC));
valuesToFill.push_back(static_cast<double>(zdcEnergyZNA));
valuesToFill.push_back(static_cast<double>(zdcEnergyZNC));

if constexpr (FillMl) {
registry.get<THnSparse>(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type"))->Fill(valuesToFill.data());
} else {
registry.get<THnSparse>(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);
}
}
}
Expand Down
130 changes: 62 additions & 68 deletions PWGHF/D2H/Tasks/taskDplus.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -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<AxisSpec> axes = {thnAxisMass, thnAxisPt};

if (doprocessDataWithMl || doprocessDataWithMlWithUpc) {
Expand Down Expand Up @@ -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<double> valuesToFill;
valuesToFill.reserve(nAxesTotal);

// Fill values in order matching histogram axes
valuesToFill.push_back(HfHelper::invMassDplusToPiKPi(candidate));
valuesToFill.push_back(static_cast<double>(candidate.pt()));
if constexpr (FillMl) {
std::vector<float> 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<double> valuesToFill;
valuesToFill.reserve(nAxesTotal);

// Fill values in order matching histogram axes
valuesToFill.push_back(HfHelper::invMassDplusToPiKPi(candidate));
valuesToFill.push_back(static_cast<double>(candidate.pt()));
if constexpr (FillMl) {
std::vector<float> 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<double>(gap));
valuesToFill.push_back(static_cast<double>(fitInfo.ampFT0A));
valuesToFill.push_back(static_cast<double>(fitInfo.ampFT0C));
valuesToFill.push_back(static_cast<double>(fitInfo.ampFV0A));
valuesToFill.push_back(static_cast<double>(fitInfo.ampFDDA));
valuesToFill.push_back(static_cast<double>(fitInfo.ampFDDC));
valuesToFill.push_back(static_cast<double>(zdcEnergyZNA));
valuesToFill.push_back(static_cast<double>(zdcEnergyZNC));
registry.get<THnSparse>(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<double>(gap));
valuesToFill.push_back(static_cast<double>(fitInfo.ampFT0A));
valuesToFill.push_back(static_cast<double>(fitInfo.ampFT0C));
valuesToFill.push_back(static_cast<double>(fitInfo.ampFV0A));
valuesToFill.push_back(static_cast<double>(fitInfo.ampFDDA));
valuesToFill.push_back(static_cast<double>(fitInfo.ampFDDC));
valuesToFill.push_back(static_cast<double>(zdcEnergyZNA));
valuesToFill.push_back(static_cast<double>(zdcEnergyZNC));
registry.get<THnSparse>(HSparseMass)->Fill(valuesToFill.data());
};

for (const auto& candidate : groupedDplusCandidates) {
if ((yCandRecoMax >= 0. && std::abs(HfHelper::yDplus(candidate)) > yCandRecoMax)) {
continue;
}
fillHisto(candidate);
fillTHnData(candidate);
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions PWGHF/Utils/utilsUpcHf.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading