h5gt 0.2.0
C++ wrapper for HDF5 library (based on HighFive project)
Loading...
Searching...
No Matches
H5Slice_traits_misc.hpp
1/*
2 * Copyright (c), 2017, Adrien Devresse <adrien.devresse@epfl.ch>
3 *
4 * Distributed under the Boost Software License, Version 1.0.
5 * (See accompanying file LICENSE_1_0.txt or copy at
6 * http://www.boost.org/LICENSE_1_0.txt)
7 *
8 */
9#ifndef H5SLICE_TRAITS_MISC_HPP
10#define H5SLICE_TRAITS_MISC_HPP
11
12#include <algorithm>
13#include <cassert>
14#include <functional>
15#include <numeric>
16#include <sstream>
17#include <string>
18
19#ifdef H5GT_USE_BOOST
20// starting Boost 1.64, serialization header must come before ublas
21#include <boost/multi_array.hpp>
22#include <boost/numeric/ublas/matrix.hpp>
23#include <boost/serialization/vector.hpp>
24#endif
25
26#include <H5Dpublic.h>
27#include <H5Ppublic.h>
28
29#include "H5ReadWrite_misc.hpp"
30#include "H5Converter_misc.hpp"
31
32namespace h5gt {
33
34namespace details {
35
36// map the correct reference to the dataset depending of the layout
37// dataset -> itself
38// subselection -> parent dataset
39inline const DataSet& get_dataset(const Selection& sel) {
40 return sel.getDataset();
41}
42
43inline const DataSet& get_dataset(const DataSet& ds) {
44 return ds;
45}
46
47// map the correct memspace identifier depending of the layout
48// dataset -> entire memspace
49// selection -> resolve space id
50inline hid_t get_memspace_id(const Selection& ptr) {
51 return ptr.getMemSpace().getId(false);
52}
53
54inline hid_t get_memspace_id(const DataSet&) {
55 return H5S_ALL;
56}
57} // namespace details
58
59inline ElementSet::ElementSet(std::initializer_list<std::size_t> list)
60 : _ids(list) {}
62inline ElementSet::ElementSet(std::initializer_list<std::vector<std::size_t>> list)
63 : ElementSet(std::vector<std::vector<std::size_t>>(list)) {}
64
65inline ElementSet::ElementSet(const std::vector<std::size_t>& element_ids)
66 : _ids(element_ids) {}
68inline ElementSet::ElementSet(const std::vector<std::vector<std::size_t>>& element_ids) {
69 for (const auto& vec : element_ids) {
70 std::copy(vec.begin(), vec.end(), std::back_inserter(_ids));
71 }
72}
73
74
75template <typename Derivate>
76inline Selection SliceTraits<Derivate>::select(const std::vector<size_t>& offset,
77 const std::vector<size_t>& count,
78 const std::vector<size_t>& stride,
79 const std::vector<size_t>& block) const {
80 // hsize_t type conversion
81 // TODO : normalize hsize_t type in h5gt namespace
82 const auto& slice = static_cast<const Derivate&>(*this);
83 std::vector<hsize_t> offset_local(offset.size());
84 std::vector<hsize_t> count_local(count.size());
85 std::vector<hsize_t> stride_local(stride.size());
86 std::vector<hsize_t> block_local(block.size());
87 std::copy(offset.begin(), offset.end(), offset_local.begin());
88 std::copy(count.begin(), count.end(), count_local.begin());
89 std::copy(stride.begin(), stride.end(), stride_local.begin());
90 std::copy(block.begin(), block.end(), block_local.begin());
91
92 DataSpace space = slice.getSpace().clone();
93 if (H5Sselect_hyperslab(space.getId(false), H5S_SELECT_SET, offset_local.data(),
94 stride.empty() ? NULL : stride_local.data(),
95 count_local.data(),
96 block.empty() ? NULL : block_local.data()) < 0) {
97 HDF5ErrMapper::ToException<DataSpaceException>("Unable to select hyperslap");
98 }
99
100 if (block.empty()){
101 return Selection(DataSpace(count), space, details::get_dataset(slice));
103
104 std::vector<size_t> count_block(block.size());
105 for (size_t i = 0; i < count_block.size(); i++){
106 count_block[i] = count[i]*block[i];
107 }
108 return Selection(DataSpace(count_block), space, details::get_dataset(slice));
109}
111template <typename Derivate>
113 const auto& slice = static_cast<const Derivate&>(*this);
114 const hsize_t* data = nullptr;
115 const DataSpace space = slice.getSpace().clone();
116 const std::size_t length = elements._ids.size();
117 if (length % space.getNumberDimensions() != 0) {
118 throw DataSpaceException("Number of coordinates in elements picking "
119 "should be a multiple of the dimensions.");
121 const std::size_t num_elements = length / space.getNumberDimensions();
122 std::vector<hsize_t> raw_elements;
123
124 // optimised at compile time
125 // switch for data conversion on 32bits platforms
126 if (std::is_same<std::size_t, hsize_t>::value) {
127 // `if constexpr` can't be used, thus a reinterpret_cast is needed.
128 data = reinterpret_cast<const hsize_t*>(&(elements._ids[0]));
129 } else {
130 raw_elements.resize(length);
131 std::copy(elements._ids.begin(), elements._ids.end(), raw_elements.begin());
132 data = raw_elements.data();
133 }
134
135 if (H5Sselect_elements(space.getId(false), H5S_SELECT_SET, num_elements, data) < 0) {
136 HDF5ErrMapper::ToException<DataSpaceException>("Unable to select elements");
137 }
138
139 return Selection(DataSpace(num_elements), space, details::get_dataset(slice));
140}
141
142
143template <typename Derivate>
145 const std::vector<size_t>& ind, size_t offset, size_t count) const {
146 const auto& slice = static_cast<const Derivate&>(*this);
147 const DataSpace& space = slice.getSpace();
148 const DataSet& dataset = details::get_dataset(slice);
149 std::vector<size_t> dims = space.getDimensions();
150 dims[0] = ind.size();
151 std::vector<hsize_t> counts(dims.size());
152 std::copy(dims.begin(), dims.end(), counts.begin());
153 counts[0] = 1;
154 std::vector<hsize_t> offsets(dims.size(), 0);
155
156 if (offset != 0 && offsets.size() > 1){
157 offsets[1] = offset;
158 // if count is not defined by the user
159 if (count == 0)
160 count = dims[1] - offset;
161 }
162
163 if (count != 0 && counts.size() > 1){
164 counts[1] = count;
165 dims[1] = count;
166 }
167
168 H5Sselect_none(space.getId(false));
169
170 for (const auto& i : ind) {
171 offsets[0] = i;
172
173 if (H5Sselect_hyperslab(space.getId(false), H5S_SELECT_OR, offsets.data(), 0,
174 counts.data(), 0) < 0) {
175 HDF5ErrMapper::ToException<DataSpaceException>("Unable to select hyperslap");
176 }
177 }
178
179 return Selection(DataSpace(dims), space, dataset);
180}
181
182template <typename Derivate>
184 const std::vector<size_t>& ind, size_t offset, size_t count) const {
185 const auto& slice = static_cast<const Derivate&>(*this);
186 const DataSpace& space = slice.getSpace();
187 const DataSet& dataset = details::get_dataset(slice);
188 std::vector<size_t> dims = space.getDimensions();
189 dims[dims.size() - 1] = ind.size();
190 std::vector<hsize_t> counts(dims.size());
191 std::copy(dims.begin(), dims.end(), counts.begin());
192 counts[dims.size() - 1] = 1;
193 std::vector<hsize_t> offsets(dims.size(), 0);
194
195 if (offset != 0 && offsets.size() > 0){
196 offsets[0] = offset;
197 // if count is not defined by the user
198 if (count == 0)
199 count = dims[0] - offset;
200 }
201
202 if (count != 0 && counts.size() > 0){
203 counts[0] = count;
204 dims[0] = count;
205 }
206
207
208 H5Sselect_none(space.getId(false));
209
210 for (const auto& i : ind) {
211 offsets[offsets.size() - 1] = i;
212
213 if (H5Sselect_hyperslab(space.getId(false), H5S_SELECT_OR, offsets.data(), 0,
214 counts.data(), 0) < 0) {
215 HDF5ErrMapper::ToException<DataSpaceException>("Unable to select hyperslap");
216 }
217 }
218
219 return Selection(DataSpace(dims), space, dataset);
220}
221
222template <typename Derivate>
223template <typename T>
224inline void SliceTraits<Derivate>::read(T& array) const {
225 const auto& slice = static_cast<const Derivate&>(*this);
226 const DataSpace& mem_space = slice.getMemSpace();
227 const details::BufferInfo<T> buffer_info(slice.getDataType());
228
229 if (!details::checkDimensions(mem_space, buffer_info.n_dimensions)) {
230 std::ostringstream ss;
231 ss << "Impossible to read DataSet of dimensions "
232 << mem_space.getNumberDimensions() << " into arrays of dimensions "
233 << buffer_info.n_dimensions;
234 throw DataSpaceException(ss.str());
235 }
236 details::data_converter<T> converter(mem_space, buffer_info.data_type);
237 if (buffer_info.data_type.getClass() == DataTypeClass::Compound){
238
239 }
240 read(converter.transform_read(array), buffer_info.data_type);
241 // re-arrange results
242 converter.process_result(array);
243}
244
245
246template <typename Derivate>
247template <typename T>
254inline void SliceTraits<Derivate>::read(T* array, const DataType& dtype) const {
255 static_assert(!std::is_const<T>::value,
256 "read() requires a non-const structure to read data into");
257 const auto& slice = static_cast<const Derivate&>(*this);
258 using element_type = typename details::inspector<T>::base_type;
259
260 // Auto-detect mem datatype if not provided
261 const DataType& mem_datatype =
262 dtype.empty() ? create_and_check_datatype<element_type>() : dtype;
263
264 if (H5Dread(details::get_dataset(slice).getId(false),
265 mem_datatype.getId(false),
266 details::get_memspace_id(slice),
267 slice.getSpace().getId(false), H5P_DEFAULT, static_cast<void*>(array)) < 0) {
268 HDF5ErrMapper::ToException<DataSetException>("Error during HDF5 Read: ");
269 }
270}
271
272
273template <typename Derivate>
274template <typename T>
275inline void SliceTraits<Derivate>::write(const T& buffer) {
276 const auto& slice = static_cast<const Derivate&>(*this);
277 const DataSpace& mem_space = slice.getMemSpace();
278 const details::BufferInfo<T> buffer_info(slice.getDataType());
279
280 if (!details::checkDimensions(mem_space, buffer_info.n_dimensions)) {
281 std::ostringstream ss;
282 ss << "Impossible to write buffer of dimensions " << buffer_info.n_dimensions
283 << " into dataset of dimensions " << mem_space.getNumberDimensions();
284 throw DataSpaceException(ss.str());
285 }
286 details::data_converter<T> converter(mem_space, buffer_info.data_type);
287 write_raw(converter.transform_write(buffer), buffer_info.data_type);
288}
289
290
291template <typename Derivate>
292template <typename T>
293inline void SliceTraits<Derivate>::write_raw(const T* buffer, const DataType& dtype) {
294 using element_type = typename details::inspector<T>::base_type;
295 const auto& slice = static_cast<const Derivate&>(*this);
296 const auto& mem_datatype =
297 dtype.empty() ? create_and_check_datatype<element_type>() : dtype;
298
299 if (H5Dwrite(details::get_dataset(slice).getId(false),
300 mem_datatype.getId(false),
301 details::get_memspace_id(slice),
302 slice.getSpace().getId(false), H5P_DEFAULT,
303 static_cast<const void*>(buffer)) < 0) {
304 HDF5ErrMapper::ToException<DataSetException>("Error during HDF5 Write: ");
305 }
306}
307
308} // namespace h5gt
309
310#endif // H5SLICE_TRAITS_MISC_HPP
Class representing a dataset.
Definition H5DataSet.hpp:28
Exception specific to h5gt DataSpace interface.
Definition H5Exception.hpp:99
Class representing the space (dimensions) of a dataset.
Definition H5DataSpace.hpp:37
DataSpace clone() const
Definition H5Dataspace_misc.hpp:86
size_t getNumberDimensions() const
getNumberDimensions
Definition H5Dataspace_misc.hpp:94
std::vector< size_t > getDimensions() const
getDimensions
Definition H5Dataspace_misc.hpp:103
HDF5 Data Type.
Definition H5DataType.hpp:48
bool empty() const noexcept
Check the DataType was default constructed. Such value might represent auto-detection of the datatype...
Definition H5DataType_misc.hpp:28
DataTypeClass getClass() const
Return the fundamental type.
Definition H5DataType_misc.hpp:32
Definition H5Slice_traits.hpp:20
ElementSet(std::initializer_list< std::size_t > list)
Create a list of points of N-dimension for selection.
Definition H5Slice_traits_misc.hpp:59
hid_t getId(const bool &increaseRefCount=false) const noexcept
getId
Definition H5Object_misc.hpp:172
Selection: represent a view on a slice/part of a dataset.
Definition H5Selection.hpp:23
Selection select_rows(const std::vector< size_t > &ind, size_t offset=0, size_t count=0) const
Select a set of rows in the first dimension of this dataset. NOTE: Selection is done in memory layout...
Definition H5Slice_traits_misc.hpp:144
void write(const T &buffer)
Definition H5Slice_traits_misc.hpp:275
void write_raw(const T *buffer, const DataType &dtype=DataType())
Definition H5Slice_traits_misc.hpp:293
void read(T &array) const
Definition H5Slice_traits_misc.hpp:224
Selection select_cols(const std::vector< size_t > &ind, size_t offset=0, size_t count=0) const
Select a set of columns in the last dimension of this dataset. NOTE: Selection is done in memory layo...
Definition H5Slice_traits_misc.hpp:183
Selection select(const std::vector< size_t > &offset, const std::vector< size_t > &count, const std::vector< size_t > &stride=std::vector< size_t >(), const std::vector< size_t > &block=std::vector< size_t >()) const
Select a region in the current Slice/Dataset of count points at offset separated by stride....
Definition H5Slice_traits_misc.hpp:76
Definition H5ReadWrite_misc.hpp:18
Definition H5Converter_misc.hpp:124