Giter Site home page Giter Site logo

transplant's Introduction

TRANSPLANT

version python status license

contributors downloads

Transplant is an easy way of calling Matlab from Python.

import transplant
matlab = transplant.Matlab()
# call Matlab functions:
length = matlab.numel([1, 2, 3])
magic = matlab.magic(2)
spectrum = matlab.fft(numpy.random.randn(100))
# inject variables into Matlab:
matlab.signal = numpy.zeros(100)

Python lists are converted to cell arrays in Matlab, dicts are converted to Maps, and Numpy arrays are converted do native Matlab matrices.

All Matlab functions and objects can be accessed from Python.

Transplant is licensed under the terms of the BSD 3-clause license
(c) 2014 Bastian Bechtold

open-issues closed-issues open-prs closed-prs

RECENT CHANGES

  • Fixes for finding libzmq on Windows (Thank you, hardmstar)
  • Now correctly encodes bool ndarrays as logical arrays (thank you, Júlio)
  • Fixes working with Matlab packages (Thank you, dani-l)
  • Fixes recursion at Matlab shutdown (Thank you, dani-l)
  • Should now reliably raise an error if Matlab dies unexpectedly.
  • Keyword arguments are now automatically translated to string-value pairs in Matlab.
  • close was renamed exit. Even though Python typically uses close to close files and connections, this conflicts with Matlab's own close function.
  • Matlab will now start Matlab at the current working directory.
  • Transplant can now be installed through pip install transplant.
  • You can now use jvm=False and desktop=False to auto-supply common command line arguments for Matlab.

STARTING MATLAB

matlab = transplant.Matlab()

Will start a Matlab session and connect to it. This will take a few seconds while Matlab starts up. All of Matlab's output will go to the standard output and will appear interspersed with Python output. Standard input is suppressed to make REPLs work, so Matlab's input function will not work.

By default, this will try to call matlab on the command line. If you want to use a different version of Matlab, or matlab is not in PATH, use Matlab(executable='/path/to/matlab').

By default, Matlab is called with -nodesktop and -nosplash (and -minimize on Windows), so no IDE or splash screen show up. You can change this by setting desktop=True.

You can start Matlab without loading the Java-based GUI system ('-nojvm') by setting jvm=False. This will speed up startup considerably, but you won't be able to open figures any more.

If you want to start Matlab with additional command line arguments, you can supply them like this: Matlab(arguments=['-c licensefile']).

By default, Matlab will be started on the local machine. To start Matlab on a different computer, supply the IP address of that computer: Matlab(address='172.168.1.5'). This only works if that computer is reachable through ssh, Matlab is available on the other computer's command line, and transplant is in the other Matlab's path.

Note that due to a limitation of Matlab on Windows, command line output from Matlab running on Windows isn't visible to Transplant.

CALLING MATLAB

matlab.disp("Hello, World")

Will call Matlab's disp function with the argument 'Hello, World'. It is equivalent to disp('Hello, World') in Matlab. Return values will be returned to Python, and errors will be converted to Python errors (Matlab stack traces will be given, too!).

Input arguments are converted to Matlab data structures:

Python Argument Matlab Type
str char vector
float double scalar
int an int{8,16,32,64} scalar
True/False logical scalar
None []
list cell
dict containers.Map
transplant.MatlabStruct(dict) struct
numpy.ndarray double matrix
scipy.sparse sparse matrix
proxy object original object
proxy function original function

Return values are treated similarly:

Matlab Return Value Python Type
char vector str
numeric scalar number
logical scalar True/False
[] None
cell list
struct or containers.Map dict
numeric matrix numpy.ndarray
sparse matrix scipy.sparse
function proxy function
object proxy object

If the function returns a function handle or an object, a matching Python functions/objects will be created that forwards every access to Matlab. Objects can also be handed back to Matlab and will work as intended.

f = matlab.figure() # create a Figure object
f.Visible = 'off' # modify a property of the Figure object
matlab.set(f, 'Visible', 'on') # pass the Figure object to a Matlab function

In Matlab, some functions behave differently depending on the number of output arguments. By default, Transplant uses the Matlab function nargout to figure out the number of return values for a function. If nargout can not determine the number of output arguments either, Matlab functions will return the value of ans after the function call.

In some cases, nargout will report a wrong number of output arguments. For example nargout profile will say 1, but x = profile('on') will raise an error that too few output arguments were used. To fix this, every function has a keyword argument nargout, which can be used in these cases: matlab.profile('on', nargout=0) calls profile on with no output arguments. s, f, t, p = matlab.spectrogram(numpy.random.randn(1000), nargout=4) returns all four output arguments of spectrogram.

All other keyword arguments are transparently translated to key-value pairs in Matlab, i.e. matlab.struct(a=1, b=2) is another way of writing matlab.struct('a', 1, 'b', 2).

When working with plots, note that the Matlab program does not wait for drawing on its own. Use matlab.drawnow() to make figures appear.

Note that functions are not called in the base workspace. Functions that access the current non-lexical workspace (this is very rare) will therefore not work as expected. For example, matlab.truth = 42, matlab.exist('truth') will not find the truth variable. Use matlab.evalin('base', "exist('truth')", nargout=1) instead in this case.

If you hit Ctrl-C, the KeyboardInterrupt will be applied to both Python and Matlab, stopping any currently running function. Due to a limitation of Matlab, the error and stack trace of that function will be lost.

MATRIX DIMENSIONS

The way multidimensional arrays are indexed in Matlab and Python are fundamentally different. Thankfully, the two-dimensional case works as expected:

           Python         |        Matlab
--------------------------+------------------------
 array([[  1,   2,   3],  |     1   2   3
        [ 10,  20,  30]]) |    10  20  30

In both languages, this array has the shape (2, 3).

With higher-dimension arrays, this becomes harder. The next array is again identical:

           Python         |        Matlab
--------------------------+------------------------
 array([[[  1,   2],      | (:,:,1) =
         [  3,   4]],     |              1    3
                          |             10   30
        [[ 10,  20],      |            100  300
         [ 30,  40]],     | (:,:,2) =
                          |              2    4
        [[100, 200],      |             20   40
         [300, 400]]])    |            200  400

Even though they look different, they both have the same shape (3, 2, 2), and are indexed in the same way. The element at position a, b, c in Python is the same as the element at position a+1, b+1, c+1 in Matlab (+1 due to zero-based/one-based indexing).

You can think about the difference in presentation like this: Python displays multidimensional arrays as [n,:,:], whereas Matlab displays them as (:,:,n).

STOPPING MATLAB

Matlab processes end when the Matlab instance goes out of scope or is explicitly closed using the exit method. Alternatively, the Matlab class can be used as a context manager, which will properly clean up after itself.

If you are not using the context manager or the exit method, you will notice that some Matlab processes don't die when you expect them to die. If you are running the regular python interpreter, chances are that the Matlab process is still referenced to in sys.last_traceback, which holds the value of the last exception that was raised. Your Matlab process will die once the next exception is raised.

If you are running ipython, though, all bets are off. I have noticed that ipython keeps all kinds of references to all kinds of things. Sometimes, %reset will clear them, sometimes it won't. Sometimes they only go away when ipython quits. And sometimes, even stopping ipython doesn't kill it (how is this even possible?). This can be quite annoying. Use the exit method or the context manager to make sure the processes are stopped correctly.

INSTALLATION

  1. Install the zeromq library on your computer and add it to your PATH. Alternatively, Transplant automatically uses conda's zeromq if you use conda.
  2. Install Transplant using pip install transplant. This will install pyzmq, numpy and msgpack as dependencies.

If you want to run Transplant over the network, the remote Matlab has to have access to ZMQ.m and transplant_remote.m and the zeromq library and has to be reachable through SSH.

INSTALLATION GUIDE FOR LINUX

  1. Install the latest version of zeromq through your package manager. Install version 4 (often called 5).
  2. Make sure that Matlab is using the system's version of libstdc++. If it is using an incompatible version, starting Transplant might fail with an error like GLIBCXX_3.4.21 not found. If you experience this, disable Matlab's own libstdc++ either by removing/renaming $MATLABROOT/sys/os/glnxa64/libstdc++, or by installing matlab-support (if you are running Ubuntu).

INSTALLATION GUIDE FOR WINDOWS

  1. Install the latest version of zeromq from here: http://zeromq.org/distro:microsoft-windows OR through conda.
  2. Install a compiler. See here for a list of supported compilers: http://uk.mathworks.com/support/compilers/R2017a/ Matlab needs a compiler in order to load and use the ZeroMQ library using loadlibrary.

HOW DOES IT WORK?

Transplant opens Matlab as a subprocess (optionally over SSH), then connects to it via 0MQ in a request-response pattern. Matlab then runs the transplant remote and starts listening for messages. Now, Python can send messages to Matlab, and Matlab will respond. Roundtrip time for sending/receiving and encoding/decoding values from Python to Matlab and back is about 2 ms.

