Saltar al contenido

“Conversión” de matrices Numpy a Matlab y viceversa

Solución:

Claro, solo usa scipy.io.savemat

Como ejemplo:

import numpy as np
import scipy.io

x = np.linspace(0, 2 * np.pi, 100)
y = np.cos(x)

scipy.io.savemat('test.mat', dict(x=x, y=y))

Del mismo modo, hay scipy.io.loadmat.

Luego carga esto en matlab con load test.

Alternativamente, como sugirió @JAB, podría simplemente guardar cosas en un archivo delimitado por tabulaciones ascii (p. Ej. numpy.savetxt). Sin embargo, estará limitado a 2 dimensiones si sigue esta ruta. Por otro lado, ascii es el formato de intercambio universal. Prácticamente cualquier cosa manejará un archivo de texto delimitado.

Una solución simple, sin pasar datos por archivo o librerías externas.

Numpy tiene un método para transformar ndarrays en listas y los tipos de datos de matlab se pueden definir a partir de listas. Entonces, ¿cuándo se puede transformar como:

np_a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
mat_a = matlab.double(np_a.tolist())

De matlab a python requiere más atención. No hay una función incorporada para convertir el tipo directamente en listas. Pero podemos acceder a los datos sin procesar, que no tienen forma, sino que son simples. Entonces, usamos reshape (formatear correctamente) y transpose (debido a la forma diferente en que MATLAB y numpy almacenan datos). Es muy importante enfatizar eso: Pruébelo en su proyecto, principalmente si está utilizando matrices con más de 2 dimensiones. Funciona para MATLAB 2015a y 2 dim.

np_a = np.array(mat_a._data.tolist())
np_a = np_a.reshape(mat_a.size).transpose()

Aquí hay una solución que evita iterar en python, o usar el archivo IO, a expensas de depender de los componentes internos (feos) de matlab:

import matlab
# This is actually `matlab._internal`, but matlab/__init__.py
# mangles the path making it appear as `_internal`.
# Importing it under a different name would be a bad idea.
from _internal.mlarray_utils import _get_strides, _get_mlsize

def _wrapper__init__(self, arr):
    assert arr.dtype == type(self)._numpy_type
    self._python_type = type(arr.dtype.type().item())
    self._is_complex = np.issubdtype(arr.dtype, np.complexfloating)
    self._size = _get_mlsize(arr.shape)
    self._strides = _get_strides(self._size)[:-1]
    self._start = 0

    if self._is_complex:
        self._real = arr.real.ravel(order="F")
        self._imag = arr.imag.ravel(order="F")
    else:
        self._data = arr.ravel(order="F")

_wrappers = {}
def _define_wrapper(matlab_type, numpy_type):
    t = type(matlab_type.__name__, (matlab_type,), dict(
        __init__=_wrapper__init__,
        _numpy_type=numpy_type
    ))
    # this tricks matlab into accepting our new type
    t.__module__ = matlab_type.__module__
    _wrappers[numpy_type] = t

_define_wrapper(matlab.double, np.double)
_define_wrapper(matlab.single, np.single)
_define_wrapper(matlab.uint8, np.uint8)
_define_wrapper(matlab.int8, np.int8)
_define_wrapper(matlab.uint16, np.uint16)
_define_wrapper(matlab.int16, np.int16)
_define_wrapper(matlab.uint32, np.uint32)
_define_wrapper(matlab.int32, np.int32)
_define_wrapper(matlab.uint64, np.uint64)
_define_wrapper(matlab.int64, np.int64)
_define_wrapper(matlab.logical, np.bool_)

def as_matlab(arr):
    try:
        cls = _wrappers[arr.dtype.type]
    except KeyError:
        raise TypeError("Unsupported data type")
    return cls(arr)

Las observaciones necesarias para llegar hasta aquí fueron:

  • Matlab parece solo mirar type(x).__name__ y type(x).__module__ para determinar si entiende el tipo
  • Parece que cualquier objeto indexable se puede colocar en el ._data atributo

Desafortunadamente, matlab no está usando el _data atributo de manera eficiente internamente, y está iterando sobre él un elemento a la vez en lugar de usar el Python memoryview protocolo :(. Entonces, la ganancia de velocidad es marginal con este enfoque.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *