2

I am very new to matlab and python and need to use some values in python from the matlab cell array.

I have a cell array of integers that after i execute this line of code and print the result, i get this:

a = loadmat('file.mat')
print a

{'__version__': '1.0', '__header__': 'MATLAB 5.0 MAT-file, Platform: PCWIN, Created on: Wed Sep 21 15:30:15 2011', 'juncForward_c': array([[ [[ [[ ([[30]], **[[91], [87]]**, [[3]], [[2.2455372690184494, 3.6052402625905993, 5.5884470309828833]], [[14.0, 4.0, 15.4]], [[-1, -1, 2]], [[91, 89, 93], [88, 85, 86]], [[500, 500, 5]], [[1, 2, 3]], [[11.133333333333333]], **[[4]]**, [[1]], [[1]], [[1.0], [20.365168528421695]])]]

[[ ([[30]], **[[99], [80]]**, [[3]], [[4.0376480381611373, 2.3561944901923448, 6.0857897473297058]], [[10.0, 15.4, 16.600000000000001]], [[-1, 1, 3]], [[98, 98, 100], [79, 81, 80]], [[500, 6, 33]], [[1, 2, 3]], **[[14]]**, [[2]], [[1]], [[1]], [[2.0], [6.6573267908372973]])]]

and the print out continues on.

Could someone explain to me how the cell array is arranged? (so how many dimensions is the above?)

I then have a few questions: 1) Within this cell array, there are variables 'label' and 'coordinates' that are assigned to one array/cell (i dont know which is the actual term to use) -- the values in bold. I would like to write in Python to access this values. How should I go about it?

2) To test, I tried this -> juncInfoF = a.get('juncForward_c') and when i try to print juncInfoF, it prints 'None'. Why is that so? I am puzzled because previously when i tried this, it works. I could even do this -> print juncInfo[0][9][0][0]. but now I cannot even do any of the above.

Amro
  • 123,847
  • 25
  • 243
  • 454
user974666
  • 359
  • 1
  • 5
  • 8

2 Answers2

1

I imagine loadmat('file.mat') returns an instance of a shelve-class, that is inherited from the dict class. I assume you are using the loadmat function from scipy.io?

from scipy.io import loadmat

The scipy doc only mentions loadmat() returns a dictionary, but my guess is that the returned object a in your example is an open shelve-file, and you can no longer access its content when a is closed, which might happen for several reasons apart from calling a.close() mannually.

To prevent this, copy all data into a real dictionary first, while loading this data:

mat_dict = {}
mat_dict.update(loadmat('file.mat'))

Now you can retrieve all keys and values from mat_dict:

a = mat_dict['juncForward_c']
print(a.shape) # should work now

note that this is a valid solution as long as you are testing and figuring out what the mat_dict data is all about. In your script/model/function you would tipically load only the part of the shelve dict that you want, and then close the file explicitly:

f = loadmat('file.mat')
a = f['juncForward_c']
f.close()

I don't know if the with statement works (shelve does not support it as yet), you'll have to test it, but it should handle closing even when an exception is thrown during loading of a:

with loadmat('file.mat') as f:
    a = f['juncForward_c']

edit: subclass from numpy array to add additional attributes

import numpy as np

class MatArray(np.array):
    def __init__(self, filepath):
        f = loadmat(filepath)
        np.array.__init__(self, f['juncForward_c'])
        self.version = f['__version__']
        self.header = f['__header__']
        f.close() 

so now if you want your array resembling the matlab structure, you do:

>>> a = MatArray('myfile.mat')
>>> a.header
'MATLAB 5.0 MAT-file, Platform: PCWIN, Created on: Wed Sep 21 15:30:15 2011'
>>> a.shape

etc

Remi
  • 20,619
  • 8
  • 57
  • 41
  • hey remi! thank you very much for your answer! I would also like to ask if theres any way the dictionary would saved the original mat file stored structures. because according to the person who coded the matfile out, she told me that the values in the matfile are stored according to certain structures. hence one could use a.label to get the label value out. could i do this using python after i have loaded the .mat file data into python using your method above? because i have actually tried keying in a.label but it does not allow me to do so. – user974666 Oct 03 '11 at 13:56
  • you can create your own class and assign the values of it's attributes according to the keys in the loaded dict. Did you try help(loadmat)? it seems that struct_as_record keyword kan be interesting for you. Otherwise post an example of your .mat file. – Remi Oct 03 '11 at 16:52
  • the dictionary keys returned when i use scipy.io.loadmat('file.mat') are ('_version_','1.0'), ('_header_','MATLAB 5.0....'), ('juncForward_c', array([[ [[ [[ ([[30.0]],[[91.0],[87.0]],[[3.0]],[[2.2454534533.785785,5.4354]], ... )]] etc) dtype = object)), so how do i get the attributes in the ndarray returned as the value of they key: juncForward_c? could it be i cannot load the .mat file this way? – user974666 Oct 04 '11 at 04:28
  • Are you saying you want the other keys as additional attributes on your numpy array? You can subclass from numpy arry and do something like in my edt above. – Remi Oct 04 '11 at 11:40
  • okae i got it ! thank you very much for your time Remi. i had to do this: a = f['juncForward_c'][0,0][0,0]['label']. =) – user974666 Oct 05 '11 at 09:53
  • The label was thus no attribute but a key to content of a cell (array element) inside a cell; hard to guess without the original file... On stackoverflow you can show your appreciation by voting up and accepting answers (hint hint ;) ) – Remi Oct 05 '11 at 14:56
0

If in your mat file there are only cell arrays with list of integers or strings, I wrote a generic code for that. For example, in matlab you can do something like that:

names = cell(1, N);
indices = cell(1, N);
for ind=1:N
    names{ind} = *some_value*;
    indices{ind} = *some_array*;
save('names_and_indices.mat', 'names', 'indices');

Here you can find how to read this mat file in python.

Noam Peled
  • 4,484
  • 5
  • 43
  • 48