Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-06-04 08:41:08

0001 /*
0002  * Copyright (c) 2014-2024 Key4hep-Project.
0003  *
0004  * This file is part of Key4hep.
0005  * See https://key4hep.github.io/key4hep-doc/ for further info.
0006  *
0007  * Licensed under the Apache License, Version 2.0 (the "License");
0008  * you may not use this file except in compliance with the License.
0009  * You may obtain a copy of the License at
0010  *
0011  *     http://www.apache.org/licenses/LICENSE-2.0
0012  *
0013  * Unless required by applicable law or agreed to in writing, software
0014  * distributed under the License is distributed on an "AS IS" BASIS,
0015  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0016  * See the License for the specific language governing permissions and
0017  * limitations under the License.
0018  */
0019 #ifndef FWCORE_CONSUMER_H
0020 #define FWCORE_CONSUMER_H
0021 
0022 #include "Gaudi/Functional/details.h"
0023 #include "Gaudi/Functional/utilities.h"
0024 #include "GaudiKernel/FunctionalFilterDecision.h"
0025 
0026 // #include "GaudiKernel/CommonMessaging.h"
0027 
0028 #include "k4FWCore/FunctionalUtils.h"
0029 
0030 #include <algorithm>
0031 #include <stdexcept>
0032 #include <type_traits>
0033 #include <utility>
0034 #include <variant>
0035 
0036 namespace k4FWCore {
0037 
0038 namespace details {
0039 
0040   template <typename Signature, typename Traits_>
0041   struct Consumer;
0042 
0043   template <typename... In, typename Traits_>
0044   struct Consumer<void(const In&...), Traits_>
0045       : Gaudi::Functional::details::DataHandleMixin<std::tuple<>, std::tuple<>, Traits_> {
0046     using Gaudi::Functional::details::DataHandleMixin<std::tuple<>, std::tuple<>, Traits_>::DataHandleMixin;
0047 
0048     static_assert(((std::is_base_of_v<podio::CollectionBase, In> || isVectorLike_v<In> ||
0049                     std::is_same_v<In, EventContext>) &&
0050                    ...),
0051                   "Consumer input types must be EDM4hep collections or vectors of collection pointers");
0052 
0053     static constexpr size_t N_in = filter_evtcontext<In...>::size;
0054 
0055     using base_class = Gaudi::Functional::details::DataHandleMixin<std::tuple<>, std::tuple<>, Traits_>;
0056 
0057     using KeyValue = base_class::KeyValue;
0058     using KeyValues = base_class::KeyValues;
0059 
0060     template <typename T>
0061     using InputHandle_t = Gaudi::Functional::details::InputHandle_t<Traits_, T>;
0062 
0063     tuple_of_handle_vec_t<InputHandle_t, filter_evtcontext_t<In...>> m_inputs;
0064 
0065     std::array<Gaudi::Property<DataObjID>, N_in> m_inputLocationsSingle;
0066     std::array<Gaudi::Property<std::vector<DataObjID>>, N_in> m_inputLocationsVector;
0067 
0068     template <typename IArgs, std::size_t... I>
0069     Consumer(std::string name, ISvcLocator* locator, const IArgs& inputs, std::index_sequence<I...>)
0070         : base_class(std::move(name), locator),
0071           // The input locations are filled by creating a property with a callback function
0072           // that creates the handles because that is when the input locations become available
0073           // (from a steering file, for example) and the handles have to be created for
0074           // Gaudi to know the data flow
0075           m_inputLocationsSingle{makeInputPropSingle<InputHandle_t<EventStoreType_t>, KeyValue>(
0076               std::get<I>(inputs), std::get<I>(m_inputs), this)...},
0077           m_inputLocationsVector{makeInputPropVector<InputHandle_t<EventStoreType_t>, KeyValues>(
0078               std::get<I>(inputs), std::get<I>(m_inputs), this)...} {}
0079 
0080     Consumer(std::string name, ISvcLocator* locator,
0081              const Gaudi::Functional::details::RepeatValues_<std::variant<KeyValue, KeyValues>, N_in>& inputs)
0082         : Consumer(std::move(name), locator, inputs, std::make_index_sequence<N_in>{}) {}
0083 
0084     StatusCode execute(const EventContext& ctx) const final {
0085       try {
0086         filter_evtcontext<In...>::apply(*this, ctx, m_inputs);
0087         return Gaudi::Functional::FilterDecision::PASSED;
0088       } catch (GaudiException& e) {
0089         (e.code() ? this->warning() : this->error()) << e.tag() << " : " << e.message() << endmsg;
0090         return e.code();
0091       }
0092     }
0093 
0094     virtual void operator()(const In&...) const = 0;
0095 
0096     /**
0097      * @brief    Get the input locations for a given input index
0098      * @param i  The index of the input
0099      * @return   A range of the input locations
0100      */
0101     auto inputLocations(size_t i) const {
0102       if (i >= N_in) {
0103         throw std::out_of_range("Called inputLocations with an index out of range, index: " + std::to_string(i) +
0104                                 ", number of inputs: " + std::to_string(N_in));
0105       }
0106       std::vector<std::string> names;
0107       if (!m_inputLocationsSingle[i].name().empty()) {
0108         names.push_back(m_inputLocationsSingle[i].value().key());
0109       } else {
0110         for (const auto& id : m_inputLocationsVector[i].value()) {
0111           names.push_back(id.key());
0112         }
0113       }
0114       return names;
0115     }
0116     /**
0117      * @brief       Get the input locations for a given input name
0118      * @param name  The name of the input
0119      * @return      A range of the input locations
0120      */
0121     auto inputLocations(std::string_view name) const {
0122       std::vector<std::string> names;
0123       const auto it =
0124           std::ranges::find_if(m_inputLocationsVector, [&name](const auto& prop) { return prop.name() == name; });
0125       if (it != m_inputLocationsVector.end()) {
0126         for (const auto& id : it->value()) {
0127           names.push_back(id.key());
0128         }
0129       } else {
0130         const auto it2 =
0131             std::ranges::find_if(m_inputLocationsSingle, [&name](const auto& prop) { return prop.name() == name; });
0132         if (it2 == m_inputLocationsSingle.end()) {
0133           throw std::out_of_range("Called inputLocations with a name that does not exist: " + std::string(name));
0134         } else {
0135           names.push_back(it2->value().key());
0136         }
0137       }
0138       return names;
0139     }
0140     static constexpr std::size_t inputLocationsSize() { return N_in; }
0141   };
0142 
0143 } // namespace details
0144 
0145 template <typename Signature, typename Traits_ = Gaudi::Functional::Traits::useDefaults>
0146 using Consumer = details::Consumer<Signature, Traits_>;
0147 
0148 } // namespace k4FWCore
0149 
0150 #endif // FWCORE_CONSUMER_H