Search code examples
pythonmatlabmlabwrap

How do I use mlabwrap to call a matlab function with cell arguments from python?


Well, I was proud of myself that I got mlabwrap installed properly, but now I cannot get it to work with matlab cells. In python, lists are analogous to cells, so I figured I would input a list and mlabwrap would convert it to a cell. Unfortunately, it does not seem to work that way.

For example, I have a matlab m-file:

function list_test(x)
display(x);

In python, if I type

mlab.list_test([[1,2],[3,4]])

I get:

x =

1     2
3     4

Thus, mlabwrap seems to take my two nested lists and turn them into a 2x2 matrix, which is not what I want.

When I try

mlab.list_test([[1,2],[3,4,5]]) 

then I get:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/Ben/.virtualenvs/test/lib/python2.7/site-packages/mlabwrap.py", line 607, in mlab_command
    return self._do(name, *args, **update({'nout':nout}, kwargs))
  File "/Users/Ben/.virtualenvs/test/lib/python2.7/site-packages/mlabwrap.py", line 534, in _do
    mlabraw.put(self._session,  argnames[-1], arg)
TypeError: a float is required

Clearly no dice.

If I have to, I imagine I could write some python code to convert lists into several 1-D arrays, feed the 1-D arrays into matlab using mlabwrap and write some matlab code to convert those 1-D arrays into cells. But this is messy, and I would like to know if there is an easier way. Can mlabwrap do this for me somehow?

Here are the details of my setup. OS: Mountain Lion (OS X 10.8), Python: 2.7, Matlab: 2010b, mlabwrap: 1.1


Solution

  • Unfortunately, mlabwrap has limited support for cell arrays; both when passing cell arrays into matlab, and when receiving cell arrays from matlab.

    Here's the answer for your immediate question:

    >>> from mlabwrap import mlab as matlab
    
    >>> a = [[1, 2], [3, 4]]
    >>> cell = matlab.mat2cell(array(a), [1, 1], [2])
    >>> matlab.display(cell)
    
    PROXY_VAL2__ = 
    
        [1x2 double]
        [1x2 double]
    

    Note that this really only works with regularly-sized lists. I.e. [[1,2],[3,4]] works, but [[1,2],[3,4,5]] does not. This is because mlabwrap doesn't handle dtype=object arrays particularly well, instead requiring dtype=float arrays.

    Let's swich over to matlab for a quick comparison:

    >> display(cell)
    
    cell = 
    
        [1x2 double]    [1x2 double]
    

    Looks good! However, when we switch back to python, and try and actually access the cell array that we've created:

    >>> cell[0][0]
    
    error: Unable to get matrix from MATLAB(TM) workspace
    
    >>> cell[0, 0]
    
    error: Unsupported index type: <type 'tuple'>
    
    >>> type(cell)
    mlabwrap.MlabObjectProxy
    

    Unfortunately, mlabwrap doesn't really allow access to the data stored in MlabObjectProxy objects. There are a few ways to try and get around this. You could write cell_insert and cell_pop functions in matlab. These should enable you to put python variables into an existing cell array, and get python-readable variables out from the cell array. Alternatively, you could write the cell array to a .mat file from matlab, and read it into python using scipy.io.loadmat()

    Honestly, unless you absolutely need cell arrays for some reason, I would try and avoid using them through mlabwrap.