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
171 changes: 93 additions & 78 deletions PWGHF/HFC/TableProducer/producerCharmHadronsCharmFemtoDream.cxx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// Copyright 2019-2025 CERN and copyright holders of ALICE O2.
// See https://alice-o2.web.cern.ch/copyright for details of the copyright
// holders. All rights not expressly granted are reserved.
//
// This software is distributed under the terms of the GNU General Public
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

Check failure on line 10 in PWGHF/HFC/TableProducer/producerCharmHadronsCharmFemtoDream.cxx

View workflow job for this annotation

GitHub Actions / PR formatting / copyright headers

Missing or malformed copyright notice

This source file is missing the correct copyright notice.

/// \file producerCharmHadronsCharmFemtoDream.cxx
/// \brief Produce reduced D-meson candidate tables for charm-charm femtoscopy
Expand All @@ -26,6 +26,7 @@
#include "Common/DataModel/Centrality.h"
#include "Common/DataModel/EventSelection.h"
#include "Common/DataModel/Multiplicity.h"
#include "Tools/ML/MlResponse.h"

#include <CCDB/BasicCCDBManager.h>
#include <CCDB/CcdbApi.h>
Expand All @@ -43,7 +44,6 @@
#include <Framework/InitContext.h>
#include <Framework/OutputObjHeader.h>
#include <Framework/runDataProcessing.h>
#include <Tools/ML/MlResponse.h>

#include <algorithm>
#include <array>
Expand All @@ -67,40 +67,40 @@
Configurable<std::string> ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch",
"CCDB URL"};
Configurable<std::string> ccdbPathGrpMag{
"ccdbPathGrpMag", "GLO/Config/GRPMagField", "Run 3 magnetic field"};
"ccdbPathGrpMag", "GLO/Config/GRPMagField", "Run 3 magnetic field"};

// Each species needs its own model, feature order and pT-dependent cuts.
struct MlConfig : ConfigurableGroup {
std::string prefix;
static inline const std::array<double, 3> DefaultCuts{1., 0., 0.};
Configurable<int> applyMlMode{
"applyMlMode", FillMlFromSelector,
"0: no ML, 1: selector scores, 2: new BDT after selector"};
"applyMlMode", FillMlFromSelector,
"0: no ML, 1: selector scores, 2: new BDT after selector"};
Configurable<std::vector<double>> binsPtMl{
"binsPtMl", std::vector<double>{0., 36.}, "pT bin limits for new BDT"};
"binsPtMl", std::vector<double>{0., 36.}, "pT bin limits for new BDT"};
Configurable<LabeledArray<double>> cutsMl{
"cutsMl",
{DefaultCuts.data(), 1, 3},
"New BDT cuts per pT bin: background, prompt, nonprompt"};
"cutsMl",
{DefaultCuts.data(), 1, 3},
"New BDT cuts per pT bin: background, prompt, nonprompt"};
Configurable<std::vector<int>> cutDirMl{
"cutDirMl", std::vector<int>{0, 1, 1},
"Reject scores above (0), below (1), or do not cut (2)"};
"cutDirMl", std::vector<int>{0, 1, 1},
"Reject scores above (0), below (1), or do not cut (2)"};
Configurable<int> nClassesMl{
"nClassesMl", 3, "Three output classes: background, prompt, nonprompt"};
"nClassesMl", 3, "Three output classes: background, prompt, nonprompt"};
Configurable<std::vector<std::string>> namesInputFeatures{
"namesInputFeatures", std::vector<std::string>{},
"Ordered input feature names for new BDT"};
"namesInputFeatures", std::vector<std::string>{},
"Ordered input feature names for new BDT"};
Configurable<std::vector<std::string>> onnxFileNames{
"onnxFileNames", std::vector<std::string>{},
"Model files, one per pT bin"};
"onnxFileNames", std::vector<std::string>{},
"Model files, one per pT bin"};
Configurable<std::vector<std::string>> modelPathsCCDB{
"modelPathsCCDB", std::vector<std::string>{},
"CCDB model paths, one per pT bin"};
"modelPathsCCDB", std::vector<std::string>{},
"CCDB model paths, one per pT bin"};
Configurable<int64_t> timestampCCDB{"timestampCCDB", -1,
"Timestamp used to retrieve models"};
Configurable<bool> loadModelsFromCCDB{
"loadModelsFromCCDB", false,
"Load new BDT from CCDB instead of local files"};
"loadModelsFromCCDB", false,
"Load new BDT from CCDB instead of local files"};
} mlD0{.prefix = "mlD0"}, mlDstar{.prefix = "mlDstar"};
Produces<aod::FDCollisions> collisions;
Produces<aod::FDColMasks> rowMasks;
Expand All @@ -122,20 +122,21 @@
using CollisionsWithFT0C = soa::Join<Collisions, aod::CentFT0Cs>;
using D0s = soa::Join<aod::HfCand2Prong, aod::HfSelD0>;
using Dstars =
soa::Join<aod::HfCandDstars, aod::HfD0FromDstar, aod::HfSelDstarToD0Pi>;
soa::Join<aod::HfCandDstars, aod::HfD0FromDstar, aod::HfSelDstarToD0Pi>;

