SciPy, input and output in MATLAB
- Tutorial

SciPy (pronounced sai pay) is a math application package based on the Numpy Python extension. With SciPy, an interactive Python session turns into the same comprehensive data processing and prototyping environment for complex systems like MATLAB, IDL, Octave, R-Lab and SciLab. In this post, I would like to talk about the capabilities of the scipy.io I / O package, which allows you to work with the Octave and MATLAB data files.
Introduction
First we import the scipy.io package as follows:
import scipy.io as sio
The main procedures of the scipy.io package, which allow working with MATLAB files:
sio.loadmat
sio.savemat
sio.whosmat
In order not to violate the MATLAB license agreement, we will work in the GNU Octave environment, which has MATLAB compatible save and load functions. Let's enter the Octave command line:
octave:1> a = 1:12
a =
1 2 3 4 5 6 7 8 9 10 11 12
octave:2> a = reshape(a, [1 3 4])
a =
ans(:,:,1) =
1 2 3
ans(:,:,2) =
4 5 6
ans(:,:,3) =
7 8 9
ans(:,:,4) =
10 11 12
octave:3> save -6 octave_a.mat a % MATLAB 6 compatible
octave:4> ls octave_a.mat
octave_a.mat
The code to import the MATLAB file into Python:
mat_contents = sio.loadmat('octave_a.mat')
mat_contents
{'__header__': b'MATLAB 5.0 MAT-file, written by Octave 4.2.2, 2019-02-02 20:26:43 UTC',
'__version__': '1.0',
'__globals__': [],
'a': array([[[ 1., 4., 7., 10.],
[ 2., 5., 8., 11.],
[ 3., 6., 9., 12.]]])}
oct_a = mat_contents['a']
oct_a
array([[[ 1., 4., 7., 10.],
[ 2., 5., 8., 11.],
[ 3., 6., 9., 12.]]])
oct_a.shape
(1, 3, 4)
As you can see, the file is read correctly. Now consider exporting from SciPy to MATLAB:
import numpy as np
vect = np.arange (10)
vect.shape
(10,)
sio.savemat ('np_vector.mat', {'vect': vect})
Import the Python file into Octave:
octave:8> load np_vector.mat
octave:9> vect
vect =
0 1 2 3 4 5 6 7 8 9
octave:10> size(vect)
ans =
1 10
To check the contents of the MATLAB file without reading the data in memory, use the whosmat command:
sio.whosmat ('octave_a.mat')
[('a', (1, 3, 4), 'double')]
The whosmat function returns a list of tuples, one for each array (or other object) contained in the MATLAB file. Each tuple contains the name, file contents, and data type.
MATLAB Structures
MATLAB structures are similar to Python dicts dictionaries. The difference is that the field name must be a string. The field value can be any object.
Recall that MATLAB is an acronym of MATrix Laboratory. Since The main purpose of MATLAB is working with matrices, so all the objects in it are matrices. Even one number is represented as a matrix of size (1, 1).
octave:11> my_struct = struct('field1', 1, 'field2', 2)
my_struct =
{
field1 = 1
field2 = 2
}
octave:12> save -6 octave_struct.mat my_struct
Download the MATLAB structure in Python:
mat_contents = sio.loadmat('octave_struct.mat')
mat_contents
{'__header__': b'MATLAB 5.0 MAT-file, written by Octave 4.2.2, 2019-02-02 20:34:26 UTC',
'__version__': '1.0',
'__globals__': [],
'my_struct': array([[(array([[1.]]), array([[2.]]))]],
dtype=[('field1', 'O'), ('field2', 'O')])}
oct_struct = mat_contents['my_struct']
oct_struct.shape
(1, 1)
val = oct_struct[0,0]
val
(array([[1.]]), array([[2.]]))
val['field1']
array([[1.]])
val['field2']
array([[2.]])
val.dtype
dtype([('field1', 'O'), ('field2', 'O')])
In SciPy versions from 0.12.0, the MATLAB structure is returned as numpy structured arrays. The names of the fields in the numpy array are the names of the fields in the MATLAB structure. Field names can be read using the dtype command, as in the example above. Learn more about the structed arrays data types .
Thus, in MATLAB, an array of structures has a size of at least 2D, which is repeated when reading in SciPy. To reduce the dimension to 1, use the squeeze_me parameter:
mat_contents = sio.loadmat ('octave_struct.mat', squeeze_me = True)
oct_struct = mat_contents ['my_struct']
oct_struct.shape
()
Sometimes it is more convenient to load MATLAB structures as python objects, rather than numpy arrays. To do this, use the parameter struct_as_record = False to load.
mat_contents = sio.loadmat ('octave_struct.mat', struct_as_record = False)
oct_struct = mat_contents ['my_struct']
oct_struct[0,0].field1
array([[1.]])
The struct_as_record = False parameter works fine with the squeeze_me parameter:
mat_contents = sio.loadmat('octave_struct.mat', struct_as_record=False, squeeze_me=True)
oct_struct = mat_contents['my_struct']
oct_struct.shape # выдаст ошибку, т.к. у скаляра нет аттрибута shape
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-23-d41d0a59bb9b> in <module>
1 mat_contents = sio.loadmat('octave_struct.mat', struct_as_record=False, squeeze_me=True)
2 oct_struct = mat_contents['my_struct']
----> 3 oct_struct.shape # выдаст ошибку, т.к. это скаляр
AttributeError: 'mat_struct' object has no attribute 'shape'
type(oct_struct)
scipy.io.matlab.mio5_params.mat_struct
oct_struct.field1
1.0
The easiest way to export structures from python to MATLAB is with the dicts dictionaries:
a_dict = {'field1': 0.5, 'field2': 'a string'}
sio.savemat ('saved_struct.mat', {'a_dict': a_dict})
The MATLAB is loaded as:
octave:21> load saved_struct
octave:22> a_dict
a_dict =
scalar structure containing the fields:
field1 = 0.50000
field2 = a string
You can also export structures from python to MATLAB using numpy arrays:
dt = [('f1', 'f8'), ('f2', 'S10')]
arr = np.zeros ((2,), dtype = dt)
arr
array([(0., b''), (0., b'')], dtype=[('f1', '<f8'), ('f2', 'S10')])
arr [0] ['f1'] = 0.5
arr [0] ['f2'] = 'python'
arr [1] ['f1'] = 99
arr [1] ['f2'] = 'not perl'
sio.savemat ('np_struct_arr.mat', {'arr': arr})
Arrays of cells (cell) MATLAB
Arrays of cells (cell) in MATLAB are similar to python lists. Elements in cell arrays can contain any type of MATLAB object. Also, the cell is very similar to arrays of numpy objects. Consider an example of exporting a cell from MATLAB to numpy.
octave:14> my_cells = {1, [2, 3]}
my_cells =
{
[1,1] = 1
[1,2] =
2 3
}
octave:15> save -6 octave_cells.mat my_cells
Let's go back to Python:
mat_contents = sio.loadmat ('octave_cells.mat')
oct_cells = mat_contents ['my_cells']
print (oct_cells.dtype)
object
val = oct_cells [0,0]
val
array([[1.]])
print (val.dtype)
float64
Exporting from numpy to the cell array MATLAB is done using the numpy-array of objects:
obj_arr = np.zeros ((2,), dtype = np.object)
obj_arr [0] = 1
obj_arr [1] = 'a string'
obj_arr
array([1, 'a string'], dtype=object)
sio.savemat ('np_cells.mat', {'obj_arr': obj_arr})
Check the export of a cell from numpy to Octave:
octave:16> load np_cells.mat
octave:17> obj_arr
obj_arr =
{
[1,1] = 1
[2,1] = a string
}
On this, perhaps, finish. I hope for someone this article will serve as a reason for the integration of research in MATLAB with free software.
Source: scipy documentation