LCOV - code coverage report
Current view: top level - variable/include/scipp/variable - bin_array_model.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 43 50 86.0 %
Date: 2024-04-28 01:25:40 Functions: 38 51 74.5 %

          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             : #include <algorithm>
       7             : 
       8             : #include "scipp/core/bucket_array_view.h"
       9             : #include "scipp/core/dimensions.h"
      10             : #include "scipp/core/eigen.h"
      11             : #include "scipp/core/except.h"
      12             : #include "scipp/variable/arithmetic.h"
      13             : #include "scipp/variable/bins.h"
      14             : #include "scipp/variable/cumulative.h"
      15             : #include "scipp/variable/element_array_model.h"
      16             : #include "scipp/variable/except.h"
      17             : #include "scipp/variable/reduction.h"
      18             : #include "scipp/variable/util.h"
      19             : 
      20             : namespace scipp::variable {
      21             : 
      22             : template <class Indices> class BinModelBase : public VariableConcept {
      23             : public:
      24      159193 :   BinModelBase(const VariableConceptHandle &indices, const Dim dim)
      25      159193 :       : VariableConcept(units::none), m_indices(indices), m_dim(dim) {}
      26             : 
      27      159190 :   scipp::index size() const override { return indices()->size(); }
      28             : 
      29           4 :   void setUnit(const units::Unit &unit) override {
      30           4 :     if (unit != units::none)
      31           4 :       throw except::UnitError(
      32             :           "Bins cannot have a unit. Did you mean to set the unit of the bin "
      33             :           "elements? This can be set with `array.bins.unit = 'm'`.");
      34           0 :   }
      35             : 
      36      100838 :   bool has_variances() const noexcept override { return false; }
      37      938260 :   const Indices &bin_indices() const override { return indices(); }
      38             : 
      39     1159422 :   const auto &indices() const { return m_indices; }
      40             :   auto &indices() { return m_indices; }
      41      977022 :   Dim bin_dim() const noexcept { return m_dim; }
      42             : 
      43             : private:
      44             :   Indices m_indices;
      45             :   Dim m_dim;
      46             : };
      47             : 
      48             : /// Specialization of ElementArrayModel for "binned" data. T could be Variable,
      49             : /// DataArray, or Dataset.
      50             : ///
      51             : /// A bin in this context is defined as an element of a variable mapping to a
      52             : /// range of data, such as a slice of a DataArray.
      53             : template <class T>
      54             : class BinArrayModel : public BinModelBase<VariableConceptHandle> {
      55             :   using Indices = VariableConceptHandle;
      56             : 
      57             : public:
      58             :   using value_type = bucket<T>;
      59             : 
      60             :   BinArrayModel(const VariableConceptHandle &indices, const Dim dim, T buffer);
      61             : 
      62             :   [[nodiscard]] VariableConceptHandle clone() const override;
      63             : 
      64             :   bool operator==(const BinArrayModel &other) const noexcept;
      65             : 
      66           0 :   bool operator!=(const BinArrayModel &other) const noexcept {
      67           0 :     return !(*this == other);
      68             :   }
      69             : 
      70             :   [[nodiscard]] VariableConceptHandle
      71             :   makeDefaultFromParent(const scipp::index size) const override;
      72             : 
      73             :   [[nodiscard]] VariableConceptHandle
      74             :   makeDefaultFromParent(const Variable &shape) const override;
      75             : 
      76           1 :   static DType static_dtype() noexcept { return scipp::dtype<bucket<T>>; }
      77     2679379 :   [[nodiscard]] DType dtype() const noexcept override {
      78     2679379 :     return scipp::dtype<bucket<T>>;
      79             :   }
      80             : 
      81             :   [[nodiscard]] bool equals(const Variable &a,
      82             :                             const Variable &b) const override;
      83             :   [[nodiscard]] bool equals_nan(const Variable &a,
      84             :                                 const Variable &b) const override;
      85             :   void copy(const Variable &src, Variable &dest) const override;
      86             :   void copy(const Variable &src, Variable &&dest) const override;
      87             :   void assign(const VariableConcept &other) override;
      88             : 
      89             :   // TODO Should the mutable version return a view to prevent risk of clients
      90             :   // breaking invariants of variable?
      91     1088170 :   const T &buffer() const noexcept { return m_buffer; }
      92      137055 :   T &buffer() noexcept { return m_buffer; }
      93             : 
      94         381 :   ElementArrayView<bucket<T>> values(const core::ElementArrayViewParams &base) {
      95         381 :     return {index_values(base), this->bin_dim(), m_buffer};
      96             :   }
      97             :   ElementArrayView<const bucket<T>>
      98       61554 :   values(const core::ElementArrayViewParams &base) const {
      99       61554 :     return {index_values(base), this->bin_dim(), m_buffer};
     100             :   }
     101             : 
     102           0 :   [[nodiscard]] scipp::index dtype_size() const override {
     103           0 :     return sizeof(scipp::index_pair);
     104             :   }
     105          98 :   scipp::index object_size() const override { return sizeof(*this); }
     106             : 
     107           0 :   void setVariances(const Variable &) override {
     108           0 :     except::throw_cannot_have_variances(core::dtype<core::bin<T>>);
     109             :   }
     110             : 
     111             : private:
     112             :   ElementArrayView<const scipp::index_pair>
     113             :   index_values(const core::ElementArrayViewParams &base) const;
     114             :   T m_buffer;
     115             : };
     116             : 
     117             : template <class T> BinArrayModel<T> copy(const BinArrayModel<T> &model);
     118             : 
     119             : template <class T>
     120       25711 : bool BinArrayModel<T>::equals(const Variable &a, const Variable &b) const {
     121             :   // TODO This implementation is slow since it creates a view for every bucket.
     122       51422 :   return a.dtype() == dtype() && b.dtype() == dtype() &&
     123       51422 :          equals_impl(a.values<bucket<T>>(), b.values<bucket<T>>());
     124             : }
     125             : 
     126             : template <class T>
     127          63 : bool BinArrayModel<T>::equals_nan(const Variable &a, const Variable &b) const {
     128             :   // TODO This implementation is slow since it creates a view for every bucket.
     129         126 :   return a.dtype() == dtype() && b.dtype() == dtype() &&
     130         126 :          equals_nan_impl(a.values<bucket<T>>(), b.values<bucket<T>>());
     131             : }
     132             : 
     133             : namespace {
     134             : template <class T>
     135        3361 : void copy_coord_alignment(const T &src_buffer, Variable &dest) {
     136        3361 :   auto &dest_buffer = dest.bin_buffer<T>();
     137       12318 :   for (const auto &[key, var] : src_buffer.coords())
     138        8957 :     dest_buffer.coords().set_aligned(key, var.is_aligned());
     139        3361 : }
     140             : } // namespace
     141             : 
     142             : template <class T>
     143       17007 : void BinArrayModel<T>::copy(const Variable &src, Variable &dest) const {
     144             :   if constexpr (std::is_same_v<T, Variable>) {
     145       13626 :     copy_data(src, dest);
     146       13621 :     dest.set_aligned(src.is_aligned());
     147             :   } else {
     148        3381 :     const auto &[indices0, dim0, buffer0] = src.constituents<T>();
     149        3381 :     auto &&[indices1, dim1, buffer1] = dest.constituents<T>();
     150             :     static_cast<void>(dim1);
     151        3401 :     copy_slices(buffer0, buffer1, dim0, indices0, indices1);
     152        3361 :     copy_coord_alignment(buffer0, dest);
     153        3401 :   }
     154       16982 : }
     155             : 
     156             : template <class T>
     157          72 : void BinArrayModel<T>::copy(const Variable &src, Variable &&dest) const {
     158          72 :   copy(src, dest);
     159          52 : }
     160             : 
     161             : } // namespace scipp::variable

Generated by: LCOV version 1.14