'HDF5: How to read an array from a dataset

I have never seen this before, but I have a file with a 1x1 dataset where the only value is a Array[3] of 64-bit floating point. I can see this using the HDFView tool, but no matter what I try, I get errors. Is there a special type I need to create for this to work?

Edit if I use H5Sget_simple_extent_npoints() to get the number of data points, the result is 1. So, it appears to be 1 array of 3 elements.

The last thing I tried was manually reading 3 doubles:

hid_t dataset = ...;  // open the dataset (dataset is valid)
double var[3];
hsize_t memdim[] = { 3 };
hid_t space = H5Screate_simple(1, memdim, nullptr);  // (space is valid)
auto rc = H5Dread(dataset, H5T_NATIVE_DOUBLE, space, space, H5P_DEFAULT, &var[0]);
// rc = -1

Also tried just reading the whole dataset:

hid_t dataset = ...;  // open the dataset (dataset is valid)
double var[3];
auto rc = H5Dread(dataset, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, &var[0]);
// rc = -1

Error text from the above tests:

HDF5-DIAG: Error detected in HDF5 (1.10.5) thread 17272:
  #000: \hdf5-1.10.5\src\H5Dio.c line 199 in H5Dread(): can't read data
    major: Dataset
    minor: Read failed
  #001: \hdf5-1.10.5\src\H5Dio.c line 467 in H5D__read(): unable to set up type info
    major: Dataset
    minor: Unable to initialize object
  #002: \hdf5-1.10.5\src\H5Dio.c line 983 in H5D__typeinfo_init(): unable to convert between src and dest datatype
    major: Dataset
    minor: Feature is unsupported
  #003: \hdf5-1.10.5\src\H5T.c line 4546 in H5T_path_find(): can't find datatype conversion path
    major: Datatype
    minor: Can't get value
  #004: \hdf5-1.10.5\src\H5T.c line 4762 in H5T__path_find_real(): no appropriate function for conversion path
    major: Datatype
    minor: Unable to initialize object

Screenshot from HDFView



Solution 1:[1]

I figured out that there is an array type that can be made that is required:

hsize_t size = { 3 };
hid_t type = H5Tarray_create(H5T_NATIVE_DOUBLE, 1, &size);

hid_t dataset = H5Dopen(...);
double var[3];
hsize_t memdim[] = { 1 };  // or how many arrays[3]'s to read
hid_t space = H5Screate_simple(1, memdim, nullptr);
auto rc = H5Dread(dataset, type, space, H5S_ALL, H5P_DEFAULT, &var[0]);

Solution 2:[2]

If you are not bound to a specific HDF5 library, you may want to check HDFql as it greatly alleviates you from HDF5 low-level details.

To read and display a one dimensional array dataset (named dset) with size 3 of data type double (64 bit) it can be done as follows using HDFql in C++:

HDFql::execute("SELECT FROM dset");

while(HDFql::cursorNext() == HDFql::Success)
{
    cout << *HDFql::cursorGetBigint() << endl;
}

Alternatively, instead of using HDFql cursor, you may directly populate a variable of yours with the values of dataset dset as follows:

double values[3];

HDFql::variableRegister(&values);

HDFql::execute("SELECT FROM dset INTO MEMORY 0");

for(int i = 0; i < 3; i++)
{
    cout << values[i] << endl;
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 steveo225
Solution 2