37namespace h5::array_interface {
44 if (v.rank() == 0)
return H5Screate(H5S_SCALAR);
47 dataspace dspace = H5Screate_simple(v.slab.rank(), v.parent_shape.data(),
nullptr);
48 if (!dspace.is_valid())
throw std::runtime_error(
"Error in make_mem_dspace: Creating the dataspace for an array_view failed");
51 herr_t err = H5Sselect_hyperslab(dspace, H5S_SELECT_SET, v.slab.offset.data(), v.slab.stride.data(), v.slab.count.data(),
52 (v.slab.block.empty() ?
nullptr : v.slab.block.data()));
53 if (err < 0)
throw std::runtime_error(
"Error in make_mem_dspace: Selecting the hyperslab failed");
63 if (rank == 0)
return {};
66 auto const view_size = std::accumulate(view_shape, view_shape + rank, 1l, std::multiplies<>());
67 if (view_size == 0)
return {
v_t(rank, 0),
v_t(rank, 1)};
80 v_t parent_shape(rank), h5_strides(rank);
85 for (
int u = 0; u < rank; ++u) h5_strides[u] = np_strides[u];
86 for (
int u = rank - 2; u >= 0; --u) {
88 for (
int v = u - 1; v >= 0; --v) { gcd = std::gcd(gcd, h5_strides[v]); }
89 parent_shape[u + 1] = gcd;
90 for (
int v = u; v >= 0; --v) { h5_strides[v] /= gcd; }
95 parent_shape[0] = view_shape[0] * h5_strides[0];
97 return {parent_shape, h5_strides};
103 bool has_complex_attribute = H5LTfind_attribute(ds,
"__complex__");
105 int rank = H5Sget_simple_extent_ndims(dspace);
107 H5Sget_simple_extent_dims(dspace, dims_out.data(),
nullptr);
109 return {.lengths = std::move(dims_out), .ty = ty, .has_complex_attribute = has_complex_attribute};
126 if (compress and (v.
rank() != 0)) {
127 int n_dims = v.
rank();
128 std::vector<hsize_t> chunk_dims(n_dims);
131 for (
int i = v.
rank() - 1; i >= 0; --i) {
132 H5_ASSERT(max_chunk_size >= chunk_size);
133 hsize_t max_dim = max_chunk_size / chunk_size;
134 chunk_dims[i] = std::clamp(hs_shape[i],
hsize_t{1}, max_dim);
135 chunk_size *= chunk_dims[i];
137 cparms = H5Pcreate(H5P_DATASET_CREATE);
138 H5Pset_chunk(cparms, n_dims, chunk_dims.data());
139 H5Pset_deflate(cparms, 1);
143 dataspace file_dspace = H5Screate_simple(v.
slab.
rank(), hs_shape.data(),
nullptr);
146 dataset ds = H5Dcreate2(g, name.c_str(), v.
ty, file_dspace, H5P_DEFAULT, cparms, H5P_DEFAULT);
148 throw std::runtime_error(
"Error in h5::array_interface::write: Creating the dataset " + name +
" in the group " + g.
name() +
" failed");
151 dataspace mem_dspace = make_mem_dspace(v);
154 if (H5Sget_simple_extent_npoints(mem_dspace) > 0) {
155 herr_t err = H5Dwrite(ds, v.
ty, mem_dspace, H5S_ALL, H5P_DEFAULT, v.
start);
157 throw std::runtime_error(
"Error in h5::array_interface::write: Writing to the dataset " + name +
" in the group" + g.
name() +
" failed");
166 if (sl.
empty())
return;
169 if (v.
slab.
size() != sl.
size())
throw std::runtime_error(
"Error in h5::array_interface::write_slice: Incompatible sizes");
173 throw std::runtime_error(
"Error in h5::array_interface::write_slice: Incompatible HDF5 types: " +
get_name_of_h5_type(v.
ty)
178 dataspace file_dspace = H5Dget_space(ds);
179 herr_t err = H5Sselect_hyperslab(file_dspace, H5S_SELECT_SET, sl.
offset.data(), sl.
stride.data(), sl.
count.data(),
180 (sl.
block.empty() ?
nullptr : sl.
block.data()));
181 if (err < 0)
throw std::runtime_error(
"Error in h5::array_interface::write_slice: Selecting the hyperslab failed");
184 dataspace mem_dspace = make_mem_dspace(v);
187 if (H5Sget_simple_extent_npoints(file_dspace) > 0) {
188 err = H5Dwrite(ds, v.
ty, mem_dspace, file_dspace, H5P_DEFAULT, v.
start);
190 throw std::runtime_error(
"Error in h5::array_interface::write_slice: Writing the dataset " + name +
" in the group " + g.
name() +
" failed");
196 if (H5LTfind_attribute(obj, name.c_str()) != 0)
197 throw std::runtime_error(
"Error in h5::array_interface::write_attribute: Attribute " + name +
" already exists");
200 dataspace mem_dspace = make_mem_dspace(v);
203 attribute attr = H5Acreate2(obj, name.c_str(), v.
ty, mem_dspace, H5P_DEFAULT, H5P_DEFAULT);
204 if (!attr.
is_valid())
throw std::runtime_error(
"Error in h5::array_interface::write_attribute: Creating the attribute " + name +
" failed");
207 herr_t err = H5Awrite(attr, v.
ty, v.
start);
208 if (err < 0)
throw std::runtime_error(
"Error in h5::array_interface::write_attribute: Writing to the attribute " + name +
" failed");
214 dataspace file_dspace = H5Dget_space(ds);
217 if (not sl.
empty()) {
218 herr_t err = H5Sselect_hyperslab(file_dspace, H5S_SELECT_SET, sl.
offset.data(), sl.
stride.data(), sl.
count.data(),
219 (sl.
block.empty() ?
nullptr : sl.
block.data()));
220 if (err < 0)
throw std::runtime_error(
"Error in h5::array_interface::read: selecting the hyperslab failed");
237 if (H5Tget_class(v.
ty) != H5Tget_class(ds_info.ty))
238 throw std::runtime_error(
"Error in h5::array_interface::read: Incompatible HDF5 types: " +
get_name_of_h5_type(v.
ty)
242 std::cerr <<
"WARNING: HDF5 type mismatch while reading into an array_view: " +
get_name_of_h5_type(v.
ty)
245 auto sl_size = sl.
size();
246 if (sl.
empty()) { sl_size = std::accumulate(ds_info.lengths.begin(), ds_info.lengths.end(), (
hsize_t)1, std::multiplies<>()); }
247 if (sl_size != v.
slab.
size())
throw std::runtime_error(
"Error in h5::array_interface::read: Incompatible sizes");
250 dataspace mem_dspace = make_mem_dspace(v);
253 if (H5Sget_simple_extent_npoints(file_dspace) > 0) {
254 herr_t err = H5Dread(ds, v.
ty, mem_dspace, file_dspace, H5P_DEFAULT, v.
start);
256 throw std::runtime_error(
"Error in h5::array_interface::read: Reading the dataset " + name +
" in the group " + g.
name() +
" failed");
262 attribute attr = H5Aopen(obj, name.c_str(), H5P_DEFAULT);
263 if (!attr.
is_valid())
throw std::runtime_error(
"Error in h5::array_interface::read_attribute: Opening the attribute " + name +
" failed");
268 int rank = H5Sget_simple_extent_ndims(space);
269 if (rank != v.
rank())
270 throw std::runtime_error(
"Error in h5::array_interface::read_attribute: Attribute " + name +
" has rank " + std::to_string(rank)
271 +
" but the view has rank " + std::to_string(v.
rank()));
274 auto eq = H5Tequal(H5Aget_type(attr), v.
ty);
275 if (eq < 0)
throw std::runtime_error(
"Error in h5::array_interface::read_attribute: H5Tequal call failed");
276 if (eq == 0)
throw std::runtime_error(
"Error in h5::array_interface::read_attribute: Incompatible HDF5 types");
279 auto err = H5Aread(attr, v.
ty, v.
start);
280 if (err < 0)
throw std::runtime_error(
"Error in h5::array_interface::read_attribute: Reading the attribute " + name +
" failed");
Provides a generic interface to read/write n-dimensional arrays from/to HDF5.
A handle to an HDF5 group.
dataset open_dataset(std::string const &key) const
Open a dataset with the given key in the group.
std::string name() const
Get the name of the group.
void unlink(std::string const &key, bool error_if_absent=false) const
Remove a link with the given key from the group.
bool is_valid() const
Ensure that the wrapped HDF5 ID is valid (by calling H5Iis_valid).
Provides a compound type and type traits for complex numbers.
object datatype
Type alias for an HDF5 datatype.
object attribute
Type alias for an HDF5 attribute.
object dataset
Type alias for an HDF5 dataset.
object dataspace
Type alias for an HDF5 dataspace.
object proplist
Type alias for an HDF5 property list.
bool hdf5_type_equal(datatype dt1, datatype dt2)
Check if two HDF5 datatypes are equal.
datatype hdf5_type()
Map a given C++ type to an HDF5 datatype.
std::string get_name_of_h5_type(datatype dt)
Get the name of an h5::datatype (for error messages).
std::string get_name_of_h5_type()
Get the name of the HDF5 datatype corresponding to a C++ type.
void read_attribute(object obj, std::string const &name, array_view v)
Read from an HDF5 attribute into an array view.
void write_slice(group g, std::string const &name, array_view const &v, hyperslab sl)
Write an array view to a selected hyperslab of an existing HDF5 dataset.
void read(group g, std::string const &name, array_view v, hyperslab sl)
Read a given hyperslab from an HDF5 dataset into an array view.
void write_attribute(object obj, std::string const &name, array_view v)
Write an array view to an HDF5 attribute.
dataset_info get_dataset_info(dataset ds)
Retrieve the shape and the h5::datatype from a dataset.
void write(group g, std::string const &name, array_view const &v, bool compress)
Write an array view to an HDF5 dataset.
std::pair< v_t, v_t > get_parent_shape_and_h5_strides(long const *np_strides, int rank, long const *view_shape)
Given a view on an n-dimensional array (dataspace) by specifying its numpy/nda-style strides and its ...
void h5_write_attribute(object, std::string const &, std::string const &)
Write a std::string to an HDF5 attribute.
std::vector< hsize_t > v_t
Vector of h5::hsize_t used throughout the h5 library.
unsigned long long hsize_t
Size type used in HDF5.
Macros used in the h5 library.
Provides functions to read/write std::string, char* and h5::char_buf objects from/to HDF5.
Struct representing a view on an n-dimensional array/dataspace.
void * start
Pointer to the data of the array.
v_t parent_shape
Shape of the (contiguous) parent array.
bool has_cplx_trailing_dim
datatype ty
h5::datatype stored in the array.
int rank() const
Get the rank of the view (including the possible added imaginary dimension).
hyperslab slab
h5::array_interface::hyperslab specifying the selection of the view.
Simple struct to store basic information about an HDF5 dataset.
Struct representing an HDF5 hyperslab.
auto size() const
Get the total number of elements in the hyperslab.
v_t block
Shape of a single block selected from the dataspace.
bool empty() const
Check whether the hyperslab is empty (has been initialized).
v_t stride
Stride in each dimension (in the HDF5 sense).
v_t offset
Index offset for each dimension.
v_t count
Number of elements or blocks to select along each dimension.
v_t shape() const
Get the shape of the selected hyperslab.
int rank() const
Get the rank of the hyperslab (including the possible added imaginary dimension).