1212#include " Framework/AODReaderHelpers.h"
1313#include " Framework/AnalysisHelpers.h"
1414#include " Framework/AnalysisDataModelHelpers.h"
15- #include " Framework/DataProcessingHelpers.h"
1615#include " Framework/ExpressionHelpers.h"
16+ #include " Framework/DataProcessingHelpers.h"
1717#include " Framework/AlgorithmSpec.h"
1818#include " Framework/ControlService.h"
1919#include " Framework/CallbackService.h"
2020#include " Framework/EndOfStreamContext.h"
2121#include " Framework/DataSpecUtils.h"
22+ #include " ExpressionJSONHelpers.h"
23+ #include " Framework/ConfigContext.h"
24+ #include " Framework/AnalysisContext.h"
2225
2326#include < Monitoring/Monitoring.h>
2427
@@ -44,28 +47,6 @@ auto setEOSCallback(InitContext& ic)
4447 });
4548}
4649
47- template <typename ... Ts>
48- static inline auto doExtractOriginal (framework::pack<Ts...>, ProcessingContext& pc)
49- {
50- if constexpr (sizeof ...(Ts) == 1 ) {
51- return pc.inputs ().get <TableConsumer>(aod::MetadataTrait<framework::pack_element_t <0 , framework::pack<Ts...>>>::metadata::tableLabel ())->asArrowTable ();
52- } else {
53- return std::vector{pc.inputs ().get <TableConsumer>(aod::MetadataTrait<Ts>::metadata::tableLabel ())->asArrowTable ()...};
54- }
55- }
56-
57- template <typename ... Os>
58- static inline auto extractOriginalsTuple (framework::pack<Os...>, ProcessingContext& pc)
59- {
60- return std::make_tuple (extractTypedOriginal<Os>(pc)...);
61- }
62-
63- template <typename ... Os>
64- static inline auto extractOriginalsVector (framework::pack<Os...>, ProcessingContext& pc)
65- {
66- return std::vector{extractOriginal<Os>(pc)...};
67- }
68-
6950template <size_t N, std::array<soa::TableRef, N> refs>
7051static inline auto extractOriginals (ProcessingContext& pc)
7152{
@@ -156,53 +137,137 @@ auto make_spawn(InputSpec const& input, ProcessingContext& pc)
156137 (typename metadata_t ::expression_pack_t {});
157138 return o2::framework::spawner<D>(extractOriginals<sources.size (), sources>(pc), input.binding .c_str (), projectors.data (), projector, schema);
158139}
140+
141+ struct Maker {
142+ std::string binding;
143+ std::vector<std::string> labels;
144+ std::vector<std::shared_ptr<gandiva::Expression>> expressions;
145+ std::shared_ptr<gandiva::Projector> projector = nullptr ;
146+ std::shared_ptr<arrow::Schema> schema;
147+
148+ header::DataOrigin origin;
149+ header::DataDescription description;
150+ header::DataHeader::SubSpecificationType version;
151+
152+ std::shared_ptr<arrow::Table> make (ProcessingContext& pc)
153+ {
154+ std::vector<std::shared_ptr<arrow::Table>> originals;
155+ for (auto const & label : labels) {
156+ originals.push_back (pc.inputs ().get <TableConsumer>(label)->asArrowTable ());
157+ }
158+ auto fullTable = soa::ArrowHelpers::joinTables (std::move (originals), std::span{labels.begin (), labels.size ()});
159+ if (projector == nullptr ) {
160+ auto s = gandiva::Projector::Make (
161+ fullTable->schema (),
162+ expressions,
163+ &projector);
164+ if (!s.ok ()) {
165+ throw o2::framework::runtime_error_f (" Failed to create projector: %s" , s.ToString ().c_str ());
166+ }
167+ }
168+
169+ return spawnerHelper (fullTable, schema, binding.c_str (), schema->num_fields (), projector);
170+ }
171+ };
172+
173+ struct Spawnable {
174+ std::string binding;
175+ std::vector<std::string> labels;
176+ std::vector<expressions::Projector> projectors;
177+ std::vector<std::shared_ptr<gandiva::Expression>> expressions;
178+ std::shared_ptr<arrow::Schema> outputSchema;
179+ std::shared_ptr<arrow::Schema> inputSchema;
180+
181+ header::DataOrigin origin;
182+ header::DataDescription description;
183+ header::DataHeader::SubSpecificationType version;
184+
185+ Spawnable (InputSpec const & spec)
186+ : binding{spec.binding }
187+ {
188+ auto && [origin_, description_, version_] = DataSpecUtils::asConcreteDataMatcher (spec);
189+ origin = origin_;
190+ description = description_;
191+ version = version_;
192+ auto loc = std::find_if (spec.metadata .begin (), spec.metadata .end (), [](ConfigParamSpec const & cps) { return cps.name .compare (" projectors" ) == 0 ; });
193+ std::stringstream iws (loc->defaultValue .get <std::string>());
194+ projectors = ExpressionJSONHelpers::read (iws);
195+
196+ loc = std::find_if (spec.metadata .begin (), spec.metadata .end (), [](ConfigParamSpec const & cps) { return cps.name .compare (" schema" ) == 0 ; });
197+ iws.clear ();
198+ iws.str (loc->defaultValue .get <std::string>());
199+ outputSchema = ArrowJSONHelpers::read (iws);
200+
201+ for (auto & i : spec.metadata ) {
202+ if (i.name .starts_with (" input:" )) {
203+ labels.emplace_back (i.name .substr (6 ));
204+ }
205+ }
206+
207+ std::vector<std::shared_ptr<arrow::Field>> fields;
208+ for (auto & p : projectors) {
209+ expressions::walk (p.node .get (),
210+ [&fields](expressions::Node* n) mutable {
211+ if (n->self .index () == 1 ) {
212+ auto & b = std::get<expressions::BindingNode>(n->self );
213+ if (std::find_if (fields.begin (), fields.end (), [&b](std::shared_ptr<arrow::Field> const & field) { return field->name () == b.name ; }) == fields.end ()) {
214+ fields.emplace_back (std::make_shared<arrow::Field>(b.name , expressions::concreteArrowType (b.type )));
215+ }
216+ }
217+ });
218+ }
219+ inputSchema = std::make_shared<arrow::Schema>(fields);
220+
221+ int i = 0 ;
222+ for (auto & p : projectors) {
223+ expressions.push_back (
224+ expressions::makeExpression (
225+ expressions::createExpressionTree (
226+ expressions::createOperations (p),
227+ inputSchema),
228+ outputSchema->field (i)));
229+ ++i;
230+ }
231+ }
232+
233+ std::shared_ptr<gandiva::Projector> makeProjector ()
234+ {
235+ return expressions::createProjectorHelper (projectors.size (), projectors.data (), inputSchema, outputSchema->fields ());
236+ }
237+
238+ Maker createMaker ()
239+ {
240+ return {
241+ binding,
242+ labels,
243+ expressions,
244+ nullptr ,
245+ outputSchema,
246+ origin,
247+ description,
248+ version};
249+ }
250+ };
251+
159252} // namespace
160253
161- AlgorithmSpec AODReaderHelpers::aodSpawnerCallback (std::vector<InputSpec>& requested)
254+ AlgorithmSpec AODReaderHelpers::aodSpawnerCallback (/* std::vector<InputSpec>& requested*/ ConfigContext const & ctx )
162255{
163- return AlgorithmSpec::InitCallback{[requested](InitContext& /* ic*/ ) {
164- return [requested](ProcessingContext& pc) {
256+ auto & ac = ctx.services ().get <AnalysisContext>();
257+ return AlgorithmSpec::InitCallback{[requested = ac.spawnerInputs ](InitContext& /* ic*/ ) {
258+ std::vector<Spawnable> spawnables;
259+ for (auto & i : requested) {
260+ spawnables.emplace_back (i);
261+ }
262+ std::vector<Maker> makers;
263+ for (auto & s : spawnables) {
264+ makers.push_back (s.createMaker ());
265+ }
266+
267+ return [makers](ProcessingContext& pc) mutable {
165268 auto outputs = pc.outputs ();
166- // spawn tables
167- for (auto & input : requested) {
168- auto && [origin, description, version] = DataSpecUtils::asConcreteDataMatcher (input);
169- if (description == header::DataDescription{" EXTRACK" }) {
170- outputs.adopt (Output{origin, description, version}, make_spawn<o2::aod::Hash<" EXTRACK/0" _h>>(input, pc));
171- } else if (description == header::DataDescription{" EXTRACK_IU" }) {
172- outputs.adopt (Output{origin, description, version}, make_spawn<o2::aod::Hash<" EXTRACK_IU/0" _h>>(input, pc));
173- } else if (description == header::DataDescription{" EXTRACKCOV" }) {
174- outputs.adopt (Output{origin, description, version}, make_spawn<o2::aod::Hash<" EXTRACKCOV/0" _h>>(input, pc));
175- } else if (description == header::DataDescription{" EXTRACKCOV_IU" }) {
176- outputs.adopt (Output{origin, description, version}, make_spawn<o2::aod::Hash<" EXTRACKCOV_IU/0" _h>>(input, pc));
177- } else if (description == header::DataDescription{" EXTRACKEXTRA" }) {
178- if (version == 0U ) {
179- outputs.adopt (Output{origin, description, version}, make_spawn<o2::aod::Hash<" EXTRACKEXTRA/0" _h>>(input, pc));
180- } else if (version == 1U ) {
181- outputs.adopt (Output{origin, description, version}, make_spawn<o2::aod::Hash<" EXTRACKEXTRA/1" _h>>(input, pc));
182- } else if (version == 2U ) {
183- outputs.adopt (Output{origin, description, version}, make_spawn<o2::aod::Hash<" EXTRACKEXTRA/2" _h>>(input, pc));
184- }
185- } else if (description == header::DataDescription{" EXMFTTRACK" }) {
186- if (version == 0U ) {
187- outputs.adopt (Output{origin, description, version}, make_spawn<o2::aod::Hash<" EXMFTTRACK/0" _h>>(input, pc));
188- } else if (version == 1U ) {
189- outputs.adopt (Output{origin, description, version}, make_spawn<o2::aod::Hash<" EXMFTTRACK/1" _h>>(input, pc));
190- }
191- } else if (description == header::DataDescription{" EXMFTTRACKCOV" }) {
192- outputs.adopt (Output{origin, description, version}, make_spawn<o2::aod::Hash<" EXMFTTRACKCOV/0" _h>>(input, pc));
193- } else if (description == header::DataDescription{" EXFWDTRACK" }) {
194- outputs.adopt (Output{origin, description, version}, make_spawn<o2::aod::Hash<" EXFWDTRACK/0" _h>>(input, pc));
195- } else if (description == header::DataDescription{" EXFWDTRACKCOV" }) {
196- outputs.adopt (Output{origin, description, version}, make_spawn<o2::aod::Hash<" EXFWDTRACKCOV/0" _h>>(input, pc));
197- } else if (description == header::DataDescription{" EXMCPARTICLE" }) {
198- if (version == 0U ) {
199- outputs.adopt (Output{origin, description, version}, make_spawn<o2::aod::Hash<" EXMCPARTICLE/0" _h>>(input, pc));
200- } else if (version == 1U ) {
201- outputs.adopt (Output{origin, description, version}, make_spawn<o2::aod::Hash<" EXMCPARTICLE/1" _h>>(input, pc));
202- }
203- } else {
204- throw runtime_error (" Not an extended table" );
205- }
269+ for (auto & maker : makers) {
270+ outputs.adopt (Output{maker.origin , maker.description , maker.version }, maker.make (pc));
206271 }
207272 };
208273 }};
0 commit comments