hops
H5Slice_traits_misc.hpp
Go to the documentation of this file.
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 H5_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 
32 namespace HighFive {
33 
34 namespace details {
35 
36 // map the correct reference to the dataset depending of the layout
37 // dataset -> itself
38 // subselection -> parent dataset
39 inline const DataSet& get_dataset(const Selection& sel) {
40  return sel.getDataset();
41 }
42 
43 inline 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
50 inline hid_t get_memspace_id(const Selection& ptr) {
51  return ptr.getMemSpace().getId();
52 }
53 
54 inline hid_t get_memspace_id(const DataSet&) {
55  return H5S_ALL;
56 }
57 } // namespace details
58 
59 inline ElementSet::ElementSet(std::initializer_list<std::size_t> list)
60  : _ids(list) {}
61 
62 inline ElementSet::ElementSet(std::initializer_list<std::vector<std::size_t>> list)
63  : ElementSet(std::vector<std::vector<std::size_t>>(list)) {}
64 
65 inline ElementSet::ElementSet(const std::vector<std::size_t>& element_ids)
66  : _ids(element_ids) {}
67 
68 inline 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 template <typename Derivate>
75 inline Selection SliceTraits<Derivate>::select(const std::vector<size_t>& offset,
76  const std::vector<size_t>& count,
77  const std::vector<size_t>& stride) const {
78  // hsize_t type conversion
79  // TODO : normalize hsize_t type in HighFive namespace
80  const auto& slice = static_cast<const Derivate&>(*this);
81  std::vector<hsize_t> offset_local(offset.size());
82  std::vector<hsize_t> count_local(count.size());
83  std::vector<hsize_t> stride_local(stride.size());
84  std::copy(offset.begin(), offset.end(), offset_local.begin());
85  std::copy(count.begin(), count.end(), count_local.begin());
86  std::copy(stride.begin(), stride.end(), stride_local.begin());
87 
88  DataSpace space = slice.getSpace().clone();
89  if (H5Sselect_hyperslab(space.getId(), H5S_SELECT_SET, offset_local.data(),
90  stride.empty() ? NULL : stride_local.data(),
91  count_local.data(), NULL) < 0) {
92  HDF5ErrMapper::ToException<DataSpaceException>("Unable to select hyperslap");
93  }
94 
95  return Selection(DataSpace(count), space, details::get_dataset(slice));
96 }
97 
98 template <typename Derivate>
99 inline Selection SliceTraits<Derivate>::select(const std::vector<size_t>& columns) const {
100  const auto& slice = static_cast<const Derivate&>(*this);
101  const DataSpace& space = slice.getSpace();
102  const DataSet& dataset = details::get_dataset(slice);
103  std::vector<size_t> dims = space.getDimensions();
104  std::vector<hsize_t> counts(dims.size());
105  std::copy(dims.begin(), dims.end(), counts.begin());
106  counts[dims.size() - 1] = 1;
107  std::vector<hsize_t> offsets(dims.size(), 0);
108 
109  H5Sselect_none(space.getId());
110 
111  for (const auto& column : columns) {
112  offsets[offsets.size() - 1] = column;
113 
114  if (H5Sselect_hyperslab(space.getId(), H5S_SELECT_OR, offsets.data(), 0,
115  counts.data(), 0) < 0) {
116  HDF5ErrMapper::ToException<DataSpaceException>("Unable to select hyperslap");
117  }
118  }
119 
120  dims[dims.size() - 1] = columns.size();
121  return Selection(DataSpace(dims), space, dataset);
122 }
123 
124 template <typename Derivate>
125 inline Selection SliceTraits<Derivate>::select(const ElementSet& elements) const {
126  const auto& slice = static_cast<const Derivate&>(*this);
127  const hsize_t* data = nullptr;
128  const DataSpace space = slice.getSpace().clone();
129  const std::size_t length = elements._ids.size();
130  if (length % space.getNumberDimensions() != 0) {
131  throw DataSpaceException("Number of coordinates in elements picking "
132  "should be a multiple of the dimensions.");
133  }
134  const std::size_t num_elements = length / space.getNumberDimensions();
135  std::vector<hsize_t> raw_elements;
136 
137  // optimised at compile time
138  // switch for data conversion on 32bits platforms
139  if (std::is_same<std::size_t, hsize_t>::value) {
140  // `if constexpr` can't be used, thus a reinterpret_cast is needed.
141  data = reinterpret_cast<const hsize_t*>(&(elements._ids[0]));
142  } else {
143  raw_elements.resize(length);
144  std::copy(elements._ids.begin(), elements._ids.end(), raw_elements.begin());
145  data = raw_elements.data();
146  }
147 
148  if (H5Sselect_elements(space.getId(), H5S_SELECT_SET, num_elements, data) < 0) {
149  HDF5ErrMapper::ToException<DataSpaceException>("Unable to select elements");
150  }
151 
152  return Selection(DataSpace(num_elements), space, details::get_dataset(slice));
153 }
154 
155 
156 template <typename Derivate>
157 template <typename T>
158 inline void SliceTraits<Derivate>::read(T& array) const {
159  const auto& slice = static_cast<const Derivate&>(*this);
160  const DataSpace& mem_space = slice.getMemSpace();
161  const details::BufferInfo<T> buffer_info(slice.getDataType());
162 
163  if (!details::checkDimensions(mem_space, buffer_info.n_dimensions)) {
164  std::ostringstream ss;
165  ss << "Impossible to read DataSet of dimensions "
166  << mem_space.getNumberDimensions() << " into arrays of dimensions "
167  << buffer_info.n_dimensions;
168  throw DataSpaceException(ss.str());
169  }
170  details::data_converter<T> converter(mem_space);
171  read(converter.transform_read(array), buffer_info.data_type);
172  // re-arrange results
173  converter.process_result(array);
174 }
175 
176 
177 template <typename Derivate>
178 template <typename T>
179 inline void SliceTraits<Derivate>::read(T* array, const DataType& dtype) const {
180  static_assert(!std::is_const<T>::value,
181  "read() requires a non-const structure to read data into");
182  const auto& slice = static_cast<const Derivate&>(*this);
183  using element_type = typename details::type_of_array<T>::type;
184 
185  // Auto-detect mem datatype if not provided
186  const DataType& mem_datatype =
187  dtype.empty() ? create_and_check_datatype<element_type>() : dtype;
188 
189  if (H5Dread(details::get_dataset(slice).getId(),
190  mem_datatype.getId(),
192  slice.getSpace().getId(), H5P_DEFAULT, static_cast<void*>(array)) < 0) {
193  HDF5ErrMapper::ToException<DataSetException>("Error during HDF5 Read: ");
194  }
195 }
196 
197 
198 template <typename Derivate>
199 template <typename T>
200 inline void SliceTraits<Derivate>::write(const T& buffer) {
201  const auto& slice = static_cast<const Derivate&>(*this);
202  const DataSpace& mem_space = slice.getMemSpace();
203  const details::BufferInfo<T> buffer_info(slice.getDataType());
204 
205  if (!details::checkDimensions(mem_space, buffer_info.n_dimensions)) {
206  std::ostringstream ss;
207  ss << "Impossible to write buffer of dimensions " << buffer_info.n_dimensions
208  << " into dataset of dimensions " << mem_space.getNumberDimensions();
209  throw DataSpaceException(ss.str());
210  }
211  details::data_converter<T> converter(mem_space);
212  write_raw(converter.transform_write(buffer), buffer_info.data_type);
213 }
214 
215 
216 template <typename Derivate>
217 template <typename T>
218 inline void SliceTraits<Derivate>::write_raw(const T* buffer, const DataType& dtype) {
219  using element_type = typename details::type_of_array<T>::type;
220  const auto& slice = static_cast<const Derivate&>(*this);
221  const auto& mem_datatype =
222  dtype.empty() ? create_and_check_datatype<element_type>() : dtype;
223 
224  if (H5Dwrite(details::get_dataset(slice).getId(),
225  mem_datatype.getId(),
227  slice.getSpace().getId(), H5P_DEFAULT,
228  static_cast<const void*>(buffer)) < 0) {
229  HDF5ErrMapper::ToException<DataSetException>("Error during HDF5 Write: ");
230  }
231 }
232 
233 } // namespace HighFive
234 
235 #endif // H5SLICE_TRAITS_MISC_HPP
H5ReadWrite_misc.hpp
HighFive::Selection
Selection: represent a view on a slice/part of a dataset.
Definition: H5Selection.hpp:23
HighFive::ElementSet::ElementSet
ElementSet(std::initializer_list< std::size_t > list)
Create a list of points of N-dimension for selection.
Definition: H5Slice_traits_misc.hpp:59
HighFive::SliceTraits::write_raw
void write_raw(const T *buffer, const DataType &dtype=DataType())
Definition: H5Slice_traits_misc.hpp:218
HighFive::DataSpace::getDimensions
std::vector< size_t > getDimensions() const
getDimensions
Definition: H5Dataspace_misc.hpp:99
HighFive::DataType
HDF5 Data Type.
Definition: H5DataType.hpp:42
HighFive::SliceTraits::read
void read(T &array) const
Definition: H5Slice_traits_misc.hpp:158
HighFive::details::get_dataset
const DataSet & get_dataset(const Selection &sel)
Definition: H5Slice_traits_misc.hpp:39
HighFive::details::data_converter::transform_write
const Scalar * transform_write(const Scalar &datamem) const noexcept
Definition: H5Converter_misc.hpp:137
HighFive::details::BufferInfo::n_dimensions
const size_t n_dimensions
Definition: H5ReadWrite_misc.hpp:28
HighFive::SliceTraits::select
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
Select a region in the current Slice/Dataset of count points at offset separated by stride....
Definition: H5Slice_traits_misc.hpp:75
HighFive::SliceTraits::write
void write(const T &buffer)
Definition: H5Slice_traits_misc.hpp:200
HighFive::Object::getId
hid_t getId() const noexcept
getId
Definition: H5Object_misc.hpp:55
HighFive::ElementSet
Definition: H5Slice_traits.hpp:20
HighFive::details::data_converter::process_result
void process_result(Scalar &) const noexcept
Definition: H5Converter_misc.hpp:141
HighFive::DataType::empty
bool empty() const noexcept
Check the DataType was default constructed. Such value might represent auto-detection of the datatype...
Definition: H5DataType_misc.hpp:28
HighFive::details::get_memspace_id
hid_t get_memspace_id(const Selection &ptr)
Definition: H5Slice_traits_misc.hpp:50
HighFive::details::BufferInfo
Definition: H5ReadWrite_misc.hpp:18
HighFive::Selection::getDataset
DataSet & getDataset() noexcept
getDataSet
Definition: H5Selection_misc.hpp:28
HighFive::details::type_of_array::type
unqualified_t< T > type
Definition: H5Utils.hpp:137
HighFive::details::data_converter::transform_read
Scalar * transform_read(Scalar &datamem) const noexcept
Definition: H5Converter_misc.hpp:133
HighFive::Selection::getMemSpace
DataSpace getMemSpace() const noexcept
getMemSpace
Definition: H5Selection_misc.hpp:24
copy
free of to any person obtaining a copy of this software and associated documentation to deal in the Software without including without limitation the rights to copy
Definition: LICENSE.txt:6
HighFive::details::BufferInfo::data_type
const DataType data_type
Definition: H5ReadWrite_misc.hpp:29
HighFive::DataSpace
Class representing the space (dimensions) of a dataset.
Definition: H5DataSpace.hpp:37
H5Converter_misc.hpp
HighFive::DataSpace::clone
DataSpace clone() const
Definition: H5Dataspace_misc.hpp:82
HighFive::details::data_converter
Definition: H5_definitions.hpp:57
HighFive::details::checkDimensions
bool checkDimensions(const DataSpace &mem_space, size_t input_dims)
dimension checks
Definition: H5Dataspace_misc.hpp:227
HighFive::DataSpace::getNumberDimensions
size_t getNumberDimensions() const
getNumberDimensions
Definition: H5Dataspace_misc.hpp:90
HighFive::DataSet
Class representing a dataset.
Definition: H5DataSet.hpp:27
HighFive
Definition: H5_definitions.hpp:15
HighFive::DataSpaceException
Exception specific to HighFive DataSpace interface.
Definition: H5Exception.hpp:99