File indexing completed on 2025-05-11 08:57:27
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019 #ifndef FWCORE_TRANSFORMER_H
0020 #define FWCORE_TRANSFORMER_H
0021
0022 #include <GaudiKernel/FunctionalFilterDecision.h>
0023 #include "Gaudi/Functional/details.h"
0024 #include "Gaudi/Functional/utilities.h"
0025
0026 #include "k4FWCore/FunctionalUtils.h"
0027
0028
0029
0030 #include <ranges>
0031 #include <stdexcept>
0032 #include <type_traits>
0033 #include <utility>
0034
0035 namespace k4FWCore {
0036
0037 namespace details {
0038
0039 template <typename Signature, typename Traits_> struct Transformer;
0040
0041 template <typename Out, typename... In, typename Traits_>
0042 struct Transformer<Out(const In&...), Traits_>
0043 : Gaudi::Functional::details::DataHandleMixin<std::tuple<>, std::tuple<>, Traits_> {
0044 using Gaudi::Functional::details::DataHandleMixin<std::tuple<>, std::tuple<>, Traits_>::DataHandleMixin;
0045
0046 static_assert(((std::is_base_of_v<podio::CollectionBase, In> || isVectorLike_v<In>)&&...),
0047 "Transformer and Producer input types must be EDM4hep collections or vectors of collections");
0048 static_assert((std::is_base_of_v<podio::CollectionBase, Out> || isVectorLike_v<Out> ||
0049 std::is_same_v<podio::CollectionBase*, Out>),
0050 "Transformer and Producer output types must be EDM4hep collections or vectors of collections");
0051
0052 template <typename T>
0053 using InputHandle_t = Gaudi::Functional::details::InputHandle_t<Traits_, std::remove_pointer_t<T>>;
0054 template <typename T>
0055 using OutputHandle_t = Gaudi::Functional::details::OutputHandle_t<Traits_, std::remove_pointer_t<T>>;
0056
0057 std::tuple<std::vector<InputHandle_t<typename EventStoreType<In>::type>>...> m_inputs;
0058 std::tuple<std::vector<OutputHandle_t<typename EventStoreType<Out>::type>>> m_outputs;
0059 std::array<Gaudi::Property<std::vector<DataObjID>>, sizeof...(In)> m_inputLocations{};
0060 Gaudi::Property<std::vector<DataObjID>> m_outputLocations{};
0061
0062 using base_class = Gaudi::Functional::details::DataHandleMixin<std::tuple<>, std::tuple<>, Traits_>;
0063
0064 using KeyValues = typename base_class::KeyValues;
0065
0066 template <typename IArgs, typename OArgs, std::size_t... I, std::size_t... J>
0067 Transformer(std::string name, ISvcLocator* locator, const IArgs& inputs, std::index_sequence<I...>,
0068 const OArgs& outputs, std::index_sequence<J...>)
0069 : base_class(std::move(name), locator),
0070
0071
0072
0073
0074
0075 m_inputLocations{Gaudi::Property<std::vector<DataObjID>>{
0076 this, std::get<I>(inputs).first, to_DataObjID(std::get<I>(inputs).second),
0077 [this](Gaudi::Details::PropertyBase&) {
0078 std::vector<InputHandle_t<typename EventStoreType<In>::type>> h;
0079 for (auto& value : this->m_inputLocations[I].value()) {
0080 auto handle = InputHandle_t<typename EventStoreType<In>::type>(value, this);
0081 h.push_back(std::move(handle));
0082 }
0083 std::get<I>(m_inputs) = std::move(h);
0084 },
0085 Gaudi::Details::Property::ImmediatelyInvokeHandler{true}}...},
0086
0087 m_outputLocations{Gaudi::Property<std::vector<DataObjID>>{
0088 this, std::get<J>(outputs).first, to_DataObjID(std::get<J>(outputs).second),
0089 [this](Gaudi::Details::PropertyBase&) {
0090 std::vector<OutputHandle_t<typename EventStoreType<Out>::type>> h;
0091 for (auto& inpID : this->m_outputLocations.value()) {
0092 if (inpID.key().empty()) {
0093 continue;
0094 }
0095 auto handle = OutputHandle_t<typename EventStoreType<Out>::type>(inpID, this);
0096 h.push_back(std::move(handle));
0097 }
0098 std::get<0>(m_outputs) = std::move(h);
0099 },
0100 Gaudi::Details::Property::ImmediatelyInvokeHandler{true}}...} {}
0101
0102 constexpr static std::size_t N_in = sizeof...(In);
0103 constexpr static std::size_t N_out = 1;
0104
0105 Transformer(std::string name, ISvcLocator* locator,
0106 Gaudi::Functional::details::RepeatValues_<KeyValues, N_in> const& inputs,
0107 Gaudi::Functional::details::RepeatValues_<KeyValues, N_out> const& outputs)
0108 : Transformer(std::move(name), locator, inputs, std::index_sequence_for<In...>{}, outputs,
0109 std::index_sequence_for<Out>{}) {}
0110
0111
0112 StatusCode execute(const EventContext& ctx) const final {
0113 try {
0114 if constexpr (isVectorLike<Out>::value) {
0115 std::tuple<Out> tmp = filter_evtcontext_tt<In...>::apply(*this, ctx, this->m_inputs);
0116 putVectorOutputs<0, Out>(std::move(tmp), m_outputs, this);
0117 } else {
0118 Gaudi::Functional::details::put(
0119 std::get<0>(this->m_outputs)[0],
0120 convertToUniquePtr(std::move(filter_evtcontext_tt<In...>::apply(*this, ctx, this->m_inputs))));
0121 }
0122 return Gaudi::Functional::FilterDecision::PASSED;
0123 } catch (GaudiException& e) {
0124 (e.code() ? this->warning() : this->error()) << e.tag() << " : " << e.message() << endmsg;
0125 return e.code();
0126 }
0127 }
0128
0129
0130
0131
0132
0133
0134 auto inputLocations(size_t i) const {
0135 if (i >= sizeof...(In)) {
0136 throw std::out_of_range("Called inputLocations with an index out of range, index: " + std::to_string(i) +
0137 ", number of inputs: " + std::to_string(sizeof...(In)));
0138 }
0139 return m_inputLocations[i] | std::views::transform([](const DataObjID& id) -> const auto& { return id.key(); });
0140 }
0141
0142
0143
0144
0145
0146 auto inputLocations(std::string_view name) const {
0147 auto it = std::ranges::find_if(m_inputLocations, [&name](const auto& prop) { return prop.name() == name; });
0148 if (it == m_inputLocations.end()) {
0149 throw std::runtime_error("Called inputLocations with an unknown name");
0150 }
0151 return it->value() | std::views::transform([](const DataObjID& id) -> const auto& { return id.key(); });
0152 }
0153
0154
0155
0156
0157
0158 auto outputLocations() const {
0159 return m_outputLocations | std::views::transform([](const DataObjID& id) -> const auto& { return id.key(); });
0160 }
0161
0162
0163
0164
0165
0166 auto outputLocations(std::string_view name) const {
0167 if (name != m_outputLocations.name()) {
0168 throw std::runtime_error("Called outputLocations with an unknown name");
0169 }
0170 return m_outputLocations | std::views::transform([](const DataObjID& id) -> const auto& { return id.key(); });
0171 }
0172 static constexpr std::size_t inputLocationsSize() { return sizeof...(In); }
0173
0174
0175 virtual Out operator()(const In&...) const = 0;
0176 };
0177
0178 template <typename Signature, typename Traits_> struct MultiTransformer;
0179
0180 template <typename... Out, typename... In, typename Traits_>
0181 struct MultiTransformer<std::tuple<Out...>(const In&...), Traits_>
0182 : Gaudi::Functional::details::DataHandleMixin<std::tuple<>, std::tuple<>, Traits_> {
0183 using Gaudi::Functional::details::DataHandleMixin<std::tuple<>, std::tuple<>, Traits_>::DataHandleMixin;
0184
0185 static_assert(((std::is_base_of_v<podio::CollectionBase, In> || isVectorLike<In>::value) && ...),
0186 "Transformer and Producer input types must be EDM4hep collections or vectors of collections");
0187 static_assert(((std::is_base_of_v<podio::CollectionBase, Out> || isVectorLike<Out>::value) && ...),
0188 "Transformer and Producer output types must be EDM4hep collections or vectors of collections");
0189
0190 template <typename T>
0191 using InputHandle_t = Gaudi::Functional::details::InputHandle_t<Traits_, std::remove_pointer_t<T>>;
0192 template <typename T>
0193 using OutputHandle_t = Gaudi::Functional::details::OutputHandle_t<Traits_, std::remove_pointer_t<T>>;
0194
0195 std::tuple<std::vector<InputHandle_t<typename EventStoreType<In>::type>>...> m_inputs;
0196 std::tuple<std::vector<OutputHandle_t<typename EventStoreType<Out>::type>>...> m_outputs;
0197 std::array<Gaudi::Property<std::vector<DataObjID>>, sizeof...(In)> m_inputLocations{};
0198 std::array<Gaudi::Property<std::vector<DataObjID>>, sizeof...(Out)> m_outputLocations{};
0199
0200 using base_class = Gaudi::Functional::details::DataHandleMixin<std::tuple<>, std::tuple<>, Traits_>;
0201
0202 using KeyValues = typename base_class::KeyValues;
0203
0204 template <typename IArgs, typename OArgs, std::size_t... I, std::size_t... J>
0205 MultiTransformer(std::string name, ISvcLocator* locator, const IArgs& inputs, std::index_sequence<I...>,
0206 const OArgs& outputs, std::index_sequence<J...>)
0207 : base_class(std::move(name), locator),
0208 m_inputLocations{Gaudi::Property<std::vector<DataObjID>>{
0209 this, std::get<I>(inputs).first, to_DataObjID(std::get<I>(inputs).second),
0210 [this](Gaudi::Details::PropertyBase&) {
0211 std::vector<InputHandle_t<typename EventStoreType<In>::type>> h;
0212 for (auto& value : this->m_inputLocations[I].value()) {
0213 auto handle = InputHandle_t<typename EventStoreType<In>::type>(value, this);
0214 h.push_back(std::move(handle));
0215 }
0216 std::get<I>(m_inputs) = std::move(h);
0217 },
0218 Gaudi::Details::Property::ImmediatelyInvokeHandler{true}}...},
0219 m_outputLocations{Gaudi::Property<std::vector<DataObjID>>{
0220 this, std::get<J>(outputs).first, to_DataObjID(std::get<J>(outputs).second),
0221 [this](Gaudi::Details::PropertyBase&) {
0222 std::vector<OutputHandle_t<typename EventStoreType<Out>::type>> h;
0223
0224
0225
0226 for (auto& inpID : this->m_outputLocations[J].value()) {
0227 if (inpID.key().empty()) {
0228 continue;
0229 }
0230 auto handle = OutputHandle_t<typename EventStoreType<Out>::type>(inpID, this);
0231 h.push_back(std::move(handle));
0232 }
0233 std::get<J>(m_outputs) = std::move(h);
0234 },
0235 Gaudi::Details::Property::ImmediatelyInvokeHandler{true}}...} {}
0236
0237 constexpr static std::size_t N_in = sizeof...(In);
0238 constexpr static std::size_t N_out = sizeof...(Out);
0239
0240 MultiTransformer(std::string name, ISvcLocator* locator,
0241 Gaudi::Functional::details::RepeatValues_<KeyValues, N_in> const& inputs,
0242 Gaudi::Functional::details::RepeatValues_<KeyValues, N_out> const& outputs)
0243 : MultiTransformer(std::move(name), locator, inputs, std::index_sequence_for<In...>{}, outputs,
0244 std::index_sequence_for<Out...>{}) {}
0245
0246
0247 StatusCode execute(const EventContext& ctx) const final {
0248 try {
0249 auto tmp = filter_evtcontext_tt<In...>::apply(*this, ctx, this->m_inputs);
0250 putVectorOutputs<0, Out...>(std::move(tmp), m_outputs, this);
0251 return Gaudi::Functional::FilterDecision::PASSED;
0252 } catch (GaudiException& e) {
0253 (e.code() ? this->warning() : this->error()) << e.tag() << " : " << e.message() << endmsg;
0254 return e.code();
0255 }
0256 }
0257
0258
0259
0260
0261
0262
0263 auto inputLocations(size_t i) const {
0264 if (i >= sizeof...(In)) {
0265 throw std::out_of_range("Called inputLocations with an index out of range, index: " + std::to_string(i) +
0266 ", number of inputs: " + std::to_string(sizeof...(In)));
0267 }
0268 return m_inputLocations[i] | std::views::transform([](const DataObjID& id) -> const auto& { return id.key(); });
0269 }
0270
0271
0272
0273
0274
0275 auto inputLocations(std::string_view name) const {
0276 auto it = std::ranges::find_if(m_inputLocations, [&name](const auto& prop) { return prop.name() == name; });
0277 if (it == m_inputLocations.end()) {
0278 throw std::runtime_error("Called inputLocations with an unknown name");
0279 }
0280 return it->value() | std::views::transform([](const DataObjID& id) -> const auto& { return id.key(); });
0281 }
0282
0283
0284
0285
0286
0287
0288 auto outputLocations(size_t i) const {
0289 if (i >= sizeof...(Out)) {
0290 throw std::out_of_range("Called outputLocations with an index out of range");
0291 }
0292 return m_outputLocations[i] |
0293 std::views::transform([](const DataObjID& id) -> const auto& { return id.key(); });
0294 }
0295
0296
0297
0298
0299
0300 auto outputLocations(std::string_view name) const {
0301 auto it = std::ranges::find_if(m_outputLocations.begin(), m_outputLocations.end(),
0302 [&name](const auto& prop) { return prop.name() == name; });
0303 if (it == m_outputLocations.end()) {
0304 throw std::runtime_error("Called outputLocations with an unknown name");
0305 }
0306 return it->value() | std::views::transform([](const DataObjID& id) -> const auto& { return id.key(); });
0307 }
0308 static constexpr std::size_t inputLocationsSize() { return sizeof...(In); }
0309 static constexpr std::size_t outputLocationsSize() { return sizeof...(Out); }
0310
0311
0312 virtual std::tuple<Out...> operator()(const In&...) const = 0;
0313 };
0314
0315 }
0316
0317 template <typename Signature, typename Traits_ = Gaudi::Functional::Traits::useDefaults>
0318 using MultiTransformer = details::MultiTransformer<Signature, Traits_>;
0319
0320 template <typename Signature, typename Traits_ = Gaudi::Functional::Traits::useDefaults>
0321 using Transformer = details::Transformer<Signature, Traits_>;
0322
0323 }
0324
0325 #endif