~wecacuee/mrol/mrol-dev

« back to all changes in this revision

Viewing changes to mrol_mapping/visualiser/mayaviclient.py

  • Committer: Vikas Dhiman
  • Date: 2012-11-20 22:12:16 UTC
  • mfrom: (0.5.3 mrol)
  • Revision ID: vikasdhi@buffalo.edu-20121120221216-nunda3pv0n8jsf4e
MergingĀ lp:~wecacuee/mrol/mrol-devĀ 

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
"""
2
 
Launch a mayavi server and execute plotting methods on the server by passing
3
 
data over the network
4
 
 
5
 
Usage:
6
 
    t = np.linspace(0, 2*np.pi, 50)
7
 
    u = np.cos(t) * np.pi
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')
11
 
    mlabproxy.clf()
12
 
    mlabproxy.plot3d(x, y, z, z)
13
 
"""
14
 
import subprocess
15
 
import socket
16
 
import signal
17
 
import sys
18
 
import tempfile
19
 
import numpy as np
20
 
import cPickle
21
 
import cStringIO
22
 
import base64
23
 
import os
24
 
import errno
25
 
import time
26
 
 
27
 
HOST = 'localhost' # changing this won't suffice
28
 
PORT = 8007
29
 
devnull = open(os.devnull, 'wb')
30
 
 
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,
37
 
                            stdout=log_stdout,
38
 
                            stderr=log_stderr)
39
 
 
40
 
 
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
44
 
        try:
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:
49
 
                raise
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")
54
 
            time.sleep(4)
55
 
 
56
 
        # keep trying 
57
 
        for i in range(5):
58
 
            try:
59
 
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
60
 
                sock.connect((HOST, PORT))
61
 
                break
62
 
            except socket.error, e:
63
 
                if e.errno != errno.ECONNREFUSED:
64
 
                    raise
65
 
                # Wait for server to start
66
 
                print("Waiting for server")
67
 
                time.sleep(2)
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""")
75
 
        self.sock = sock
76
 
        self.sockfile = sockfile
77
 
        self.tempfiles = []
78
 
        self.returnnumber = 0
79
 
 
80
 
    def pass_numpy_args(self, *args):
81
 
        """
82
 
        Pass numpy arrays by using numpy.ndarray.tostring() instead of
83
 
        cPickle.
84
 
        """
85
 
        nargs = len(args)
86
 
        names = ['a%d' % i for i in range(nargs)]
87
 
        tf = tempfile.NamedTemporaryFile(delete=False)
88
 
        np.savez(tf, **dict(zip(names, args)))
89
 
        tf.close()
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))
94
 
        return names
95
 
 
96
 
    def pass_args(self, *args, **kwargs):
97
 
        """
98
 
        Pass arbitrary Python arguments and kwargs by using cPickle and base64
99
 
        encoding.
100
 
        """
101
 
        tf = tempfile.NamedTemporaryFile(delete=False)
102
 
        cPickle.dump(dict(args=args, kwargs=kwargs), tf)
103
 
        tf.close()
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)
109
 
 
110
 
    def _set_args(self, *args, **kwargs):
111
 
        if 'numpyargs' in kwargs:
112
 
            numpyargs = kwargs['numpyargs']
113
 
            del kwargs['numpyargs']
114
 
        else:
115
 
            numpyargs = 0
116
 
        if 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
121
 
 
122
 
    def exec_func(self, funcname, *args, **kwargs):
123
 
        numpynames = 0
124
 
        if 'numpyargs' in kwargs:
125
 
            numpyargs = kwargs['numpyargs']
126
 
            del kwargs['numpyargs']
127
 
        else:
128
 
            numpyargs = 0
129
 
 
130
 
        self.pass_args(*args, **kwargs)
131
 
        if numpynames:
132
 
            self.sock.send(
133
 
                """ret{rn} = mlab.{func}({numpyargs}, *args,**kwargs)\n""".format(
134
 
                    rn=self.returnnumber, func=funcname, numpyargs=(', '.join(numpynames))))
135
 
        else:
136
 
            self.sock.send(
137
 
                """ret{rn} = mlab.{func}(*args,**kwargs)\n""".format(
138
 
                    rn=self.returnnumber, func=funcname))
139
 
 
140
 
    def getreturnvar(self):
141
 
        r = self.returnnumber
142
 
        self.returnnumber += 1
143
 
        return "ret{rn}".format(rn=r)
144
 
 
145
 
    def ex(self, statement, *args, **kwargs):
146
 
        """
147
 
        Execute the given statement assuming the args are
148
 
        """
149
 
        self._set_args(*args, **kwargs)
150
 
        self.sock.send(statement + "\n")
151
 
 
152
 
    def points3d(self, x, y, z, t, **kwargs):
153
 
        self.exec_func("points3d", x, y, z, t, numpyargs=4, **kwargs)
154
 
 
155
 
    def __getattr__(self, name):
156
 
        def func(*args, **kwargs):
157
 
            self.exec_func(name, *args, **kwargs)
158
 
        return func
159
 
 
160
 
    def close(self, client_only=False):
161
 
        self.sock.shutdown(socket.SHUT_WR)
162
 
        self.sock.close()
163
 
        for tf in self.tempfiles:
164
 
            os.remove(tf)
165
 
        if not client_only:
166
 
            self.subprocess.kill()
167
 
            os.wait()