All messages are Msgpack-encoded or JSON-encoded objects. You can choose between Msgpack (faster) and JSON (slower, human-readable) using the msgformat attribute of the Matlab constructor. There are seven messages types used by Python:

  • set_global and get_global set and retrieve a global variable.
  • del_proxy removes a cached object.
  • call calls a Matlab function with some function arguments and returns the result.
  • die tells Matlab to shut down.

Matlab can then respond with one of three message types:

  • ack for successful execution.
  • value for return values.
  • error if there was an error during execution.

In addition to the regular Msgpack/JSON data types, _transplant_ uses specially formatted Msgpack/JSON arrays for transmitting numerical matrices as binary data. A numerical 2x2 32-bit integer matrix containing [[1, 2], [3, 4]] would be encoded as ["__matrix__", "int32", [2, 2], "AQAAAAIAAAADAAAABAAAA==\n"], where "int32" is the data type, [2, 2] is the matrix shape and the long string is the base64-encoded matrix content. This allows for efficient data exchange and prevents rounding errors due to JSON serialization. In Msgpack, the data is not base64-encoded.

When Matlab returns a function handle, it is encoded as ["__function__", func2str(f)]. When Matlab returns an object, it caches its value and returns ["__object__", cache_idx]. These arrays are translated back to their original Matlab values if passed to Matlab.

Note that this project includes a Msgpack serializer/parser, a JSON serializer/parser, and a Base64 encoder/decoder in pure Matlab.

FAQ

  • I get errors with integer numbers Many Matlab functions crash if called with integers. Convert your numbers to float in Python to fix this problem.
  • How do I pass structs to Matlab? Since Matlab structs can't use arbitrary keys, all Python dictionaries are converted to Matlab containers.Map instead of structs. Wrap your dicts in transplant.MatlabStruct in Python to have them converted to structs. Note that this will change all invalid keys to whatever Matlab thinks is an appropriate key name using matlab.lang.makeValidName.
  • I get errors like GLIBCXX_3.4.21 not found Matlab's version of libstdc++ is incompatible with your OS's version. See INSTALLATION GUIDE FOR LINUX for details.
  • Does Transplant work in Python 2.7? No, it does not.
  • How to integrate Transplant with Jupyter? Use the provided transplant_magic.py, to get %%matlab cell magic.

SIMILAR PROGRAMS

I know of two programs that try to do similar things as Transplant:

  • Mathwork's own MATLAB Engine API for Python provides a CPython extension for calling Matlab code from some versions of Python. In my experience, it is significantly slower than Transplant, less feature-complete (no support for non-scalar structs, objects, methods, packages, numpy), and more cumbersome to use (all arguments and return values need to be wrapped in a matlab.double instead of Numpy Arrays). For a comparison of the two, here are two blog posts on the topic: Intro to Transplant, Transplant speed.
  • Oct2Py calls Octave from Python. It is very similar to Transplant, but uses Octave instead of Matlab. This has huge benefits in startup time, but of course doesn't support all Matlab code.

KNOWN ISSUES

Transplant is a side project of mine that I use for running cross-language experiments on a small compute cluster. As such, my usage of Transplant is very narrow, and I do not see bugs that don't happen in my typical usage. That said, I have used Transplant for hundreds of hours, and hundreds of Gigabytes of data without errors.

If you find a bug, or would like to discuss a new feature, or would like to contribute code, please open an issue on Github.

I do not have a Windows machine to test Transplant. Windows support might contain bugs, but at least one user has used it on Windows in the past. If you are hitting problems on Windows, please open an issue on Github.

Running Transplant over the network might contain bugs. If you are hitting problems, please open an issue on Github.

Finally, I would like to remind you that I am developing this project for free, and in my spare time. While I try to be as accomodating as possible, I can not guarantee a timely response to issues. Publishing Open Source Software on Github does not imply an obligation to fix your problem right now. Please be civil.

transplant's People

Contributors

bastibe avatar dlaidig avatar foucl avatar hardmstar avatar iled avatar indivisibleatom avatar janw avatar jooh avatar siggigue avatar toddrme2178 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

transplant's Issues

Performance on windows

I'll start by saying that as you've discovered, matlab.engine is practically not usable for me, due to their massive memory leaks.

Note: I'm using Matlab 2014b

However, unlike what you found on linux, on windows it seems that transplant is much slower than matlab.engine, at least in certain operations.

I can't provide a fully reproducable scenario, but here are the main relevant functions:

import transplant
matlab = transplant.Matlab()
...
def load_mat_TRANSPLANT(filename,verbose=False):
    matlab.evalin('base', 'my_obj = load(\'{0}\');'.format(filename))
    matlab.evalin('base', 't1 = my_obj.study.series_index.type.T1_dynamic_contrast;')
    if verbose:
        print('T1_dynamic_contrast serieses:',matlab.t1)

    t1_dyn_con_volumes = list(map(int,matlab.t1[0]))

    volumes = []

    for v in t1_dyn_con_volumes:
        matlab.evalin('base', 'my_vol = my_obj.study.series{{{0}}}.image;'.format(t1_dyn_con_volumes[0]))
        if verbose:
            print('volume shape:', matlab.my_vol.shape)
        #plt.imshow(matlab.my_vol[:, :, 30])

        volumes.append(matlab.my_vol)


    return volumes

And here's the code using matlab.engine (it's a bit different, I actually do MORE there...)

def load_mat_MATLAB_ENGINE(filename,verbose=False):
    cmd_text = 'load(\'{0}\');'.format(filename)
    my_obj = eng.eval(cmd_text)

    eng.workspace['my_obj'] = my_obj

    t1 = eng.eval('my_obj.study.series_index.type.T1_dynamic_contrast;')

    if verbose:
        print('T1_dynamic_contrast serieses:',t1)

    t1_dyn_con_volumes = list(map(int,t1[0]))

    volumes = []

    for v in t1_dyn_con_volumes:
        my_vol = eng.eval('my_obj.study.series{{{0}}}.image;'.format(t1_dyn_con_volumes[0]))
        arr = np.array(my_vol._data).reshape((my_vol.size[2], my_vol.size[0], my_vol.size[1]), order='C')
        arr = np.swapaxes(arr,1,2)

        if verbose:
            print('volume shape:', arr.shape)

        volumes.append(arr)
    return volumes

Each .mat file may contain few volumes.

Here's the comparison run times
filename matlab_engine_seconds transplant_seconds
mat_file_1 5.4 18.3
mat_file_2 30.8 75.3
mat_file_3 36.3 174.2

If possible, please test your library on windows passing around big volumes and say if you see the same performance issue.

suggestion for the readme

Hi,
I have a suggestion for the readme - you can add a part about making it run on windows.
This can save few precious minutes to the people intending to run it on windows.
It is also especially important since part of your library audience may be windows matlab users which are not necessarily l33t haxxors ;)

