Proper importing of MATLAB structures into Python

388 views (last 30 days)
Milad K
Milad K on 19 Feb 2018
Edited: Milad K on 20 Feb 2018
I have a MATLAB (2017b) structure which is saved (attached) as lib.mat. This structure, at its highest level, is basically a library with three different fields including an array of structures: ['name', 'structures' [1 x 32 struct], 'structlist', {1 x 32 cell}].
I have tried two different methods to import this structure into Python (v3.5):
a) Import using the io module from Scipy library
import scipy.io as spio
lib = spio.loadmat('lib.mat')
which produces a dict in python called 'lib' whose fields are not accessible (at least I am not aware how to access, for example, the 32 structures listed in the field 'structures' [1 x 32 struct]).
b) calling MATLAB engine in Python (v3.5) and using getfield function to access different fields of the structure:
import matlab.engine
eng = matlab.engine.start_matlab()
Obj = eng.load('lib.mat')['lib']
Names = eng.getfield(Obj, 'name')
Strs = eng.getfield(Obj, 'structures')
StrLists = eng.getfield(Obj, 'structlist')
where everything works but
Strs = eng.getfield(Obj, 'structures')
is not able to restore the 32 structures in variable Strs. For example if you try:
>>> eng.size(StrLists)
the result would be: matlab.double([[1.0,32.0]]), which is correct, but if you try
>>> eng.size(Strs)
the results is: matlab.double([[0.0,0.0]]), which is incorrect (must be the same size as StrList).
Now my question is how to properly import such data structures into Python and access to their fields.
Thanks

Answers (1)

Bo Li
Bo Li on 20 Feb 2018
Would you share more details about how the file "lib.mat" is created? I tried following steps:
>>lib.name='hello'
>>Strs(1).id=1
>>Strs(2).id=2
>>Strs(3).id=3
>>lib.Strs = Strs
>>lib.StrList = {1,2,3}
>>save('lib', 'lib')
This what I see in Python:
>>>Obj = eng.load('lib.mat')['lib']
...
ValueError: only a scalar struct can be returned from MATLAB
This is the expected behavior as Struct array is not supported according to the doc:
https://www.mathworks.com/help/matlab/matlab_external/handle-data-returned-from-matlab-to-python.html
In this case, "lib" itself is a scalar struct but the element "Strs" is a struct array.
  1 Comment
Milad K
Milad K on 20 Feb 2018
Edited: Milad K on 20 Feb 2018
Thanks for the reply. To shortly answer your question: lib.mat contains an object created using a GDS-generator library supported by MATLAB.
The way I found to go around this is to first convert this object to an array of structures in MATLAB:
step 1) Make a 1x1 "nested" structure in Matlab
lib2 = struct(lib)
and save it as lib.mat. This conversion from the original object produces a 1x1 structure containing all the fields ['name', 'structures' [1 x 32 struct], 'structlist', {1 x 32 cell}].
Step 2) load the nested structures in Python using scipy.io
By employing the modified version of scipy.io.loadmat, explained in Stackoverflow, the nested structure lib2 saved in lib.mat can be then properly imported as a dictionary into python.

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!