Я использую пакет Python h5py (версия 2.5.0) для доступа к моим файлам hdf5.

Я хочу просмотреть содержимое файла и что-то сделать с каждым набором данных.

Используя метод visit:

import h5py

def print_it(name):
    dset = f[name]
    print(dset)
    print(type(dset))


with h5py.File('test.hdf5', 'r') as f:
    f.visit(print_it)

Для тестового файла я получаю:

<HDF5 group "/x" (1 members)>
<class 'h5py._hl.group.Group'>
<HDF5 dataset "y": shape (100, 100, 100), type "<f8">
<class 'h5py._hl.dataset.Dataset'>

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

Я хотел бы иметь что-то вроде:

f = h5py.File(..)
for key in f.keys():
    x = f[key]
    print(x.is_group(), x.is_dataset()) # does not exist

Как отличить группы от наборов данных при чтении неизвестного файла hdf5 в Python с помощью h5py? Как я могу получить список всех наборов данных, всех групп, всех ссылок?

16
Trilarion 17 Дек 2015 в 11:53

5 ответов

Лучший ответ

К сожалению, в API h5py нет встроенного способа проверить это, но вы можете просто проверить тип элемента с помощью is_dataset = isinstance(item, h5py.Dataset).

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

13
Gall 17 Дек 2015 в 09:09

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

def h5printR(item, leading = ''):
    for key in item:
        if isinstance(item[key], h5py.Dataset):
            print(leading + key + ': ' + str(item[key].shape))
        else:
            print(leading + key)
            h5printR(item[key], leading + '  ')

# Print structure of a `.h5` file            
def h5print(filename):
    with h5py.File(filename, 'r') as h:
        print(filename)
        h5printR(h, '  ')

Примере

>>> h5print('/path/to/file.h5')

file.h5
  test
    repeats
      cell01: (2, 300)
      cell02: (2, 300)
      cell03: (2, 300)
      cell04: (2, 300)
      cell05: (2, 300)
    response
      firing_rate_10ms: (28, 30011)
    stimulus: (300, 50, 50)
    time: (300,)
0
Yas 23 Окт 2018 в 07:23

Я предпочитаю это решение. Он находит список всех объектов в hdf5-файле "h5file", затем сортирует их по классам, аналогично тому, что было упомянуто ранее, но не таким кратким образом:

import h5py
fh5 = h5py.File(h5file,'r')
fh5.visit(all_h5_objs.append)
all_groups   = [ obj for obj in all_h5_objs if isinstance(fh5[obj],h5py.Group) ]
all_datasets = [ obj for obj in all_h5_objs if isinstance(fh5[obj],h5py.Dataset) ]
0
Scott N 11 Окт 2016 в 16:40

В то время как ответы Галла и Джеймса Смита указывают на решение в целом, обход иерархической структуры HDF и фильтрация всех наборов данных еще не завершены. Я сделал это, используя yield from, который доступен в Python 3.3+, который прекрасно работает, и представил его здесь.

import h5py

def h5py_dataset_iterator(g, prefix=''):
    for key in g.keys():
        item = g[key]
        path = '{}/{}'.format(prefix, key)
        if isinstance(item, h5py.Dataset): # test for dataset
            yield (path, item)
        elif isinstance(item, h5py.Group): # test for group (go down)
            yield from h5py_dataset_iterator(item, path)

with h5py.File('test.hdf5', 'r') as f:
    for (path, dset) in h5py_dataset_iterator(f):
        print(path, dset)
8
Trilarion 21 Дек 2015 в 17:14

Поскольку h5py использует словари python в качестве метода выбора для взаимодействия, вам нужно использовать функцию values () для фактического доступа к элементам. Таким образом, вы можете использовать фильтры списка:

datasets = [item for item in f["Data"].values() if isinstance(item, h5py.Dataset)]

Делать это рекурсивно должно быть достаточно просто.

1
James Smith 17 Дек 2015 в 09:22