
SciPy (pronuncia-se sai pie) é um pacote de aplicativos matemáticos baseado na extensão Numpy Python. Com o SciPy, uma sessão interativa em Python se transforma no mesmo ambiente completo de processamento e prototipagem de dados para sistemas complexos como MATLAB, IDL, Octave, R-Lab e SciLab. Neste post, gostaria de falar sobre as possibilidades do pacote de E / S do scipy.io, que permite trabalhar com arquivos de dados Octave e MATLAB.
1. Introdução
Primeiro, importe o pacote scipy.io da seguinte maneira:
import scipy.io as sio
Os principais procedimentos do pacote scipy.io que permitem trabalhar com arquivos MATLAB:
sio.loadmat sio.savemat sio.whosmat
Para não violar o contrato de licença do MATLAB, trabalharemos no ambiente GNU Octave, que possui funções de salvar e carregar compatíveis com o MATLAB. No prompt Octave, digite:
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
Código para importar o arquivo MATLAB em 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)
Como você pode ver, o arquivo foi lido corretamente. Agora considere exportar do SciPy para o MATLAB:
import numpy as np vect = np.arange (10) vect.shape
(10,)
sio.savemat ('np_vector.mat', {'vect': vect})
Importe o arquivo Python para o 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
Para verificar o conteúdo do arquivo MATLAB sem ler os dados na memória, use o comando whosmat:
sio.whosmat ('octave_a.mat')
[('a', (1, 3, 4), 'double')]
A função whosmat retorna uma lista de tuplas, uma para cada matriz (ou outro objeto) contida no arquivo MATLAB. Cada tupla contém um nome, conteúdo do arquivo e tipo de dados.
Estruturas MATLAB
As estruturas do MATLAB são semelhantes aos dicionários de dicionários do Python. A diferença é que o nome do campo deve ser uma sequência. O valor do campo pode ser qualquer objeto.
Lembre-se de que MATLAB é um acrônimo para MATrix LABoratory. Porque o principal objetivo do MATLAB é trabalhar com matrizes, portanto todos os objetos nele são matrizes. Até um único número é representado como uma matriz de tamanho (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
Faça o download da estrutura do MATLAB em 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')])
Nas versões SciPy de 0.12.0, as estruturas MATLAB são retornadas como matrizes estruturadas numpy. Os nomes dos campos da matriz numpy são os nomes dos campos na estrutura MATLAB. Os nomes dos campos podem ser lidos usando o comando dtype, como no exemplo acima. Saiba mais sobre os tipos de dados de matrizes estruturadas .
Assim, no MATLAB, uma matriz de estruturas tem um tamanho de pelo menos 2D, que é repetido ao ler no SciPy. Para reduzir a dimensão para 1, use o parâmetro squeeze_me:
mat_contents = sio.loadmat ('octave_struct.mat', squeeze_me = True) oct_struct = mat_contents ['my_struct'] oct_struct.shape
()
Às vezes, é mais conveniente carregar estruturas MATLAB como objetos python, em vez de matrizes numpy. Para fazer isso, use o parâmetro struct_as_record = False para carregar.
mat_contents = sio.loadmat ('octave_struct.mat', struct_as_record = False) oct_struct = mat_contents ['my_struct'] oct_struct[0,0].field1
array([[1.]])
O parâmetro struct_as_record = False funciona muito bem em conjunto com o parâmetro squeeze_me:
mat_contents = sio.loadmat('octave_struct.mat', struct_as_record=False, squeeze_me=True) oct_struct = mat_contents['my_struct'] oct_struct.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
A maneira mais fácil de exportar estruturas de python para MATLAB é com dicionários dict:
a_dict = {'field1': 0.5, 'field2': 'a string'} sio.savemat ('saved_struct.mat', {'a_dict': a_dict})
No MATLAB, ele carrega como:
octave:21> load saved_struct octave:22> a_dict a_dict = scalar structure containing the fields: field1 = 0.50000 field2 = a string
Você também pode exportar estruturas de python para MATLAB usando matrizes numpy:
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})
Matrizes de células (célula) MATLAB
Matrizes de células no MATLAB são como listas de python. Os elementos nas matrizes de células podem conter qualquer tipo de objeto MATLAB. Além disso, as células são muito semelhantes às matrizes de objetos numpy. Considere um exemplo de exportação de uma célula do MATLAB para 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
De volta ao 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
Exportaremos de numpy para o array de células MATLAB usando um array numpy de objetos:
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})
Verifique se a exportação da célula de numpy para o Octave está correta:
octave:16> load np_cells.mat octave:17> obj_arr obj_arr = { [1,1] = 1 [2,1] = a string }
Este é talvez o fim. Espero que este artigo sirva de pretexto para integrar a pesquisa no MATLAB com o software livre.
Fonte: documentação scipy