2
Launch a mayavi server and execute plotting methods on the server by passing
6
t = np.linspace(0, 2*np.pi, 50)
8
x, y, z = np.sin(u), np.cos(u), np.sin(t)
9
mlabproxy = RemoteMlab()
10
mlabproxy.points3d(x, y, z, z, scale_mode='none')
12
mlabproxy.plot3d(x, y, z, z)
27
HOST = 'localhost' # changing this won't suffice
29
devnull = open(os.devnull, 'wb')
31
def launch_server(port, log_stdout, log_stderr):
32
dir = os.path.dirname(__file__)
33
serverscript = os.path.join(dir, "mayaviserver.py")
34
cmd = ['python', serverscript, str(port)]
35
print("Launching " + " ".join(cmd))
36
return subprocess.Popen(cmd,
41
class RemoteMlab(object):
42
def __init__(self, port=PORT, log_stdout=sys.stdout, log_stderr=sys.stderr):
43
# Don't launch the server if already running
45
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
46
sock.connect((HOST, PORT))
47
except socket.error, e:
48
if e.errno != errno.ECONNREFUSED:
50
# server not running, let's launch
51
self.subprocess = launch_server(port, log_stdout, log_stderr)
52
# Wait for server to start
53
print("Waiting for server")
59
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
60
sock.connect((HOST, PORT))
62
except socket.error, e:
63
if e.errno != errno.ECONNREFUSED:
65
# Wait for server to start
66
print("Waiting for server")
68
sockfile = sock.makefile()
69
sock.send("""import numpy as np\n""")
70
sock.send("""import cPickle\n""")
71
sock.send("""import base64\n""")
72
sock.send("""import cStringIO\n""")
73
sock.send("""args = []\n""")
74
sock.send("""kwargs = {}\n""")
76
self.sockfile = sockfile
80
def pass_numpy_args(self, *args):
82
Pass numpy arrays by using numpy.ndarray.tostring() instead of
86
names = ['a%d' % i for i in range(nargs)]
87
tf = tempfile.NamedTemporaryFile(delete=False)
88
np.savez(tf, **dict(zip(names, args)))
90
self.sock.send("""tf = open('{0}', 'rb')\n""".format(tf.name))
91
self.sock.send("""arguments = np.load(tf)\n""")
92
for n, a in zip(names, args):
93
self.sock.send("""{n} = arguments['{n}']\n""".format(n=n))
96
def pass_args(self, *args, **kwargs):
98
Pass arbitrary Python arguments and kwargs by using cPickle and base64
101
tf = tempfile.NamedTemporaryFile(delete=False)
102
cPickle.dump(dict(args=args, kwargs=kwargs), tf)
104
self.sock.send("""tf = open('{0}', 'rb')\n""".format(tf.name))
105
self.sock.send("""arguments = cPickle.load(tf)\n""")
106
self.sock.send("""args = arguments['args']\n""")
107
self.sock.send("""kwargs = arguments['kwargs']\n""")
108
self.tempfiles.append(tf.name)
110
def _set_args(self, *args, **kwargs):
111
if 'numpyargs' in kwargs:
112
numpyargs = kwargs['numpyargs']
113
del kwargs['numpyargs']
117
numpynames = self.pass_numpy_args(*args[:numpyargs])
118
nonnumpyargs = args[numpyargs:]
119
self.pass_args(*nonnumpyargs, **kwargs)
120
return numpynames if (numpyargs) else None
122
def exec_func(self, funcname, *args, **kwargs):
124
if 'numpyargs' in kwargs:
125
numpyargs = kwargs['numpyargs']
126
del kwargs['numpyargs']
130
self.pass_args(*args, **kwargs)
133
"""ret{rn} = mlab.{func}({numpyargs}, *args,**kwargs)\n""".format(
134
rn=self.returnnumber, func=funcname, numpyargs=(', '.join(numpynames))))
137
"""ret{rn} = mlab.{func}(*args,**kwargs)\n""".format(
138
rn=self.returnnumber, func=funcname))
140
def getreturnvar(self):
141
r = self.returnnumber
142
self.returnnumber += 1
143
return "ret{rn}".format(rn=r)
145
def ex(self, statement, *args, **kwargs):
147
Execute the given statement assuming the args are
149
self._set_args(*args, **kwargs)
150
self.sock.send(statement + "\n")
152
def points3d(self, x, y, z, t, **kwargs):
153
self.exec_func("points3d", x, y, z, t, numpyargs=4, **kwargs)
155
def __getattr__(self, name):
156
def func(*args, **kwargs):
157
self.exec_func(name, *args, **kwargs)
160
def close(self, client_only=False):
161
self.sock.shutdown(socket.SHUT_WR)
163
for tf in self.tempfiles:
166
self.subprocess.kill()