using D0sMl = soa::Join<aod::HfCand2ProngWPid, aod::HfSelD0, aod::HfMlD0>;
using DstarsMl = soa::Join<aod::HfCandDstarsWPid, aod::HfD0FromDstar,
aod::HfSelDstarToD0Pi, aod::HfMlDstarToD0Pi>;

Filter filterSelectCandidateD0 =
(aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 ||
aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0);
(aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 ||
aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0);
Filter filterSelectCandidateDstar =
aod::hf_sel_candidate_dstar::isSelDstarToD0Pi == true;
aod::hf_sel_candidate_dstar::isSelDstarToD0Pi == true;

template <typename Response>
void initMl(MlConfig const &cfg, Response &response, bool withMl) {
void initMl(MlConfig const& cfg, Response& response, bool withMl)
{
if (cfg.applyMlMode.value < NoMl ||
cfg.applyMlMode.value > FillMlFromNewBDT) {
LOGP(fatal, "{}: invalid applyMlMode", cfg.prefix);
Expand All @@ -146,7 +147,7 @@
if (!withMl) {
LOGP(fatal, "{}: new BDT requires an Ml producer process", cfg.prefix);
}
auto const &edges = cfg.binsPtMl.value;
auto const& edges = cfg.binsPtMl.value;
if (edges.size() < 2 ||
!std::all_of(edges.begin(), edges.end(),
[](double x) { return std::isfinite(x); }) ||
Expand Down Expand Up @@ -195,16 +196,17 @@
response.init();
}

void init(InitContext const &) {
void init(InitContext const&)
{
const std::array<bool, 8> processSwitches{
static_cast<bool>(doprocessD0D0),
static_cast<bool>(doprocessD0Dstar),
static_cast<bool>(doprocessD0D0Ml),
static_cast<bool>(doprocessD0DstarMl),
static_cast<bool>(doprocessD0D0WithFT0C),
static_cast<bool>(doprocessD0DstarWithFT0C),
static_cast<bool>(doprocessD0D0MlWithFT0C),
static_cast<bool>(doprocessD0DstarMlWithFT0C)};
static_cast<bool>(doprocessD0D0),
static_cast<bool>(doprocessD0Dstar),
static_cast<bool>(doprocessD0D0Ml),
static_cast<bool>(doprocessD0DstarMl),
static_cast<bool>(doprocessD0D0WithFT0C),
static_cast<bool>(doprocessD0DstarWithFT0C),
static_cast<bool>(doprocessD0D0MlWithFT0C),
static_cast<bool>(doprocessD0DstarMlWithFT0C)};
if (std::count(processSwitches.begin(), processSwitches.end(), true) != 1) {
LOGP(fatal, "Enable exactly one charm-charm producer process");
}
Expand All @@ -230,11 +232,12 @@

template <o2::hf_centrality::CentralityEstimator CentEstimator,
typename Collision>
bool acceptCollision(Collision const &col) {
bool acceptCollision(Collision const& col)
{
registry.fill(HIST("events"), 0);
float cent = -1.f; // No centrality for pp MB.
const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask<
true, CentEstimator, aod::BCsWithTimestamps>(col, cent, ccdb, registry);
true, CentEstimator, aod::BCsWithTimestamps>(col, cent, ccdb, registry);
hfEvSel.fillHistograms(col, rejectionMask, cent);
if (rejectionMask != 0) {
return false;
Expand All @@ -245,7 +248,7 @@
initCCDB(bc, runNumber, ccdb, ccdbPathGrpMag.value, nullptr, false);
// Propagator field is in kG; FemtoDream uses Tesla.
const float fieldTesla =
0.1f * o2::base::Propagator::Instance()->getNominalBz();
0.1f * o2::base::Propagator::Instance()->getNominalBz();
// MultV0M is the common reduced percentile column: FT0C or -1 (no
// estimator).
collisions(col.posZ(), cent, col.multNTracksPV(), 2.f, fieldTesla);
Expand All @@ -255,7 +258,8 @@
}

template <typename Scores>
std::array<float, 3> readScores(Scores const &scores) {
std::array<float, 3> readScores(Scores const& scores)
{
if (scores.size() != 3) {
LOGP(fatal,
"Expected three selector ML scores: background, prompt, nonprompt");
Expand All @@ -270,10 +274,11 @@
}

template <bool WithMl, typename Collision, typename Candidates>
void fillD0(Collision const &col, Candidates const &candidates) {
void fillD0(Collision const& col, Candidates const& candidates)
{
const auto timestamp =
col.template bc_as<aod::BCsWithTimestamps>().timestamp();
for (auto const &cand : candidates) {
col.template bc_as<aod::BCsWithTimestamps>().timestamp();
for (auto const& cand : candidates) {
auto p0 = cand.template prong0_as<aod::Tracks>();
auto p1 = cand.template prong1_as<aod::Tracks>();
// The OR filter accepts the row if either hypothesis passes. Write only
Expand All @@ -299,7 +304,7 @@
const int pdgCode = hypothesis == 0 ? o2::constants::physics::kD0
: -o2::constants::physics::kD0;
auto features =
hfMlResponseD0.getInputFeatures<true>(cand, pdgCode);
hfMlResponseD0.getInputFeatures<true>(cand, pdgCode);
std::vector<float> output;
if (!hfMlResponseD0.isSelectedMl(features, cand.pt(), output)) {
continue; // Reject this hypothesis only.
Expand All @@ -318,10 +323,11 @@
}

template <bool WithMl, typename Collision, typename Candidates>
void fillDstar(Collision const &col, Candidates const &candidates) {
void fillDstar(Collision const& col, Candidates const& candidates)
{
const auto timestamp =
col.template bc_as<aod::BCsWithTimestamps>().timestamp();
for (auto const &cand : candidates) {
col.template bc_as<aod::BCsWithTimestamps>().timestamp();
for (auto const& cand : candidates) {
auto p0 = cand.template prong0_as<aod::Tracks>();
auto p1 = cand.template prong1_as<aod::Tracks>();
auto soft = cand.template prongPi_as<aod::Tracks>();
Expand Down Expand Up @@ -354,9 +360,10 @@
}
}

void processD0D0(Collisions::iterator const &col,
aod::BCsWithTimestamps const &, aod::Tracks const &,
soa::Filtered<D0s> const &d0s) {
void processD0D0(Collisions::iterator const& col,
aod::BCsWithTimestamps const&, aod::Tracks const&,
soa::Filtered<D0s> const& d0s)
{
if (acceptCollision<o2::hf_centrality::CentralityEstimator::None>(col)) {
fillD0<false>(col, d0s);
rowMasks(hasD0 ? 1 : 0, hasDstar ? 1 : 0, 0);
Expand All @@ -365,10 +372,11 @@
PROCESS_SWITCH(HfProducerCharmHadronsCharmFemtoDream, processD0D0,
"D0 only, data", true);

void processD0Dstar(Collisions::iterator const &col,
aod::BCsWithTimestamps const &, aod::Tracks const &,
soa::Filtered<D0s> const &d0s,
soa::Filtered<Dstars> const &dstars) {
void processD0Dstar(Collisions::iterator const& col,
aod::BCsWithTimestamps const&, aod::Tracks const&,
soa::Filtered<D0s> const& d0s,
soa::Filtered<Dstars> const& dstars)
{
if (acceptCollision<o2::hf_centrality::CentralityEstimator::None>(col)) {
fillD0<false>(col, d0s);
fillDstar<false>(col, dstars);
Expand All @@ -378,9 +386,10 @@
PROCESS_SWITCH(HfProducerCharmHadronsCharmFemtoDream, processD0Dstar,
"D0 and Dstar, data", false);

void processD0D0Ml(Collisions::iterator const &col,
aod::BCsWithTimestamps const &, aod::Tracks const &,
soa::Filtered<D0sMl> const &d0s) {
void processD0D0Ml(Collisions::iterator const& col,
aod::BCsWithTimestamps const&, aod::Tracks const&,
soa::Filtered<D0sMl> const& d0s)
{
if (acceptCollision<o2::hf_centrality::CentralityEstimator::None>(col)) {
fillD0<true>(col, d0s);
rowMasks(hasD0 ? 1 : 0, hasDstar ? 1 : 0, 0);
Expand All @@ -389,10 +398,11 @@
PROCESS_SWITCH(HfProducerCharmHadronsCharmFemtoDream, processD0D0Ml,
"D0 with selector ML scores", false);

void processD0DstarMl(Collisions::iterator const &col,
aod::BCsWithTimestamps const &, aod::Tracks const &,
soa::Filtered<D0sMl> const &d0s,
soa::Filtered<DstarsMl> const &dstars) {
void processD0DstarMl(Collisions::iterator const& col,
aod::BCsWithTimestamps const&, aod::Tracks const&,
soa::Filtered<D0sMl> const& d0s,
soa::Filtered<DstarsMl> const& dstars)
{
if (acceptCollision<o2::hf_centrality::CentralityEstimator::None>(col)) {
fillD0<true>(col, d0s);
fillDstar<true>(col, dstars);
Expand All @@ -402,9 +412,10 @@
PROCESS_SWITCH(HfProducerCharmHadronsCharmFemtoDream, processD0DstarMl,
"D0 and Dstar with selector ML scores", false);

void processD0D0WithFT0C(CollisionsWithFT0C::iterator const &col,
aod::BCsWithTimestamps const &, aod::Tracks const &,
soa::Filtered<D0s> const &d0s) {
void processD0D0WithFT0C(CollisionsWithFT0C::iterator const& col,
aod::BCsWithTimestamps const&, aod::Tracks const&,
soa::Filtered<D0s> const& d0s)
{
if (acceptCollision<o2::hf_centrality::CentralityEstimator::FT0C>(col)) {
fillD0<false>(col, d0s);
rowMasks(hasD0 ? 1 : 0, hasDstar ? 1 : 0, 0);
Expand All @@ -413,11 +424,12 @@
PROCESS_SWITCH(HfProducerCharmHadronsCharmFemtoDream, processD0D0WithFT0C,
"D0 only, data with FT0C centrality", false);

void processD0DstarWithFT0C(CollisionsWithFT0C::iterator const &col,
aod::BCsWithTimestamps const &,
aod::Tracks const &,
soa::Filtered<D0s> const &d0s,
soa::Filtered<Dstars> const &dstars) {
void processD0DstarWithFT0C(CollisionsWithFT0C::iterator const& col,
aod::BCsWithTimestamps const&,
aod::Tracks const&,
soa::Filtered<D0s> const& d0s,
soa::Filtered<Dstars> const& dstars)
{
if (acceptCollision<o2::hf_centrality::CentralityEstimator::FT0C>(col)) {
fillD0<false>(col, d0s);
fillDstar<false>(col, dstars);
Expand All @@ -427,10 +439,11 @@
PROCESS_SWITCH(HfProducerCharmHadronsCharmFemtoDream, processD0DstarWithFT0C,
"D0 and Dstar, data with FT0C centrality", false);

void processD0D0MlWithFT0C(CollisionsWithFT0C::iterator const &col,
aod::BCsWithTimestamps const &,
aod::Tracks const &,
soa::Filtered<D0sMl> const &d0s) {
void processD0D0MlWithFT0C(CollisionsWithFT0C::iterator const& col,
aod::BCsWithTimestamps const&,
aod::Tracks const&,
soa::Filtered<D0sMl> const& d0s)
{
if (acceptCollision<o2::hf_centrality::CentralityEstimator::FT0C>(col)) {
fillD0<true>(col, d0s);
rowMasks(hasD0 ? 1 : 0, hasDstar ? 1 : 0, 0);
Expand All @@ -439,11 +452,12 @@
PROCESS_SWITCH(HfProducerCharmHadronsCharmFemtoDream, processD0D0MlWithFT0C,
"D0 with selector ML scores and FT0C centrality", false);

void processD0DstarMlWithFT0C(CollisionsWithFT0C::iterator const &col,
aod::BCsWithTimestamps const &,
aod::Tracks const &,
soa::Filtered<D0sMl> const &d0s,
soa::Filtered<DstarsMl> const &dstars) {
void processD0DstarMlWithFT0C(CollisionsWithFT0C::iterator const& col,
aod::BCsWithTimestamps const&,
aod::Tracks const&,
soa::Filtered<D0sMl> const& d0s,
soa::Filtered<DstarsMl> const& dstars)
{
if (acceptCollision<o2::hf_centrality::CentralityEstimator::FT0C>(col)) {
fillD0<true>(col, d0s);
fillDstar<true>(col, dstars);
Expand All @@ -456,7 +470,8 @@
false);
};

WorkflowSpec defineDataProcessing(ConfigContext const &cfgc) {
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)
{
return WorkflowSpec{
adaptAnalysisTask<HfProducerCharmHadronsCharmFemtoDream>(cfgc)};
adaptAnalysisTask<HfProducerCharmHadronsCharmFemtoDream>(cfgc)};
}
Loading
Loading