12

Consider the following Matlab code:

pmod(1).name{1}  = 'regressor1';
pmod(1).param{1} = [1 2 4 5 6];
pmod(1).poly{1}  = 1; 
pmod(2).name{1}  = 'regressor2-1';
pmod(2).param{1} = [1 3 5 7]; 
pmod(2).poly{1}  = 1;

This creates a struct array. Each struct in the array contains three fields of type cell. As such, we have the following hierarchy in pmod:

pmod  // struct array
|
*- struct
|  |
|  *- cell  // contains 1 or more strings
|  *- cell  // contains 1 or more arrays
|  *- cell  // contains 1 or more arrays
|
*- struct [...]

I'm trying to use scipy.io to produce the above data structures in Python, such that they can be loaded into Matlab (this hierarchy is required by SPM).

Creating a struct is straightforward, as scipy.io.savemat saves any dict whose keys are all of type str as a Matlab struct:

from scipy.io import savemat

struct = {
    'field1': 1,
    'field2': 2,
}

savemat('/tmp/p.mat', {'a_struct': struct})

However, when trying to generalize this to a struct array, I hit the following roadblock:

struct_array = [struct, struct]
savemat('/tmp/p.mat', {'s_array': struct_array})

This does not behave as expected; when loading p.mat into Matlab, I get a 1x2 cell array, not a struct array.

How can I create a struct array using scipy.io?

Notes:

  1. I have tried savemat('/tmp/p.mat', np.array(struct_array)) and savemat('/tmp/p.mat', np.array(struct_array, dtype=object)), to no avail.
1
  • found this post from a search about struct array to deal with the exact same problem in SPM. Thanks for posting! Commented May 24, 2022 at 16:32

1 Answer 1

14

You can use np.core.records.fromarrays to construct a record array, which is roughly equivalent to a MATLAB struct, and will be converted to a MATLAB struct by scip.io.savemat.

from numpy.core.records import fromarrays
from scipy.io import savemat

myrec = fromarrays([[1, 10], [2, 20]], names=['field1', 'field2'])
savemat('p.mat', {'myrec': myrec})

When opened in MATLAB, this gives:

>> load('p.mat')
>> myrec

myrec = 

1x2 struct array with fields:

    field1
    field2
Sign up to request clarification or add additional context in comments.

5 Comments

I can create an array struct using this code, but I am not sure how to create an array of structs. I tried creating the structures first and then the array, but I have a dictionary with fields that change in size, so fromarrays does not work.
@IvanFelipeRodríguez did you try creating an object array where each element is a record array? You can create each element using the above method and then assign them to the object array.
hey @TheBlackCat. thank you for taking a look on this. I just tried initializing first every element as a record but when I run fromarrays... it raises this error " Empty data-type"
I posted my question here
This works for me except in a case like this: myrec = fromarrays([[1, 10], [[2,3], [20, 22]]], names=['field1', 'field2']) . I want to use this to store an array of structs where some fields of the structs are matlab arrays. I get ValueError: array-shape mismatch. How do I store an array as a struct field?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.