如何使用mlabwrap从Python调用带有单元参数的MATLAB函数?
我之前很自豪自己成功安装了mlabwrap,但现在我发现它和matlab的单元格(cells)不太兼容。在Python中,列表可以看作是单元格的替代品,所以我想把一个列表输入进去,mlabwrap应该能把它转换成单元格。可惜,似乎并不是这样。
举个例子,我有一个matlab的m文件:
function list_test(x)
display(x);
在Python中,如果我输入
mlab.list_test([[1,2],[3,4]])
我得到的结果是:
x =
1 2
3 4
所以,mlabwrap似乎把我两个嵌套的列表变成了一个2x2的矩阵,这并不是我想要的结果。
当我尝试输入
mlab.list_test([[1,2],[3,4,5]])
然后我得到:
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
显然,这也不行。
如果真的没办法,我想我可以写一些Python代码,把列表转换成几个一维数组,然后通过mlabwrap把这些一维数组传给matlab,再写一些matlab代码把这些一维数组转换成单元格。但这样做太麻烦了,我想知道有没有更简单的方法。mlabwrap能不能帮我做到这一点呢?
这是我设置的详细信息:
操作系统:Mountain Lion (OS X 10.8),
Python版本:2.7,
Matlab版本:2010b,
mlabwrap版本:1.1
2 个回答
如果几年后有人看到这个,其实对单元数组和字符数组是有基本支持的,你只需要输入这个:
mlab._dont_proxy["cell"] = True
在使用返回单元数组或字符数组的matlab命令之前。这是在https://github.com/aweinstein/mlabwrap和https://github.com/cpbotha/mlabwrap-purepy上测试过的。
很遗憾,mlabwrap对单元数组的支持有限;无论是把单元数组传入matlab,还是从matlab接收单元数组,都有一些问题。
下面是你立即想知道的答案:
>>> 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]
请注意,这个方法只适用于大小一致的列表。也就是说,像[[1,2],[3,4]]这样的可以用,但像[[1,2],[3,4,5]]就不行。这是因为mlabwrap对dtype=object类型的数组处理得不好,它更需要dtype=float类型的数组。
接下来我们快速切换到matlab做个对比:
>> display(cell)
cell =
[1x2 double] [1x2 double]
看起来不错!不过,当我们切换回python,尝试访问我们创建的单元数组时:
>>> 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
很遗憾,mlabwrap并不允许直接访问存储在MlabObjectProxy对象中的数据。有几种方法可以尝试解决这个问题。你可以在matlab中写一些cell_insert
和cell_pop
函数。这些函数可以让你把python变量放入现有的单元数组中,并从单元数组中取出python可读的变量。或者,你也可以把单元数组写入一个.mat文件,然后用scipy.io.loadmat()
在python中读取它。
老实说,除非你真的需要单元数组,否则我建议尽量避免通过mlabwrap使用它们。