Here's a bunch of tips - you may think that some (or most) of this goes beyond the scope of your readme, but I think that if it helps people install and use it quickly, than why not :)

  • Install zeromq from here:
    http://zeromq.org/distro:microsoft-windows
    "Stable Release 4.0.4" worked well for me.
  • Copy libzmq-v90-mt-4_0_4.dll into libzmq.dll
  • Make sure that matlab knows the path of this dll (I don't remember if I did this using the PATH env. variable, or by adding addpath('path/to/zeromq/bin') to matlabrc.m )
  • Put addpath('path/to/transplant_library') in matlabrc.m
  • Matlab doesn't always ship with a C/C++ compiler, In my case of Matlab 2014b x64 it didn't.
    Matlab needs a compiler in order to load and use the zeromq binary DLLs, which is a C++ library. Note that it's needed for using matlab "LoadLibrary" function to load any C/C++ DLL.
  • In the case that you don't have a compiler that Matlab knows, one of the options that you can do is download Win 7 SDK.
    https://www.microsoft.com/en-us/download/details.aspx?id=8279
    Note that the sdk installer checks for .net framework 4, and in the likely case that you have a newer version it will not install.
    You can trick it into installing with some simple registry trickery (remember to restore it back after the installation is complete)
    Make sure that compilers are selected as a component to be installed.
    Look at the accepted answer here for the registry trickery:
    http://stackoverflow.com/questions/31455926/windows-sdk-setup-failure
  • I had to change transplantzmq.h into this:
    transplantzmq.zip
    Due to typedef conflicts and unkown variable types.
  • Now, manually run a new Matlab session, and verify that you can manually use LoadLibrary('lib
    zmq.dll','transplantzmq.h') without getting any errors/warnings.
  • You are ready to go!

Switch communication format to MsgPack

MsgPack would be easier to encode (which doesn't matter much, since encoding is fast anyway), and faster to decode in Matlab. This is not as much of a problem any more, now that parsejson has gotten quite fast, but it would eliminate some more overhead.

Error when Matlab function does not exist

I am using OSX 10.12 with Matlab R2017a and Python 3.6.0 with transplant installed with pip. When I execute a matlab function that does not exist, I get a long error stack that contains no information on what does went wrong. For example executing:
mlab.wrongfunction()
I get the following error:

>>> mlab.wrongfunction()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.6/site-packages/transplant/transplant_master.py", line 501, in __getattr__
    return self._get_global(name)
  File "/usr/local/lib/python3.6/site-packages/transplant/transplant_master.py", line 92, in _get_global
    response = self.send_message('get_global', name=name)
  File "/usr/local/lib/python3.6/site-packages/transplant/transplant_master.py", line 162, in send_message
    trace += '    ' + open(frame['file'], 'r', errors='replace').readlines()[int(frame['line'])-1].strip(' ')
IndexError: list index out of range

Would it be possible to return the error from Matlab:
Undefined function or variable 'wrongfunction'.

Matlab plot() and imagesc()

Did not find how to use this matlab commands with transplant. Can you give simple example on how to plot 1d numpy array with matlab.plot() and 2d with matlab.imagesc()? Of course there is a native matplotlib, but I personally prefer those Matlab functions, already use it with matlab's proprietary python API engine.

0.9 documentation out of synch?

Dear Bastian,

First, thank you for providing pysoundfile, the libsoundfile interface is a blessing. The 0.9 docs appear to be out of synch with the 0.9 pip distribution. The current 0.9 documentation notes frames() as supporting additional parameters (e.g. start, stop) that are not in the 0.9 distribution but are in the git repository.

Best regards,
Marie

Transplant with Python2

I tried to import transplant on Python 2.7.13 but I get the following error:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/tothsa/.pyenv/versions/2.7.13/lib/python2.7/site-packages/transplant/__init__.py", line 1, in <module>
    from .transplant_master import Matlab, TransplantError, MatlabStruct
  File "/Users/tothsa/.pyenv/versions/2.7.13/lib/python2.7/site-packages/transplant/transplant_master.py", line 124
    print(line.decode(), end='')
                            ^
SyntaxError: invalid syntax

Is transplant planned to run on Python 2.7?

/sys/os/glnxa64/libstdc++ and GLIBCXX_3.4.20

Hi, I'm getting some issues loading the matlab engine. Before, it used to work fine. But upon install on a new machine, running into an error despite following the same steps.

The error:

$ python
Python 3.6.5 |Anaconda, Inc.| (default, Apr 29 2018, 16:14:56) 
[GCC 7.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import transplant
>>> eng = transplant.Matlab()

                            < M A T L A B (R) >
                  Copyright 1984-2016 The MathWorks, Inc.
                   R2016a (9.0.0.341360) 64-bit (glnxa64)
                             February 11, 2016

 
To get started, type one of these: helpwin, helpdesk, or demo.
For product information, visit www.mathworks.com.
 
Error loading libzmq: There was an error loading the library "/opt/conda/lib/libzmq.so.5"
/lib64/libstdc++.so.6: version `GLIBCXX_3.4.20' not found (required by /opt/conda/lib/libzmq.so.5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/conda/lib/python3.6/site-packages/transplant/transplant_master.py", line 490, in __init__
    self.eval('0;') # no-op. Wait for Matlab startup to complete.
  File "/opt/conda/lib/python3.6/site-packages/transplant/transplant_master.py", line 548, in __getattr__
    return self._get_global(name)
  File "/opt/conda/lib/python3.6/site-packages/transplant/transplant_master.py", line 92, in _get_global
    response = self.send_message('get_global', name=name)
  File "/opt/conda/lib/python3.6/site-packages/transplant/transplant_master.py", line 148, in send_message
    self._wait_socket(zmq.POLLOUT)
  File "/opt/conda/lib/python3.6/site-packages/transplant/transplant_master.py", line 178, in _wait_socket
    raise RuntimeError('Process died unexpectedly')
RuntimeError: Process died unexpectedly
>>> 

Some verifications:

$ ls -al /opt/conda/lib/libzmq.so.5*
lrwxrwxrwx 1 root root     15 Jul 12 16:54 /opt/conda/lib/libzmq.so.5 -> libzmq.so.5.1.5
-rwxrwxr-x 2 root root 745392 Apr 13 09:38 /opt/conda/lib/libzmq.so.5.1.5
$ ls -al /opt/conda/lib/libstdc++.so.6*
lrwxrwxrwx 1 root root      19 Jul 12 17:40 /opt/conda/lib/libstdc++.so.6 -> libstdc++.so.6.0.19
-rwxrwxr-x 2 root root 1055192 Nov 15  2016 /opt/conda/lib/libstdc++.so.6.0.19
-rw-rw-r-- 1 root root    2311 Jul 12 17:40 /opt/conda/lib/libstdc++.so.6.0.19-gdb.py
lrwxrwxrwx 1 root root      19 Jul 12 17:43 /opt/conda/lib/libstdc++.so.6.0.21 -> libstdc++.so.6.0.24
-rwxrwxr-x 2 root root 8167184 Mar  8 10:42 /opt/conda/lib/libstdc++.so.6.0.24
$ ls -al /usr/lib64/libstdc++.so.6*
lrwxrwxrwx. 1 root root     19 Jul 12 15:12 /usr/lib64/libstdc++.so.6 -> libstdc++.so.6.0.19
-rwxr-xr-x. 1 root root 991616 May 15 14:52 /usr/lib64/libstdc++.so.6.0.19

I even moved the libstdc++.so files out of that directory:

$ ls -al /usr/local/MATLAB/R2016a/sys/os/glnxa64
total 27812
drwxrwxr-x 2 root root      291 Jul 12 18:15 .
drwxrwxr-x 3 root root       70 Jul 12 18:15 ..
-r-xr-xr-x 1 root root   521073 Dec 28  2015 libgcc_s.so.1
lrwxrwxrwx 1 root root       20 Jul 12 16:57 libgfortran.so.3 -> libgfortran.so.3.0.0
-r-xr-xr-x 1 root root  5811979 Dec 28  2015 libgfortran.so.3.0.0
-r-xr-xr-x 1 root root  1303868 Dec 28  2015 libifcore.so.5
-r-xr-xr-x 1 root root   196634 Dec 28  2015 libifport.so.5
-r-xr-xr-x 1 root root  3083165 Dec 28  2015 libimf.so
-r-xr-xr-x 1 root root   397899 Dec 28  2015 libintlc.so.5
-r-xr-xr-x 1 root root  1380283 Dec 28  2015 libiomp5.so
-r-xr-xr-x 1 root root   397899 Dec 28  2015 libirc.so
lrwxrwxrwx 1 root root       20 Jul 12 16:57 libquadmath.so.0 -> libquadmath.so.0.0.0
-r-xr-xr-x 1 root root   866238 Dec 28  2015 libquadmath.so.0.0.0
-r-xr-xr-x 1 root root 14494114 Dec 28  2015 libsvml.so
-r--r--r-- 1 root root      291 Dec 28  2015 README.libstdc++

Any ideas?

Stdout is delayed?

When I run the following command the STDOUT from Matlab is not transferred:

S = {'a':1.0}
mlab.disp(S)

Strangely, I get the output later after running a few more commands.

Unicode problem?

I got this issue from a user when using transplant on MacOS with my compiled code:

Last login: Fri Aug 11 11:31:29 on ttys000
[rosss-imac:~] rossstewart% python3
Python 3.6.2 (default, Jul 17 2017, 16:44:45) 
[GCC 4.2.1 Compatible Apple LLVM 8.1.0 (clang-802.0.42)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> spinw='/Applications/pyspinw.app/pyspinw.sh'
>>> from transplant import Matlab
>>> from transplant import MatlabStruct
>>> import numpy as np
>>> m=Matlab(spinw)
SpinW process is running...
>>> tri = m.sw_model('triAF',1.)
Preparing 'triAF' model ...
Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/local/Cellar/python3/3.6.2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/threading.py", line 916, in _bootstrap_inner
    self.run()
  File "/usr/local/Cellar/python3/3.6.2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/threading.py", line 864, in run
    self._target(*self._args, **self._kwargs)
  File "/usr/local/lib/python3.6/site-packages/transplant/transplant_master.py", line 124, in reader
    print(line.decode(), end='')
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc5 in position 41: invalid continuation byte

It seems it is related to a problem that we solved before by changing the encoding in MATLAB to UTF-8. I compiled the MATLAB code after fixing this issue and it works fine on my machine. Just wanted to ask if you have any idea whether there might be some setting in Python/terminal which also has an effect.
The original string in MATLAB that caused the error was:
Creating the bond list (maxDistance = 10 Å, nCell = 7x5x2)...
seemingly the Angstrom symbol (which is at position 42) is responsible.

Seems I have to remove these special symbols from the output of my code.
Any idea is welcome!

Few suggestions

As playing for a longer time with transplant I have suggestions for a few minor improvements. Maybe you find some of the usefull.

  • in transplant_remote.m calling nargout(msg('name')) instead of nargout(fun) solves the problem with class methods in some case, so I added this little extension to transplant_remote.m, maybe you like it:
[~, funType] = which(msg('name'));
funType = strsplit(funType,' ');
if numel(funType)==2 && strcmp(funType{2},'method')
    argTemp = msg('args');
    className = funType{1};
    if ~isempty(argTemp) && isa(argTemp{1},className)
        % the function name corresponds to the
        % class of the first argument
        resultsize = nargout(msg('name'));
    end
end
  • python keyword arguments could be automatically translated to matlab string value pairs, such as mlab.myfun(option1=value1) would be called in Matlab myfun(option1,value1). You might not like it though due to ambiguity.
  • in Matlab the usage of the struct data type is far more common than the usage of the containers.Map so it would be nice to make it a bit easyer to work with structures. For example using the MatlabStruct class in python should be applied recursively to all nested structures. Again it might be again an ambiguity problem.
  • calling a chain of functions on large matrices or other objects makes transferring large amount of data multiple times between python and matlab, e.g.
A = mlab.myfun()
B = mlab.myfun2(A)
C = mlab.myfun3(B)

If A, B and C are large matrices the above command might be limited by the data transfer. It would be nice to specify per function call to keep the result in the proxy in matlab and send only a pointer to python as you are already doing it for objects. For example:

A = mlab.myfun(inproxy=True)
B = mlab.myfun2(A,inproxy=True)
C = mlab.myfun3(B,inproxy=True)

Finding libzmq for Matlab

The search for the location of libzmq fails. Most probably because on my platform (OSX, python installed with homebrew) the sys.prefix() call returns:
'/usr/local/Cellar/python3/3.6.0/Frameworks/Python.framework/Versions/3.6'

And transplant searches for libzmq in this path instead of in /usr/local as it should be.

Using transplant with Python 2.7

I tried importing transplant in Python 2.7, but got the following error:

Traceback (most recent call last):
File "Experiment.py", line 19, in
import transplant
File "/usr/local/lib/python2.7/dist-packages/transplant/init.py", line 1, in
from .transplant_master import Matlab, TransplantError, MatlabStruct
File "/usr/local/lib/python2.7/dist-packages/transplant/transplant_master.py", line 123
print(line.decode(), end='')

I believe this occurs because you are using the print statement from Python 3.

@bastibe , how hard do you believe it would be to make transplant usable in Python 2.7? I can definitely attempt to do this on my own, but I would like some background info to guide me.

Thanks,
Alex Williams

SyntaxError: can use starred expression only as assignment target

Hi Basti,
I receive the following error for transplant installed in a Ubuntu 14.04, miniconda3 (Python3.4) environment:

Traceback (most recent call last):
  File "Python-Interface_Transplant.py", line 6, in <module>
    import transplant
  File "/home/user/miniconda3/envs/transplant/lib/python3.4/site-packages/transplant/__init__.py", line 1, in <module>
    from .transplant_master import Matlab, TransplantError, MatlabStruct
  File "/home/user/miniconda3/envs/transplant/lib/python3.4/site-packages/transplant/transplant_master.py", line 524
    search_dirs = [*(os.getenv('LD_LIBRARY_PATH') or '').split(':'),
                              ^
SyntaxError: can use starred expression only as assignment target

Here is the list of installed packages in this environment:

chaospy                   2.2.3                     <pip>
cycler                    0.10.0                    <pip>
decorator                 4.0.11                    <pip>
f90wrap                   0.1.4                     <pip>
libsodium                 1.0.10                        0  
matplotlib                2.0.2                     <pip>
msgpack-python            0.4.8                     <pip>
networkx                  1.11                      <pip>
numpy                     1.13.0                    <pip>
openssl                   1.0.2l                        0  
pip                       9.0.1                    py34_1  
pyparsing                 2.2.0                     <pip>
python                    3.4.5                         0  
python-dateutil           2.6.0                     <pip>
pytz                      2017.2                    <pip>
pyzmq                     16.0.2                    <pip>
readline                  6.2                           2  
scipy                     0.19.1                    <pip>
setuptools                27.2.0                   py34_0  
six                       1.10.0                    <pip>
sqlite                    3.13.0                        0  
tk                        8.5.18                        0  
transplant                0.7.8                     <pip>
wheel                     0.29.0                   py34_0  
xz                        5.2.2                         1  
zeromq                    4.1.5                         0  
zlib                      1.2.8                         3 

I'm not sure if this is a syntax error or if I should try to set the LD_LIBRARY_PATH although the transplant package was installed in the environment.

improve string performance

  • character substitution could be done on the whole string instead of the individual substrings.
  • String starts/ends could be identified ahead of time.

Using transplant to import java classes

Hello,

I am working on a school project where I need to use java classes in MATLAB. In a regular matlab script you can import java classes using the following syntax:import edu.stanford.math.plex4.*;. How can I execute these types of statements using transplant?

Thanks,
Alex WIlliams

Matlab help()

This is not really an issue, but a question. In a deployed Matlab code the help() function is blocked, so I created an alternative function that generates the help script with the same header as the original help:

helpStr = help(functionName)

Do you know what would be the easiest way to redefine the __doc__ method in python to call the alternative command? It seems by creating a user function with the same name does not help. Could you provide an additional argument in Matlab() to define the help function / make some fixed alternative name.

Thanks!

Use Python's libzmq

It should be possible to re-use Python's libzmq. This would obviate the need to have a separate installation of libzmq on a system.

Calling methods on Matlab objects

I have a user defined matlab object with a method, e.g. myObj.cut(). When I try the following lines in python:

import transplant
mat = transplant.Matlab()
a = mat.myObj()
mat.cut(a)

I get the following error:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/ttt/phys/transplant/transplant_master.py", line 110, in __getattr__
    return self._get_global(name)
  File "/Users/ttt/phys/transplant/transplant_master.py", line 92, in _get_global
    response = self.send_message('get_global', name=name)
  File "/Users/ttt/phys/transplant/transplant_master.py", line 173, in send_message
    response['stack'], response['identifier'], response['message'])
transplant.transplant_master.TransplantError: Undefined variable 'genlattice'. (TRANSPLANT:novariable)
Traceback (most recent call last):
  File "/Users/ttt/phys/transplant/transplant_remote.m", line 96.0, in transplant_remote
    error('TRANSPLANT:novariable' , ...

What would be the right way to call the cut() method? The above script works with the official Matlab Python interface.
Also would it be possible to modify transplant, that object methods could be called directly:
a.cut() instead of mat.cut(a)?

Keyword argument to force return values to proxy

As per #46:

calling a chain of functions on large matrices or other objects makes transferring large amount of data multiple times between python and matlab, e.g.

A = mlab.myfun()
B = mlab.myfun2(A)
C = mlab.myfun3(B)

If A, B and C are large matrices the above command might be limited by the data transfer. It would be nice to specify per function call to keep the result in the proxy in matlab and send only a pointer to python as you are already doing it for objects. For example:

A = mlab.myfun(inproxy=True)
B = mlab.myfun2(A,inproxy=True)
C = mlab.myfun3(B,inproxy=True)

Returns only 1 value from output of mex function

Hi,
First off, I just want to say, this is great library.

My issue occurs when calling a mex function from python as:
tmp = eng.mymexfun(*args)

I am expecting two output arguments, both of size 1683x2250, but instead I am receiving only 1. This same call works fine if I use a Matlab-function from a .m file. Could it be something to do with how the values are read out from main memory? (I don't know much about the implementation, just postulating here).

Unfortunately I can't share my mex function, but I know that it works because it works correctly when called from matlab, with the same exact variables loaded.

Any ideas? Thanks in advance!

python 2.7 compatability

following error occurs when installing transplant in a python 2.7 environment

import transplant
matlab = transplant.Matlab()
# call Matlab functions:
length = matlab.numel([1, 2, 3])
magic = matlab.magic(2)
spectrum = matlab.fft(numpy.random.randn(100))
# inject variables into Matlab:
matlab.signal = numpy.zeros(100)
  File "/home/jos/anaconda/envs/PBM_testing/lib/python2.7/site-packages/transplant/transplant_master.py", line 124
    print(line.decode(), end='')
                            ^
SyntaxError: invalid syntax

This example code snippet runs just fine in python 3.5

transplant version:
0.8.1 for python 2.7
0.8.2 for python 3.5

Sparse Matrixes

Hey,

I really like the package. Unfortunately it seems like it doesn't support sparse matrices.
Doing matlab.sparse(3,3) already fails.

Is there a quick fix possible?

Opening libzmq on mac

Hello,
I am trying to use transplant to open a python app that uses matlab runtime 2017a. i have editted the search paths for libzmq to include the locations where libzmq is installed on my computer. These are my edits:

575 search_dirs = ((os.getenv('LD_LIBRARY_PATH') or '').split(':') +
576 (os.getenv('DYLD_LIBRARY_PATH') or '').split(':') +
577 (os.getenv('DYLD_FALLBACK_PATH') or '').split(':') +
578 [os.getenv('HOME') + '/lib']+
579 '/usr/local/lib'+
580 '/usr/lib'+
581 '/opt/local/lib'+
582 'anaconda/lib')

I thought to edit the file after reading https://github.com/bastibe/transplant/issues/40 < this post. I do not have access to dlopen. I am also quite new to python.

When running my app, I get the error:

Error loading libzmq: Undefined function or variable 'notfound'.

Thanks for your attention.

Improve eval

eval does not always return all return values and it is impossible to run eval with nargout=0. Also, it would be nice to not having eval as a special function at all--__getattr__ should be able to call eval.

How to hide Matlab Command Window

The transplant works nicely on my WIN7 64bit system. But when I active Matlab everytime as follows:

import transplant
matlab = transplant.Matlab()

A "Matlab Command Window" will comes up.
image
Is there any way to hide this window?

The possibile solution like this?
Matlab(arguments=('-nodesktop', '-nosplash'......more?))

Howto get remote working?

import transplant
matlab = transplant.Matlab(address='127.0.0.1',executable='/home/nbecker/.local/bin/matlab')#jvm=False)

...
Trial License -- for use to evaluate programs for possible purchase as an end-user only.

Undefined function or variable 'transplant_remote'.

Sorry if this is a stupid question - I don't know anything about matlab. I'm guessing it isn't finding the needed .m file, but I don't know how to fix that.

License file

I am trying to package transplant for openSUSE. However, there is no license file I can find, either in the github or tarball. In order for people to know how they can use your code it is really important to have a license file. Would it be possible to add one? Thank you.

Cannot find libzmq in linux

On my linux installation transplant cannot find the libzmq library. The location of the libzmq library is /usr/local/lib64/libzmq.so.5.1.3, however it is not searched by transplant:

          search_dirs = ((os.getenv('LD_LIBRARY_PATH') or '').split(':') +
                           self._read_ldsoconf('/etc/ld.so.conf') +
                           ['/lib/', '/lib64/',
                            '/usr/lib/', '/usr/lib64/'])

If you prefer, I can create a pull request for these kind of simple fixes, however you come up most often a better solution than mine. I also have a different libzmq version in /usr/local/lib so it might be good to search that folder as well.

Win64: ctypes.util.find_library('zmq')) returns None (should be 'libzmq.dll'?)

Hi,

I can't get transplant to work on win64 according to the installation instructions. transplant.matlab() fails with

Traceback (most recent call last):

  File "<ipython-input-3-8cd221b830b5>", line 1, in <module>
    transplant.Matlab()

  File "C:\Users\chdan\Anaconda2\envs\mymu\lib\site-packages\transplant\transplant_master.py", line 425, in __init__
    raise RuntimeError('could not locate libzmq for Matlab')

RuntimeError: could not locate libzmq for Matlab

Simply changing https://github.com/bastibe/transplant/blob/master/transplant/transplant_master.py#L413 to ctypes.util.find_library('libzmq.dll')) resolves the issue on my machine and everything works as expected.

According to https://docs.python.org/3/library/ctypes.html#finding-shared-libraries, this is to be expected on windows:

On Windows, find_library() searches along the system search path, and returns the full pathname, but since there is no predefined naming scheme a call like find_library("c") will fail and return None.

If wrapping a shared library with ctypes, it may be better to determine the shared library name at development time, and hardcode that into the wrapper module instead of using find_library() to locate the library at runtime.

example code not working (newbie here)

n, m = matlab.size([1, 2, 3])

ValueError: not enough values to unpack (expected 2, got 1)

matlab.size([1, 2, 3])
Out[78]: array([[ 1., 3.]])

I guess this is just a documentation error?

This is python 3.6

Calling Matlab module functions

In Matlab functions can be defined within a module by placing them in a folder with name starting with +: e.g. +myModule. To call them in Matlab one has to use:

myModule.myFun()

This causes problem in transplant, as a simple matlab.myModule.myFun() won't work. I simple workaround could be that we define a symbol for the dot notation, for example calling matlab.myModule__myFun() where the __ symbol would be translated to . in Matlab.

MATLAB:Containers:Map doesn't allow empty keys

While trying to work with Labstreaming Layer's xdf-files and the way they are read into matlab by their importer, I ran into an issue in dumpmsgpack.m. LSL's reader function generates deeply nested structs that sometimes have empty 'substructs'.

Example:
In Matlab:

function [ s ] = gen_struct_empty_fields(  )
    s = struct();
    s.field1 = 'test';
    s.field2 = struct();
end

Trying to execute this from a transplant.Matlab() instance (s = matlab.gen_struct_empty_fields()) throws the following traceback:

Traceback (most recent call last):

  File "<ipython-input-13-55a6fd42c0fa>", line 1, in <module>
    matlab.gen_struct_empty_fields()

  File "C:\Users\chdan\Anaconda2\envs\mymu\lib\site-packages\transplant\transplant_master.py", line 481, in __call__
    return self._call(data[1], args, nargout=nargout)

  File "C:\Users\chdan\Anaconda2\envs\mymu\lib\site-packages\transplant\transplant_master.py", line 461, in _call
    nargout=nargout)

  File "C:\Users\chdan\Anaconda2\envs\mymu\lib\site-packages\transplant\transplant_master.py", line 163, in send_message
    response['stack'], response['identifier'], response['message'])

TransplantError: Empty keys are not allowed in this container. (MATLAB:Containers:Map:EmptyKey)
Traceback (most recent call last):
  File "C:\Users\chdan\Anaconda2\envs\mymu\lib\site-packages\transplant\transplant_remote.m", line 128, in transplant_remote
    send_value(results{1});
  File "C:\Users\chdan\Anaconda2\envs\mymu\lib\site-packages\transplant\transplant_remote.m", line 187, in transplant_remote/send_value
    send_message('value', message);
  File "C:\Users\chdan\Anaconda2\envs\mymu\lib\site-packages\transplant\transplant_remote.m", line 155, in transplant_remote/send_message
    messenger.send(dumpmsgpack(message));
  File "C:\Users\chdan\Anaconda2\envs\mymu\lib\site-packages\transplant\dumpmsgpack.m", line 22, in dumpmsgpack
    msgpack = dump(data);
  File "C:\Users\chdan\Anaconda2\envs\mymu\lib\site-packages\transplant\dumpmsgpack.m", line 68, in dump
    msgpack = dumpmap(data);
  File "C:\Users\chdan\Anaconda2\envs\mymu\lib\site-packages\transplant\dumpmsgpack.m", line 219, in dumpmap
    valuestuff = dump(values{n});
  File "C:\Users\chdan\Anaconda2\envs\mymu\lib\site-packages\transplant\dumpmsgpack.m", line 68, in dump
    msgpack = dumpmap(data);
  File "C:\Users\chdan\Anaconda2\envs\mymu\lib\site-packages\transplant\dumpmsgpack.m", line 219, in dumpmap
    valuestuff = dump(values{n});
  File "C:\Users\chdan\Anaconda2\envs\mymu\lib\site-packages\transplant\dumpmsgpack.m", line 46, in dump
    data = containers.Map(fieldnames(data), struct2cell(data));

For me, simply doing this

if isstruct(data)
    if isempty(fieldnames(data))
        data = [];
    else
        data = containers.Map(fieldnames(data), struct2cell(data));
    end
end

in dumpmsgpack.m L45 solves the issue (at least for my use case). Would this be worthy of a pull request?

Problem with from transplant_master import Matlab

Hello, i'm facing problem with importing Matlab class. I'm using python 2.7 and Matlab R2015b.

transplant_master.py, line 446
def call(_self, *args, nargout=-1):
^
SyntaxError: invalid syntax

also had problem with line 133 from the same file
print(line.decode(), end='')
that i fixed by adding : from future import print_function in the beggining of the file.

May be you have some suggestions about first problem?
Thanks in advance.

cell2mat fails for the shape due to different data types when using msgpack

When using transplant, I got an error "All contents of the input cell array must be of the same data type. (MATLAB:cell2mat:MixedDataTypes)". It turns out that this happens in the function decode_matrix() of transplant_remote.m when trying to convert the shape to a matrix. The different entries of the shape are stored as the smallest fitting integer type which causes cell2mat to fail.

In decode_matrix():

disp(value{3});
    [7479]    [3]
disp(class(value{3}));
    cell
disp(class(value{3}{1}));
    uint16
disp(class(value{3}{2}));
    uint8

As a quick fix, I changed the python side to transmit the shape as floats, but I don't know transplant and msgpack good enough to suggest an elegant solution.

Windows, Matlab process dies on start

When opening a Matlab instance on Windows, the Matlab process dies immediately. Transplant throws a runtime error. No error message is displayed in the Matlab command window, it becomes unresponsive.

Attempted solutions

Reinstall all relevant packages

No change

Running with admin permissions

No change

Install ZMQ without Anaconda

Same problem as far as I can tell

Fully removed:

In [2]: transplant.Matlab()
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-2-d12f35e2c1f4> in <module>()
----> 1 transplant.Matlab()

C:\ProgramData\Anaconda3\lib\site-packages\transplant\transplant_master.py in __
init__(self, executable, arguments, msgformat, address, user, print_to_stdout, d
esktop, jvm)
    468                                   "transplant_remote('{}','{}','{}');".f
ormat(
    469                                       os.path.dirname(__file__), os.getc
wd(),
--> 470                                       msgformat, zmq_address, self._loca
te_libzmq()
    471 )])
    472         else:

C:\ProgramData\Anaconda3\lib\site-packages\transplant\transplant_master.py in _l
ocate_libzmq(self)
    606                 return candidates[0]
    607
--> 608         raise RuntimeError('could not locate libzmq for Matlab')
    609
    610     def _ask_ld_for_paths(self):

RuntimeError: could not locate libzmq for Matlab

Reinstalled with ZeroMQ executable:

In [2]: transplant.Matlab()
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-2-d12f35e2c1f4> in <module>()
----> 1 transplant.Matlab()
...
RuntimeError: Process died unexpectedly

In [3]: %debug
> c:\programdata\anaconda3\lib\site-packages\transplant\transplant_master.py(178
)_wait_socket()
    176         while True:
    177             if self.process.poll() is not None:
--> 178                 raise RuntimeError('Process died unexpectedly')
    179             if self.socket.poll(timeout, flags) != 0:
    180                 return

ipdb> self._locate_libzmq()
'C:/Program Files\\ZeroMQ 4.0.4\\bin\\libzmq-v100-mt-4_0_4.dll'

Load the ZMQ library from Matlab

No errors
e.g.

loadlibrary('C:\ProgramData\Anaconda3\Library\bin\libzmq.dll', 'C:\ProgramData\Anaconda3\pkgs\zeromq-4.2.3-hd6b2f15_3\Library\include\zmq.h')

Create a ZMQ (transplant) class instance from within Matlab

Using the path given by _locate_libzmq()
Can create the ZMQ object without problems

e.g.

ZMQ('C:\ProgramData\Anaconda3\Library\bin\libzmq.dll', 'tcp://127.0.0.1:65535')

Install on another (fresh) Windows machine

Same problem

Installation steps

conda create --name test
activate test
conda install zeromq
pip install transplant

(Visual C++ was already installed)

Use Visual C++ 2015 instead of MinGW/GCC

As a Matlab compiler

Reproduction and error messages

Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.
C:\Windows\system32>ipython
Python 3.5.5 |Anaconda custom (64-bit)| (default, Apr  7 2018, 04:52:34) [MSC v.
1900 64 bit (AMD64)]
Type 'copyright', 'credits' or 'license' for more information
IPython 6.3.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import transplant

In [2]: transplant.Matlab()
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-2-d12f35e2c1f4> in <module>()
----> 1 transplant.Matlab()

C:\ProgramData\Anaconda3\lib\site-packages\transplant\transplant_master.py in __
init__(self, executable, arguments, msgformat, address, user, print_to_stdout, d
esktop, jvm)
    495         if print_to_stdout:
    496             self._start_reader()
--> 497         self.eval('0;') # no-op. Wait for Matlab startup to complete.
    498
    499     def exit(self):

C:\ProgramData\Anaconda3\lib\site-packages\transplant\transplant_master.py in __
getattr__(self, name)
    532         """Retrieve a value or function from the remote."""
    533         try:
--> 534             return self._get_global(name)
    535         except TransplantError as err:
    536             # package identifiers for `what` use '/' instead of '.':

C:\ProgramData\Anaconda3\lib\site-packages\transplant\transplant_master.py in _g
et_global(self, name)
     90     def _get_global(self, name):
     91         """Retrieve a value from a named variable."""
---> 92         response = self.send_message('get_global', name=name)
     93         return response['value']
     94

C:\ProgramData\Anaconda3\lib\site-packages\transplant\transplant_master.py in se
nd_message(self, msg_type, **kwargs)
    146         kwargs = self._encode_values(kwargs)
    147
--> 148         self._wait_socket(zmq.POLLOUT)
    149         if self.msgformat == 'msgpack':
    150             self.socket.send(msgpack.packb(dict(kwargs, type=msg_type),
use_bin_type=True), flags=zmq.NOBLOCK)

C:\ProgramData\Anaconda3\lib\site-packages\transplant\transplant_master.py in _w
ait_socket(self, flags, timeout)
    176         while True:
    177             if self.process.poll() is not None:
--> 178                 raise RuntimeError('Process died unexpectedly')
    179             if self.socket.poll(timeout, flags) != 0:
    180                 return

RuntimeError: Process died unexpectedly

Matlab crash dump

------------------------------------------------------------------------
    Unknown exception 0x40000015 detected at Tue Apr 17 14:05:36 2018
------------------------------------------------------------------------

Configuration:
  Crash Decoding      : Disabled - No sandbox or build area path
  Crash Mode          : continue (default)
  Current Graphics Driver: Unknown hardware 
  Default Encoding    : windows-1252
  Deployed            : false
  Graphics card 1     : RealVNC ( 0x0 ) VNC Mirror Driver Version 1.8.0.0
  Graphics card 2     : NVIDIA ( 0x10de ) NVIDIA GeForce GTX 1080 Ti Version 23.21.13.8813
  Host Name           : ADRLAB-32
  MATLAB Architecture : win64
  MATLAB Entitlement ID: 3463632
  MATLAB Root         : C:\Program Files\MATLAB\R2017a
  MATLAB Version      : 9.2.0.556344 (R2017a)
  OpenGL              : hardware
  Operating System    : Microsoft Windows 7 Enterprise 
  Processor ID        : x86 Family 6 Model 60 Stepping 3, GenuineIntel
  Virtual Machine     : Java 1.7.0_60-b19 with Oracle Corporation Java HotSpot(TM) 64-Bit Server VM mixed mode
  Window System       : Version 6.1 (Build 7601: Service Pack 1)

Fault Count: 1


Abnormal termination:
Unknown exception 0x40000015

Register State (from fault):
  RAX = 00000000730ce15e  RBX = 000007fee1c43b70
  RCX = 0000000004027df0  RDX = 00000000000000d8
  RSP = 0000000004028400  RBP = 00000000ffffffff
  RSI = 0000000004028600  RDI = 00000000338314e0
 
   R8 = 0000000000000000   R9 = 0000000000000000
  R10 = 43d6dde6d86822b7  R11 = 0000000004028440
  R12 = 0000000004028980  R13 = 0000000000000003
  R14 = 0000000000000000  R15 = 0000000000000000
 
  RIP = 000007fefcdca06d  EFL = 00000202
 
   CS = 0033   FS = 0053   GS = 002b

Stack Trace (from fault):
[  0] 0x000007fefcdca06d                 C:\Windows\system32\KERNELBASE.dll+00106605 RaiseException+00000061
[  1] 0x000007fee1c1d6bb    C:\ProgramData\Anaconda3\Library\bin\libzmq.dll+00186043
[  2] 0x000007fee1c03ffb    C:\ProgramData\Anaconda3\Library\bin\libzmq.dll+00081915
[  3] 0x000007fee1c21b88    C:\ProgramData\Anaconda3\Library\bin\libzmq.dll+00203656
[  4] 0x000007fee1c217c0    C:\ProgramData\Anaconda3\Library\bin\libzmq.dll+00202688
[  5] 0x000007fee1c35c48    C:\ProgramData\Anaconda3\Library\bin\libzmq.dll+00285768 zmq_msg_recv+00000040
[  6] 0x0000000092e114fb C:\Users\adkins\AppData\Local\Temp\tp0c88deb0_6b3e_493a_9c92_2fe78c8e2736\libzmq_thunk_pcwin64.dll+00005371 int32voidPtrvoidPtrint32Thunk+00000084
[  7] 0x0000000092d62792                             bin\win64\libmwcli.dll+00010130
[  8] 0x0000000092d6cdb4                             bin\win64\libmwcli.dll+00052660
[  9] 0x0000000092d710f5                             bin\win64\libmwcli.dll+00069877
[ 10] 0x0000000092d8c280                             bin\win64\libmwcli.dll+00180864 PointerMapSize+00084384
[ 11] 0x0000000092d8d34e                             bin\win64\libmwcli.dll+00185166 PointerMapSize+00088686
[ 12] 0x000000000c3ab0ee                     bin\win64\pgo\m_dispatcher.dll+00045294 mdLogging::~mdLogging+00000154
[ 13] 0x000000000c3a9be1                     bin\win64\pgo\m_dispatcher.dll+00039905 Mfh_MATLAB_fn::dispatch_fh+00000641
[ 14] 0x000000000d95a61c                            bin\win64\pgo\m_lxe.dll+00108060
[ 15] 0x000000000dab1ffb                            bin\win64\pgo\m_lxe.dll+01515515 boost::archive::detail::iserializer<boost::archive::binaryTerm_iarchive,std::vector<MathWorks::lxe::MatlabIrTree * __ptr64,std::allocator<MathWorks::lxe::MatlabIrTree * __ptr64> > >::load_object_data+00013323
[ 16] 0x000000000dab0aa7                            bin\win64\pgo\m_lxe.dll+01510055 boost::archive::detail::iserializer<boost::archive::binaryTerm_iarchive,std::vector<MathWorks::lxe::MatlabIrTree * __ptr64,std::allocator<MathWorks::lxe::MatlabIrTree * __ptr64> > >::load_object_data+00007863
[ 17] 0x000000000d95a717                            bin\win64\pgo\m_lxe.dll+00108311
[ 18] 0x000000000d9e9eb5                            bin\win64\pgo\m_lxe.dll+00695989
[ 19] 0x000000000d978e6a                            bin\win64\pgo\m_lxe.dll+00233066
[ 20] 0x000000000daba423                            bin\win64\pgo\m_lxe.dll+01549347 boost::archive::detail::iserializer<boost::archive::binaryTerm_iarchive,std::vector<MathWorks::lxe::MatlabIrTree * __ptr64,std::allocator<MathWorks::lxe::MatlabIrTree * __ptr64> > >::load_object_data+00047155
[ 21] 0x000000000db21a97                            bin\win64\pgo\m_lxe.dll+01972887 boost::archive::detail::iserializer<boost::archive::binaryTerm_iarchive,std::vector<MathWorks::lxe::MatlabIrTree * __ptr64,std::allocator<MathWorks::lxe::MatlabIrTree * __ptr64> > >::load_object_data+00470695
[ 22] 0x000000000db21a05                            bin\win64\pgo\m_lxe.dll+01972741 boost::archive::detail::iserializer<boost::archive::binaryTerm_iarchive,std::vector<MathWorks::lxe::MatlabIrTree * __ptr64,std::allocator<MathWorks::lxe::MatlabIrTree * __ptr64> > >::load_object_data+00470549
[ 23] 0x000000000d9626c9                            bin\win64\pgo\m_lxe.dll+00141001
[ 24] 0x000000000d9632f3                            bin\win64\pgo\m_lxe.dll+00144115
[ 25] 0x000000000d96474c                            bin\win64\pgo\m_lxe.dll+00149324
[ 26] 0x000000000d965288                            bin\win64\pgo\m_lxe.dll+00152200
[ 27] 0x000000000d96498f                            bin\win64\pgo\m_lxe.dll+00149903
[ 28] 0x000000000d958c4b                            bin\win64\pgo\m_lxe.dll+00101451
[ 29] 0x000000000d96004a                            bin\win64\pgo\m_lxe.dll+00131146
[ 30] 0x000000000d95f7d0                            bin\win64\pgo\m_lxe.dll+00128976
[ 31] 0x000000000dab5d0f                            bin\win64\pgo\m_lxe.dll+01531151 boost::archive::detail::iserializer<boost::archive::binaryTerm_iarchive,std::vector<MathWorks::lxe::MatlabIrTree * __ptr64,std::allocator<MathWorks::lxe::MatlabIrTree * __ptr64> > >::load_object_data+00028959
[ 32] 0x000000000dab52d3                            bin\win64\pgo\m_lxe.dll+01528531 boost::archive::detail::iserializer<boost::archive::binaryTerm_iarchive,std::vector<MathWorks::lxe::MatlabIrTree * __ptr64,std::allocator<MathWorks::lxe::MatlabIrTree * __ptr64> > >::load_object_data+00026339
[ 33] 0x000000000dab51b9                            bin\win64\pgo\m_lxe.dll+01528249 boost::archive::detail::iserializer<boost::archive::binaryTerm_iarchive,std::vector<MathWorks::lxe::MatlabIrTree * __ptr64,std::allocator<MathWorks::lxe::MatlabIrTree * __ptr64> > >::load_object_data+00026057
[ 34] 0x000000000db40ea9                            bin\win64\pgo\m_lxe.dll+02100905 boost::archive::detail::iserializer<boost::archive::binaryTerm_iarchive,MathWorks::lxe::MatlabIrTree>::load_object_data+00015609
[ 35] 0x000000000db40e32                            bin\win64\pgo\m_lxe.dll+02100786 boost::archive::detail::iserializer<boost::archive::binaryTerm_iarchive,MathWorks::lxe::MatlabIrTree>::load_object_data+00015490
[ 36] 0x000000000dab3383                            bin\win64\pgo\m_lxe.dll+01520515 boost::archive::detail::iserializer<boost::archive::binaryTerm_iarchive,std::vector<MathWorks::lxe::MatlabIrTree * __ptr64,std::allocator<MathWorks::lxe::MatlabIrTree * __ptr64> > >::load_object_data+00018323
[ 37] 0x000000000ca59aa9                    bin\win64\pgo\m_interpreter.dll+00170665 inEvalCmdWithLocalReturnInDesiredWSAndPublishEvents+00000081
[ 38] 0x00000000fcfe4926                                  bin\win64\iqm.dll+00346406 iqm::InternalEvalPlugin::inEvalCmdWithLocalReturn+00000246
[ 39] 0x00000000fcfe444d                                  bin\win64\iqm.dll+00345165 iqm::InternalEvalPlugin::execute+00000253
[ 40] 0x000000000d71d2e5                                  bin\win64\mcr.dll+00316133 mcrRegisterExternalFunction+00031957
[ 41] 0x00000000fcfd111a                                  bin\win64\iqm.dll+00266522 iqm::Iqm::setupIqmFcnPtrs+00072250
[ 42] 0x00000000fcfd0ff3                                  bin\win64\iqm.dll+00266227 iqm::Iqm::setupIqmFcnPtrs+00071955
[ 43] 0x00000000fcfb72da                                  bin\win64\iqm.dll+00160474 iqm::Iqm::deliver+00001114
[ 44] 0x00000000fb5fb7d5                          bin\win64\libmwbridge.dll+00047061 ioReadLine+00000517
[ 45] 0x00000000fb5fb692                          bin\win64\libmwbridge.dll+00046738 ioReadLine+00000194
[ 46] 0x00000000fb609dc9                          bin\win64\libmwbridge.dll+00105929 mnDebugPrompt+00001545
[ 47] 0x00000000fb609903                          bin\win64\libmwbridge.dll+00104707 mnDebugPrompt+00000323
[ 48] 0x00000000fb60a04a                          bin\win64\libmwbridge.dll+00106570 mnParser+00000426
[ 49] 0x000000000d7075f1                                  bin\win64\mcr.dll+00226801 mcr::runtime::setInterpreterThreadSingletonToCurrent+00027889
[ 50] 0x000000000d7064e7                                  bin\win64\mcr.dll+00222439 mcr::runtime::setInterpreterThreadSingletonToCurrent+00023527
[ 51] 0x000000000d706563                                  bin\win64\mcr.dll+00222563 mcr::runtime::setInterpreterThreadSingletonToCurrent+00023651
[ 52] 0x000000000d706e81                                  bin\win64\mcr.dll+00224897 mcr::runtime::setInterpreterThreadSingletonToCurrent+00025985
[ 53] 0x00000000fd01e647                                  bin\win64\iqm.dll+00583239 iqm::UserEvalPlugin::pre+00030695
[ 54] 0x00000000fd02af8c                                  bin\win64\iqm.dll+00634764 iqm::UserEvalPlugin::pre+00082220
[ 55] 0x00000000fd018770                                  bin\win64\iqm.dll+00558960 iqm::UserEvalPlugin::pre+00006416
[ 56] 0x00000000fd02de9a                                  bin\win64\iqm.dll+00646810 iqm::UserEvalPlugin::pre+00094266
[ 57] 0x00000000fcffad17                                  bin\win64\iqm.dll+00437527 iqm::PackagedTaskPlugin::PackagedTaskPlugin+00000727
[ 58] 0x00000000fcffb36f                                  bin\win64\iqm.dll+00439151 iqm::PackagedTaskPlugin::execute+00000575
[ 59] 0x00000000fcffad89                                  bin\win64\iqm.dll+00437641 iqm::PackagedTaskPlugin::PackagedTaskPlugin+00000841
[ 60] 0x00000000fcffb1e4                                  bin\win64\iqm.dll+00438756 iqm::PackagedTaskPlugin::execute+00000180
[ 61] 0x00000000fcfd111a                                  bin\win64\iqm.dll+00266522 iqm::Iqm::setupIqmFcnPtrs+00072250
[ 62] 0x00000000fcfd0ff3                                  bin\win64\iqm.dll+00266227 iqm::Iqm::setupIqmFcnPtrs+00071955
[ 63] 0x00000000fcfb7b95                                  bin\win64\iqm.dll+00162709 iqm::Iqm::deliver+00003349
[ 64] 0x00000000fcfb8815                                  bin\win64\iqm.dll+00165909 iqm::Iqm::deliver+00006549
[ 65] 0x0000000004786383                        bin\win64\libmwservices.dll+01074051 services::system_events::PpeDispatchHook::dispatchOne+00019811
[ 66] 0x000000000478abe3                        bin\win64\libmwservices.dll+01092579 sysq::addProcessPendingEventsUnitTestHook+00002099
[ 67] 0x000000000478add0                        bin\win64\libmwservices.dll+01093072 sysq::addProcessPendingEventsUnitTestHook+00002592
[ 68] 0x000000000478c095                        bin\win64\libmwservices.dll+01097877 sysq::getCondition+00003269
[ 69] 0x000000000478cf8f                        bin\win64\libmwservices.dll+01101711 svWS_ProcessPendingEvents+00000287
[ 70] 0x000000000d70795e                                  bin\win64\mcr.dll+00227678 mcr::runtime::setInterpreterThreadSingletonToCurrent+00028766
[ 71] 0x000000000d708046                                  bin\win64\mcr.dll+00229446 mcr::runtime::setInterpreterThreadSingletonToCurrent+00030534
[ 72] 0x000000000d6fe832                                  bin\win64\mcr.dll+00190514 mcr_process_events+00010210
[ 73] 0x000000000d700782                                  bin\win64\mcr.dll+00198530 mcr_process_events+00018226
[ 74] 0x000000000820c21e                             bin\win64\MVMLocal.dll+00246302 mvm_server::inproc::LocalFactory::terminate+00073982
[ 75] 0x00000000fa95a3d9                                  bin\win64\mvm.dll+01221593 mvm::detail::initLocalMvmHack+00000521
[ 76] 0x00000000fa95ab25                                  bin\win64\mvm.dll+01223461 mvm::detail::SessionImpl::privateSession+00000533
[ 77] 0x00000000fa95ad31                                  bin\win64\mvm.dll+01223985 mvm::detail::SessionImpl::privateSession+00001057
[ 78] 0x0000000140006fd5                               bin\win64\MATLAB.exe+00028629
[ 79] 0x0000000140007661                               bin\win64\MATLAB.exe+00030305
[ 80] 0x0000000076d159cd                   C:\Windows\system32\kernel32.dll+00088525 BaseThreadInitThunk+00000013
[ 81] 0x0000000076f7383d                      C:\Windows\SYSTEM32\ntdll.dll+00342077 RtlUserThreadStart+00000029

Versions

C:\Windows\system32>ipython --version
6.3.1
C:\Windows\system32>python --version
Python 3.5.5 :: Anaconda custom (64-bit)
C:\Windows\system32>conda --version
conda 4.5.1
C:\Windows\system32>pip show transplant
Name: Transplant
Version: 0.8.5
Summary: Call Matlab from Python (requires Matlab)
Home-page: https://github.com/bastibe/transplant
Author: Bastian Bechtold
Author-email: [email protected]
License: BSD 3-clause License
Location: c:\programdata\anaconda3\lib\site-packages
Requires: numpy, pyzmq, msgpack-python
C:\Windows\system32>conda list zeromq
# packages in environment at C:\ProgramData\Anaconda3:
#
# Name                    Version                   Build  Channel
zeromq                    4.2.3                hd6b2f15_3
>> mex -setup
MEX configured to use 'MinGW64 Compiler (C)' for C language compilation.
>> cc.Details

  CompilerConfigurationDetails with properties:

         CompilerExecutable: 'C:\ProgramData\MATLAB\SupportPackages\R2017a\3P.instrset\mingw_492.instrset\bin\g++'
              CompilerFlags: '-fexceptions -fno-omit-frame-pointer -std=c++11'
          OptimizationFlags: '-O -DNDEBUG'
                 DebugFlags: '-g'
           LinkerExecutable: 'C:\ProgramData\MATLAB\SupportPackages\R2017a\3P.instrset\mingw_492.instrset\bin\g++'
                LinkerFlags: '-m64 -Wl,--no-undefined -shared'
    LinkerOptimizationFlags: '-s'
           LinkerDebugFlags: '-g'
                     SetEnv: 'set COMPILER=C:\ProgramData\MATLAB\SupportPackages\R2017a\3P.instrset\mingw_492.instrset\bin\g++↵                set CCOMPILER=C:\ProgramData\MATLAB\SupportPackages\R2017a\3P.instrset\mingw_492.instrset\bin\gcc↵                set COMPFLAGS=-c -fexceptions -fno-omit-frame-pointer -std=c++11 -DTARGET_API_VERSION=700   -m64 -DMATLAB_MEX_FILE  -DMATLAB_MEX_FILE ↵                set CCOMPFLAGS=-c -fexceptions -fno-omit-frame-pointer -DTARGET_API_VERSION=700   -m64 -DMATLAB_MEX_FILE  -DMATLAB_MEX_FILE ↵                set OPTIMFLAGS=-O -DNDEBUG↵                set DEBUGFLAGS=-g↵                set LINKER=C:\ProgramData\MATLAB\SupportPackages\R2017a\3P.instrset\mingw_492.instrset\bin\g++↵                set CLINKER=C:\ProgramData\MATLAB\SupportPackages\R2017a\3P.instrset\mingw_492.instrset\bin\gcc↵                set LINKFLAGS=-m64 -Wl,--no-undefined -shared -L"C:\Program Files\MATLAB\R2017a\extern\lib\win64\mingw64" -llibmx -llibmex -llibmat -lm -llibmwlapack -llibmwblas -Wl,"C:\Program Files\MATLAB\R2017a/extern/lib/win64/mingw64/mexFunction.def"↵                set LINKDEBUGFLAGS=-g↵                set NAME_OUTPUT= -o "%OUTDIR%%MEX_NAME%%MEX_EXT%"↵set PATH=C:\ProgramData\MATLAB\SupportPackages\R2017a\3P.instrset\mingw_492.instrset\bin;C:\Program Files\MATLAB\R2017a\extern\include\win64;C:\Program Files\MATLAB\R2017a\extern\include;C:\Program Files\MATLAB\R2017a\simulink\include;C:\Program Files\MATLAB\R2017a\lib\win64;%MATLAB_BIN%;%PATH%↵set INCLUDE=C:\ProgramData\MATLAB\SupportPackages\R2017a\3P.instrset\mingw_492.instrset\include;%INCLUDE%↵set LIB=C:\ProgramData\MATLAB\SupportPackages\R2017a\3P.instrset\mingw_492.instrset\lib;;%LIB%↵set LIBPATH=C:\Program Files\MATLAB\R2017a\extern\lib\win64;%LIBPATH%↵'
           CommandLineShell: 'set MINGW_ROOT_PATH=C:\ProgramData\MATLAB\SupportPackages\R2017a\3P.instrset\mingw_492.instrset'
        CommandLineShellArg: ''

Quitting Matlab connection

At present the .close method closes the connection to Matlab. The problem is that this hides the Matlab command with the same name that closes figures (although the alternative matlab.delete(handle) can be still used of course). Also this allows to call matlab.quit() and matlab.exit(), which hangs transplant (probably by closing Matlab but without Transplant registering it). Would it be possible to change the Transplant .close method name to exit() and use quit() as alias? I understand this would break compatibility with older versions though.

Function handles

Dear Bastian,

Is there a way of using function handles in function arguments?

For example in matlab syntax:
result = gateway_func('func',@func,'vars',xx,'additional',yy);
I've tried:
result = matlab. gateway_func('func',matlab.str2func('func'),'vars',xx,'additional',yy)
Without success as the matlab_function object cannot be transferred.

Any help or suggestions would be great.

Simon

Nargout for class methods

08478bb: This fails when a class method name is identical to a function on the MATLAB search path. For example calling the method myclass.plot(), nargout will return the number of arguments of the MATLAB built-in plot function. That's why I added a bit more checking:

try
    [~, funType] = which(msg('name'));
    funType = strsplit(funType,' ');
    if numel(funType)==2 && strcmp(funType{2},'method')
        argTemp = msg('args');
        className = funType{1};
        if ~isempty(argTemp) && isa(argTemp{1},className)
            % the function name corresponds to the
            % class of the first argument
            resultsize = nargout(msg('name'));
        end
    end

    if isempty(resultsize)
        resultsize = nargout(fun);
    end
catch
    resultsize = -1;
end

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.