Прием данных HDF5: ключи внутри ключей, получение данных в массивы

#python #hdf5 #h5py

Вопрос:

Мне нужна помощь.

У меня есть файл HDF5, содержащий данные о спектре (время, частоты и уровень мощности заданной частоты в данный момент времени). Вот как структурирован файл (с использованием HDFView):

HDF-представление файла данных

Основными группами (ключами) являются ЧАСЫ, а затем внутри находятся минуты, причем каждая минута является своей собственной группой (ключом). Данные были собраны за 0,02 секунды в течение 60 секунд… таким образом, существует 3000 строк…и диапазоны частот 256 (т. Е. Начинаются с 1 МГц и заканчиваются на 26 МГц, на расстоянии 256 друг от друга. Например.e. 23 —gt; 23:10 —gt;gt; 2D массив мощности

 0 0 1 2 ..... 255 1 -53.672386 -53.82235 -53.773468 ..... -50.566887 2 -53.85694 -53.945183 -53.63385 ..... -51.306465  3 -53.709038 -53.55101 -53.55305 ..... -52.7324906 . . . 2999 -53.23989 -51.501495 -50.681602 -52.227474  

Я могу получить доступ к данным отдельных минут и собрать их в массивы, а затем построить данные. Подобный этому:

 import h5py import numpy as np import matplotlib.pyplot as plt  # Read in the HDF5 file file = h5py.File("/home/tom/Desktop/2021-10-28_ch0.hdf5", 'r')  # Search for the main groups in the file. The main groups are hours: 20, 22, etc...  # Select one of the hours (i.e. 23) hour = file['23']  # Search for the subgroups (keys) within the chosen hour. There are "hour:minutes" i.e. 23:10 #for key in hour.keys():  #print( key )  # Select key with data for minutes 10, 11, 12, 13 and save into individual arrays: minute_data_10=hour['23:10'][()] minute_data_11=hour['23:11'][()] minute_data_12=hour['23:12'][()] minute_data_13=hour['23:13'][()]  # Generate a 1D array of TIME spanning 4 minutes (because we ingested # 4x 1 minute slices of data:  time = np.linspace(0, 60*4, 3000*4)  # Generate a 1D array of FREQUENCY frequency = np.linspace(1.575E0, 26.82402336E0, 256)  # Combine minute_data_10 minute_data_11 minute_data_12 and minute_data_13 along the time axis (axis=0) comb_min = np.concatenate( (minute_data_10, minute_data_11, minute_data_12, minute_data_13), axis=0 )  print( comb_min.shape )  # Plot the data im = plt.pcolormesh(frequency, time, comb_min, cmap='jet') plt.colorbar(im).ax.tick_params(labelsize=10) plt.title('Spectrum') plt.ylabel('Seconds ago...') #plt.xlabel('frequency in Hz') im.axes.xaxis.set_ticklabels([]) plt.show()  

Нанесенный Спектр

Я вручную определяю каждую минуту (мин. 10, 11, 12, 13), объединяя их, а затем нанося на график.

но…что я хотел бы сделать, так это автоматически проглотить ВСЕ минуты за ВСЕ часы по моему выбору, а затем объединить их в один сюжет. Например, как я могу проглотить ВСЕ минуты за 15 часов, а затем построить график спектра ? ИЛИ, как я мог бы построить график первых 5 часов данных ?

Комментарии:

1. просто зацикливайтесь на всех ключах в час или зацикливайтесь на всех часах и ключах в течение тех часов, которые вы выберете

2. Да, попробовал это, и это хорошо работает (хотя все еще изучает Python). Спасибо!

Ответ №1:

Файлы HDF5 являются самоописывающимися. (Другими словами, вы можете получить имена групп или наборов данных из файла-вам не нужно знать их заранее.) Как отмечалось выше, вы делаете это с .keys() помощью метода. (Примечание: объекты h5py НЕ являются словарями; h5py просто использует синтаксис словаря Python для доступа к именам.)

Использование ключей/имен имеет дополнительное преимущество, заключающееся в том, что вы читаете только существующие наборы данных. Глядя на ваше изображение, можно увидеть наборы данных для времени 15:00 и 15:02 , но не для 15:01 . (Этот пробел имеет дополнительные последствия при создании вашего сюжета — но это другая проблема.)

Приведенный ниже код показывает, как это сделать. Он использует тот же подход: создайте список объектов h5py, затем объедините их в один массив с np.concatenate помощью . Он также собирает hh:mm время (из имен наборов данных) в списке, который вы можете использовать для создания time массива.

Я использовал файловый контекстный менеджер Python. Это предпочтительнее методов открытия/закрытия (позволяет избежать оставления файлов открытыми и улучшает читаемость).

Простой пример (жестко закодированный для [’15’] часовой группы):

 with h5py.File('/home/tom/Desktop/2021-10-28_ch0.hdf5.h5','r') as h5f:   times = []  collect = []  hh = '15'  for hhmm in h5f[hh].keys():  times.append(hhmm)  collect.append(h5f[hh][hhmm])    comb_min = np.concatenate( collect, axis=0 )  print(times)  print(len(collect), comb_min.shape)  

Более общий пример (считывает все группы[часы] и наборы данных[‘чч:мм’]):

 with h5py.File('/home/tom/Desktop/2021-10-28_ch0.hdf5.h5','r') as h5f:   times = []  collect = []  for hh in h5f.keys():  for hhmm in h5f[hh].keys():  times.append(hhmm)  collect.append(h5f[hh][hhmm])    comb_min = np.concatenate( collect, axis=0 )  print(times)  print( len(collect), comb_min.shape )   

Ответ №2:

Это просто обобщение того, что у вас уже есть. Чтобы получить все 15 часов:

 hh = '15' hour = file[hh]  collect = [hour[f'{hh}:{mm:02d}'] for mm in range(60)] comb_min = np.concatenate( collect, axis=0 ) print( comb_min.shape )  

Чтобы получить первые 5 часов:

 collect = [hours[f'{hh:02d}:{mm:02d}'] for hh in range(5) for mm in range(60)] comb_min = np.concatenate( collect, axis=0 ) print( comb_min.shape )  

И похоже for , что пункты написаны наоборот, но это не так.

Комментарии:

1. Может потребоваться проверка наличия каждого hh:mm набора данных. Например, на изображении показано 15:00 и 15:02 , но нет 15:01 .

2. Я не вижу этого в постановке задачи, но мой код получит такую проверку в том смысле, что он вызовет найденное исключение, если запись не существует.