It is more or less an equivalent to pymat but the other way around. At the moment it’s for sure more low-level than an equivalent to mlabwrap would be but it could be used as a foundation for such equivalent (as pymat was used as foundation for mlabwrap).
Its core functionality is enclosed in three calls: py(‘eval’, stmt), py(‘set’, var_name, var) and var=py(‘get’, var_name). As you have probably guessed the first one evaluates whatever Python statement you throw at it. The second one sets a variable in Python environment to value taken from MATLAB (var_name specifies name of the variable and var – the value). And finally – the third one gets a variable from Python enviroment and returns its value converted to MATLAB type (again, var_name specifies name of the variable, var is the resulting MATLAB value).
matpy supports conversions of cell, numeric, logical and character MATLAB arrays. This leaves out only functions, structures and classes/objects – these cannot be transferred between Python and MATLAB environments. matpy converts arrays to numpy.ndarray with exception of character arrays – these are converted to Python strings. All numeric types are supported and the most suitable numpy.dtype is used instead of treating everything as double as is the case in many other MATLAB<->Python bridges. Also, unlike in some other interfaces – all dimensionalities are supported (2-D, 3-D, 4-D, … N-D). It maps 1:1 with numpy.ndarray functionality so it was no big deal.
Along with main MEX module there are three higher level helper functions provided – py_export(var1, …varN), py_import(var1, …varN) and py_shell(). The first two are used for mass-exporting/importing variables by name from/to MATLAB workspace. The last one starts a simple interactive Python shell (multi-line statements not supported, type ‘exit’ to go back to MATLAB).
Their usage is illustrated in this simple example using matplotlib:
>> [X,Y]=meshgrid(-10:0.1:10,-10:0.1:10); >> Z=sin(X)+cos(Y); >> py_export('X','Y','Z') >> py_shell py> import matplotlib py> matplotlib.use('Qt4Agg') py> import matplotlib.pyplot as plt py> from mpl_toolkits.mplot3d import axes3d py> f=plt.figure() py> ax=f.gca(projection='3d') py> cset=ax.plot_surface(X,Y,Z) py> ax.clabel(cset,fontsize=9,inline=1) py> plt.show() py> exit >>
The same code executed in non-interactive manner would have to look like this:
[X,Y]=meshgrid(-10:0.1:10,-10:0.1:10); Z=sin(X)+cos(Y); py_export('X','Y','Z') stmt = sprintf(['import matplotlibn' ... 'matplotlib.use(''Qt4Agg'')n' ... 'import matplotlib.pyplot as pltn' ... 'from mpl_toolkits.mplot3d import axes3dn' ... 'f=plt.figure()n' ... 'ax=f.gca(projection=''3d'')n' ... 'cset=ax.plot_surface(X,Y,Z)n' ... 'ax.clabel(cset,fontsize=9,inline=1)n' ... 'plt.show()']); py('eval', stmt);
So… basically that’s it. In order to run matpy you have to compile the provided py.cpp file using MEX and link against Python library. On Linux the following was sufficient:
mex py.cpp -lpython2.6
However there were some issues with dynamically loaded extensions. For this reason I had to add dlopen(‘libpython2.6.so’, RTLD_GLOBAL|RTLD_LAZY) before Py_Initialize() and exported LD_PRELOAD=”libstdc++.6.so” before running MATLAB. From what I’ve heard (will check myself tomorrow) this shouldn’t be a problem on Windows. MSVC compiler version might be though. Optimally MSVC version used to compile Python+extensions should be the same one used by your version of MATLAB to build MEX files but I’m not sure if this is really necessary.
Anyway 😉 … here goes the BSD-licensed source code:
Enjoy and let me know if you find it useful!
UPDATE 2012/05/29: I gave it a try on Windows and as expected there was no issues. Just type:
mex py.cpp -IC:/Python27/include C:/Python27/libs/python27.lib
and you are ready to go. I tested it with pythonxy distribution containing ETS (Enthought Tool Suite) with its highly renowned mayavi VTK-based 3D visualization library. It works great as can be seen in the screenshot below.