GCC Code Coverage Report


Directory: gridformat/
File: gridformat/vtk/vti_reader.hpp
Date: 2024-11-10 16:24:00
Exec Total Coverage
Lines: 75 84 89.3%
Functions: 20 21 95.2%
Branches: 38 86 44.2%

Line Branch Exec Source
1 // SPDX-FileCopyrightText: 2022-2023 Dennis Gläser <dennis.glaeser@iws.uni-stuttgart.de>
2 // SPDX-License-Identifier: MIT
3 /*!
4 * \file
5 * \ingroup VTK
6 * \copydoc GridFormat::VTIReader
7 */
8 #ifndef GRIDFORMAT_VTK_VTI_READER_HPP_
9 #define GRIDFORMAT_VTK_VTI_READER_HPP_
10
11 #include <string>
12 #include <optional>
13 #include <algorithm>
14 #include <utility>
15 #include <ranges>
16 #include <array>
17 #include <cmath>
18
19 #include <gridformat/common/exceptions.hpp>
20 #include <gridformat/common/precision.hpp>
21 #include <gridformat/common/ranges.hpp>
22 #include <gridformat/common/field.hpp>
23 #include <gridformat/common/lazy_field.hpp>
24
25 #include <gridformat/grid/reader.hpp>
26 #include <gridformat/vtk/common.hpp>
27 #include <gridformat/vtk/xml.hpp>
28
29 namespace GridFormat {
30
31 /*!
32 * \ingroup VTK
33 * \brief Reader for .vti file format
34 */
35 class VTIReader : public GridReader {
36 private:
37 struct ImageSpecs {
38 std::array<std::size_t, 6> extents;
39 std::array<double, 3> spacing;
40 std::array<double, 3> origin;
41 std::array<double, 9> direction;
42 };
43
44 300 void _open(const std::string& filename, typename GridReader::FieldNames& fields) override {
45
1/2
✓ Branch 2 taken 300 times.
✗ Branch 3 not taken.
300 auto helper = VTK::XMLReaderHelper::make_from(filename, "ImageData");
46 300 auto specs = ImageSpecs{};
47
3/6
✓ Branch 2 taken 300 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 300 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 300 times.
✗ Branch 10 not taken.
300 specs.extents = Ranges::array_from_string<std::size_t, 6>(helper.get("ImageData/Piece").get_attribute("Extent"));
48
3/6
✓ Branch 2 taken 300 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 300 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 300 times.
✗ Branch 10 not taken.
300 specs.spacing = Ranges::array_from_string<double, 3>(helper.get("ImageData").get_attribute("Spacing"));
49
3/6
✓ Branch 2 taken 300 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 300 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 300 times.
✗ Branch 10 not taken.
300 specs.origin = Ranges::array_from_string<double, 3>(helper.get("ImageData").get_attribute("Origin"));
50
3/6
✓ Branch 2 taken 300 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 300 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 300 times.
✗ Branch 10 not taken.
600 specs.direction = Ranges::array_from_string<double, 9>(helper.get("ImageData").get_attribute_or(
51
1/2
✓ Branch 1 taken 300 times.
✗ Branch 2 not taken.
600 std::string{"1 0 0 0 1 0 0 0 1"}, "Direction"
52 ));
53
54
2/4
✓ Branch 2 taken 300 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 300 times.
✗ Branch 6 not taken.
300 VTK::XMLDetail::copy_field_names_from(helper.get("ImageData"), fields);
55 300 _helper.emplace(std::move(helper));
56 300 _image_specs.emplace(std::move(specs));
57 300 }
58
59 44 void _close() override {
60 44 _helper.reset();
61 44 _image_specs.reset();
62 44 }
63
64 1 std::string _name() const override {
65
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 return "VTIReader";
66 }
67
68 1543 std::size_t _number_of_cells() const override {
69 1543 return VTK::CommonDetail::number_of_entities(_specs().extents);
70 }
71
72 1544 std::size_t _number_of_points() const override {
73
2/4
✓ Branch 1 taken 1544 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1404 times.
✗ Branch 5 not taken.
1544 return VTK::CommonDetail::number_of_entities(_point_extents());
74 }
75
76 7 std::size_t _number_of_pieces() const override {
77 7 return 1;
78 }
79
80 13 typename GridReader::Vector _origin() const override {
81 13 return _specs().origin;
82 }
83
84 13 typename GridReader::Vector _spacing() const override {
85 13 return _specs().spacing;
86 }
87
88 typename GridReader::Vector _basis_vector(unsigned int i) const override {
89 const auto specs = _specs();
90 return {
91 specs.direction.at(i),
92 specs.direction.at(i+3),
93 specs.direction.at(i+6)
94 };
95 }
96
97 314 typename GridReader::PieceLocation _location() const override {
98 314 const auto& specs = _specs();
99 typename GridReader::PieceLocation result;
100 314 result.lower_left = {specs.extents[0], specs.extents[2], specs.extents[4]};
101 314 result.upper_right = {specs.extents[1], specs.extents[3], specs.extents[5]};
102 314 return result;
103 }
104
105 34 std::vector<double> _ordinates(unsigned int direction) const override {
106
1/2
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
34 const auto& specs = _specs();
107
1/2
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
34 const auto extents = _point_extents();
108 34 const auto extent_begin = extents[direction*2];
109 34 const std::size_t num_ordinates = extents[2*direction + 1] - extent_begin;
110
1/2
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
34 std::vector<double> ordinates(num_ordinates);
111
1/2
✓ Branch 2 taken 34 times.
✗ Branch 3 not taken.
68 std::ranges::copy(
112
2/4
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 34 times.
✗ Branch 5 not taken.
34 std::views::iota(std::size_t{0}, num_ordinates) | std::views::transform([&] (std::size_t i) {
113 122 return specs.origin[direction] + (extent_begin + i)*specs.spacing[direction];
114
1/2
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
34 }),
115 ordinates.begin()
116 );
117 34 return ordinates;
118 }
119
120 85 bool _is_sequence() const override {
121 85 return false;
122 }
123
124 217 FieldPtr _points() const override {
125
1/2
✓ Branch 1 taken 217 times.
✗ Branch 2 not taken.
217 const auto pextents = _point_extents();
126
1/2
✓ Branch 1 taken 207 times.
✗ Branch 2 not taken.
217 const auto num_points = VTK::CommonDetail::number_of_entities(pextents);
127 217 return make_field_ptr(LazyField{
128 int{}, // dummy "source"
129 MDLayout{{num_points, std::size_t{3}}},
130 Precision<double>{},
131
1/2
✓ Branch 1 taken 217 times.
✗ Branch 2 not taken.
217 [specs=_specs(), pextents=pextents] (const int&) {
132 return VTK::CommonDetail::serialize_structured_points(
133 217 pextents,
134 217 specs.origin,
135 217 specs.spacing,
136 217 specs.direction
137 217 );
138 }
139
3/6
✓ Branch 1 taken 217 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 217 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 217 times.
✗ Branch 9 not taken.
651 });
140 }
141
142 321 void _visit_cells(const typename GridReader::CellVisitor& visitor) const override {
143 321 VTK::CommonDetail::visit_structured_cells(visitor, _specs().extents);
144 321 }
145
146 737 FieldPtr _cell_field(std::string_view name) const override {
147
2/4
✓ Branch 2 taken 737 times.
✗ Branch 3 not taken.
✓ Branch 7 taken 737 times.
✗ Branch 8 not taken.
737 return _helper.value().make_data_array_field(name, "ImageData/Piece/CellData", _number_of_cells());
148 }
149
150 740 FieldPtr _point_field(std::string_view name) const override {
151
2/4
✓ Branch 2 taken 740 times.
✗ Branch 3 not taken.
✓ Branch 7 taken 740 times.
✗ Branch 8 not taken.
740 return _helper.value().make_data_array_field(name, "ImageData/Piece/PointData", _number_of_points());
152 }
153
154 54 FieldPtr _meta_data_field(std::string_view name) const override {
155
1/2
✓ Branch 4 taken 54 times.
✗ Branch 5 not taken.
54 return _helper.value().make_data_array_field(name, "ImageData/FieldData");
156 }
157
158 1795 std::array<std::size_t, 6> _point_extents() const {
159 1795 auto result = _specs().extents;
160 1795 result[1] += 1;
161 1795 result[3] += 1;
162 1795 result[5] += 1;
163 1795 return result;
164 }
165
166 4250 const ImageSpecs& _specs() const {
167
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4250 times.
4250 if (!_image_specs.has_value())
168 throw ValueError("No data has been read");
169 4250 return _image_specs.value();
170 }
171
172 std::optional<VTK::XMLReaderHelper> _helper;
173 std::optional<ImageSpecs> _image_specs;
174 };
175
176 } // namespace GridFormat
177
178 #endif // GRIDFORMAT_VTK_VTI_READER_HPP_
179