【问题标题】:Reading a HDF5 dataset with compound data type containing multiple sets with variable numbers of floats and ints读取具有复合数据类型的 HDF5 数据集,其中包含多个具有可变数量的浮点数和整数的集合
【发布时间】:2016-05-30 09:21:57
【问题描述】:

我正在尝试使用 C++ 中的 H5Cpp 库读取具有复合数据类型的 HDF5 数据集。 HDF5 文件是由模拟器创建的,所以很遗憾我无法控制结构。每个单元格包含多组可变长度浮点数和一组可变长度整数。 h5dump显示的头结构为:

DATASET "SET_NAME" {
         DATATYPE  H5T_COMPOUND {
            H5T_VLEN { H5T_IEEE_F64LE} "dProp1";
            H5T_VLEN { H5T_IEEE_F64LE} "dProp2";
            H5T_VLEN { H5T_STD_I32LE} "iProp1";
            H5T_VLEN { H5T_IEEE_F64LE} "dProp3";
         }
         DATASPACE  SIMPLE { ( 5, 122 ) / ( H5S_UNLIMITED, H5S_UNLIMITED ) }
}

我试图创建一个包含VarLenTypes 的CompType,但是在运行时会抛出异常,指出一个成员与另一个成员重叠(当任何地方给出的唯一大小是包含指针的结构的大小)。这是我到目前为止的摘录:

#include <H5Cpp.h>
typedef struct mytype_t {
    double* dprop1;
    double* dprop2;
    int* iprop1;
    double* dprop3;
} mytype_t;

H5::CompType ctype(sizeof(mytype_t));
auto double_type = H5::PredType::NATIVE_DOUBLE;
auto int_type = H5::PredType::NATIVE_INT;
auto vdouble_type = H5::VarLenType(&double_type);
auto vint_type = H5::VarLenType(&int_type);
ctype.insertMember("dProp1", HOFFSET(mytype_t, dprop1), vdouble_type);
ctype.insertMember("dProp2", HOFFSET(mytype_t, dprop2), vdouble_type);
ctype.insertMember("vProp1", HOFFSET(mytype_t, iprop1), vint_type);
ctype.insertMember("dProp3", HOFFSET(mytype_t, dprop3), vdouble_type);

std::vector<mytype_t> data_vector;
data_vector.resize(dims[0]*dims[1]);
dataset.read(data_vector.data(), ctype);

如何读取这样的数据集?

【问题讨论】:

    标签: c++ hdf5


    【解决方案1】:

    HDF5 文档和示例在这个问题上相当薄弱。

    HDF5 要求用户保留可变长度数据的句柄(类型为 hvl_t),并在将数组作为成员插入复合类型时引用该句柄。

    这引入了保持这些句柄和向量、数组...等与句柄同步的开销。也就是说,如果你保持动态数组,每当你改变元素的数量时,你需要更新 "len" 字段并且每当数组被重新分配你需要设置 "p" 字段到新数组的第一个元素。

    这也可以与 std::vector 一起使用,请记住,您需要随时更新 plen在向量中添加/删除元素。 dguest 在https://github.com/dguest/hdf5-ntuples/blob/master/include/h5container.hh 有一段很好的代码。

    您的案例的解决方案(简化):

    #include <H5Cpp.h>
    typedef struct mytype_t {
        double* dProp;
        hvl_t dPropHandle;
        int* iProp;
        hvl_t iPropHandle;
    } mytype_t;
    
    H5::CompType ctype(sizeof(mytype_t));
    auto double_type = H5::PredType::NATIVE_DOUBLE;
    auto int_type = H5::PredType::NATIVE_INT;
    auto vdouble_type = H5::VarLenType(&double_type);
    auto vint_type = H5::VarLenType(&int_type);
    
    // use handles instead of array pointers
    ctype.insertMember("dProp", HOFFSET(mytype_t, dPropHandle), vdouble_type);
    ctype.insertMember("iProp", HOFFSET(mytype_t, iPropHandle), vint_type);
    
    std::vector<mytype_t> data_vector;
    data_vector.resize(dims[0]*dims[1]);
    dataset.read(data_vector.data(), ctype);
    
    // update array pointers accordingly
    for(mytype_t &m : data_vector)
    {
        m.dProp = dPropHandle.p;
        m.iProp = iPropHandle.p;
    }
    

    使用向量:

    #include <H5Cpp.h>
    typedef struct mytype_t {
        std::vector<double> dProp;
        hvl_t dPropHandle;
        std::vector<int> iProp;
        hvl_t iPropHandle;
    } mytype_t;
    
    H5::CompType ctype(sizeof(mytype_t));
    auto double_type = H5::PredType::NATIVE_DOUBLE;
    auto int_type = H5::PredType::NATIVE_INT;
    auto vdouble_type = H5::VarLenType(&double_type);
    auto vint_type = H5::VarLenType(&int_type);
    
    // use handles instead of array pointers
    ctype.insertMember("dProp", HOFFSET(mytype_t, dPropHandle), vdouble_type);
    ctype.insertMember("iProp", HOFFSET(mytype_t, iPropHandle), vint_type);
    
    std::vector<mytype_t> data_vector;
    data_vector.resize(dims[0]*dims[1]);
    dataset.read(data_vector.data(), ctype);
    
    // update vectors accordingly
    for(mytype_t &m : data_vector)
    {
        m.dProp.assign(static_cast<double*>(m.dPropHandle.p),
        static_cast<double*>(m.dPropHandle.p) + m.dPropHandle.len);
    
        m.iProp.assign(static_cast<int*>(m.iPropHandle.p),
        static_cast<int*>(m.iPropHandle.p) + m.iPropHandle.len);
    }
    

    【讨论】:

    • 谢谢!这,至少是使用向量的变体,似乎非常适合我的情况。
    • 我有一个类似的复合结构,以数组作为成员,但问题是如何写入 HDF5 文件,您能帮忙吗?谢谢!
    • 对不起,自 2016 年以来,我不必处理 HDF5 甚至 C++。如果您对此有任何发言权,我会从 HDF5 作为序列化格式迁移。例如,protobuf 要好得多,并且支持许多其他语言。
    猜你喜欢
    • 2021-05-03
    • 1970-01-01
    • 2019-08-02
    • 2019-08-14
    • 2012-09-04
    • 2015-10-26
    • 1970-01-01
    • 1970-01-01
    • 2016-01-19
    相关资源
    最近更新 更多