我想使用 C++ 读取一个包含对象引用数组的 HDF5 文件。我可以在 python 中得到正确的结果,但我在 C++ 中遇到了麻烦。
我尝试了教程文档中的几个 C 示例,但看起来缺少 C++ 包装器,而且很难填补空白。
H5File file = H5File("example.h5", H5F_ACC_RDONLY);
DataSet dataset = file.openDataSet("units/electrode_group");
H5T_class_t type_class = dataset.getTypeClass();
cout << type_class << endl; // correctly obtains H5T_REFERENCE.
// Need to read and apply the references next.
以下 python 代码可以完成我想要的一切,但我需要一个 c++ 版本。
import h5py
FileName = 'example.h5'
myHDF5file = h5py.File(FileName)
ElectrodeGroup = myHDF5file['units/electrode_group']
for electrodeRef in ElectrodeGroup:
print(myHDF5file[electrodeRef].name)
python 代码正确打印:
/general/extracellular_ephys/shank1
/general/extracellular_ephys/shank1
/general/extracellular_ephys/shank2
/general/extracellular_ephys/shank3
虽然 OP 使用 C API 使它工作,但如果您(像我一样)通过 Google 来到这里并想要 C++ API 答案:
HDF5 C++ API 文档很烂。我煞费苦心地将 C API 文档与我通过在 C++ API 标头中搜索并与
h5dump
告诉我的有关 .h5
的内容进行比较而发现的内容进行了交叉关联,其中包含区域引用。最终发现有两个重要的方法:
诀窍在于,因为
H5Location
是一个抽象类,所以您必须在具体派生类的实例上调用它们。在这个问题的情况下,人们只想要 dereference()
一个,它用引用指向的东西填充 H5Location
对象(有点不直观,恕我直言,但这就是它的作用)。在这种情况下,我们知道 ref 指向的东西是一个 DataSet
,所以我们直接创建一个 DataSet
并调用它的 dereference()
参数。 (如果您的引用是指向数据集中记录的 subset,则可以使用 getRegion()
方法获取指向所选元素的 DataSpace
。)
因为数据集包含only一组参考,我想你做这样的事情:
// create holder for the references when they're read
// references are of type `hdset_reg_ref_t`
std::vector<hdset_reg_ref_t> refs(dataset.getSpace().getSimpleExtentNdims());
// read them out of the dataset.
// `H5::PredType::STD_REF_DSETREG` is the H5 internal type for region references
dataset.read(refs.data(), H5::PredType::STD_REF_DSETREG);
for (const auto & ref : refs)
{
// we know these are dataset region refs,
// so we create DataSet objects directly
H5::DataSet ds_ref;
// make the dataset point to the right object using the reference
ds_ref.dereference(file, ref, H5R_DATASET_REGION);
std::cout << ds_ref.getObjName() << "\n";
// if you wanted to use the corresponding DataSpace
// (say, your region ref was to a subset of records),
// you'd grab it by doing:
// H5::DataSpace dspc_ref = file.getRegion(ref);
}