Чтение данных HDF5 из C ++: как читать этот конкретный формат?

У меня есть файл HDF5, который мне нужно прочитать на C ++, но у меня возникают проблемы, поскольку формат файла кажется немного сложным …

Файл HDF5 содержит данные, сохраненные с двух устройств. Данные представляют собой временные ряды; это можно рассматривать как два массива, один для времени и второй для фактического вывода с устройства.
Количество приобретений определяется пользователем, но количество приобретений одинаково для обоих устройств (поскольку их данные получаются одновременно).

Например, один файл будет содержать данные, скажем, из 10 приобретений, организованных в нечто похожее на:

/Device1/Acquisition_000
/Device1/Acquisition_001
[...]
/Device2/Acquisition_000
/Device2/Acquisition_001
[...]

Каждое приобретение будет содержать массив времени и массив данных.

Вот скриншот того, что HDFView видит в файле:
Файл открыт в 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]

Большое спасибо.

2

Решение

Имена членов используются для извлечения правильных полей данных из файла. «имя_сигнала» не соответствует имени данных в файле. Попробуйте использовать «Сигнал», как видно из 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.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]