Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 33 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ development of the two repositories has significantly diverged.

This implementation also includes an [IPython](http://ipython.org) `matlab_magic`
extension, which provides a simple interface for weaving python and
Matlab code together (requires ipython > 0.13).
Matlab code together (requires ipython > 0.13).


## Installation
Expand All @@ -37,7 +37,7 @@ If you intend to use the Matlab magic extension, you'll also need
[Scipy](http://scipy.org/) and [Numpy](http://www.numpy.org/). These can be
installed from PyPI, or using distributions such as
[Anaconda](https://store.continuum.io/cshop/anaconda/) or [Enthought
Canopy](https://store.enthought.com/downloads/)
Canopy](https://store.enthought.com/downloads/)

Note thatIPython notebooks also depend on `pyzmq` so if you have IPython notebooks
installed, you likely have `pyzmq` already.
Expand All @@ -54,10 +54,10 @@ This creates a matlab session class instance, into which you will be able to
inject code and variables, and query for results. By default, when you use
`start`, this will open whatever gets called when you type `matlab`
in your Terminal, but you can also specify the location of your Matlab
application when initializing your matlab session class:
application when initializing your matlab session class:

mlab = Matlab(executable='/Applications/MATLAB_R2011a.app/bin/matlab')

You can then start the Matlab server, which will kick off your matlab session,
and create the connection between your Python interpreter and this session:

Expand All @@ -80,7 +80,7 @@ In this case, the variable `a` is available on the Python side, by using
the `get_variable` method:

mlab.get_variable('a')

You can run any MATLAB functions contained within a .m file of the
same name. For example, to call the function jk in jk.m:

Expand Down Expand Up @@ -121,7 +121,11 @@ Rather than `~/startup.m`, Octave looks for an `~/.octaverc` file for
commands to execute before every session. (This is a good place to manipulate
the runtime path, for example).

### Matlab magic:
Requires Version 3.8 or higher. Notice: Neither the MXE 3.8.1 nor the Cygwin 3.8.2 version is compatible on Windows. No Windows support will be available
until a working version of Octave 3.8+ with Java support is released.


### Matlab magic:

The Matlab magic allows you to use pymatbridge in the context of the IPython
notebook format.
Expand All @@ -132,7 +136,7 @@ These lines will automatically start the matlab session for you. Then, you can
simply decorate a line/cell with the '%matlab' or '%%matlab' decorator and
write matlab code:

%%matlab
%%matlab
a = linspace(0.01,6*pi,100);
plot(sin(a))
grid on
Expand All @@ -143,14 +147,21 @@ More examples are provided in the `examples` directory

## Building the pymatbridge messenger from source

The installation of `pymatbridge` includes a binary of a mex function to communicate between
Python and Matlab using the [0MQ](http://zeromq.org/) messaging library. This should work
The installation of `pymatbridge` includes a binary of a mex function to communicate between
Python and Matlab using the [0MQ](http://zeromq.org/) messaging library. This should work
without any need for compilation on most computers. However, in some cases, you might want
to build the pymatbridge messenger from source. To do so, you will need to follow the instructions below:

### Install zmq library
Please refer to the [official guide](http://zeromq.org/intro:get-the-software) on how to
build and install zmq. On Ubuntu, it is as simple as `sudo apt-get install libzmq3-dev`. After zmq is installed, make sure you can find the location where
build and install zmq. On Ubuntu, it is as simple as `sudo apt-get install libzmq3-dev`.
On Windows, suggest using the following method:
- Install [MSYS2](http://sourceforge.net/projects/msys2/)
- Run `$ pacman -S make`
- From the zmq source directory, run: `$ sh configure --prefix=$(pwd) --build=x86_64-w64-mingw32`
- Run `$ make`.

After zmq is installed, make sure you can find the location where
libzmq is installed. The library extension name and default location on different systems
are listed below.

Expand Down Expand Up @@ -198,36 +209,37 @@ On MacOS, you can do this from the root of the pymatbridge code with:
On Linux, you can add it to the RPATH:

patchelf --set-rpath <Path to your zmq lib directory> messenger/mexa64/messenger.mexa64

### Install pyzmq
After step 1 is finished, please grab the latest version of
[pyzmq](http://zeromq.org/bindings:python) and follow the instructions on the official
page. Note that pymatbridge is developed with pyzmq 14.0.0 and older versions might not
be supported. If you have an old version of pyzmq, please update it.
After step 1 is finished, please grab the latest version of
[pyzmq](http://zeromq.org/bindings:python) and follow the instructions on the official
page. Note that pymatbridge is developed with pyzmq 14.0.0 and older versions might not
be supported. If you have an old version of pyzmq, please update it.

### Install pymatbridge
After the steps above are done, you can install pymatbridge. Download the zip file of the
After the steps above are done, you can install pymatbridge. Download the zip file of the
latest release. Unzip it somewhere on your machine.

For Matlab:

cd messenger
python make.py
# edit local.cfg in the directory for your platform
python make.py
cd ..
python setup.py install


For Octave:

cd messenger/octave
# edit make.py if not using Ubuntu-derivative
python make.py
# edit local_octave.cfg in the directory for your platform
python make_octave.py
cd ..
python setup.py

This should make the python-matlab-bridge import-able.


### Warnings

Python communicates with Matlab via an ad-hoc zmq messenger. This is inherently
Expand Down
Empty file added messenger/__init__.py
Empty file.
26 changes: 26 additions & 0 deletions messenger/get_messenger_dir.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import sys
import platform


def get_messenger_dir():
# Check the system platform first
splatform = sys.platform

if splatform.startswith('linux'):
messenger_dir = 'mexa64'
elif splatform.startswith('darwin'):
messenger_dir = 'mexmaci64'
elif splatform.startswith('win32'):
if splatform == "win32":
# We have a win64 messenger, so we need to figure out if this is 32 or 64
# bit Windows:
if not platform.machine().endswith('64'):
raise ValueError("pymatbridge does not work on win32")

# We further need to differniate 32 from 64 bit:
maxint = sys.maxsize
if maxint == 9223372036854775807:
messenger_dir = 'mexw64'
elif maxint == 2147483647:
messenger_dir = 'mexw32'
return messenger_dir
19 changes: 2 additions & 17 deletions messenger/make.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,11 @@
#!/usr/bin/python
from __future__ import print_function
import os
import sys
import fnmatch
from get_messenger_dir import get_messenger_dir
import subprocess
import shutil

# Check the system platform first
platform = sys.platform
print("This is a " + platform + " system")

if platform.startswith('linux'):
messenger_dir = 'mexa64'
elif platform.startswith('darwin'):
messenger_dir = 'mexmaci64'
elif platform.startswith('win32'):
# We further need to differniate 32 from 64 bit:
maxint = sys.maxint()
if maxint == 9223372036854775807:
messenger_dir = 'mexw64'
elif maxint == 2147483647:
messenger_dir = 'mexw32'
messenger_dir = get_messenger_dir()

# Open the configure file and start parsing
with open(os.path.join(messenger_dir, 'local.cfg'), 'r') as config:
Expand Down
29 changes: 29 additions & 0 deletions messenger/make_octave.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/python
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the look of this file. I think make.py could be made to look like this after some cleanup, and then more duplication could be extracted out. But that doesn't have to be done now.

from __future__ import print_function
import os
from get_messenger_dir import get_messenger_dir
import shutil
import subprocess

messenger_dir = get_messenger_dir()

with open(os.path.join(messenger_dir, 'local_octave.cfg')) as fid:
lines = fid.readlines()

cfg = {}
for line in lines:
name, path = line.split('=')
cfg[name.lower()] = path.strip() or '.'

print("Building messenger.mex...")

paths = "-L%(octave_lib)s -I%(octave_inc)s -L%(zmq_lib)s -I%(zmq_inc)s" % cfg
make_cmd = "mkoctfile --mex %s -lzmq ./src/messenger.c" % paths
print(make_cmd)
subprocess.check_output(make_cmd.split())

messenger_exe = 'messenger.mex'
messenger_loc = os.path.join(messenger_dir, messenger_exe)

shutil.move(messenger_exe, messenger_loc)
os.remove('messenger.o')
4 changes: 4 additions & 0 deletions messenger/mexa64/local_octave.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
OCTAVE_INC=/usr/include
OCTAVE_LIB=/usr/lib/x86_64-linux-gnu/
ZMQ_INC=
ZMQ_LIB=
Binary file added messenger/mexa64/messenger.mex
Binary file not shown.
4 changes: 4 additions & 0 deletions messenger/mexmaci64/local_octave.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
OCTAVE_INC=/usr/include
OCTAVE_LIB=/usr/lib/x86_64-linux-gnu/
ZMQ_INC=
ZMQ_LIB=
4 changes: 4 additions & 0 deletions messenger/mexw64/local_octave.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
OCTAVE_INC="C:\Octave\Octave-3.8.2\include\octave-3.8.2\octave"
OCTAVE_LIB="C:\Octave\Octave-3.8.2\lib\octave\3.8.2"
ZMQ_INC="C:\zeromq-4.0.5\include"
ZMQ_LIB="C:\zeromq-4.0.5\src\.libs"
7 changes: 0 additions & 7 deletions messenger/octave/make.py

This file was deleted.

Binary file removed messenger/octave/messenger.mex
Binary file not shown.
4 changes: 2 additions & 2 deletions messenger/src/messenger.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ int initialize(char *socket_addr) {
* Now the receiver buffer is pre-allocated
* In the future we can possibly use multi-part messaging
*/
int listen(char *buffer, int buflen) {
int listen_zmq(char *buffer, int buflen) {
if (!initialized) {
mexErrMsgTxt("Error: ZMQ session not initialized");
}
Expand Down Expand Up @@ -106,7 +106,7 @@ void mexFunction(int nlhs, mxArray *plhs[],
} else if (strcmp(cmd, "listen") == 0) {
char *recv_buffer = mxCalloc(BUFLEN, sizeof(char));

int byte_recvd = listen(recv_buffer, BUFLEN);
int byte_recvd = listen_zmq(recv_buffer, BUFLEN);

/* Check if the received data is complete and correct */
if ((byte_recvd > -1) && (byte_recvd <= BUFLEN)) {
Expand Down
28 changes: 9 additions & 19 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,39 +1,29 @@
#!/usr/bin/env python
"""Setup file for python-matlab-bridge"""

import platform
import os
import sys
import shutil
import glob


# BEFORE importing distutils, remove MANIFEST. distutils doesn't properly
# update it when the contents of directories change.
if os.path.exists('MANIFEST'):
os.remove('MANIFEST')


from distutils.core import setup

# Find the messenger binary file and copy it to /matlab folder.

def copy_bin(bin_path):
if os.path.exists(bin_path):
shutil.copy(bin_path, "./pymatbridge/matlab")
return True
else:
return False
# Find the messenger binary file(s) and copy it to /matlab folder.
from messenger.get_messenger_dir import get_messenger_dir
messenger_dir = get_messenger_dir()

for f in glob.glob("./messenger/%s/messenger.*" % messenger_dir):
shutil.copy(f, "./pymatbridge/matlab")

if sys.platform == "win32":
# We have a win64 messenger, so we need to figure out if this is 32 or 64
# bit Windows:
if not platform.machine().endswith('64'):
raise ValueError("pymatbridge does not work on win32")

for copy_this in ["./messenger/mexmaci64/messenger.mexmaci64",
"./messenger/mexa64/messenger.mexa64",
"./messenger/mexw64/messenger.mexw64",
"./messenger/octave/messenger.mex"]:
copy_bin(copy_this)

# Get version and release info, which is all stored in pymatbridge/version.py
ver_file = os.path.join('pymatbridge', 'version.py')
exec(open(ver_file).read())
Expand Down