From 2f49e130ec36ff8e9af94c92f8b3dfcaa14733e8 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Sat, 14 Feb 2015 21:31:58 -0600 Subject: [PATCH 1/9] Use raw doubles to avoid truncating in Octave --- pymatbridge/matlab/util/json_v0.2.2/json/json_dump.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pymatbridge/matlab/util/json_v0.2.2/json/json_dump.m b/pymatbridge/matlab/util/json_v0.2.2/json/json_dump.m index ed8ef62..8f83aac 100644 --- a/pymatbridge/matlab/util/json_v0.2.2/json/json_dump.m +++ b/pymatbridge/matlab/util/json_v0.2.2/json/json_dump.m @@ -143,7 +143,7 @@ end elseif isnumeric(value) if isreal(value) - obj = javaObject('java.lang.Double', value); + obj = value; % Encode complex number as a struct else complex_struct = struct; From c618a33ce2034f48c2a9b26c35185e6aefe25bf0 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Sat, 14 Feb 2015 21:32:27 -0600 Subject: [PATCH 2/9] Indicate success in pymat_get_variable --- pymatbridge/matlab/util/pymat_get_variable.m | 1 + 1 file changed, 1 insertion(+) diff --git a/pymatbridge/matlab/util/pymat_get_variable.m b/pymatbridge/matlab/util/pymat_get_variable.m index 9de9cf1..1b22952 100644 --- a/pymatbridge/matlab/util/pymat_get_variable.m +++ b/pymatbridge/matlab/util/pymat_get_variable.m @@ -34,6 +34,7 @@ else response.exists = true; response.var = evalin('base', varname); + response.success = 'true'; end json_response = json_dump(response); From 1d14fe985d84e3bc26e5b89329dc6d13cb2f9d5b Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Sat, 14 Feb 2015 21:42:31 -0600 Subject: [PATCH 3/9] Update travis script to run test suite Update travis script to run test suite Update travis script to actually do testing Install zmq Install pyzmq Remove doctesting Remove unsupported --no-gui option in Octave Attempt to spoof javaclasspath Attempt to spoof javaclasspath Use newer Octave Try an explicit java install --- .travis.yml | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9d099c3..a3475f2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,4 @@ language: python -sudo: false deploy: provider: pypi user: arokem @@ -10,5 +9,37 @@ deploy: repo: arokem/python-matlab-bridge # until this is fixed: https://github.com/travis-ci/travis-ci/issues/1675 all_branches: true +env: + - CONDA="python=2.7 numpy=1.7" + - CONDA="python=3.3 numpy" + - CONDA="python=3.4 numpy" +before_install: + - sudo apt-add-repository -y ppa:octave/stable; + - sudo apt-get update -qq; + - sudo apt-get install -qq octave liboctave-dev default-jdk; + - wget http://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh -O miniconda.sh; + - bash miniconda.sh -b -p $HOME/miniconda + - export PATH="$HOME/miniconda/bin:$PATH" + - hash -r + - conda config --set always_yes yes + - conda update conda + - conda info -a + - travis_retry conda create -n test $CONDA IPython pip nose pyzmq + - source activate test + - travis_retry pip install coveralls + +install: + - export PYTHONWARNINGS=all + - export USE_OCTAVE=True + - python setup.py install + script: - - true + # run coverage on py2.7, regular on others + - if [[ $CONDA == python=2.7* ]]; then + nosetests --exe -v --with-cov --cover-package pymatbridge; + else + nosetests --exe -v pymatbridge; + fi + +after_success: + - coveralls From 7ff7474d13e0b46aba8c1189dac480279f51e18c Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Sat, 14 Feb 2015 22:31:35 -0600 Subject: [PATCH 4/9] Add support for Octave magic --- pymatbridge/matlab_magic.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pymatbridge/matlab_magic.py b/pymatbridge/matlab_magic.py index d1e4251..170aaa9 100644 --- a/pymatbridge/matlab_magic.py +++ b/pymatbridge/matlab_magic.py @@ -95,7 +95,10 @@ def __init__(self, shell, super(MatlabMagics, self).__init__(shell) self.cache_display_data = cache_display_data - self.Matlab = pymat.Matlab(matlab, maxtime=maxtime) + if 'octave' in matlab: + self.Matlab = pymat.Octave(matlab, maxtime=maxtime) + else: + self.Matlab = pymat.Matlab(matlab, maxtime=maxtime) self.Matlab.start() self.pyconverter = pyconverter From 7c45e122b0404a87d0ad6b1e658e1d1da9c787ae Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Sat, 14 Feb 2015 22:31:51 -0600 Subject: [PATCH 5/9] Use gnuplot so figures are created properly Use gnuplot so figures are created properly Add support for octave magic in test --- pymatbridge/pymatbridge.py | 1 + pymatbridge/tests/test_magic.py | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/pymatbridge/pymatbridge.py b/pymatbridge/pymatbridge.py index 543bc26..a53b885 100644 --- a/pymatbridge/pymatbridge.py +++ b/pymatbridge/pymatbridge.py @@ -428,6 +428,7 @@ def _preamble_code(self): if self.log: code.append("diary('./pymatbridge/logs/octavelog_%s.txt')" % self.id) code.append("set(0, 'defaultfigurevisible', 'off');") + code.append("graphics_toolkit('gnuplot')") return code def _execute_flag(self): diff --git a/pymatbridge/tests/test_magic.py b/pymatbridge/tests/test_magic.py index 57e3677..2a50a9e 100644 --- a/pymatbridge/tests/test_magic.py +++ b/pymatbridge/tests/test_magic.py @@ -1,3 +1,5 @@ +import os + import pymatbridge as pymat import IPython @@ -11,7 +13,11 @@ def setup_class(cls): cls.ip = IPython.InteractiveShell() cls.ip.run_cell('import random') cls.ip.run_cell('import numpy as np') - pymat.load_ipython_extension(cls.ip) + if 'USE_OCTAVE' in os.environ: + matlab = 'octave' + else: + matlab = 'matlab' + pymat.load_ipython_extension(cls.ip, matlab=matlab) # Unload the magic, shut down Matlab @classmethod From 6a6599bcba8f33d662dbecd0b567129591d6dc0e Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Sun, 15 Feb 2015 05:40:10 -0600 Subject: [PATCH 6/9] Add octave mex file and Makefile --- messenger/octave/Makefile | 7 +++++++ messenger/octave/messenger.mex | Bin 0 -> 21121 bytes 2 files changed, 7 insertions(+) create mode 100644 messenger/octave/Makefile create mode 100755 messenger/octave/messenger.mex diff --git a/messenger/octave/Makefile b/messenger/octave/Makefile new file mode 100644 index 0000000..d7ade23 --- /dev/null +++ b/messenger/octave/Makefile @@ -0,0 +1,7 @@ + + +all: + sudo apt-get install libzmq3-dev liboctave-dev + cd ../src; mkoctfile --mex -lzmq messenger.c + mv ../src/messenger.mex . + cp messenger.mex ../pymatbridge/matlab diff --git a/messenger/octave/messenger.mex b/messenger/octave/messenger.mex new file mode 100755 index 0000000000000000000000000000000000000000..8a22d09d351d79c24f08d66e0d4b8c0a04a7e2c2 GIT binary patch literal 21121 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 VH)-jN6X}Ug4?Z{ literal 0 HcmV?d00001 From bbfb2355c332dcf3096b4678f228b78a727a746f Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Sun, 15 Feb 2015 05:40:47 -0600 Subject: [PATCH 7/9] Add the octave messenger to setup.py --- setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 43dd4b7..acd6769 100755 --- a/setup.py +++ b/setup.py @@ -30,7 +30,8 @@ def copy_bin(bin_path): for copy_this in ["./messenger/mexmaci64/messenger.mexmaci64", "./messenger/mexa64/messenger.mexa64", - "./messenger/mexw64/messenger.mexw64"]: + "./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 From 2fabe1c906e74442a1465a170dfd649d448f895e Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Sun, 15 Feb 2015 05:45:15 -0600 Subject: [PATCH 8/9] Cleanup Avoid short-circuit operator for Octave compatibility Install scipy Add base64 handling Clean up and use get_ipython Clean up, do no require scipy, and do not close matlab twice Do not require scipy Prevent file resource warnings Avoid deprecationwarning --- pymatbridge/matlab/util/isrow.m | 4 +-- pymatbridge/matlab_magic.py | 56 +++++++++++---------------------- pymatbridge/pymatbridge.py | 10 +++--- pymatbridge/tests/test_magic.py | 8 ++--- 4 files changed, 29 insertions(+), 49 deletions(-) diff --git a/pymatbridge/matlab/util/isrow.m b/pymatbridge/matlab/util/isrow.m index 767adef..12848f7 100644 --- a/pymatbridge/matlab/util/isrow.m +++ b/pymatbridge/matlab/util/isrow.m @@ -7,8 +7,8 @@ % % -if ndims(X)==2 & size(X,1)==1 & size(X,2)>=1 +if ndims(X)==2 && size(X,1)==1 && size(X,2)>=1 Y = logical(1); else Y = logical(0); -end \ No newline at end of file +end diff --git a/pymatbridge/matlab_magic.py b/pymatbridge/matlab_magic.py index 170aaa9..ca8c326 100644 --- a/pymatbridge/matlab_magic.py +++ b/pymatbridge/matlab_magic.py @@ -7,36 +7,23 @@ """ -import sys, os -import tempfile -from glob import glob from shutil import rmtree -from getopt import getopt import numpy as np -try: - import scipy.io as sio - has_io = True -except ImportError: - has_io = False - no_io_str = "Must have scipy.io to perform i/o" - no_io_str += "operations with the Matlab session" - import IPython -ipython_version = int(IPython.__version__[0]) - from IPython.core.displaypub import publish_display_data -from IPython.core.magic import (Magics, magics_class, cell_magic, line_magic, +from IPython.core.magic import (Magics, magics_class, line_cell_magic, needs_local_scope) -from IPython.testing.skipdoctest import skip_doctest from IPython.core.magic_arguments import (argument, magic_arguments, parse_argstring) -from IPython.utils.py3compat import str_to_unicode, unicode_to_str, PY3 +from IPython.utils.py3compat import unicode_to_str, PY3 import pymatbridge as pymat from .compat import text_type +ipython_version = int(IPython.__version__[0]) + class MatlabInterperterError(RuntimeError): """ @@ -95,7 +82,7 @@ def __init__(self, shell, super(MatlabMagics, self).__init__(shell) self.cache_display_data = cache_display_data - if 'octave' in matlab: + if 'octave' in matlab.lower(): self.Matlab = pymat.Octave(matlab, maxtime=maxtime) else: self.Matlab = pymat.Matlab(matlab, maxtime=maxtime) @@ -176,19 +163,15 @@ def matlab(self, line, cell=None, local_ns=None): self.Matlab.set_default_plot_size(width, height) if args.input: - if has_io: - for input in ','.join(args.input).split(','): - try: - val = local_ns[input] - except KeyError: - val = self.shell.user_ns[input] - # The _Session.set_variable function which this calls - # should correctly detect numpy arrays and serialize them - # as json correctly. - self.set_matlab_var(input, val) - - else: - raise RuntimeError(no_io_str) + for input in ','.join(args.input).split(','): + try: + val = local_ns[input] + except KeyError: + val = self.shell.user_ns[input] + # The _Session.set_variable function which this calls + # should correctly detect numpy arrays and serialize them + # as json correctly. + self.set_matlab_var(input, val) try: result_dict = self.eval(code) @@ -219,7 +202,8 @@ def matlab(self, line, cell=None, local_ns=None): if len(imgf): # Store the path to the directory so that you can delete it # later on: - image = open(imgf, 'rb').read() + with open(imgf, 'rb') as fid: + image = fid.read() if ipython_version < 3: display_data.append(('MatlabMagic.matlab', {'image/png':image})) @@ -237,11 +221,8 @@ def matlab(self, line, cell=None, local_ns=None): rmtree(data_dir) if args.output: - if has_io: - for output in ','.join(args.output).split(','): - self.shell.push({output:self.Matlab.get_variable(output)}) - else: - raise RuntimeError(no_io_str) + for output in ','.join(args.output).split(','): + self.shell.push({output:self.Matlab.get_variable(output)}) _loaded = False @@ -256,6 +237,5 @@ def unload_ipython_extension(ip): global _loaded if _loaded: magic = ip.magics_manager.registry.pop('MatlabMagics') - magic.Matlab.stop() _loaded = False diff --git a/pymatbridge/pymatbridge.py b/pymatbridge/pymatbridge.py index a53b885..2e12f47 100644 --- a/pymatbridge/pymatbridge.py +++ b/pymatbridge/pymatbridge.py @@ -23,7 +23,7 @@ import os import time -import codecs +import base64 import zmq import subprocess import sys @@ -60,7 +60,7 @@ def encode_ndarray(obj): except AttributeError: data = obj.astype(float64).tostring() - data = codecs.encode(data, 'base64').decode('utf-8') + data = base64.b64encode(data).decode('utf-8') return data, shape @@ -89,19 +89,19 @@ def default(self, obj): def decode_arr(data): """Extract a numpy array from a base64 buffer""" data = data.encode('utf-8') - return frombuffer(codecs.decode(data, 'base64'), float64) + return frombuffer(base64.b64decode(data), float64) # JSON decoder for arrays and complex numbers def decode_pymat(dct): if 'ndarray' in dct and 'data' in dct: value = decode_arr(dct['data']) - shape = decode_arr(dct['shape']) + shape = decode_arr(dct['shape']).astype(int) return value.reshape(shape, order='F') elif 'ndarray' in dct and 'imag' in dct: real = decode_arr(dct['real']) imag = decode_arr(dct['imag']) - shape = decode_arr(dct['shape']) + shape = decode_arr(dct['shape']).astype(int) data = real + 1j * imag return data.reshape(shape, order='F') elif 'real' in dct and 'imag' in dct: diff --git a/pymatbridge/tests/test_magic.py b/pymatbridge/tests/test_magic.py index 2a50a9e..3b5d7f8 100644 --- a/pymatbridge/tests/test_magic.py +++ b/pymatbridge/tests/test_magic.py @@ -1,16 +1,17 @@ import os import pymatbridge as pymat -import IPython +from IPython.testing.globalipapp import get_ipython import numpy.testing as npt + class TestMagic: # Create an IPython shell and load Matlab magic @classmethod def setup_class(cls): - cls.ip = IPython.InteractiveShell() + cls.ip = get_ipython() cls.ip.run_cell('import random') cls.ip.run_cell('import numpy as np') if 'USE_OCTAVE' in os.environ: @@ -19,12 +20,11 @@ def setup_class(cls): matlab = 'matlab' pymat.load_ipython_extension(cls.ip, matlab=matlab) - # Unload the magic, shut down Matlab + # Unload the magic @classmethod def teardown_class(cls): pymat.unload_ipython_extension(cls.ip) - # Test single operation on different data structures def test_cell_magic_number(self): # A double precision real number From ef4ec9565a972a950ec9ee32e223ec15c465d9df Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Sun, 15 Feb 2015 07:27:09 -0600 Subject: [PATCH 9/9] More cleanup Update installation instructions Move to a platform-indepented octave makefile Do not test on Py3.4 due to bug in importlib causing hangup Try python 3.4 again without warnings Fix travis syntax error Add debug output in travis Do not install scipy in travis Remove py3.4 build to to hanging Remove redundant conda info --- .travis.yml | 2 -- README.md | 29 +++++++++++++++-------------- messenger/octave/Makefile | 7 ------- messenger/octave/make.py | 7 +++++++ 4 files changed, 22 insertions(+), 23 deletions(-) delete mode 100644 messenger/octave/Makefile create mode 100644 messenger/octave/make.py diff --git a/.travis.yml b/.travis.yml index a3475f2..2b5a690 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,6 @@ deploy: env: - CONDA="python=2.7 numpy=1.7" - CONDA="python=3.3 numpy" - - CONDA="python=3.4 numpy" before_install: - sudo apt-add-repository -y ppa:octave/stable; - sudo apt-get update -qq; @@ -29,7 +28,6 @@ before_install: - travis_retry pip install coveralls install: - - export PYTHONWARNINGS=all - export USE_OCTAVE=True - python setup.py install diff --git a/README.md b/README.md index 3aa3c6f..0e9a283 100644 --- a/README.md +++ b/README.md @@ -115,17 +115,7 @@ Rather than looking for `matlab` at the shell, this will look for `octave`. As with `pymatbridge.Matlab`, you can override this by specifying the `executable` keyword argument. -There are a few caveats to note about Octave support: - -* The zmq messenger used to communicate with the Octave session is written in C -and needs to be compiled. For MATLAB various prebuilt binaries are provided -and added to MATLAB's runtime path, but as of this writing the same isn't -true for Octave. You'll need to compile the messenger (in -`messenger/src/messenger.c`) using an incantation like -`mkoctfile --mex -lzmq messenger.c` and place the resulting `messenger.mex` -file somewhere in Octave's runtime path. - -Finally, rather than `~/startup.m`, Octave looks for an `~/.octaverc` file for +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). @@ -154,11 +144,11 @@ More examples are provided in the `examples` directory 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 +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. 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`. 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. @@ -215,12 +205,23 @@ 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 -latest release. Unzip it somewhere on your machine and then issue: +latest release. Unzip it somewhere on your machine. + +For Matlab: cd messenger python make.py cd .. python setup.py install + + +For Octave: + + cd messenger/octave + # edit make.py if not using Ubuntu-derivative + python make.py + cd .. + python setup.py This should make the python-matlab-bridge import-able. diff --git a/messenger/octave/Makefile b/messenger/octave/Makefile deleted file mode 100644 index d7ade23..0000000 --- a/messenger/octave/Makefile +++ /dev/null @@ -1,7 +0,0 @@ - - -all: - sudo apt-get install libzmq3-dev liboctave-dev - cd ../src; mkoctfile --mex -lzmq messenger.c - mv ../src/messenger.mex . - cp messenger.mex ../pymatbridge/matlab diff --git a/messenger/octave/make.py b/messenger/octave/make.py new file mode 100644 index 0000000..3ee5160 --- /dev/null +++ b/messenger/octave/make.py @@ -0,0 +1,7 @@ + +import os + +os.system('sudo apt-get install libzmq3-dev liboctave-dev') +os.system('cd ../src; mkoctfile --mex -lzmq messenger.c') +os.system('mv ../src/messenger.mex .') +os.system('cp messenger.mex ../pymatbridge/matlab')