“Converting” Numpy arrays to Matlab and vice versa

后端 未结 6 1418
孤独总比滥情好
孤独总比滥情好 2020-11-30 00:27

I am looking for a way to pass NumPy arrays to Matlab.

I\'ve managed to do this by storing the array into an image using scipy.misc.imsave and then loa

6条回答
  •  忘掉有多难
    2020-11-30 00:59

    Here's a solution that avoids iterating in python, or using file IO - at the expense of relying on (ugly) matlab internals:

    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)
    

    The observations necessary to get here were:

    • Matlab seems to only look at type(x).__name__ and type(x).__module__ to determine if it understands the type
    • It seems that any indexable object can be placed in the ._data attribute

    Unfortunately, matlab is not using the _data attribute efficiently internally, and is iterating over it one item at a time rather than using the python memoryview protocol :(. So the speed gain is marginal with this approach.

提交回复
热议问题