📜 ⬆️ ⬇️

SciPy, input and output in MATLAB


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 structures are 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. The cell is also 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



Source: https://habr.com/ru/post/438600/