LCOV - code coverage report
Current view: top level - variable/include/scipp/variable - variable_factory.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 28 35 80.0 %
Date: 2024-04-28 01:25:40 Functions: 81 123 65.9 %

          Line data    Source code
       1             : // SPDX-License-Identifier: BSD-3-Clause
       2             : // Copyright (c) 2023 Scipp contributors (https://github.com/scipp)
       3             : /// @file
       4             : /// @author Simon Heybrock
       5             : #pragma once
       6             : 
       7             : #include <functional>
       8             : 
       9             : #include "scipp/core/flags.h"
      10             : 
      11             : #include "scipp/variable/variable.h"
      12             : 
      13             : namespace scipp::variable {
      14             : 
      15             : /// Abstract base class for "variable makers", used by VariableFactory to
      16             : /// dynamically create variables with given type.
      17             : class SCIPP_VARIABLE_EXPORT AbstractVariableMaker {
      18             : protected:
      19           0 :   auto unreachable() const {
      20           0 :     return std::logic_error("This code path should never be reached");
      21             :   }
      22             : 
      23             : public:
      24             :   using parent_list = std::vector<std::reference_wrapper<const Variable>>;
      25             : 
      26         245 :   virtual ~AbstractVariableMaker() = default;
      27             :   virtual bool is_bins() const = 0;
      28             :   virtual Variable create(const DType elem_dtype, const Dimensions &dims,
      29             :                           const units::Unit &unit, const bool variances,
      30             :                           const parent_list &parents) const = 0;
      31             :   virtual Dim elem_dim(const Variable &var) const = 0;
      32             :   virtual DType elem_dtype(const Variable &var) const = 0;
      33             :   virtual units::Unit elem_unit(const Variable &var) const = 0;
      34             :   virtual void expect_can_set_elem_unit(const Variable &var,
      35             :                                         const units::Unit &u) const = 0;
      36             :   virtual void set_elem_unit(Variable &var, const units::Unit &u) const = 0;
      37           0 :   virtual bool has_masks(const Variable &) const { return false; }
      38             :   virtual bool has_variances(const Variable &var) const = 0;
      39           0 :   virtual const Variable &data(const Variable &) const { throw unreachable(); }
      40           0 :   virtual Variable data(Variable &) const { throw unreachable(); }
      41           0 :   virtual core::ElementArrayViewParams array_params(const Variable &) const {
      42           0 :     throw unreachable();
      43             :   }
      44             :   virtual Variable empty_like(const Variable &prototype,
      45             :                               const std::optional<Dimensions> &shape,
      46             :                               const Variable &sizes) const = 0;
      47       33450 :   [[nodiscard]] virtual Variable apply_event_masks(const Variable &var,
      48             :                                                    const FillValue) const {
      49       33450 :     return var;
      50             :   }
      51             : 
      52             :   [[nodiscard]] virtual Variable
      53           6 :   irreducible_event_mask([[maybe_unused]] const Variable &var) const {
      54           6 :     return Variable{};
      55             :   }
      56             : };
      57             : 
      58             : SCIPP_VARIABLE_EXPORT bool is_bins(const Variable &var);
      59             : 
      60             : /// Dynamic factory for variables.
      61             : ///
      62             : /// The factory can be used for creating variables with a dtype that is not
      63             : /// known in the current module, e.g., dtype<bucket<Dataset>> can be used in
      64             : /// scipp::variable. The main purpose of this is the implementation of
      65             : /// `transform`.
      66             : class SCIPP_VARIABLE_EXPORT VariableFactory {
      67             : private:
      68             :   using parent_list = typename AbstractVariableMaker::parent_list;
      69             :   DType bin_dtype(const parent_list &vars) const noexcept;
      70             : 
      71             : public:
      72           5 :   VariableFactory() = default;
      73             :   VariableFactory(const VariableFactory &) = delete;
      74             :   VariableFactory &operator=(const VariableFactory &) = delete;
      75             :   void emplace(const DType key, std::unique_ptr<AbstractVariableMaker> makes);
      76             :   bool contains(const DType key) const noexcept;
      77             :   bool is_bins(const Variable &var) const;
      78             :   template <class... Parents>
      79     1334963 :   Variable create(const DType elem_dtype, const Dimensions &dims,
      80             :                   const units::Unit &unit, const bool with_variances,
      81             :                   const Parents &...parents) const {
      82     1334963 :     const auto parents_ = parent_list{parents...};
      83     1334963 :     const auto key = bin_dtype(parents_);
      84     1334963 :     return m_makers.at(key == dtype<void> ? elem_dtype : key)
      85     2669925 :         ->create(elem_dtype, dims, unit, with_variances, parents_);
      86     1334963 :   }
      87             :   Dim elem_dim(const Variable &var) const;
      88             :   DType elem_dtype(const Variable &var) const;
      89             :   units::Unit elem_unit(const Variable &var) const;
      90             :   void expect_can_set_elem_unit(const Variable &var,
      91             :                                 const units::Unit &u) const;
      92             :   void set_elem_unit(Variable &var, const units::Unit &u) const;
      93             :   bool has_masks(const Variable &var) const;
      94             :   bool has_variances(const Variable &var) const;
      95     5598518 :   template <class T, class Var> auto values(Var &&var) const {
      96     5598518 :     if (!is_bins(var))
      97     5488438 :       return var.template values<T>();
      98      110080 :     const auto &maker = *m_makers.at(var.dtype());
      99      110080 :     auto &&data = maker.data(var);
     100      110080 :     return ElementArrayView(maker.array_params(var),
     101      110080 :                             data.template values<T>().data());
     102       41110 :   }
     103       26880 :   template <class T, class Var> auto variances(Var &&var) const {
     104       26880 :     if (!is_bins(var))
     105       26422 :       return var.template variances<T>();
     106         458 :     const auto &maker = *m_makers.at(var.dtype());
     107         458 :     auto &&data = maker.data(var);
     108         458 :     return ElementArrayView(maker.array_params(var),
     109         458 :                             data.template variances<T>().data());
     110          88 :   }
     111             :   Variable empty_like(const Variable &prototype,
     112             :                       const std::optional<Dimensions> &shape,
     113             :                       const Variable &sizes = {});
     114             :   /// Return a binned variable where masked elements are replaced by fill.
     115             :   /// Coords and attrs of the input are not propagated to the output.
     116             :   [[nodiscard]] Variable apply_event_masks(const Variable &var,
     117             :                                            const FillValue fill) const;
     118             :   [[nodiscard]] Variable irreducible_event_mask(const Variable &var) const;
     119             : 
     120             : private:
     121             :   std::map<DType, std::unique_ptr<AbstractVariableMaker>> m_makers;
     122             : };
     123             : 
     124             : /// Return the global variable factory instance
     125             : SCIPP_VARIABLE_EXPORT VariableFactory &variableFactory();
     126             : 
     127             : } // namespace scipp::variable

Generated by: LCOV version 1.14