Michael Forbes avatar Michael Forbes committed d469bb6

Prototype for asynchronous plotting with separate processes using sockets
Still Needs:
- socket buffer overflow (recv)
- cleanup thread and socket command line termination
- error handling. ex. when a client disconnects then server listen continues, network errors
- hard coded ports - put args.
- multiple clients (plotting)

Comments (0)

Files changed (5)

 README.html
+
+syntax: glob
+*.pyc

asyncplot/__init__.py

+__all__ = ['Plot', 'Client', 'Server']
+
+from threading_server import Plot, Client, Server

asyncplot/example1.py

+r"""Example computation server."""
+import time
+
+import numpy as np
+from matplotlib import pyplot as plt
+
+import threading_server
+
+
+class Plot(threading_server.Plot):
+    def draw(self, x, y):
+        plt.ioff()
+        plt.clf()
+        plt.plot(x, y)
+        print y
+        plt.ion()
+        plt.draw()
+        time.sleep(0.5)     # Pretend this is slow
+
+
+def run_server():
+    # Create a plot instance.  This should launch the plot process, and pop up
+    # the initial plot window.
+    s = threading_server.Server()
+    s.start()
+
+    raw_input("Position plot window, and press enter to run...")
+
+    # Start the computation
+    x = np.linspace(0, 2*np.pi, 10)
+    dt = 0.001
+    t = 0
+    for n in xrange(10000000):
+        if n % 100000 == 0:
+            print n
+        t += dt
+        y = np.sin(x - t)
+        s.update(x=x, y=y)
+
+
+def run_client():
+    #create the Client instance and pass the Plot object, then call run().
+    c = threading_server.Client(Plot=Plot)
+    c.run()
+
+if __name__ == "__main__":
+    run()

asyncplot/thread.py

 from Queue import Queue, Empty, Full
 import warnings
 
-#from multiprocessing import Process as Thread
-#from multiprocessing import Queue, Event
+from multiprocessing import Process as Thread
+from multiprocessing import Queue, Event
 
 from IPython import embed
 
-from matplotlib import pyplot as plt
-
 
 class PylabPlot(Thread):
     def __init__(self, timeout=60, block=False, maxsize=1, _debug=False):
         maxsize : int
            Maximum number of items to cache in the queue.
         """
+        from matplotlib import pyplot as plt
+        self.plt = plt
         self._debug = _debug
         if self._debug:
             print "Initializing thread"
                 self.update_no_wait(*v, **kw)
         
     def run(self):
+        self.plt.clf()
         self.running = True
         if self._debug:
             print "Starting thread"
 
     class Plot(PylabPlot):
         def draw(self, x, y):
-            plt.ioff()
-            plt.clf()
-            plt.plot(x, y)
+            self.plt.ioff()
+            self.plt.clf()
+            self.plt.plot(x, y)
             print y
-            plt.ion()
-            plt.draw()
-            mdb()
+            self.plt.ion()
+            self.plt.draw()
             time.sleep(0.5)     # Pretend this is slow
+
+    mdb()
+    p = Plot(block=True, _debug=True)
     
-    plt.clf()
-    tmp = raw_input("Position plot window, and press enter to run...")
+    raw_input("Position plot window, and press enter to run...")
     x = np.linspace(0, 2*np.pi, 10)
     dt = 0.001
     t = 0
-    p = Plot(block=True, _debug=True)
     for n in xrange(100000):
         t += dt
         y = np.sin(x - t)

asyncplot/threading_server.py

+r"""Server that uses threading."""
+
+__all__ = ['Plot', 'Client', 'Server']
+
+import time
+from threading import Thread
+import socket
+import cPickle
+
+
+class Plot(object):
+    def __init__(self):
+        from matplotlib import pyplot as plt
+        self.plt = plt
+
+    def draw(self, *v, **kw):
+        r"""Overload this to effect the actual drawing.  All arguments must be
+        pickelable.  This will be called on the client"""
+        raise NotImplementedError
+    
+    def update(self, *v, **kw):
+        r"""Call this with the same arguments required by the overloaded draw
+        method.  This will be called on the server."""
+        raise NotImplementedError
+
+
+class Server(Plot, Thread):
+    def __init__(self, host='', port=9999):
+        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        self.sock.bind((host, port))
+        print "Server listening on port %i" % (port, )
+        self.args = None
+
+        Thread.__init__(self)
+        Plot.__init__(self)
+
+    def run(self):
+        print "Waiting for connection..."
+        self.sock.listen(1)
+        conn, addr = self.sock.accept()
+        print "Connected by %s" % (str(addr), )
+
+        while True:
+            data = conn.recv(1024)
+            print "Got request %s" % (data, )
+            if data.startswith('get'):
+                while self.args is None:
+                    # wait for data... should use an Event
+                    time.sleep(0.1)
+                conn.sendall(cPickle.dumps(self.args))
+                self.args = None
+                print "Send plot data"
+            elif not data or data.startswith("quit"):
+                break
+
+        conn.close()
+        print "Done"
+
+    def update(self, *v, **kw):
+        self.args = (v, kw)
+        
+
+class Client(object):
+    def __init__(self, Plot, host='localhost', port=9999):
+        self.host = host
+        self.port = port
+        self.plot = Plot()
+        self.plot.plt.clf()
+
+    def run(self):
+        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        print "Trying to connect to port %i..." % (self.port,)
+        sock.connect((self.host, self.port))
+        print "Connected to port %i." % (self.port,)
+        while True:
+            sock.send('get')
+            data = sock.recv(4096)
+            v, kw = cPickle.loads(data)
+            self.plot.draw(*v, **kw)
+
+
+if __name__ == '__main__':
+    s = Server()
+    s.start()
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.