Package: mlab
Mlab is a high-level python to Matlab bridge that lets Matlab look like a normal python library.This python library is based on the work of original mlabwrap projecthttp://mlabwrap.sourceforge.net/and Dani Valevski (from Dana Pe'er's lab):http://code.google.com/p/danapeerlab/source/browse/trunk/freecell/depends/common/python/matlabpipe.pyPrimerQuick installation:pip install mlabStart working with the library by picking a MATLAB release that you have locally installed:from mlab.releases import latest_releasefrom matlab import matlabrootprint matlabroot()where latest_release is a MlabWrap instance, matlabroot is wrapper around MATLAB function.Please note that matlab module is dynamically created instance, which is in this case referencinglatest_release object.MATLAB installation discovery mechanism is implemented by mlab.releases module in such a way, thatyou have to specify the release version you want to use first, by importing it. Only then you canimport from matlab module:from mlab.releases import R2010bfrom matlab import matlabrootAlso see mlab.releases.get_available_releases().ContentsPrimerDescriptionRelatedNewsLicenseDownloadInstallationLinuxWindowsDocumentationTutorialComparison to other existing modulesWhat's Missing?Implementation NotesTroubleshootingStrange hangs under Matlab R2008amatlab not in path"Can't open engine""`GLIBCXX_3.4.9' not found" on importing mlab (or similar)Old Matlab versionOS XNotes on runningWindowsFunction Handles and callbacks into pythonDirectly manipulating variables in Matlab spaceSupport and FeedbackCreditsDescriptionMlabwrap is a high-level python to Matlab bridge that lets Matlab looklike a normal python library.Thanks for your terrific work on this very-useful Python tool!George A. Blaha, Senior Systems Engineer,Raytheon Integrated Defense Systemsmlab is a repackaging effort to make things up-to-date.RelatedThereis is a copy of mlabwrap v1.1-pre (http://mlabwrap.sourceforge.net/) patchedas described here:http://sourceforge.net/mailarchive/message.php?msg_id=27312822with a patch fixing the error:mlabraw.cpp:225: *error*: invalid conversion from const mwSize* to const int*Also note that in Ubuntu you need to sudo apt-get install cshFor details seehttp://github.com/aweinstein/mlabwrapNews2014-08-26 1.1.3 Applying patch to add support for Windows via COM.Credits to Sergey Matyunin, Amro@stackoverflow2013-07-26 1.1.1 Repacking a library as mlab project. Including codefor Windows (matlabraw.cpp is off for now).2009-10-26 1.1 fixes an incorrect declaration in mlabraw.cppthat caused compilation problems for some users and incorporates asetup.py fix for windows suggested by Alan Brooks. More significantlythere is a new spiffy logo!2009-09-14 1.1-pre finally brings N-D array support, thanks to VivekRathod who joined the project! Also fixed a missing import for saveVarsInMat(thanks to Nicolas Pinto).Since a few people have run into problems that appear to relate to compilingMatlab C-extensions in general and aren't mlabwrap-specific, I should probablystress that in case of any problems that look C-related, verifying whetherengdemo.c works is a great litmus test (see Troubleshooting ).2009-03-23 1.0.1 is finally out. This is a minor release that fixes someannoying but mostly minor bugs in mlabwrap (it also slightly improves theindexing support for proxy-objects, but the exact semantics are still subjectto change.)installation is now easier, in particularly LD_LIBRARY_PATH no longerneeds to be set and some quoting issues with the matlab call duringinstallation have been addressed.sparse Matlab matrices are now handled correctly(mlab.sparse([0,0,0,0]) will now return a proxy for a sparse doublematrix, rather than incorrectly treat at as plain double array and returnjunk or crash).replaced the (optional) use of the outdated netcdf package for theunit-tests with homegrown matlab helper class.several bugs squashed (length of mlabraw.eval'ed strings is checked, bettererror-messages etc.) and some small documentation improvements and quite afew code clean-ups.Many thanks to Iain Murray at Toronto and Nicolas Pinto at MIT for lettingthemselves be roped into helping me test my stupidly broken releasecandidates.Licensemlab (and mlabwrap) is under MIT license, see LICENSE.txt. mlabraw is under a BSD-stylelicense, see the mlabraw.cpp.Download<http://github.com/ewiger/mlab>Installationmlab should work with python>=2.7 (downto python 2.2, with minor coaxing) andeither numpy (recommended) or Numeric (obsolete) installed and Matlab 6, 6.5,7.x and 8.x under Linux, OS X and Windows (see OS X) on 32- or 64-bitmachines.LinuxIf you're lucky (linux, Matlab binary in PATH):python setup.py install(As usual, if you want to install just in your homedir add --prefix=$HOME;and make sure your PYTHONPATH is set accordingly.)If things do go awry, see Troubleshooting.WindowsAssuming you have python 2.7.5 (e.g. C:Python27) and setuptools("easy_install.exe") installed and on your PATH.1) Download and install numpy package. You can use packages provided byChristoph Gohlke: http://www.lfd.uci.edu/~gohlke/pythonlibs/ Also see officialSciPy website for latest status, it might that:easy_install.exe numpywould do the trick.You would also need The PyWin32 module by Mark Hammond:<string>:175: (WARNING/2) Literal block expected; none found.<string>:5: (INFO/1) Enumerated list start value not ordinal-1: "2" (ordinal 2)easy_install.exe pywin32also see Windows in Troubleshooting.Documentationfor lazy people>>> from mlab.releases import latest_release as matlab>>> matlab.plot([1,2,3],'-o')ugly-plota slightly prettier example>>> from mlab.releases import latest_release as matlab>>> from numpy import *>>> xx = arange(-2*pi, 2*pi, 0.2)>>> mlab.surf(subtract.outer(sin(xx),cos(xx)))surface-plotfor a complete description:Just run pydoc mlab.for people who like tutorials:see belowTutorial[This is adapted from an email I wrote someone who asked me about mlabwrap.Compatibility Note: Since matlab is becoming increasingly lessdouble-centric, the default conversion rules might change in post 1.0mlabwrap; so whilst using mlab.plot([1,2,3]) rather thanmlab.plot(array([1.,2.,3.])) is fine for interactive use as in thetutorial below, the latter is recommended for production code.]Legend: [...] = omitted outputLet's say you want to do use Matlab to calculate the singular valuedecomposition of a matrix.  So first you import the mlab pseudo-module andNumeric:>>> from mlab import mlab>>> import numpyNow you want to find out what the right function is, so you simply do:>>> mlab.lookfor('singular value')GSVD   Generalized Singular Value Decompostion.SVD    Singular value decomposition.[...]Then you look up what svd actually does, just as you'd look up thedocstring of a python function:>>> help(mlab.svd)mlab_command(*args, **kwargs)SVD    Singular value decomposition.[U,S,V] = SVD(X) produces a diagonal matrix S, of the samedimension as X and with nonnegative diagonal elements in[...]Then you try it out:>>> mlab.svd(array([[1,2], [1,3]]))array([[ 3.86432845],[ 0.25877718]])Notice that we only got 'U' back -- that's because python hasn't got somethinglike Matlab's multiple value return. Since Matlab functions can havecompletely different behavior depending on how many output parameters arerequested, you have to specify explicitly if you want more than 1. So to get'U' and also 'S' and 'V' you'd do:>>> U, S, V = mlab.svd([[1,2],[1,3]], nout=3)The only other possible catch is that Matlab (to a good approximation)basically represents everything as a double matrix. So there are noscalars, or 'flat' vectors. They correspond to 1x1 and 1xN matricesrespectively. So, when you pass a flat vector or a scalar to amlab-function, it is autoconverted. Also, integer values are automaticallyconverted to double floats. Here is an example:>>> mlab.abs(-1)array([       [ 1.]])Strings also work as expected:>>> mlab.upper('abcde')'ABCDE'However, although matrices and strings should cover most needs and can bedirectly converted, Matlab functions can also return structs or indeedclasses and other types that cannot be converted into pythonequivalents. However, rather than just giving up, mlabwrap just hidesthis fact from the user by using proxies:E.g. to create a netlab neural net with 2 input, 3 hidden and 1 output node:>>> net = mlab.mlp(2,3,1,'logistic')Looking at net reveals that is a proxy:>>> net<MLabObjectProxy of matlab-class: 'struct'; internal name: 'PROXY_VAL0__';has parent: no>type: 'mlp'nin: 3nhidden: 3nout: 3nwts: 24outfn: 'linear'w1: [3x3 double]b1: [0.0873 -0.0934 0.3629]w2: [3x3 double]b2: [-0.6681 0.3572 0.8118]When net or other proxy objects a passed to mlab functions, they areautomatically converted into the corresponding Matlab-objects. So to obtaina trained network on the 'xor'-problem, one can simply do:>>> net = mlab.mlptrain(net, [[1,1], [0,0], [1,0], [0,1]], [0,0,1,1], 1000)And test with:>>> mlab.mlpfwd(net2, [[1,0]])array([       [ 1.]])>>> mlab.mlpfwd(net2, [[1,1]])array([       [  7.53175454e-09]])As previously mentioned, normally you shouldn't notice at all when you areworking with proxy objects; they can even be pickled (!), although that isstill somewhat experimental.mlabwrap also offers proper error handling and exceptions! So trying topass only one input to a net with 2 input nodes raises an Exception:>>> mlab.mlpfwd(net2, 1)Traceback (most recent call last):[...]mlabraw.error: Error using ==> mlpfwdDimension of inputs 1 does not match number of model inputs 2Warning messages (and messages to stdout) are also displayed:>>> mlab.log(0)Warning: Log of zero.array([       [             -inf]])Comparison to other existing modulesTo get a vague impression just how high-level all this, consider attempting todo something similar to the first example with pymat (upon which theunderlying mlabraw interface to Matlab is based).this:>>> A, B, C = mlab.svd([[1,2],[1,3]], 0, nout=3)becomes this:>>> session = pymat.open()>>> pymat.put(session, "X", [[1,2], [1,3]])>>> pymat.put(session, "cheap", 0)>>> pymat.eval(session, '[A, B, C] = svd(X, cheap)')>>> A = pymat.get(session, 'A')>>> B = pymat.get(session, 'B')>>> C = pymat.get(session, 'C')Plus, there is virtually no error-reporting at all, if something goes wrong inthe eval step, you'll only notice because the subsequent get mysteriouslyfails. And of course something more fancy like the netlab example above (whichuses proxies to represent matlab class instances in python) would beimpossible to accomplish in pymat in a similar manner.However should you need low-level access, then that is equally available(and with error reporting); basically just replace pymat withmlabraw above and use mlab._session as session), i.e>>> from mlab import mlab>>> import mlabraw>>> mlabraw.put(mlab._session, "X", [[1,2], [1,3]])[...]Before you resort to this you should ask yourself if it's really a good idea;the inherent overhead associated with Matlab's C interface appears to be quitehigh, so the additional python overhead shouldn't normally matter much -- ifefficiency becomes an issue it's probably better to try to chunk togetherseveral matlab commands in an .m-file in order to reduce the number ofmatlab calls. If you're looking for a way to execute "raw" matlab for specificpurposes, mlab._do is probably a better idea. The low-level mlabrawAPI is much more likely to change in completely backwards incompatible ways infuture versions of mlabwrap. You've been warned.What's Missing?Handling of as arrays of (array) rank 3 or more as well asnon-double/complex arrays (currently everything is converted todouble/complex for passing to Matlab and passing non-double/complex fromMatlab is not not supported). Both should be reasonably easy to implement,but not that many people have asked for it and I haven't got around to ityet.Better support for cells.Thread-safety. If you think there's a need please let me know (on theStackOverflow tagged query); at the moment you can /probably/ get away withusing one seperate MlabWrap object per thread without implementing your ownlocking, but even that hasn't been tested.Implementation NotesSo how does it all work?I've got a C extension module (a heavily bug-fixed and somewhat modifiedversion of pymat, an open-source, low-level python-matlab interface) to takecare of opening Matlab sessions, sending Matlab commands as strings to arunning Matlab session and and converting Numeric arrays (and sequences andstrings...) to Matlab matrices and vice versa. On top of this I then built apure python module that with various bells and whistles gives the impressionof providing a Matlab "module".This is done by a class that manages a single Matlab session (of which mlabis an instance) and creates methods with docstrings on-the-fly. Thus, on thefirst call of mlab.abs(1), the wrapper looks whether there already is amatching function in the cache. If not, the docstring for abs is looked upin Matlab and Matlab's flimsy introspection abilities are used to determinethe number of output arguments (0 or more), then a function with the rightdocstring is dynamically created and assigned to mlab.abs. This functiontakes care of the conversion of all input parameters and the return values,using proxies where necessary. Proxy are a bit more involved and the proxypickling scheme uses Matlab's save command to create a binary version ofthe proxy's contents which is then pickled, together with the proxy object bypython itself. Hope that gives a vague idea, for more info study the source.TroubleshootingStrange hangs under Matlab R2008aIt looks like this particular version of matlab might be broken (I was able toreproduced the problem with just a stripped down engdemo.c under 64-bitlinux). R2008b is reported to be working correctly (as are several earlierversions).matlab not in pathsetup.py will call matlab in an attempt to query the version and otherinformation relevant for installation, so it has to be in your PATHunless you specify everything by hand in setup.py. Of course to be ableto use mlabwrap in any way matlab will have to be in your path anyway(unless that is you set the environment variable MLABRAW_CMD_STR thatspecifies how exactly Matlab should be called)."Can't open engine"If you see something like mlabraw.error: Unable to start MATLAB(TM) enginethen you may be using an incompatible C++ compiler (or version), or if you'reusing unix you might not have csh installed under /bin/csh, see below.Try if you can get the engdemo.c file to work that comes with your Matlabinstallation -- engdemo provides detailed instructions, but in a nutshell:copy it to a directory where you have write access and do(assuming Matlab is installed in /opt/MatlabR14 and you're running unix,otherwise modify as requird):mex -f /opt/MatlabR14/bin/engopts.sh engdemo.c./engdemoif you get Can't start MATLAB engine chances are you're trying to use acompiler version that's not in Mathworks's list of compatible compilers orsomething else with your compiler/Matlab installation is broken that needs tobe resolved before you can successfully build mlabwrap. Chances are that youor you institution pays a lot of money to the Mathworks, so they should behappy to give you some tech support. Here's what some user who recently(2007-02-04) got Matlab 7.04's mex support to work under Ubuntu Edgy after anexchange with support reported back; apart from installing gcc-3.2.3, he didthe following:The code I'd run (from within Matlab) is...> mex -setup;     # then select: 2 - gcc Mex options> optsfile = [matlabroot '/bin/engopts.sh'];> mex -v -f optsfile 'engdemo.c';> !./engdemo;Update John Bender reports that under unix csh needs to be installed in/bin/csh for the matlab external engine to work -- since many linuxdistros don't install csh by default, you might have to do something likesudo apt-get install csh (e.g. under ubuntu or other debian-basedsystems). He also pointed out this helpful engdemo troubleshooting page atthe Mathworks(tm) site."`GLIBCXX_3.4.9' not found" on importing mlab (or similar)As above, first try to see if you can get engdemo.c to work, becauseas long as even the examples that come with Matlab don't compile,chances of mlabwrap compiling are rather slim. On the plus-sideif the problem isn't mlabwrap specific, The Mathworks and/orMatlab-specific support forums should be able to help.Old Matlab versionIf you get something like this on python setup.py install:mlabraw.cpp:634: `engGetVariable' undeclared (first use this function)Then you're presumably using an old version of Matlab (i.e. < 6.5);setup.py ought to have detected this though (try adjustingMATLAB_VERSION by hand and write me a bug report).OS XJosh Marshall tried it under OS X and sent me the following notes (thanks!).Notes on runningBefore running python, run:export  DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH$:/Applications/MATLAB701/bin/mac/export MLABRAW_CMD_STR=/Applications/MATLAB701/bin/matlab[Edit: I'm not sure DYLD_LIBRARY_PATH modification is still necessary.]As far as graphics commands go, the python interpreter will need to  be runfrom within the X11 xterm to be able to display anything to the  screen.ie, the command for lazy people>>> from mlabwrap import mlab; mlab.plot([1,2,3],'-o')won't work unless python is run from an xterm, and the matlab startupstring ischanged to:export MLABRAW_CMD_STR="/Applications/MATLAB701/bin/matlab -nodesktop"Windows<string>:529: (INFO/1) Duplicate implicit target name: "windows".I'm thankfully not using windows myself, but I try to keep mlabwrap workingunder windows, for which I depend on the feedback from windows users.Since there are several popular C++ compilers under windows, you might have totell setup.py which one you'd like to use (unless it's VC 7).George A. Blaha sent me a patch for Borland C++ support; search for "BorlandC++" in setup.py and follow the instructions.Dylan T Walker writes mingw32 will also work fine, but for some reason(distuils glitch?) the following invocation is required:> setup.py build --compiler=mingw32> setup.py install --skip-buildFunction Handles and callbacks into pythonPeople sometimes try to pass a python function to a matlab function (e.g.mlab.fzero(lambda x: x**2-2, 0)) which will result in an error messagesbecause callbacks into python are not implemented (I'm not even it would evenbe feasible). Whilst there is no general workaround, in some cases you canjust create an equivalent matlab function on the fly, e.g. do something likethis: mlab.fzero(mlab.eval('@(x) x^2-2', 0)).Directly manipulating variables in Matlab spaceIn certain (rare!) certain cases it might be necessary to directly access orset a global variable in matlab. In these cases you can use mlab._get('SOME_VAR')and mlab._set('SOME_VAR', somevalue).Support and FeedbackPost your questions directly on Stack overflow with tags matlab, mlaband pythonCreditsAlejandro Weinstein for patches of 1.1prehttps://github.com/aweinstein/mlabwrapAlexander Schmolck and Vivek Rathod for mlabwrap:http://mlabwrap.sourceforge.net/Andrew Sterian for writing pymat without which this module would never haveexisted.Matthew Brett contributed numpy compatibility and nice setup.py improvements(which I adapted a bit) to further reduce the need for manual userintervention for installation.I'm only using linux myself -- so I gratefully acknowledge the help of Windowsand OS X users to get things running smoothly under these OSes as well;particularly those who provided patches to setup.py or mlabraw.cpp (Joris vanZwieten, George A. Blaha and others).Matlab is a registered trademark of The Mathworks.