2013-10-11 23 views
12

Ho un array di struct creato da MATLAB e memorizzati in file di formato v7.3 mat:Come leggere un file mat v7.3 tramite h5py?

struArray = struct('name', {'one', 'two', 'three'}, 
        'id', {1,2,3}, 
        'data', {[1:10], [3:9], [0]}) 
save('test.mat', 'struArray', '-v7.3') 

Ora voglio leggere questo file tramite Python usando h5py:

data = h5py.File('test.mat') 
struArray = data['/struArray'] 

ho idea come ottenere i dati struct uno per uno da struArray:

for index in range(<the size of struArray>): 
    elem = <the index th struct in struArray> 
    name = <the name of elem> 
    id = <the id of elem> 
    data = <the data of elem> 
+0

Hai trovato una soluzione reale per questo? – Pastafarian

+0

avevo una domanda simile, con una soluzione parziale: http://stackoverflow.com/questions/29852481/reading-all-variables-in-a-mat-file-with-python-h5py/29856030#29856030 – CodyF

risposta

0

Matlab formato di 7.3 file non è estremamente facile da lavorare h5py. Si basa sul riferimento HDF5, cfr. h5py documentation on references.

>>> import h5py 
>>> f = h5py.File('test.mat') 
>>> list(f.keys()) 
['#refs#', 'struArray'] 
>>> struArray = f['struArray'] 
>>> struArray['name'][0, 0] # this is the HDF5 reference 
<HDF5 object reference> 
>>> f[struArray['name'][0, 0]].value # this is the actual data 
array([[111], 
     [110], 
     [101]], dtype=uint16) 

Per leggere struArray(i).id:

>>> f[struArray['id'][0, 0]][0, 0] 
1.0 
>>> f[struArray['id'][1, 0]][0, 0] 
2.0 
>>> f[struArray['id'][2, 0]][0, 0] 
3.0 

notare che memorizza Matlab un numero come una matrice di dimensioni (1, 1), quindi la finale [0, 0] per ottenere il numero.

Per leggere struArray(i).data:

>>> f[struArray['data'][0, 0]].value 
array([[ 1.], 
     [ 2.], 
     [ 3.], 
     [ 4.], 
     [ 5.], 
     [ 6.], 
     [ 7.], 
     [ 8.], 
     [ 9.], 
     [ 10.]]) 

Per leggere struArray(i).name, è necessario convertire l'array di interi a stringa:

>>> f[struArray['name'][0, 0]].value.tobytes()[::2].decode() 
'one' 
>>> f[struArray['name'][1, 0]].value.tobytes()[::2].decode() 
'two' 
>>> f[struArray['name'][2, 0]].value.tobytes()[::2].decode() 
'three' 
0

vorrei iniziare sparando l'interprete e funzionante help su struarray. Dovrebbe darti abbastanza informazioni per iniziare. In caso contrario, è possibile scaricare gli attributi di qualsiasi oggetto Python mediante print dell'attributo __dict__.

0

Mi dispiace, ma penso che sarà molto impegnativo per ottenere contenuti di cellule/strutture dall'esterno Matlab. Se visualizzi i file prodotti (ad es. Con HDFView) vedrai che ci sono molti riferimenti incrociati e nessun modo ovvio per procedere.

Se ci si limita a semplici array numerici, funziona perfettamente. Se si dispone di array di piccole dimensioni contenenti matrici numeriche, è possibile convertirli in variabili separate (ad es. Contenuto di cella1, contenuto di celle2 ecc.) Che di solito è composto da poche righe e consente di salvarle e caricarle direttamente. Quindi nel tuo esempio vorrei salvare un file con Vars name1, name2, name3, id1, id2, id3 ... ecc

EDIT: È stato specificato h5py nella questione in modo da questo è quello che ho risposto, ma vale la pena ricordare che con scipy.io.loadmat si dovrebbe essere in grado di ottenere le variabili originali convertito in numpy equivalenti (es. matrici di oggetti).

+4

