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 <algorithm> // for std::sort
6 : #include <iomanip>
7 : #include <set>
8 : #include <sstream>
9 :
10 : #include "scipp/core/dict.h"
11 : #include "scipp/dataset/dataset.h"
12 : #include "scipp/dataset/except.h"
13 : #include "scipp/dataset/string.h"
14 :
15 : namespace scipp::dataset {
16 :
17 185 : std::ostream &operator<<(std::ostream &os, const DataArray &data) {
18 185 : return os << to_string(data);
19 : }
20 :
21 1 : std::ostream &operator<<(std::ostream &os, const Dataset &dataset) {
22 1 : return os << to_string(dataset);
23 : }
24 :
25 : constexpr const char *tab = " ";
26 : constexpr const char *tab_minus_1 = " ";
27 :
28 195 : template <class T> auto sorted(const T &map) {
29 : using core::to_string;
30 195 : std::vector<std::pair<std::string, Variable>> elems;
31 957 : for (const auto &[dim, var] : map)
32 762 : elems.emplace_back(to_string(dim), var);
33 195 : std::sort(elems.begin(), elems.end(),
34 1319 : [](const auto &a, const auto &b) { return a.first < b.first; });
35 195 : return elems;
36 0 : }
37 :
38 : namespace {
39 972 : std::string format_variable(const std::string &key, const Variable &variable,
40 : const std::optional<Sizes> &datasetSizes,
41 : const bool show_alignment = false) {
42 972 : std::stringstream s;
43 972 : s << (show_alignment && variable.is_aligned() ? '*' : ' ') << tab_minus_1
44 972 : << std::left << std::setw(24) << key
45 972 : << format_variable(variable, datasetSizes) << '\n';
46 1944 : return s.str();
47 972 : }
48 :
49 : template <class Key>
50 210 : auto format_data_view(const Key &name, const DataArray &data,
51 : const Sizes &datasetSizes, const std::string &shift,
52 : const bool inline_meta) {
53 210 : std::stringstream s;
54 210 : s << shift << format_variable(name, data.data(), datasetSizes);
55 :
56 210 : const std::string header_shift = inline_meta ? shift : (shift + tab + tab);
57 210 : const std::string data_shift = inline_meta ? shift : (header_shift + tab);
58 210 : if (!data.masks().empty()) {
59 0 : s << header_shift << "Masks:\n";
60 0 : for (const auto &[key, var] : sorted(data.masks()))
61 0 : s << data_shift << format_variable(key, var, datasetSizes);
62 : }
63 210 : if (!data.attrs().empty()) {
64 0 : s << header_shift << "Attributes:\n";
65 0 : for (const auto &[key, var] : sorted(data.attrs()))
66 0 : s << data_shift << format_variable(key, var, datasetSizes);
67 : }
68 420 : return s.str();
69 210 : }
70 :
71 : template <class D>
72 207 : std::string do_to_string(const D &dataset, const std::string &id,
73 : const Sizes &dims, const std::string &shift = "") {
74 207 : std::stringstream s;
75 207 : if (!id.empty())
76 207 : s << shift << id + '\n';
77 207 : s << shift << "Dimensions: " << to_string(dims) << '\n';
78 :
79 207 : if (!dataset.coords().empty()) {
80 195 : s << shift << "Coordinates:\n";
81 195 : const Coords &map = dataset.coords();
82 957 : for (const auto &[name, var] : sorted(map))
83 762 : s << shift << format_variable(name, var, dims, true);
84 : }
85 :
86 : if constexpr (std::is_same_v<D, DataArray>) {
87 : s << shift << "Data:\n"
88 192 : << format_data_view(dataset.name(), dataset, dims, shift, true);
89 : } else {
90 15 : if (!dataset.empty())
91 13 : s << shift << "Data:\n";
92 15 : std::set<std::string> sorted_items;
93 33 : for (const auto &item : dataset)
94 18 : sorted_items.insert(item.name());
95 33 : for (const auto &name : sorted_items)
96 18 : s << shift << format_data_view(name, dataset[name], dims, shift, false);
97 15 : }
98 :
99 207 : s << '\n';
100 414 : return s.str();
101 207 : }
102 : } // namespace
103 :
104 192 : std::string to_string(const DataArray &data) {
105 192 : return do_to_string(data, "<scipp.DataArray>", data.dims());
106 : }
107 :
108 15 : std::string to_string(const Dataset &dataset) {
109 15 : return do_to_string(dataset, "<scipp.Dataset>", dataset.sizes());
110 : }
111 :
112 : namespace {
113 : template <class Key, class Value>
114 136 : std::string dict_to_string(const SizedDict<Key, Value> &view) {
115 136 : std::stringstream ss;
116 136 : ss << "<scipp.Dict>\n";
117 309 : for (const auto &[key, item] : view)
118 173 : ss << " " << key << ": " << to_string(item) << "\n";
119 272 : return ss.str();
120 136 : }
121 : } // namespace
122 :
123 102 : std::string to_string(const Coords &coords) { return dict_to_string(coords); }
124 34 : std::string to_string(const Masks &masks) { return dict_to_string(masks); }
125 :
126 4547 : std::string dict_keys_to_string(const Coords &coords) {
127 4547 : return core::dict_keys_to_string(coords.keys_begin(), coords.keys_end(),
128 13641 : "scipp.Dict.keys");
129 : }
130 :
131 39 : std::string dict_keys_to_string(const Masks &masks) {
132 39 : return core::dict_keys_to_string(masks.keys_begin(), masks.keys_end(),
133 117 : "scipp.Dict.keys");
134 : }
135 :
136 25 : std::string dict_keys_to_string(const Dataset &dataset) {
137 25 : return core::dict_keys_to_string(dataset.keys_begin(), dataset.keys_end(),
138 75 : "scipp.Dataset.keys");
139 : }
140 :
141 : } // namespace scipp::dataset
|