2015-12-17 9 views
7

Używam pakietu Python h5py (wersja 2.5.0), aby uzyskać dostęp do moich plików hdf5.Jak rozróżnić zestawy danych HDF5 i grupy za pomocą h5py?

Chcę przejść przez zawartość pliku i zrobić coś z każdym zestawem danych.

Stosując metodę 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) 

dla pliku testowego ja uzyskania:

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

który mówi mi, że istnieje zbiór danych i grupy w pliku. Jednak nie ma oczywistego sposobu, z wyjątkiem użycia type() do rozróżnienia między zestawami danych i grupami. The h5py documentation niestety nie mówi nic na ten temat. Zawsze zakładają, że wiesz wcześniej, jakie są grupy i jakie są zestawy danych, na przykład dlatego, że same tworzyły zestawy danych.

Chciałbym mieć coś takiego:

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

Jak mogę odróżnić między grupami i zbiorów danych podczas odczytu nieznany plik hdf5 w Pythonie z h5py? Jak mogę uzyskać listę wszystkich zestawów danych, wszystkich grup wszystkich linków?

Odpowiedz

6

Niestety, nie ma wbudowanego sposobu w apelu h5py, aby to sprawdzić, ale można po prostu sprawdzić typ przedmiotu za pomocą is_dataset = isinstance(item, h5py.Dataset).

Aby wyświetlić całą zawartość pliku (oprócz atrybutów pliku), można użyć opcji Group.visititems z opcją wywołania, która pobiera nazwę i wystąpienie elementu.

+0

Dzięki. Domyślam się, że wszystkie grupy wywodzą się z 'h5py.Group', wszystkich miękkich linków z' h5py.SoftLink' i wszystkich twardych linków z 'h5py.HardLink'. – Trilarion

+0

Ho, jeden wyjątek, o którym zapomniałem wspomnieć. Jeśli dobrze pamiętam, '' visititems'' nie odwiedza linków zewnętrznych. – Gall

1

Ponieważ h5py używa słowników python jako metody interakcji, należy użyć funkcji "values ​​()", aby uzyskać rzeczywisty dostęp do elementów. Możesz więc użyć filtrów listy:

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

Robienie tego w sposób rekursywny powinno być proste.

3

Podczas gdy odpowiedzi Galla i Jamesa Smitha wskazują ogólnie na rozwiązanie, konieczne jest wykonanie przejścia przez hierarchiczną strukturę HDF i filtrowanie wszystkich zestawów danych. Zrobiłem to za pomocą yield from, który jest dostępny w Pythonie 3.3+, który działa całkiem ładnie i przedstawia go tutaj.

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) 
0

Preferuję to rozwiązanie. Okazuje się lista wszystkich obiektów w pliku hdf5 „h5file”, a następnie sortuje je w oparciu o klasy, podobnego do tego, co zostało wspomniane wcześniej, ale nie w taki sposób zwięzły:

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) ]