Grazie comunque ! Ho qualche problema con questo problema da qualche giorno. Ho sempre qualcosa di simile a ' 'piuttosto che al valore reale. Tuttavia, il 'scipy.io.loadmat' non funziona per il formato di file di v7.3 mat. – Eastsun

-1

È davvero un problema con Matlab 7.3 e h5py. Il mio trucco è convertire il tipo h5py._hl.dataset.Dataset nell'array numpy. Per esempio,

np.array(data['data']) 

risolverà il tuo problema con il campo 'data'.

+0

Non funziona. Aggiunge semplicemente un altro livello array sopra quello esistente. Per esempio. 'Array ([[, , ]], dtype = oggetto)' E i dati esistenti è del tipo 'h5py._hl.dataset.Dataset' – Pastafarian

2

visit o visititems è semplice modo di vedere la struttura generale di un file h5py:

fs['struArray'].visititems(lambda n,o:print(n, o)) 

Quando ho eseguito questo su un file prodotto da Octave save -hdf5 ottengo:

type <HDF5 dataset "type": shape(), type "|S7"> 
value <HDF5 group "/struArray/value" (3 members)> 
value/data <HDF5 group "/struArray/value/data" (2 members)> 
value/data/type <HDF5 dataset "type": shape(), type "|S5"> 
value/data/value <HDF5 group "/struArray/value/data/value" (4 members)> 
value/data/value/_0 <HDF5 group "/struArray/value/data/value/_0" (2 members)> 
value/data/value/_0/type <HDF5 dataset "type": shape(), type "|S7"> 
value/data/value/_0/value <HDF5 dataset "value": shape (10, 1), type "<f8"> 
value/data/value/_1 <HDF5 group "/struArray/value/data/value/_1" (2 members)> 
... 
value/data/value/dims <HDF5 dataset "dims": shape (2,), type "<i4"> 
value/id <HDF5 group "/struArray/value/id" (2 members)> 
value/id/type <HDF5 dataset "type": shape(), type "|S5"> 
value/id/value <HDF5 group "/struArray/value/id/value" (4 members)> 
value/id/value/_0 <HDF5 group "/struArray/value/id/value/_0" (2 members)> 
... 
value/id/value/_2/value <HDF5 dataset "value": shape(), type "<f8"> 
value/id/value/dims <HDF5 dataset "dims": shape (2,), type "<i4"> 
value/name <HDF5 group "/struArray/value/name" (2 members)> 
... 
value/name/value/dims <HDF5 dataset "dims": shape (2,), type "<i4"> 

Questo può non è la stessa cosa che produce MATLAB 7.3, ma dà un'idea della complessità di una struttura.

Una più raffinata richiamata in grado di visualizzare i valori, e potrebbe essere il punto di partenza per ricreare un oggetto Python (dizionario, liste, ecc).

def callback(name, obj): 
    if name.endswith('type'): 
     print('type:', obj.value) 
    elif name.endswith('value'): 
     if type(obj).__name__=='Dataset': 
      print(obj.value.T) # http://stackoverflow.com/questions/21624653 
    elif name.endswith('dims'): 
     print('dims:', obj.value) 
    else: 
     print('name:', name) 

fs.visititems(callback) 

produce:

name: struArray 
type: b'struct' 
name: struArray/value/data 
type: b'cell' 
name: struArray/value/data/value/_0 
type: b'matrix' 
[[ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.]] 
name: struArray/value/data/value/_1 
type: b'matrix' 
[[ 3. 4. 5. 6. 7. 8. 9.]] 
name: struArray/value/data/value/_2 
type: b'scalar' 
0.0 
dims: [3 1] 
name: struArray/value/id 
type: b'cell' 
name: struArray/value/id/value/_0 
type: b'scalar' 
1.0 
... 
dims: [3 1] 
name: struArray/value/name 
type: b'cell' 
name: struArray/value/name/value/_0 
type: b'sq_string' 
[[111 110 101]] 
... 
dims: [3 1]