【发布时间】:2022-02-18 04:02:54
【问题描述】:
我正在尝试保存一个包含一些 arma::vec 的结构,但我不确定如何将它们写入 hdf5 文件。
#define ARMA_DONT_USE_WRAPPER
#include <armadillo>
#include <string>
#include <iostream>
#include "H5Cpp.h"
#define ARMA_ALLOW_FAKE_GCC //allows the use of GCC compiled armadillo with ICC compiler
using namespace std;
using namespace arma;
struct info_struct{
double frequency_MHz;
vec beam_centres_deg;
vec beam_crossover_deg;
double task_centre_azimuth_deg;
double WRF_Hz;
double bandwidth_kHz;
double beam_spacing_dB;
int direct_wave_range_bin;
double fs;
vec rx_rng_twoway_vec_km;
string date;
};
int main(void)
{
info_struct header;
header.frequency_MHz=7;
header.beam_centres_deg=8*ones<vec>(10);
header.beam_crossover_deg=9*ones<vec>(10);
header.task_centre_azimuth_deg=10;
header.WRF_Hz = 11;
header.bandwidth_kHz=12;
header.beam_spacing_dB=13;
header.direct_wave_range_bin=14;
header.fs=15e3;
header.rx_rng_twoway_vec_km=16*ones<vec>(10);
header.date="14-Oct-2020 17:02:30";
// the array of each length of multidimentional data.
hsize_t dim_header[1];
dim_header[0] = sizeof(header) / sizeof(info_struct);
// the length of dim
int rank_header = sizeof(dim_header) / sizeof(hsize_t);
// defining the datatype to pass HDF55
H5::CompType h5_header(sizeof(info_struct));
h5_header.insertMember("frequency_MHz", HOFFSET(info_struct, frequency_MHz), H5::PredType::NATIVE_DOUBLE);
h5_header.insertMember("beam_centres_deg", HOFFSET(info_struct, beam_centres_deg), H5::PredType::NATIVE_DOUBLE);
h5_header.insertMember("beam_crossover_deg", HOFFSET(info_struct, beam_crossover_deg), H5::PredType::NATIVE_DOUBLE);
h5_header.insertMember("task_centre_azimuth_deg", HOFFSET(info_struct, task_centre_azimuth_deg), H5::PredType::NATIVE_DOUBLE);
h5_header.insertMember("WRF_Hz", HOFFSET(info_struct, WRF_Hz), H5::PredType::NATIVE_DOUBLE);
h5_header.insertMember("bandwidth_kHz", HOFFSET(info_struct, bandwidth_kHz), H5::PredType::NATIVE_DOUBLE);
h5_header.insertMember("beam_spacing_dB", HOFFSET(info_struct, beam_spacing_dB), H5::PredType::NATIVE_DOUBLE);
h5_header.insertMember("direct_wave_range_bin", HOFFSET(info_struct, direct_wave_range_bin), H5::PredType::NATIVE_INT);
h5_header.insertMember("fs", HOFFSET(info_struct, fs), H5::PredType::NATIVE_DOUBLE);
h5_header.insertMember("rx_rng_twoway_vec_km", HOFFSET(info_struct, rx_rng_twoway_vec_km), H5::PredType::NATIVE_DOUBLE);
h5_header.insertMember("date", HOFFSET(info_struct, date), H5::StrType(H5::PredType::C_S1, H5T_VARIABLE));
// preparation of a dataset and a file.
H5::DataSpace space_header(rank_header, dim_header);
H5::H5File *file = new H5::H5File("data_test.h5", H5F_ACC_TRUNC);
H5::DataSet *dataset_header = new H5::DataSet(file->createDataSet("MOTHR_header", h5_header, space_header));
// Write
dataset_header->write(&header, h5_header);
delete dataset_header;
delete file;
return 0;
}
如果我注释掉与向量有关的所有内容,它会很好地写入文件,但是当我不注释它们时,我会在编译时收到此警告:
In file included from /usr/include/unistd.h:226,
from /usr/include/armadillo:62,
from save_data.cpp:2:
save_data.cpp: In function ‘int main()’:
save_data.cpp:65:53: warning: offsetof within non-standard-layout type ‘info_struct’ is conditionally-supported [-Winvalid-offsetof]
h5_header.insertMember("frequency_MHz", HOFFSET(info_struct, frequency_MHz), H5::PredType::NATIVE_DOUBLE);
save_data.cpp:65:45: note: in expansion of macro ‘HOFFSET’
h5_header.insertMember("frequency_MHz", HOFFSET(info_struct, frequency_MHz), H5::PredType::NATIVE_DOUBLE);
^~~~~~~
save_data.cpp:67:56: warning: offsetof within non-standard-layout type ‘info_struct’ is conditionally-supported [-Winvalid-offsetof]
h5_header.insertMember("beam_centres_deg", HOFFSET(info_struct, beam_centres_deg), H5::PredType::NATIVE_DOUBLE);
save_data.cpp:67:48: note: in expansion of macro ‘HOFFSET’
h5_header.insertMember("beam_centres_deg", HOFFSET(info_struct, beam_centres_deg), H5::PredType::NATIVE_DOUBLE);
^~~~~~~
save_data.cpp:68:58: warning: offsetof within non-standard-layout type ‘info_struct’ is conditionally-supported [-Winvalid-offsetof]
h5_header.insertMember("beam_crossover_deg", HOFFSET(info_struct, beam_crossover_deg), H5::PredType::NATIVE_DOUBLE);
save_data.cpp:68:50: note: in expansion of macro ‘HOFFSET’
h5_header.insertMember("beam_crossover_deg", HOFFSET(info_struct, beam_crossover_deg), H5::PredType::NATIVE_DOUBLE);
^~~~~~~
save_data.cpp:70:63: warning: offsetof within non-standard-layout type ‘info_struct’ is conditionally-supported [-Winvalid-offsetof]
h5_header.insertMember("task_centre_azimuth_deg", HOFFSET(info_struct, task_centre_azimuth_deg), H5::PredType::NATIVE_DOUBLE);
save_data.cpp:70:55: note: in expansion of macro ‘HOFFSET’
h5_header.insertMember("task_centre_azimuth_deg", HOFFSET(info_struct, task_centre_azimuth_deg), H5::PredType::NATIVE_DOUBLE);
^~~~~~~
save_data.cpp:71:46: warning: offsetof within non-standard-layout type ‘info_struct’ is conditionally-supported [-Winvalid-offsetof]
h5_header.insertMember("WRF_Hz", HOFFSET(info_struct, WRF_Hz), H5::PredType::NATIVE_DOUBLE);
save_data.cpp:71:38: note: in expansion of macro ‘HOFFSET’
h5_header.insertMember("WRF_Hz", HOFFSET(info_struct, WRF_Hz), H5::PredType::NATIVE_DOUBLE);
^~~~~~~
save_data.cpp:72:53: warning: offsetof within non-standard-layout type ‘info_struct’ is conditionally-supported [-Winvalid-offsetof]
h5_header.insertMember("bandwidth_kHz", HOFFSET(info_struct, bandwidth_kHz), H5::PredType::NATIVE_DOUBLE);
save_data.cpp:72:45: note: in expansion of macro ‘HOFFSET’
h5_header.insertMember("bandwidth_kHz", HOFFSET(info_struct, bandwidth_kHz), H5::PredType::NATIVE_DOUBLE);
^~~~~~~
save_data.cpp:73:55: warning: offsetof within non-standard-layout type ‘info_struct’ is conditionally-supported [-Winvalid-offsetof]
h5_header.insertMember("beam_spacing_dB", HOFFSET(info_struct, beam_spacing_dB), H5::PredType::NATIVE_DOUBLE);
save_data.cpp:73:47: note: in expansion of macro ‘HOFFSET’
h5_header.insertMember("beam_spacing_dB", HOFFSET(info_struct, beam_spacing_dB), H5::PredType::NATIVE_DOUBLE);
^~~~~~~
save_data.cpp:74:61: warning: offsetof within non-standard-layout type ‘info_struct’ is conditionally-supported [-Winvalid-offsetof]
h5_header.insertMember("direct_wave_range_bin", HOFFSET(info_struct, direct_wave_range_bin), H5::PredType::NATIVE_INT);
save_data.cpp:74:53: note: in expansion of macro ‘HOFFSET’
h5_header.insertMember("direct_wave_range_bin", HOFFSET(info_struct, direct_wave_range_bin), H5::PredType::NATIVE_INT);
^~~~~~~
save_data.cpp:75:42: warning: offsetof within non-standard-layout type ‘info_struct’ is conditionally-supported [-Winvalid-offsetof]
h5_header.insertMember("fs", HOFFSET(info_struct, fs), H5::PredType::NATIVE_DOUBLE);
save_data.cpp:75:34: note: in expansion of macro ‘HOFFSET’
h5_header.insertMember("fs", HOFFSET(info_struct, fs), H5::PredType::NATIVE_DOUBLE);
^~~~~~~
save_data.cpp:79:44: warning: offsetof within non-standard-layout type ‘info_struct’ is conditionally-supported [-Winvalid-offsetof]
h5_header.insertMember("date", HOFFSET(info_struct, date), H5::StrType(H5::PredType::C_S1, H5T_VARIABLE));
save_data.cpp:79:36: note: in expansion of macro ‘HOFFSET’
h5_header.insertMember("date", HOFFSET(info_struct, date), H5::StrType(H5::PredType::C_S1, H5T_VARIABLE));
而且该功能似乎运行良好,但是当我在生成的文件上尝试 h5dump 时,我得到:
HDF5 "data_test.h5" {
GROUP "/" {
DATASET "MOTHR_header" {
DATATYPE H5T_COMPOUND {
H5T_IEEE_F64LE "frequency_MHz";
H5T_IEEE_F64LE "beam_centres_deg";
H5T_IEEE_F64LE "beam_crossover_deg";
H5T_IEEE_F64LE "task_centre_azimuth_deg";
H5T_IEEE_F64LE "WRF_Hz";
H5T_IEEE_F64LE "bandwidth_kHz";
H5T_IEEE_F64LE "beam_spacing_dB";
H5T_STD_I32LE "direct_wave_range_bin";
H5T_IEEE_F64LE "fs";
H5T_IEEE_F64LE "rx_rng_twoway_vec_km";
H5T_STRING {
STRSIZE H5T_VARIABLE;
STRPAD H5T_STR_NULLTERM;
CSET H5T_CSET_ASCII;
CTYPE H5T_C_S1;
} "date";
}
DATASPACE SIMPLE { ( 1 ) / ( 1 ) }
DATA {
(0): {
7,
4.94066e-323,
4.94066e-323,
10,
11,
12,
13,
14,
15000,
4.94066e-323,
"14-Oct-2020 17:02:30"
}
}
}
}
}
我对 hdf5 很陌生,所以我完全不知道如何保存这些向量,任何帮助都将不胜感激。我还有另一个带有 arma:cx_mat 的结构。我知道在阅读它们时我必须单独阅读它们然后将它们组合起来,所以可以假设我必须为编写它们做同样的事情吗?
更新:
在阅读了有关复合数据类型的更多信息后,我对代码进行了修改:
#define ARMA_DONT_USE_WRAPPER
#include <armadillo>
#include <string>
#include <iostream>
#include "H5Cpp.h"
#define ARMA_ALLOW_FAKE_GCC //allows the use of GCC compiled armadillo with ICC compiler
using namespace std;
using namespace arma;
typedef std::vector<double> stdvec;
struct info_struct{
double frequency_MHz;
vec beam_centres_deg;
stdvec beam_centres_deg_c;
vec beam_crossover_deg;
stdvec beam_crossover_deg_c;
double task_centre_azimuth_deg;
double WRF_Hz;
double bandwidth_kHz;
double beam_spacing_dB;
int direct_wave_range_bin;
double fs;
vec rx_rng_twoway_vec_km;
stdvec rx_rng_twoway_vec_km_c;
string date;
};
struct info_struct_hdf5{
double frequency_MHz;
double* beam_centres_deg;
hvl_t beam_centres_deg_handle;
double* beam_crossover_deg;
hvl_t beam_crossover_deg_handle;
double task_centre_azimuth_deg;
double WRF_Hz;
double bandwidth_kHz;
double beam_spacing_dB;
int direct_wave_range_bin;
double fs;
double* rx_rng_twoway_vec_km;
hvl_t rx_rng_twoway_vec_km_handle;
string date;
};
int main(void)
{
info_struct header;
info_struct_hdf5 header_hdf5;
header.frequency_MHz=7;
header.beam_centres_deg=8*ones<vec>(10);
header.beam_crossover_deg=9*ones<vec>(10);
header.task_centre_azimuth_deg=10;
header.WRF_Hz = 11;
header.bandwidth_kHz=12;
header.beam_spacing_dB=13;
header.direct_wave_range_bin=14;
header.fs=15e3;
header.rx_rng_twoway_vec_km=16*ones<vec>(10);
header.date="14-Oct-2020 17:02:30";
header_hdf5.frequency_MHz=header.frequency_MHz;
header_hdf5.beam_centres_deg=header.beam_centres_deg.memptr();
//header_hdf5.beam_crossover_deg=eader.beam_crossover_deg;
header_hdf5.task_centre_azimuth_deg=header.task_centre_azimuth_deg;
header_hdf5.WRF_Hz = header.WRF_Hz;
header_hdf5.bandwidth_kHz=header.bandwidth_kHz;
header_hdf5.beam_spacing_dB=header.beam_spacing_dB;
header_hdf5.direct_wave_range_bin=header.direct_wave_range_bin;
header_hdf5.fs=header.fs;
//header_hdf5.rx_rng_twoway_vec_km=header.rx_rng_twoway_vec_km;
header_hdf5.date=header.date;
// the array of each length of multidimentional data.
hsize_t dim_header[1];
dim_header[0] = sizeof(header_hdf5) / sizeof(info_struct_hdf5);
// the length of dim
int rank_header = sizeof(dim_header) / sizeof(hsize_t);
// defining the datatype to pass HDF55
H5::CompType h5_header(sizeof(info_struct_hdf5));
h5_header.insertMember("frequency_MHz", HOFFSET(info_struct_hdf5, frequency_MHz), H5::PredType::NATIVE_DOUBLE);
h5_header.insertMember("beam_centres_deg", HOFFSET(info_struct_hdf5, beam_centres_deg_handle), H5::VarLenType(H5::PredType::NATIVE_DOUBLE));
h5_header.insertMember("beam_crossover_deg", HOFFSET(info_struct_hdf5, beam_crossover_deg_handle), H5::VarLenType(H5::PredType::NATIVE_DOUBLE));
h5_header.insertMember("task_centre_azimuth_deg", HOFFSET(info_struct_hdf5, task_centre_azimuth_deg), H5::PredType::NATIVE_DOUBLE);
h5_header.insertMember("WRF_Hz", HOFFSET(info_struct_hdf5, WRF_Hz), H5::PredType::NATIVE_DOUBLE);
h5_header.insertMember("bandwidth_kHz", HOFFSET(info_struct_hdf5, bandwidth_kHz), H5::PredType::NATIVE_DOUBLE);
h5_header.insertMember("beam_spacing_dB", HOFFSET(info_struct_hdf5, beam_spacing_dB), H5::PredType::NATIVE_DOUBLE);
h5_header.insertMember("direct_wave_range_bin", HOFFSET(info_struct_hdf5, direct_wave_range_bin), H5::PredType::NATIVE_INT);
h5_header.insertMember("fs", HOFFSET(info_struct_hdf5, fs), H5::PredType::NATIVE_DOUBLE);
h5_header.insertMember("rx_rng_twoway_vec_km", HOFFSET(info_struct_hdf5, rx_rng_twoway_vec_km_handle), H5::VarLenType(H5::PredType::NATIVE_DOUBLE));
h5_header.insertMember("date", HOFFSET(info_struct_hdf5, date), H5::StrType(H5::PredType::C_S1, H5T_VARIABLE));
// preparation of a dataset and a file.
H5::DataSpace space_header(rank_header, dim_header);
H5::H5File *file = new H5::H5File("data_test.h5", H5F_ACC_TRUNC);
H5::DataSet *dataset_header = new H5::DataSet(file->createDataSet("MOTHR_header", h5_header, space_header));
// Write
dataset_header->write(&header_hdf5, h5_header);
delete dataset_header;
delete file;
return 0;
}
现在编译时出现警告或错误,所以我认为这至少是朝着正确方向迈出的一步,但是当我运行代码时,我得到:
HDF5-DIAG: Error detected in HDF5 (1.10.4) thread 140528006936384:
#000: ../../../src/H5Dio.c line 336 in H5Dwrite(): can't write data
major: Dataset
minor: Write failed
#001: ../../../src/H5Dio.c line 828 in H5D__write(): can't write data
major: Dataset
minor: Write failed
#002: ../../../src/H5Dcontig.c line 633 in H5D__contig_write(): contiguous write failed
major: Dataset
minor: Write failed
#003: ../../../src/H5Dscatgath.c line 704 in H5D__scatgath_write(): datatype conversion failed
major: Dataset
minor: Can't convert datatypes
#004: ../../../src/H5T.c line 5025 in H5T_convert(): datatype conversion failed
major: Datatype
minor: Can't convert datatypes
#005: ../../../src/H5Tconv.c line 2512 in H5T__conv_struct_opt(): unable to convert compound datatype member
major: Datatype
minor: Unable to initialize object
#006: ../../../src/H5T.c line 5025 in H5T_convert(): datatype conversion failed
major: Datatype
minor: Can't convert datatypes
#007: ../../../src/H5Tconv.c line 3272 in H5T__conv_vlen(): can't write VL data
major: Datatype
minor: Write failed
#008: ../../../src/H5Tvlen.c line 913 in H5T_vlen_disk_write(): Unable to write VL information
major: Datatype
minor: Write failed
#009: ../../../src/H5HG.c line 543 in H5HG_insert(): unable to allocate a global heap collection
major: Heap
minor: Unable to initialize object
#010: ../../../src/H5HG.c line 163 in H5HG__create(): memory allocation failed
major: Resource unavailable
minor: No space available for allocation
#011: ../../../src/H5FL.c line 922 in H5FL_blk_malloc(): memory allocation failed for chunk
major: Resource unavailable
minor: No space available for allocation
#012: ../../../src/H5FL.c line 250 in H5FL_malloc(): memory allocation failed for chunk
major: Resource unavailable
minor: No space available for allocation
terminate called after throwing an instance of 'H5::DataSetIException'
Aborted (core dumped)
【问题讨论】:
-
这只是错误/警告的一部分。请在问题中包含完整的编译器消息
-
问题很可能是因为您告诉 HDF5 库犰狳向量“只是一个双倍”(
insertMember的最后一个参数)。您可能需要首先为犰狳向量定义一个新的复合数据类型。只有在那之后,您才能定义info_struct的复合数据类型,因为您需要将犰狳矢量的相应复合数据类型指定为作为insertMember的最后一个参数传递给vec成员的“HDF5 类型” . -
@darcamo 我看了一下这个post 并试图从那个开始工作(它关于阅读而不是写作)并且它现在编译现在的问题但是当我运行它时得到
memory allocation error我将使用新代码和错误更新我的原始帖子 -
这可能会变得很棘手,因为 HDF5 基本上是一个 C 库。一种解决方法是创建一个不同的结构,使用更简单的类型(使用 C 数组来存储原始犰狳矢量)并使用这个结构而不是原始结构来保存/加载到 HDF5。
-
@darcamo 所以这就是我正在尝试的。我使用
double *而不是arma::vec创建了一个副本结构。malloc()对于vec的大小,然后是memcpy(),这似乎有效,但是当我尝试保存它时,前面评论中提到的方式编译并运行时没有警告或错误,但是当我使用 h5dump查看文件,该条目是空白的。我想我又回到了insertmember()的问题上,但我对 HDF5 非常陌生,所以我不确定下一步该去哪里......