2015-12-17 21 views
7

Uso il pacchetto Python h5py (versione 2.5.0) per accedere ai miei file hdf5.Come distinguere tra set di dati HDF5 e gruppi con h5py?

Voglio attraversare il contenuto di un file e fare qualcosa con ogni set di dati.

Usando il metodo 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) 

per un file di test ottengo:

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

che mi dice che c'è un insieme di dati e un gruppo nel file. Tuttavia, non esiste un modo ovvio tranne che per utilizzare type() per distinguere tra i set di dati e i gruppi. Il h5py documentation purtroppo non dice nulla su questo argomento. Presuppongono sempre che tu sappia in anticipo quali sono i gruppi e quali sono i set di dati, ad esempio perché hanno creato i set di dati stessi.

Mi piacerebbe avere qualcosa di simile:

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

Come posso distinguere tra i gruppi e le serie di dati durante la lettura di un file HDF5 sconosciuta in Python con h5py? Come posso ottenere un elenco di tutti i set di dati, di tutti i gruppi, di tutti i link?

risposta

6

Sfortunatamente, non è presente un modo incorporato in h5py api per verificarlo, ma è sufficiente verificare il tipo di articolo con is_dataset = isinstance(item, h5py.Dataset).

Per elencare tutto il contenuto del file (tranne gli attributi del file), è possibile utilizzare Group.visititems con un callable che prende il nome e l'istanza di un elemento.

+0

Grazie. Immagino che tutti i gruppi derivino da "h5py.Group", tutti i collegamenti "soft" da "h5py.SoftLink" e tutti gli hard link da "h5py.HardLink". – Trilarion

+0

Ho, un'eccezione che ho dimenticato di menzionare. Se ricordo male, '' visititems'' non visita i link esterni. – Gall

1

Poiché h5py utilizza i dizionari python come metodo di scelta per l'interazione, è necessario utilizzare la funzione "values ​​()" per accedere effettivamente agli elementi. Quindi potresti essere in grado di usare i filtri di lista:

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

Fare questo in modo ricorsivo dovrebbe essere abbastanza semplice.

3

Mentre le risposte di Gall e James Smith indicano la soluzione in generale, l'attraversamento attraverso la struttura gerarchica HDF e il filtraggio di tutti i set di dati devono ancora essere eseguiti. L'ho fatto usando yield from che è disponibile in Python 3.3+ che funziona abbastanza bene e lo presenta qui.

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

Preferisco questa soluzione. Essa trova l'elenco di tutti gli oggetti presenti nel file HDF5 "h5file", quindi li ordina in base alla classe, simile a quello che è stato detto prima, ma non in modo così succinta:

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