LCOV - code coverage report
Current view: top level - variable - string.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 66 73 90.4 %
Date: 2024-12-01 01:56:34 Functions: 21 43 48.8 %

          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             : #include <chrono>
       6             : #include <iomanip>
       7             : #include <set>
       8             : 
       9             : #include "scipp/core/array_to_string.h"
      10             : #include "scipp/core/eigen.h"
      11             : #include "scipp/core/string.h"
      12             : #include "scipp/core/tag_util.h"
      13             : #include "scipp/variable/string.h"
      14             : #include "scipp/variable/variable.h"
      15             : 
      16             : namespace scipp::variable {
      17             : 
      18         126 : std::ostream &operator<<(std::ostream &os, const Variable &variable) {
      19         126 :   return os << to_string(variable);
      20             : }
      21             : 
      22             : namespace {
      23             : 
      24         972 : std::string make_dims_labels(const Variable &variable,
      25             :                              const std::optional<Sizes> datasetSizes) {
      26         972 :   const auto &dims = variable.dims();
      27         972 :   if (dims.empty())
      28           7 :     return "()";
      29         965 :   std::string diminfo = "(";
      30        1930 :   for (const auto &dim : dims.labels()) {
      31         965 :     diminfo += to_string(dim);
      32         965 :     if (datasetSizes) {
      33         965 :       if ((datasetSizes->contains(dim) ? (*datasetSizes)[dim] : 1) + 1 ==
      34         965 :           dims[dim])
      35           0 :         diminfo += " [bin-edge]";
      36             :     }
      37         965 :     diminfo += ", ";
      38             :   }
      39         965 :   diminfo.resize(diminfo.size() - 2);
      40         965 :   diminfo += ")";
      41         965 :   return diminfo;
      42         965 : }
      43             : 
      44             : template <class T> struct ValuesToString {
      45        1605 :   static std::string apply(const Variable &var) {
      46        1605 :     if (var.ndim() == 0)
      47         193 :       return core::scalar_array_to_string(var.template values<T>(), var.unit());
      48        1414 :     return core::array_to_string(var.template values<T>(), var.unit());
      49             :   }
      50             : };
      51             : template <class T> struct VariancesToString {
      52         212 :   static std::string apply(const Variable &var) {
      53             :     if constexpr (core::canHaveVariances<T>()) {
      54         212 :       if (var.ndim() == 0)
      55             :         return core::scalar_array_to_string(var.template variances<T>(),
      56          14 :                                             var.unit());
      57         198 :       return core::array_to_string(var.template variances<T>());
      58             :     } else
      59           0 :       return std::string{};
      60             :   }
      61             : };
      62             : 
      63             : template <template <class> class Callable, class... Args>
      64        1892 : auto apply(const DType dtype, Args &&...args) {
      65             :   // Note that formatting via registry ignores the Callable, but custom types
      66             :   // should typically not have variances, so Callable should always be
      67             :   // `ValuesToString` in this case.
      68        1892 :   if (formatterRegistry().contains(dtype))
      69          75 :     return formatterRegistry().format(args...);
      70             :   return core::callDType<Callable>(
      71        3634 :       std::tuple<double, float, int64_t, int32_t, std::string, bool,
      72             :                  scipp::core::time_point, Eigen::Vector3d, Eigen::Matrix3d,
      73             :                  Variable, bucket<Variable>, scipp::index_pair, Eigen::Affine3d,
      74             :                  scipp::core::Quaternion, scipp::core::Translation>{},
      75        3634 :       dtype, std::forward<Args>(args)...);
      76             : }
      77             : } // namespace
      78             : 
      79         182 : std::string format_variable_compact(const Variable &variable) {
      80         182 :   const auto s = to_string(variable.dtype());
      81         182 :   if (variable.unit() == units::none)
      82           0 :     return s;
      83             :   else
      84         364 :     return s + '[' + variable.unit().name() + ']';
      85         182 : }
      86             : 
      87        1681 : std::string format_variable(const Variable &variable,
      88             :                             const std::optional<Sizes> &datasetSizes) {
      89        1681 :   if (!variable.is_valid())
      90           1 :     return "invalid variable\n";
      91        1680 :   std::stringstream s;
      92        1680 :   const std::string colSep("  ");
      93        1680 :   if (!datasetSizes)
      94         708 :     s << to_string(variable.dims()) << colSep;
      95        1680 :   s << std::setw(9) << to_string(variable.dtype());
      96        1680 :   if (variable.unit() == units::none)
      97         189 :     s << colSep << std::setw(15) << "<no unit>";
      98             :   else
      99        1491 :     s << colSep << std::setw(15) << '[' + variable.unit().name() + ']';
     100        1680 :   if (datasetSizes)
     101         972 :     s << colSep << make_dims_labels(variable, datasetSizes);
     102        1680 :   s << colSep;
     103        1680 :   s << apply<ValuesToString>(variable.dtype(), variable);
     104        1678 :   if (variable.has_variances())
     105         212 :     s << colSep << apply<VariancesToString>(variable.dtype(), variable);
     106        1678 :   return s.str();
     107        1682 : }
     108             : 
     109         551 : std::string to_string(const Variable &variable) {
     110        1100 :   return std::string("<scipp.Variable> ") + format_variable(variable);
     111             : }
     112             : 
     113           0 : std::string to_string(const std::pair<Dim, Variable> &coord) {
     114             :   using units::to_string;
     115           0 :   return to_string(coord.first) + ":\n" + to_string(coord.second);
     116             : }
     117             : 
     118           0 : std::string to_string(const std::pair<std::string, Variable> &coord) {
     119           0 :   return coord.first + ":\n" + to_string(coord.second);
     120             : }
     121             : 
     122          29 : void FormatterRegistry::emplace(const DType key,
     123             :                                 std::unique_ptr<AbstractFormatter> formatter) {
     124          29 :   m_formatters.emplace(key, std::move(formatter));
     125          29 : }
     126             : 
     127        1892 : bool FormatterRegistry::contains(const DType key) const noexcept {
     128        1892 :   return m_formatters.find(key) != m_formatters.end();
     129             : }
     130             : 
     131          75 : std::string FormatterRegistry::format(const Variable &var) const {
     132         150 :   return m_formatters.at(var.dtype())->format(var);
     133             : }
     134             : 
     135        1996 : FormatterRegistry &formatterRegistry() {
     136        1996 :   static FormatterRegistry registry;
     137        1996 :   return registry;
     138             : }
     139             : 
     140             : } // namespace scipp::variable

Generated by: LCOV version 1.14