LCOV - code coverage report
Current view: top level - dataset - dataset_operations_common.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 37 39 94.9 %
Date: 2024-11-24 01:48:31 Functions: 93 143 65.0 %

          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/core/dict.h"
       8             : #include "scipp/dataset/dataset.h"
       9             : #include "scipp/dataset/except.h"
      10             : #include "scipp/variable/arithmetic.h"
      11             : 
      12             : namespace scipp::dataset {
      13             : template <bool ApplyToData, class Func, class... Args>
      14       50374 : DataArray apply_or_copy_dim_impl(const DataArray &da, Func func, const Dim dim,
      15             :                                  Args &&...args) {
      16      262291 :   const auto copy_independent = [&](const auto &mapping, const bool share) {
      17      151122 :     typename std::decay_t<decltype(mapping)>::holder_type out;
      18      211917 :     for (auto &&[d, var] : mapping)
      19       60795 :       if (!var.dims().contains(dim))
      20        4227 :         out.insert_or_assign(d, share ? var : copy(var));
      21      151122 :     return out;
      22           0 :   };
      23       50374 :   auto coords = copy_independent(da.coords(), true);
      24       50374 :   auto attrs = copy_independent(da.attrs(), true);
      25       50374 :   auto masks = copy_independent(da.masks(), false);
      26             : 
      27             :   if constexpr (ApplyToData) {
      28        2781 :     return DataArray(func(da.data(), dim, args...), std::move(coords),
      29        8343 :                      std::move(masks), std::move(attrs), da.name());
      30             :   } else {
      31       47593 :     return DataArray(func(da, dim, std::forward<Args>(args)...),
      32      142779 :                      std::move(coords), std::move(masks), std::move(attrs),
      33      285560 :                      da.name());
      34             :   }
      35       50376 : }
      36             : 
      37             : /// Helper for creating operations that return an object with modified data with
      38             : /// a dropped dimension or different dimension extent.
      39             : ///
      40             : /// Examples are mostly reduction operations such as `sum` (dropping a
      41             : /// dimension), or `resize` (altering a dimension extent). Creates new data
      42             : /// array by applying `func` to data and dropping coords/masks/attrs depending
      43             : /// on dim.
      44             : template <class Func, class... Args>
      45        2781 : DataArray apply_to_data_and_drop_dim(const DataArray &a, Func func,
      46             :                                      const Dim dim, Args &&...args) {
      47             :   return apply_or_copy_dim_impl<true>(a, func, dim,
      48        2781 :                                       std::forward<Args>(args)...);
      49             : }
      50             : 
      51             : /// Helper for creating operations that return an object with a dropped
      52             : /// dimension or different dimension extent.
      53             : ///
      54             : /// In contrast to `apply_to_data_and_drop_dim`, `func` is applied to the input
      55             : /// array, not just its data. This is useful for more complex operations such as
      56             : /// `histogram`, which require access to coords when computing output data.
      57             : template <class Func, class... Args>
      58       47593 : DataArray apply_and_drop_dim(const DataArray &a, Func func, const Dim dim,
      59             :                              Args &&...args) {
      60             :   return apply_or_copy_dim_impl<false>(a, func, dim,
      61       47593 :                                        std::forward<Args>(args)...);
      62             : }
      63             : 
      64             : template <class Func, class... Args>
      65             : DataArray apply_to_items(const DataArray &d, Func func, Args &&...args) {
      66             :   return func(d, std::forward<Args>(args)...);
      67             : }
      68             : 
      69             : template <class... Args>
      70             : bool copy_attr(const Variable &attr, const Dim dim, const Args &...) {
      71             :   return !attr.dims().contains(dim);
      72             : }
      73             : template <class... Args> bool copy_attr(const Variable &, const Args &...) {
      74             :   return true;
      75             : }
      76             : 
      77             : template <class Func, class... Args>
      78         203 : Dataset apply_to_items(const Dataset &d, Func func, Args &&...args) {
      79         203 :   Dataset result;
      80         428 :   for (const auto &data : d)
      81         225 :     result.setDataInit(data.name(), func(data, std::forward<Args>(args)...));
      82         406 :   return std::move(result).or_empty();
      83         203 : }
      84             : 
      85             : /// Return a copy of map-like objects such as Coords with `func` applied to each
      86             : /// item.
      87             : ///
      88             : /// If `func` returns an invalid object it will not be inserted into the output
      89             : /// map. This can be used to drop/filter items.
      90             : template <class OutMapping, class Mapping, class Func>
      91       32304 : auto transform_map(const Mapping &map, Func func) {
      92       32304 :   OutMapping out;
      93       61751 :   for (const auto &[key, item] : map) {
      94       29447 :     auto transformed = func(item);
      95       29447 :     if (transformed.is_valid())
      96       29413 :       out.insert_or_assign(key, std::move(transformed));
      97             :   }
      98       32304 :   return out;
      99           0 : }
     100             : 
     101       10768 : template <class T, class Func> DataArray transform(const T &a, Func func) {
     102             :   return DataArray(
     103             :       func(a.data()),
     104        2310 :       transform_map<typename Coords::holder_type>(a.coords(), func),
     105        2310 :       transform_map<typename Masks::holder_type>(a.masks(), func),
     106       15390 :       transform_map<typename Attrs::holder_type>(a.attrs(), func), a.name());
     107             : }
     108             : 
     109             : [[nodiscard]] DataArray strip_if_broadcast_along(const DataArray &a,
     110             :                                                  const Dim dim);
     111             : [[nodiscard]] Dataset strip_if_broadcast_along(const Dataset &d, const Dim dim);
     112             : 
     113             : // Helpers for reductions for DataArray and Dataset, which include masks.
     114             : [[nodiscard]] Variable mean(const Variable &var, const Dim dim,
     115             :                             const Masks &masks);
     116             : [[nodiscard]] Variable nanmean(const Variable &var, const Dim dim,
     117             :                                const Masks &masks);
     118             : [[nodiscard]] Variable sum(const Variable &var, const Dim dim,
     119             :                            const Masks &masks);
     120             : [[nodiscard]] Variable nansum(const Variable &var, const Masks &masks);
     121             : [[nodiscard]] Variable nansum(const Variable &var, const Dim dim,
     122             :                               const Masks &masks);
     123             : [[nodiscard]] Variable max(const Variable &var, const Dim dim,
     124             :                            const Masks &masks);
     125             : [[nodiscard]] Variable nanmax(const Variable &var, const Dim dim,
     126             :                               const Masks &masks);
     127             : [[nodiscard]] Variable min(const Variable &var, const Dim dim,
     128             :                            const Masks &masks);
     129             : [[nodiscard]] Variable nanmin(const Variable &var, const Dim dim,
     130             :                               const Masks &masks);
     131             : [[nodiscard]] Variable all(const Variable &var, const Dim dim,
     132             :                            const Masks &masks);
     133             : [[nodiscard]] Variable any(const Variable &var, const Dim dim,
     134             :                            const Masks &masks);
     135             : 
     136             : [[nodiscard]] Variable
     137             : masked_data(const DataArray &array, const Dim dim,
     138             :             const std::optional<Variable> &fill_value = std::nullopt);
     139             : 
     140             : } // namespace scipp::dataset

Generated by: LCOV version 1.14