У меня есть файл HDF5, который мне нужно прочитать на C ++, но у меня возникают проблемы, поскольку формат файла кажется немного сложным …
Файл HDF5 содержит данные, сохраненные с двух устройств. Данные представляют собой временные ряды; это можно рассматривать как два массива, один для времени и второй для фактического вывода с устройства.
Количество приобретений определяется пользователем, но количество приобретений одинаково для обоих устройств (поскольку их данные получаются одновременно).
Например, один файл будет содержать данные, скажем, из 10 приобретений, организованных в нечто похожее на:
/Device1/Acquisition_000
/Device1/Acquisition_001
[...]
/Device2/Acquisition_000
/Device2/Acquisition_001
[...]
Каждое приобретение будет содержать массив времени и массив данных.
Вот скриншот того, что HDFView видит в файле:
Я, хотя «путь» / Device2 / Acquisition_000 был набор данных и пытался прочитать его как таковой, но у меня возникли проблемы. Затем я сбросил файл .h5 с помощью h5dump и получил следующее:
HDF5 "data.h5" {
GROUP "/" {
GROUP "Device1" {
DATASET "Acquisition_000" {
DATATYPE H5T_COMPOUND {
H5T_IEEE_F64BE "Time";
H5T_IEEE_F64BE "Signal";
}
DATASPACE SIMPLE { ( 270000 ) / ( 270000 ) }
DATA {
(0): {
0,
-0.0933597
},
(1): {
2e-05,
-0.0476648
},
(2): {
4e-05,
-0.0628964
},
[...]
Теперь я не знаю, как мне читать эту структуру. Я видел H5T_COMPOUND, поэтому я попробовал составной пример из http://www.hdfgroup.org/HDF5/doc/cpplus_RM/compound_8cpp-example.html но набор данных-> read () не может читать данные; valgrind сообщает о доступе к неинициализированным данным, когда std :: cout’ит данные в цикле.
Еще одним источником путаницы является «H5T_IEEE_F64BE» в дампе; не является ли часть для big-endian? И машина, генерирующая данные, и читающая их, — x86_64 …
Как я могу прочитать массивы «Time» и «Signal» в массивы C / C ++?
Для справки, вот моя попытка адаптировать пример:
const H5std_string FILE_NAME("data.h5");
const H5std_string DATASET_NAME("/Device1/Acquisition_000/");
H5File file(FILE_NAME, H5F_ACC_RDONLY);
DataSet dataset = file.openDataSet(DATASET_NAME);
const H5std_string MEMBER_TIME("time_name");
const H5std_string MEMBER_SIGN("signal_name");
// Try reading a single array:
CompType mtype3( sizeof(double) );
mtype3.insertMember(MEMBER_SIGN, 0, PredType::NATIVE_DOUBLE);
double *data_signal = new double[270000];
memset(data_signal, 0, 270000);
dataset.read(data_signal, mtype3);
// Print the data
for (int i = 0 ; i < 10 ; i++)
{
std::cout << "data_signal[i=" << i << "] = " << data_signal[i] << std::endl;
}
и его вывод:
data_signal[i=0] = 0
data_signal[i=1] = 0
data_signal[i=2] = 0
data_signal[i=3] = 0
data_signal[i=4] = 0
data_signal[i=5] = 0
data_signal[i=6] = 0
data_signal[i=7] = 0
data_signal[i=8] = 0
data_signal[i=9] = 0
Кроме того, Matlab может прочитать файл, используя:
data = h5read('data.h5', '/Device1/Acquisition_000')
data =
Time: [270000x1 double]
Signal: [270000x1 double]
Большое спасибо.
Имена членов используются для извлечения правильных полей данных из файла. «имя_сигнала» не соответствует имени данных в файле. Попробуйте использовать «Сигнал», как видно из MATLAB и из GUI Viewer.
В конце концов, вы захотите определить структуру c ++, которая представляет пару время / сигнал, как в сложном примере:
struct dataPoint
{
double timePoint;
double signal;
};
CompType hdf5DataPointType( sizeof(dataPoint) );
hdf5DataPointType.insertMember(MEMBER_TIME, 0, PredType::NATIVE_DOUBLE);
hdf5DataPointType.insertMember(MEMBER_SIGN, sizeof(double), PredType::NATIVE_DOUBLE);
Затем читайте непосредственно в массив dataPoint.
Других решений пока нет …