RMF
ConstDataSetD.h
Go to the documentation of this file.
1 /**
2  * \file RMF/HDF5/ConstDataSetD.h
3  * \brief Handle read/write of Model data from/to files.
4  *
5  * Copyright 2007-2022 IMP Inventors. All rights reserved.
6  *
7  */
8 
9 #ifndef RMF_HDF5_CONST_DATA_SET_D_H
10 #define RMF_HDF5_CONST_DATA_SET_D_H
11 
12 #include "RMF/config.h"
13 #include "RMF/log.h"
14 #include "types.h"
15 #include "ConstAttributes.h"
16 #include "Object.h"
17 #include "DataSetIndexD.h"
19 #include "infrastructure_macros.h"
20 #include <algorithm>
21 #include <memory>
22 
23 RMF_ENABLE_WARNINGS
24 
25 namespace RMF {
26 namespace HDF5 {
27 class Group;
28 typedef ConstAttributes<Object> ConstDataSetAttributes;
29 #ifndef RMF_DOXYGEN
30 typedef std::vector<ConstDataSetAttributes> ConstDataSetAttributesList;
31 #endif
32 
33 /** Wrap an HDF5 data set. Typedefs and python types are provided for
34  data sets in 1,2, and 3 dimensions with all the supported types. They are
35  named as
36  RMF::HDF5IndexDataSet2D (or RMF.HDF5IndexDataSet2).
37  See
38  \external{https://support.hdfgroup.org/HDF5/doc/RM/RM_H5D.html,
39  the HDF5 manual} for more information.
40  */
41 template <class TypeTraits, unsigned int D>
43  typedef ConstDataSetAttributes P;
44  struct Data {
45  Handle ids_;
46  Handle rds_;
47  Handle sel_;
48  hsize_t ones_[D];
49  DataSetIndexD<D> size_;
50  };
51 
52  std::shared_ptr<Data> data_;
53  int compare(const ConstDataSetD<TypeTraits, D>& o) const {
54  // not great, but...
55  if (data_ && !o.data_)
56  return -1;
57  else if (o.data_ && !data_)
58  return 1;
59  else if (!o.data_ && !data_)
60  return 0;
61  else if (get_name() < o.get_name())
62  return -1;
63  else if (get_name() > o.get_name())
64  return 1;
65  else
66  return 0;
67  }
68 
69  bool get_is_null_value(const DataSetIndexD<D>& ijk) const {
70  return TypeTraits::get_is_null_value(get_value(ijk));
71  }
72  void initialize() {
73  hsize_t one = 1;
74  data_->ids_.open(H5Screate_simple(1, &one, nullptr), &H5Sclose);
75  std::fill(data_->ones_, data_->ones_ + D, 1);
76  // pos_.reset(new hsize_t[dim_]);
77  // sel_= new SharedHandle(H5Dget_space(h_->get_hid()), &H5Sclose);
78  initialize_handles();
79  RMF_TRACE("Opened data set with size " << get_size());
80  }
81  friend class ConstGroup;
82 
83  protected:
86 
87  ConstDataSetD(std::shared_ptr<SharedHandle> parent, std::string name,
88  CreationProperties props)
89  : data_(new Data()) {
90  // std::cout << "Creating data set " << name << std::endl;
91  RMF_USAGE_CHECK(
92  !H5Lexists(parent->get_hid(), name.c_str(), H5P_DEFAULT),
93  RMF::internal::get_error_message("Data set ", name, " already exists"));
94  hsize_t dims[D] = {0};
95  hsize_t maxs[D];
96  std::fill(maxs, maxs + D, H5S_UNLIMITED);
97  RMF_HDF5_HANDLE(ds, H5Screate_simple(D, dims, maxs), &H5Sclose);
98  // std::cout << "creating..." << name << std::endl;
99  P::open(std::make_shared<SharedHandle>(
100  H5Dcreate2(parent->get_hid(), name.c_str(),
101  TypeTraits::get_hdf5_disk_type(), ds, H5P_DEFAULT,
102  props.get_handle(), H5P_DEFAULT),
103  &H5Dclose, name));
104  initialize();
105  // std::cout << "done..." << std::endl;
106  }
107  ConstDataSetD(std::shared_ptr<SharedHandle> parent, std::string name,
108  AccessProperties props)
109  : data_(new Data()) {
110  RMF_USAGE_CHECK(
111  H5Lexists(parent->get_hid(), name.c_str(), H5P_DEFAULT),
112  RMF::internal::get_error_message("Data set ", name, " does not exist"));
113  P::open(std::make_shared<SharedHandle>(
114  H5Dopen2(parent->get_hid(), name.c_str(), props.get_handle()),
115  &H5Dclose, name));
116  // RMF_HDF5_HANDLE(s, H5Dget_space(h_->get_hid()), H5Sclose);
117  RMF_HDF5_HANDLE(sel, H5Dget_space(Object::get_handle()), &H5Sclose);
118  RMF_USAGE_CHECK(H5Sget_simple_extent_ndims(sel) == D,
119  RMF::internal::get_error_message(
120  "Dimensions don't match. Got ",
121  H5Sget_simple_extent_ndims(sel), " but expected ", D));
122  initialize();
123  }
124  hsize_t* get_ones() const { return data_->ones_; }
125  const Handle& get_row_data_space() const { return data_->rds_; }
126  const Handle& get_data_space() const { return data_->sel_; }
127  const Handle& get_input_data_space() const { return data_->ids_; }
128  void check_index(const DataSetIndexD<D>& ijk) const {
129  DataSetIndexD<D> sz = get_size();
130  for (unsigned int i = 0; i < D; ++i) {
131  RMF_USAGE_CHECK(ijk[i] < sz[i],
132  RMF::internal::get_error_message(
133  "Index is out of range: ", ijk[i], " >= ", sz[i]));
134  }
135  }
136  void initialize_handles() {
137  data_->sel_.open(H5Dget_space(Object::get_handle()), &H5Sclose);
138  // must be second
139  hsize_t ret[D];
140  std::fill(ret, ret + D, -1);
141  RMF_HDF5_CALL(H5Sget_simple_extent_dims(get_data_space(), ret, nullptr));
142  RMF_INTERNAL_CHECK(ret[D - 1] < 1000000, "extents not returned properly");
143  if (ret[D - 1] > 0) {
144  // some versions will spew an error on this
145  // we will call this function again before rds_ is needed
146  // std::cout << "initializing row to " << ret[data_->dim_-1] << std::endl;
147  data_->rds_.open(H5Screate_simple(1, ret + D - 1, nullptr), &H5Sclose);
148  } else {
149  // std::cout << "clearing row data" << std::endl;
150  data_->rds_.close();
151  }
152  RMF_HDF5_CALL(H5Sget_simple_extent_dims(get_data_space(),
153  data_->size_.begin(), nullptr));
154  }
155 
156  public:
157 #if !defined(SWIG) && !defined(RMF_DOXYGEN)
158  ConstDataSetD(hid_t file, std::string name) : data_(new Data()) {
159  RMF_USAGE_CHECK(
160  H5Lexists(file, name.c_str(), H5P_DEFAULT),
161  RMF::internal::get_error_message("Data set ", name, " does not exist"));
162  P::open(std::make_shared<SharedHandle>(
163  H5Dopen2(file, name.c_str(), H5P_DEFAULT), &H5Dclose, name));
164  // RMF_HDF5_HANDLE(s, H5Dget_space(h_->get_hid()), H5Sclose);
165  RMF_HDF5_HANDLE(sel, H5Dget_space(Object::get_handle()), &H5Sclose);
166  RMF_USAGE_CHECK(H5Sget_simple_extent_ndims(sel) == D,
167  RMF::internal::get_error_message(
168  "Dimensions don't match. Got ",
169  H5Sget_simple_extent_ndims(sel), " but expected ", D));
170  initialize();
171  }
172 #endif
173  typedef DataSetIndexD<D> Index;
174  ConstDataSetD() {}
175  DataSetIndexD<D> get_size() const {
176  // RMF_HDF5_HANDLE(s, H5Dget_space(h_->get_hid()), H5Sclose);
177  return data_->size_;
178  }
179  typename TypeTraits::Type get_value(const DataSetIndexD<D>& ijk) const {
180  RMF_IF_CHECK { check_index(ijk); }
181  // RMF_HDF5_HANDLE(sel, H5Dget_space(h_->get_hid()), &H5Sclose);
182  RMF_HDF5_CALL(H5Sselect_hyperslab(get_data_space(), H5S_SELECT_SET,
183  ijk.get(), data_->ones_, data_->ones_,
184  nullptr));
185  return TypeTraits::read_value_dataset(
186  Object::get_handle(), data_->ids_.get_hid(), get_data_space());
187  }
188  RMF_SHOWABLE(ConstDataSetD, "ConstDataSet" << D << "D " << P::get_name());
189 #ifndef SWIG
190  typedef DataSetIndexD<D - 1> RowIndex;
191  typename TypeTraits::Types get_row(const RowIndex ijkr) const {
192  DataSetIndexD<D> ijk;
193  std::copy(ijkr.begin(), ijkr.end(), ijk.begin());
194  ijk[D - 1] = 0;
195  RMF_IF_CHECK { check_index(ijk); }
196  hsize_t size[D];
197  std::fill(size, size + D - 1, 1);
198  size[D - 1] = get_size()[D - 1]; // set last to size of row
199  // RMF_HDF5_HANDLE(sel, H5Dget_space(h_->get_hid()), &H5Sclose);
200  RMF_HDF5_CALL(H5Sselect_hyperslab(get_data_space(), H5S_SELECT_SET,
201  ijk.get(), data_->ones_, &size[0],
202  nullptr));
203  return TypeTraits::read_values_dataset(Object::get_handle(),
204  get_row_data_space().get_hid(),
205  get_data_space(), size[D - 1]);
206  }
207 #endif
208  //! Read a rectangular block starting at ln of size size
209  typename TypeTraits::Types get_block(const Index& lb,
210  const Index& size) const {
211  hsize_t total = 1;
212  for (unsigned int i = 0; i < D; ++i) {
213  total *= size[i];
214  }
215  RMF_IF_CHECK { check_index(lb); }
216  // RMF_HDF5_HANDLE(sel, H5Dget_space(h_->get_hid()), &H5Sclose);
217  RMF_HDF5_CALL(H5Sselect_hyperslab(get_data_space(), H5S_SELECT_SET,
218  lb.get(), data_->ones_, size.get(),
219  nullptr));
220  RMF_HDF5_HANDLE(input, H5Screate_simple(1, &total, nullptr), &H5Sclose);
221  typename TypeTraits::Types ret = TypeTraits::read_values_dataset(
222  Object::get_handle(), input, get_data_space(), total);
223  RMF_INTERNAL_CHECK(ret.size() == total, "Size mismatch");
224  return ret;
225  }
227 };
228 
229 #ifndef RMF_DOXYGEN
230 #define RMF_HDF5_DECLARE_CONST_DATA_SET(lcname, Ucname, PassValue, \
231  ReturnValue, PassValues, ReturnValues) \
232  typedef ConstDataSetD<Ucname##Traits, 1> Ucname##ConstDataSet1D; \
233  typedef std::vector<Ucname##ConstDataSet1D> Ucname##ConstDataSet1Ds; \
234  typedef ConstDataSetD<Ucname##Traits, 2> Ucname##ConstDataSet2D; \
235  typedef std::vector<Ucname##ConstDataSet2D> Ucname##ConstDataSet2Ds; \
236  typedef ConstDataSetD<Ucname##Traits, 3> Ucname##ConstDataSet3D; \
237  typedef std::vector<Ucname##ConstDataSet3D> Ucname##ConstDataSet3Ds
238 
239 /** \name Basic data set types
240  \ingroup hdf5
241  @{
242  */
243 RMF_HDF5_FOREACH_TYPE(RMF_HDF5_DECLARE_CONST_DATA_SET);
244 /** @} */
245 #endif
246 
247 } /* namespace HDF5 */
248 } /* namespace RMF */
249 
250 RMF_DISABLE_WARNINGS
251 
252 #endif /* RMF_HDF5_CONST_DATA_SET_D_H */
Handle read/write of Model data from/to files.
Various general useful macros for IMP.
int Index
Definition: HDF5/types.h:38
Make sure an HDF5 handle is released.
Definition: handle.h:40
Handle read/write of Model data from/to files.
#define RMF_COMPARISONS(Name)
Implement comparison in a class using field as the variable to compare.
TypeTraits::Types get_block(const Index &lb, const Index &size) const
Read a rectangular block starting at ln of size size.
#define RMF_HDF5_CALL(v)
Handle read/write of Model data from/to files.
Handle read/write of Model data from/to files.
Functions and macros for logging.
Handle read/write of Model data from/to files.