echelon  0.8.0
hdf5/dataset.hpp
1 // Copyright (c) 2012-2014 Christopher Hinz
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 #ifndef ECHELON_HDF5_DATASET_HPP
7 #define ECHELON_HDF5_DATASET_HPP
8 
9 #include <echelon/hdf5/object.hpp>
10 
11 #include <echelon/hdf5/type.hpp>
12 #include <echelon/hdf5/type_factory.hpp>
13 #include <echelon/hdf5/object_reference.hpp>
14 
15 #include <echelon/hdf5/slice.hpp>
16 #include <echelon/hdf5/range.hpp>
17 #include <echelon/hdf5/container_adaption.hpp>
18 #include <echelon/hdf5/array_slice.hpp>
19 
20 #include <echelon/hdf5/attribute_repository.hpp>
21 #include <echelon/hdf5/dataset_dimensions.hpp>
22 #include <echelon/hdf5/storage_layer.hpp>
23 
24 #include <echelon/hdf5/precursor/dataset.hpp>
25 #include <echelon/hdf5/precursor/dataspace.hpp>
26 #include <echelon/hdf5/precursor/property_list.hpp>
27 
28 #include <echelon/utility/macros.hpp>
29 
30 #include <vector>
31 #include <tuple>
32 #include <string>
33 #include <type_traits>
34 #include <cassert>
35 #include <iterator>
36 #include <exception>
37 #include <utility>
38 
39 namespace echelon
40 {
41 namespace hdf5
42 {
43 
44 class invalid_layout_exception : public std::exception
45 {
46 public:
47  explicit invalid_layout_exception(std::string what_) : what_{std::move(what_)}
48  {
49  }
50 
51  const char* what() const noexcept override
52  {
53  return what_.c_str();
54  }
55 
56 private:
57  std::string what_;
58 };
59 
62 class dataset
63 {
64 public:
67  using native_handle_type = hdf5::precursor::dataset;
68 
71  dataset() = default;
72 
73  dataset(const object& parent, const std::string& name, const type& datatype,
74  const std::vector<hsize_t>& shape, const std::vector<hsize_t>& max_dims, int comp_level,
75  bool auto_chunking, bool shuffle_filter, const std::vector<hsize_t> chunk_shape);
76 
77  explicit dataset(native_handle_type native_handle_);
78 
89  template <typename T>
90  friend void operator<<=(dataset& sink, const T& source)
91  {
92  using std::begin;
93  using std::end;
94 
95  const auto& current_shape = shape_adl(source);
96 
97  std::vector<hsize_t> mem_shape(begin(current_shape), end(current_shape));
98 
99  hdf5::precursor::dataspace mem_space(mem_shape);
100  hdf5::precursor::dataspace file_space = sink.dataset_handle_.get_space();
101  hdf5::precursor::type datatype = sink.dataset_handle_.datatype();
102 
103  write(sink.dataset_handle_, datatype, mem_space, file_space, source);
104  }
105 
114  template <typename T>
115  friend void operator<<=(T& sink, const dataset& source)
116  {
117  using std::begin;
118  using std::end;
119 
120  const auto& current_shape = shape_adl(sink);
121 
122  std::vector<hsize_t> mem_shape(begin(current_shape), end(current_shape));
123 
124  hdf5::precursor::dataspace mem_space(mem_shape);
125  hdf5::precursor::dataspace file_space = source.dataset_handle_.get_space();
126  hdf5::precursor::type datatype = source.dataset_handle_.datatype();
127 
128  read(source.dataset_handle_, datatype, mem_space, file_space, sink);
129  }
130 
140  template <typename T>
141  friend void operator<<=(dataset& sink, const array_slice<T>& source)
142  {
143  using std::begin;
144  using std::end;
145 
146  const auto& current_shape = source.original_shape();
147 
148  std::vector<hsize_t> mem_shape(begin(current_shape), end(current_shape));
149 
150  hdf5::precursor::dataspace mem_space(mem_shape);
151  hdf5::precursor::dataspace file_space = sink.dataset_handle_.get_space();
152  hdf5::precursor::type datatype = sink.dataset_handle_.datatype();
153 
154  auto slice_shape = source.shape();
155  std::vector<hsize_t> count;
156 
157  for (std::size_t i = 0; i < slice_shape.size(); ++i)
158  {
159  count.push_back(slice_shape[i] / source.stride()[i]);
160  }
161 
162  mem_space.select_hyperslab(H5S_SELECT_SET, source.offset(), source.stride(), count);
163 
164  write(sink.dataset_handle_, datatype, mem_space, file_space, source);
165  }
166 
174  template <typename T>
175  friend void operator<<=(const array_slice<T>& sink, const dataset& source)
176  {
177  using std::begin;
178  using std::end;
179 
180  const auto& current_shape = sink.original_shape();
181 
182  std::vector<hsize_t> mem_shape(begin(current_shape), end(current_shape));
183 
184  hdf5::precursor::dataspace mem_space(mem_shape);
185  hdf5::precursor::dataspace file_space = source.dataset_handle_.get_space();
186  hdf5::precursor::type datatype = source.dataset_handle_.datatype();
187 
188  auto slice_shape = sink.shape();
189  std::vector<hsize_t> count;
190 
191  for (std::size_t i = 0; i < slice_shape.size(); ++i)
192  {
193  count.push_back(slice_shape[i] / sink.stride()[i]);
194  }
195 
196  mem_space.select_hyperslab(H5S_SELECT_SET, sink.offset(), sink.stride(), count);
197 
198  read(source.dataset_handle_, datatype, mem_space, file_space, sink);
199  }
200 
209  template <typename Container>
210  void extend_along(std::size_t dimension_index, const Container& container) const
211  {
212  using std::begin;
213  using std::end;
214 
215  auto extent = shape();
216  auto new_extent = extent;
217  auto container_shape = shape_adl(container);
218 
219  for (std::size_t i = 0; i < extent.size(); ++i)
220  {
221  if (i != dimension_index && container_shape[i] != extent[i])
222  throw invalid_layout_exception(
223  "extent of non-extended dimension differs between container and dataset");
224  }
225 
226  new_extent[dimension_index] += container_shape[dimension_index];
227 
228  dataset_handle_.set_extent(new_extent);
229 
230  // FIXME: extend slicing and refactor this code
231  std::vector<hsize_t> mem_shape(begin(container_shape), end(container_shape));
232 
233  hdf5::precursor::dataspace mem_space(mem_shape);
234  hdf5::precursor::dataspace file_space = dataset_handle_.get_space();
235  hdf5::precursor::type datatype = dataset_handle_.datatype();
236 
237  std::vector<hsize_t> offset(rank());
238  offset[dimension_index] = extent[dimension_index];
239 
240  file_space.select_hyperslab(H5S_SELECT_SET, offset, mem_shape);
241 
242  write(dataset_handle_, datatype, mem_space, file_space, container);
243  }
244 
247  std::vector<hsize_t> shape() const;
248 
251  std::size_t rank() const;
252 
255  type datatype() const;
256 
312  template <typename... Args>
313  slice operator()(Args... args) const
314  {
315  std::vector<hsize_t> current_shape = shape();
316 
317  std::vector<totally_bound_range_t> boundaries;
318 
319  detail::calculate_slice_boundaries<0, Args...>::eval(current_shape, boundaries, args...);
320 
321  return slice(dataset_handle_, boundaries);
322  }
323 
326  object_reference ref() const;
327 
330  const native_handle_type& native_handle() const;
331 
334  explicit operator bool() const;
335 private:
336  hdf5::precursor::dataset dataset_handle_;
337 
338 public:
341  attribute_repository<dataset> attributes() const;
342 
345  dataset_dimensions dimensions() const;
346 };
347 }
348 }
349 
350 #endif
echelon&#39;s core namespace
Definition: attribute.cpp:10
A handle to an HDF5 dataset.
Definition: hdf5/dataset.hpp:62
Accessor class for the dimensions of a dataset.
Definition: hdf5/dataset_dimensions.hpp:87
void extend_along(std::size_t dimension_index, const Container &container) const
Extends the dataset along a given dimension.
Definition: hdf5/dataset.hpp:210
A slice (rectangular portion) of an HDF5 dataset.
Definition: hdf5/slice.hpp:27
friend void operator<<=(T &sink, const dataset &source)
Reads the content of the dataset into a data sink.
Definition: hdf5/dataset.hpp:115
friend void operator<<=(dataset &sink, const T &source)
Writes the content of a data source into the dataset.
Definition: hdf5/dataset.hpp:90
A handle to an HDF5 type.
Definition: hdf5/type.hpp:23
Attribute manager, which should be embedded into a parent object, which supports attributes.
Definition: hdf5/attribute_repository.hpp:52
A reference to an HDF5 object.
Definition: hdf5/object_reference.hpp:25
slice operator()(Args...args) const
Slices the dataset.
Definition: hdf5/dataset.hpp:313
hdf5::precursor::dataset native_handle_type
Type of the underlying HDF5 low-level handle.
Definition: hdf5/dataset.hpp:67