matplotlib, GTK and Threads

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-1

Jon 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 suggest

looking 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-class

I 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 math

import sys
import os

import pygtk

if sys.platform == ‘win32’:
os.environ[‘PATH’] += ‘;lib;’

else:
pygtk.require(‘2.0’)
import gtk

import 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 Subplot

from 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

()