Message: 2
Date: Mon, 04 Sep 2006 09:56:22 -0700
From: Andrew Straw <
strawman@…106…>
Subject: Re: [Matplotlib-users] matplotlib, GTK and Threads
To: Jon Roadley-Battin <jon.roadleybattin@…287…>,matplotlib-users@lists.sourceforge.net
Message-ID: <44FC5AB6.6010806@…106…>
Content-Type: text/plain; charset=ISO-8859-1Jon Roadley-Battin wrote:
The problem I have with with the non-GUI thread calling the “plot”
function.That’s your problem – you should only call the GUI code (including
matplotlib, which eventually calls GTK) from a single thread. I suggestlooking at the Queue module to pass your data to the GUI thread if it’s
not too much. If it’s more, you could use threading.Lock() to regulate
access to a giant array or something.-Andrew
I was pretty convinced that is was due to the threading since early one with GTK I had some issues with it.
I was hoping that there was some form of enable_threading method with matplotlib.The
problem that makes this hard and what forced me down the thread route
is that the thread polls the RS232 every second or so, thus it needs to
be separate (ie threaded) from the GUI, this have been done with hte
enter/leave thread statement for GTK.But now it seems that updating the Matplotlib MUST be done
from within the GUI and not initilised by another thread (be it if the
thread enabled GTK events) I must think of a way around it.The
only other option is to start a GTK timer event (did use this
originally, but they had problems with the whole asyncronous of the
RS232) that every second check’s if my plot array has been updated (via
some flag) and if it has then update plot, this way it would be within
the GUI-classI stipped the code down to its most basic instance (the window will have to be dragged wider)
is there any thread_init for matplotlib. short of having a timer within the GUI class that checks if any new data is present I cant see a way around this. It has to be done this way, the GUI doesn’t instigate things, the GUI only reports things, the thread gets the data at set intervals and then updates the GUI
···
#!/usr/bin/env python
import threading
import time
import mathimport sys
import osimport pygtk
if sys.platform == ‘win32’:
os.environ[‘PATH’] += ‘;lib;’else:
pygtk.require(‘2.0’)
import gtkimport gobject
assert gtk.pygtk_version >= (1,99,16), ‘pygtk should be >= 1.99.16’#import gtk.glade
from pylab import *
rcParams[‘numerix’] = ‘numpy’
import matplotlib
matplotlib.use
(‘GTK’)
from matplotlib.figure import Figure
from matplotlib.axes import Subplotfrom matplotlib.backends.backend_gtk import FigureCanvasGTK as FigureCanvas
TIME = range(360)
VOLT = [math.sin(math.radians(x)) for x in TIME]VOLT2 = [2]*360
VOLT3 = [x for x in range(360)]class my_thread(threading.Thread):
def init(self,GUI):
super(my_thread, self).init()self.GUI = GUI def run(self): time.sleep(10) gtk.threads_enter() try: self.GUI.Graph([TIME,VOLT3]) finally: gtk.threads_leave()
gtk.gdk.threads_init()
class GUI(object):def GUI_Plot(self,widget,event,data=None): self.Graph([TIME,VOLT2]) def delete_event(self,widget,event,data=None): return False def destroy(self,widget,data=None): gtk.main_quit() def __init__(self): super(GUI,self).__init__() self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) self.window.set_title("Matplotlib GTK test") self.window.connect("delete_event",self.delete_event) self.window.connect("destroy",self.destroy) self.window.set_border_width
(10)
self.box1 = gtk.VBox(False,0)
self.window.add(self.box1)self.button = gtk.Button("GUI Plot") self.button.connect("clicked",self.GUI_Plot,None) self.box1.pack_start(self.button,True,True,0) self.button.show() self.box1.show() self.window.show() self.Graph([TIME,VOLT]) def Graph(self,DATA): try: self.canvas.destroy
()
self.toolbar.destroy() except:pass self.figure = Figure(figsize=(6,3), dpi=100)#{{{ self.axis = self.figure.add_subplot(111) self.axis.grid(True) self.axis.set_xlabel('Time (s)')
self.axis.plot(DATA[0],DATA[1],linewidth=2.0)
self.canvas = FigureCanvas(
self.figure) # a gtk.DrawingArea
self.canvas.show()
self.graphview
= self.box1
self.graphview.pack_start(self.canvas, True, True)
def main(self): gtk.main()
if name == “main”:
A = GUI()B = my_thread(A) B.start() gtk.threads_enter() A.main() gtk.threads_leave
()