From 38e15e3dd86ccbb3c15df2a8031ab8c290473454 Mon Sep 17 00:00:00 2001 From: Anton Alkin Date: Wed, 28 May 2025 12:58:25 +0200 Subject: [PATCH 1/3] DPL Analysis: add `DefinesDelayed` allowing to set the expressions in a process function, e.g. after calculating some required input values --- .../Core/include/Framework/AnalysisHelpers.h | 16 ++++++++- .../Core/include/Framework/AnalysisManagers.h | 36 +++++++++++++++++++ .../Core/include/Framework/AnalysisTask.h | 2 ++ Framework/Core/test/test_Concepts.cxx | 12 +++++++ 4 files changed, 65 insertions(+), 1 deletion(-) diff --git a/Framework/Core/include/Framework/AnalysisHelpers.h b/Framework/Core/include/Framework/AnalysisHelpers.h index 95be6c7e407b3..6e9b1e211bb76 100644 --- a/Framework/Core/include/Framework/AnalysisHelpers.h +++ b/Framework/Core/include/Framework/AnalysisHelpers.h @@ -340,8 +340,9 @@ concept is_spawns = requires(T t) { /// The actual expressions have to be set in init() for the configurable expression /// columns, used to define the table -template +template struct Defines : decltype(transformBase()) { + static constexpr bool delayed = DELAYED; using spawnable_t = T; using metadata = decltype(transformBase())::metadata; using extension_t = typename metadata::extension_table_t; @@ -373,13 +374,26 @@ struct Defines : decltype(transformBase()) { std::array projectors; std::shared_ptr projector = nullptr; std::shared_ptr schema = std::make_shared(o2::soa::createFieldsFromColumns(placeholders_pack_t{})); + std::shared_ptr inputSchema = nullptr; + + bool needRecompilation = false; + + void recompile() + { + projector = framework::expressions::createProjectorHelper(N, projectors.data(), inputSchema, schema->fields()); + } }; +template +using DefinesDelayed = Defines; + template concept is_defines = requires(T t) { typename T::metadata; requires std::same_as; requires std::same_as>; + requires std::same_as; + &T::recompile; }; /// Policy to control index building diff --git a/Framework/Core/include/Framework/AnalysisManagers.h b/Framework/Core/include/Framework/AnalysisManagers.h index 2a052c0b07218..5149bee3d57b1 100644 --- a/Framework/Core/include/Framework/AnalysisManagers.h +++ b/Framework/Core/include/Framework/AnalysisManagers.h @@ -307,6 +307,7 @@ bool prepareOutput(ProcessingContext& context, T& builds) template bool prepareOutput(ProcessingContext& context, T& defines) + requires(T::delayed == false) { using metadata = o2::aod::MetadataTrait>::metadata; auto originalTable = soa::ArrowHelpers::joinTables(extractOriginals(context), std::span{metadata::base_table_t::originalLabels}); @@ -314,6 +315,41 @@ bool prepareOutput(ProcessingContext& context, T& defines) using base_table_t = typename T::base_table_t::table_t; originalTable = makeEmptyTable(o2::aod::label()); } + if (defines.inputSchema == nullptr) { + defines.inputSchema = originalTable->schema(); + } + using D = o2::aod::Hash; + + defines.extension = std::make_shared(o2::framework::spawner(originalTable, + o2::aod::label(), + defines.projectors.data(), + defines.projector, + defines.schema)); + defines.table = std::make_shared(soa::ArrowHelpers::joinTables({defines.extension->asArrowTable(), originalTable}, std::span{T::spawnable_t::table_t::originalLabels})); + return true; +} + +template +bool prepareDelayedOutput(ProcessingContext&, T&) +{ + return false; +} + +template +bool prepareDelayedOutput(ProcessingContext& context, T& defines) +{ + if (defines.needRecompilation) { + defines.recompile(); + } + using metadata = o2::aod::MetadataTrait>::metadata; + auto originalTable = soa::ArrowHelpers::joinTables(extractOriginals(context), std::span{metadata::base_table_t::originalLabels}); + if (originalTable->schema()->fields().empty() == true) { + using base_table_t = typename T::base_table_t::table_t; + originalTable = makeEmptyTable(o2::aod::label()); + } + if (defines.inputSchema == nullptr) { + defines.inputSchema = originalTable->schema(); + } using D = o2::aod::Hash; defines.extension = std::make_shared(o2::framework::spawner(originalTable, diff --git a/Framework/Core/include/Framework/AnalysisTask.h b/Framework/Core/include/Framework/AnalysisTask.h index b53929f326712..56f9a91c240d2 100644 --- a/Framework/Core/include/Framework/AnalysisTask.h +++ b/Framework/Core/include/Framework/AnalysisTask.h @@ -643,6 +643,8 @@ DataProcessorSpec adaptAnalysisTask(ConfigContext const& ctx, Args&&... args) return false; }, *task.get()); + // prepare delayed outputs + homogeneous_apply_refs([&pc](auto& element) { return analysis_task_parsers::prepareDelayedOutput(pc, element); }, *task.get()); // finalize outputs homogeneous_apply_refs([&pc](auto& element) { return analysis_task_parsers::finalizeOutput(pc, element); }, *task.get()); }; diff --git a/Framework/Core/test/test_Concepts.cxx b/Framework/Core/test/test_Concepts.cxx index 4bf4f977ec3a8..4a791996d75a4 100644 --- a/Framework/Core/test/test_Concepts.cxx +++ b/Framework/Core/test/test_Concepts.cxx @@ -32,6 +32,13 @@ struct P { PROCESS_SWITCH(P, process1, "", true); }; +namespace o2::aod { +namespace ct { +DECLARE_SOA_CONFIGURABLE_EXPRESSION_COLUMN(Test, test, float, "test"); +} +DECLARE_SOA_CONFIGURABLE_EXTENDED_TABLE(TracksMore, TracksIU, "TRKMORE", ct::Test); +} + TEST_CASE("IdentificationConcepts") { // ASoA @@ -122,6 +129,11 @@ TEST_CASE("IdentificationConcepts") Builds bld; REQUIRE(is_builds); + Defines def; + DefinesDelayed ddef; + REQUIRE(is_defines); + REQUIRE(is_defines); + OutputObj oo{"test"}; REQUIRE(is_outputobj); From 72a4bd38e029553f652674384961884e23264df5 Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Wed, 28 May 2025 11:01:02 +0000 Subject: [PATCH 2/3] Please consider the following formatting changes --- Framework/Core/test/test_Concepts.cxx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Framework/Core/test/test_Concepts.cxx b/Framework/Core/test/test_Concepts.cxx index 4a791996d75a4..5e2ad6d96b30f 100644 --- a/Framework/Core/test/test_Concepts.cxx +++ b/Framework/Core/test/test_Concepts.cxx @@ -32,12 +32,14 @@ struct P { PROCESS_SWITCH(P, process1, "", true); }; -namespace o2::aod { -namespace ct { +namespace o2::aod +{ +namespace ct +{ DECLARE_SOA_CONFIGURABLE_EXPRESSION_COLUMN(Test, test, float, "test"); } DECLARE_SOA_CONFIGURABLE_EXTENDED_TABLE(TracksMore, TracksIU, "TRKMORE", ct::Test); -} +} // namespace o2::aod TEST_CASE("IdentificationConcepts") { From 1606f04df5aeeb564d47d939010ac8703256a31d Mon Sep 17 00:00:00 2001 From: Anton Alkin Date: Thu, 5 Jun 2025 09:44:05 +0200 Subject: [PATCH 3/3] Update AnalysisManagers.h --- Framework/Core/include/Framework/AnalysisManagers.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Framework/Core/include/Framework/AnalysisManagers.h b/Framework/Core/include/Framework/AnalysisManagers.h index 5149bee3d57b1..7717d5cb3a6a2 100644 --- a/Framework/Core/include/Framework/AnalysisManagers.h +++ b/Framework/Core/include/Framework/AnalysisManagers.h @@ -336,6 +336,7 @@ bool prepareDelayedOutput(ProcessingContext&, T&) } template + requires(T::delayed == true) bool prepareDelayedOutput(ProcessingContext& context, T& defines) { if (defines.needRecompilation) {