LCOV - code coverage report
Current view: top level - dataset/include/scipp/dataset - bins_view.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 63 91 69.2 %
Date: 2024-04-28 01:25:40 Functions: 70 94 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             : 
       7             : #include "scipp/dataset/dataset.h"
       8             : #include "scipp/dataset/string.h"
       9             : #include "scipp/variable/bins.h"
      10             : #include "scipp/variable/except.h"
      11             : 
      12             : namespace scipp::dataset {
      13             : 
      14             : namespace bins_view_detail {
      15             : template <class T> class BinsCommon {
      16             : public:
      17       25701 :   explicit BinsCommon(Variable var) : m_var(std::move(var)) {}
      18       41545 :   auto indices() const { return std::get<0>(get()); }
      19       63284 :   auto dim() const { return std::get<1>(get()); }
      20       89584 :   auto &buffer() const { return m_var.bin_buffer<T>(); }
      21        4092 :   auto &buffer() { return m_var.bin_buffer<T>(); }
      22             : 
      23             : protected:
      24       37648 :   auto make(const variable::Variable &view) const {
      25       37648 :     return make_bins_no_validate(this->indices(), this->dim(), view);
      26             :   }
      27        3898 :   auto check_and_get_buf(const Variable &var) const {
      28        3898 :     const auto &[i, d, buf] = var.constituents<Variable>();
      29        3903 :     core::expect::equals(i, this->indices());
      30        3895 :     core::expect::equals(d, this->dim());
      31        7790 :     return buf;
      32        3897 :   }
      33           0 :   [[nodiscard]] const Variable &get_var() const noexcept { return m_var; }
      34             : 
      35             : private:
      36      104829 :   auto get() const { return m_var.constituents<T>(); }
      37             :   Variable m_var;
      38             : };
      39             : 
      40             : template <class T, class MapGetter> class BinsMapView : public BinsCommon<T> {
      41             :   struct make_value {
      42             :     const BinsMapView *view;
      43       21741 :     template <class Value> auto operator()(const Value &value) const {
      44       21741 :       if (value.dims().contains(view->dim()))
      45       21723 :         return view->make(value);
      46             :       else
      47          18 :         return copy(value);
      48             :     }
      49             :   };
      50             :   struct make_item {
      51             :     const BinsMapView *view;
      52       21739 :     template <class Item> auto operator()(const Item &item) const {
      53       21739 :       return std::pair(item.first, make_value{view}(item.second));
      54             :     }
      55             :   };
      56             :   using MapView =
      57             :       std::decay_t<decltype(std::declval<MapGetter>()(std::declval<T>()))>;
      58             : 
      59             : public:
      60             :   using key_type = typename MapView::key_type;
      61             :   using mapped_type = typename MapView::mapped_type;
      62       42262 :   BinsMapView(const BinsCommon<T> base, MapGetter map)
      63       42262 :       : BinsCommon<T>(base), m_map(map) {}
      64           6 :   scipp::index size() const noexcept { return mapView().size(); }
      65       11105 :   auto operator[](const key_type &key) const {
      66       11105 :     return this->make(mapView()[key]);
      67             :   }
      68           7 :   void erase(const key_type &key) { return mapView().erase(key); }
      69          58 :   auto extract(const key_type &key) {
      70          58 :     return this->make(mapView().extract(key));
      71             :   }
      72        3896 :   void set(const key_type &key, const Variable &var) {
      73        3896 :     mapView().set(key, this->check_and_get_buf(var));
      74        3892 :   }
      75       25076 :   auto begin() const noexcept {
      76       25076 :     return mapView().begin().transform(make_item{this});
      77             :   }
      78       25076 :   auto end() const noexcept {
      79       25076 :     return mapView().end().transform(make_item{this});
      80             :   }
      81           8 :   auto keys_begin() const noexcept { return mapView().keys_begin(); }
      82           8 :   auto keys_end() const noexcept { return mapView().keys_end(); }
      83           2 :   auto values_begin() const noexcept {
      84           2 :     return mapView().values_begin().transform(make_value{this});
      85             :   }
      86           2 :   auto values_end() const noexcept {
      87           2 :     return mapView().values_end().transform(make_value{this});
      88             :   }
      89           2 :   auto items_begin() const noexcept { return begin(); }
      90           2 :   auto items_end() const noexcept { return end(); }
      91        5598 :   bool contains(const key_type &key) const noexcept {
      92        5598 :     return mapView().contains(key);
      93             :   }
      94        5834 :   scipp::index count(const key_type &key) const noexcept {
      95        5834 :     return mapView().count(key);
      96             :   }
      97         129 :   void set_aligned(const key_type &key, const bool aligned) {
      98         129 :     mapView().set_aligned(key, aligned);
      99         129 :   }
     100           0 :   bool is_edges(const key_type &, std::optional<Dim>) const noexcept {
     101           0 :     return false; // event-coordinates are never edges
     102             :   }
     103           0 :   bool operator==(const BinsMapView &other) const noexcept {
     104           0 :     return mapView() == other.mapView();
     105             :   }
     106           0 :   bool operator!=(const BinsMapView &other) const noexcept {
     107           0 :     return mapView() != other.mapView();
     108             :   }
     109             : 
     110           0 :   friend std::string dict_keys_to_string(const BinsMapView &view) {
     111           0 :     return dict_keys_to_string(view.mapView());
     112             :   }
     113           0 :   friend std::string to_string(const BinsMapView &view) {
     114           0 :     return to_string(view.mapView());
     115             :   }
     116           0 :   friend BinsMapView copy(const BinsMapView &view) {
     117           0 :     return BinsMapView{BinsCommon<T>{copy(view.get_var())}, view.m_map};
     118             :   }
     119             : 
     120             : private:
     121       72715 :   decltype(auto) mapView() const { return m_map(this->buffer()); }
     122        4090 :   decltype(auto) mapView() { return m_map(this->buffer()); }
     123             :   MapGetter m_map;
     124             : };
     125             : 
     126             : template <class T> class Bins : public BinsCommon<T> {
     127             : public:
     128             :   using BinsCommon<T>::BinsCommon;
     129        8511 :   auto data() const { return this->make(this->buffer().data()); }
     130             :   // TODO how to handle const-ness?
     131           2 :   void setData(const Variable &var) {
     132           2 :     this->buffer().setData(this->check_and_get_buf(var));
     133           2 :   }
     134        4969 :   auto meta() const { return BinsMapView(*this, get_meta); }
     135       20533 :   auto coords() const { return BinsMapView(*this, get_coords); }
     136        8383 :   auto attrs() const { return BinsMapView(*this, get_attrs); }
     137        8377 :   auto masks() const { return BinsMapView(*this, get_masks); }
     138        8358 :   auto &name() const { return this->buffer().name(); }
     139           0 :   auto drop_coords(const scipp::span<const Dim> coord_names) const {
     140           0 :     auto result = *this;
     141           0 :     for (const auto &name : coord_names)
     142           0 :       result.coords().erase(name);
     143           0 :   }
     144           0 :   auto drop_masks(const scipp::span<const std::string> mask_names) const {
     145           0 :     auto result = *this;
     146           0 :     for (const auto &name : mask_names)
     147           0 :       result.masks().erase(name);
     148           0 :   }
     149           0 :   auto drop_attrs(const scipp::span<const Dim> attr_names) const {
     150           0 :     auto result = *this;
     151           0 :     for (const auto &name : attr_names)
     152           0 :       result.attrs().erase(name);
     153           0 :   }
     154             : };
     155             : } // namespace bins_view_detail
     156             : 
     157             : /// Return helper for accessing bin data and coords as non-owning views
     158             : ///
     159             : /// Usage:
     160             : /// auto data = bins_view<DataArray>(var).data();
     161             : /// auto coord = bins_view<DataArray>(var).coords()[dim];
     162             : ///
     163             : /// The returned objects are variables referencing data in `var`. They do not
     164             : /// own or share ownership of any data.
     165       25701 : template <class T> auto bins_view(Variable var) {
     166       25701 :   return bins_view_detail::Bins<T>(std::move(var));
     167             : }
     168             : 
     169             : } // namespace scipp::dataset

Generated by: LCOV version 1.14