dynamic plot problem

I have been trying to get a dynamic plot using imagesc. I have copied some examples I have found. The problem is that if I make another window come in front of the matplotlib wondow the plot window freezes. If I click in the window it will tell me that it is not responding. I have tried to modify several of the examples but all end up where the plot window freeze. I attach the latest code at the end. It will not run as I am including another file I have. Any tips on what the problem is would be very helpful.

Is there any way to use the pylab interface to make dynamic plots?

Svein-Erik

import matplotlib
matplotlib.use("WXAgg")
matplotlib.interactive(True)
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
from matplotlib.figure import Figure
from matplotlib.axes import Subplot
from pyFDTD06 import *

import wx

class PlotFigure(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, -1, "Test embedded wxFigure")

        self.fig = Figure((5,4), 75)
        self.canvas = FigureCanvasWxAgg(self, -1, self.fig)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.canvas, 1, wx.TOP)

        # create start/stop buttons
        self.button_start = wx.Button(self,-1, " Start ", size=(-1,-1))
        self.button_stop = wx.Button(self,-1, " Stop ", size=(-1,-1))

        # bind actions to the buttons
        self.button_start.Bind(wx.EVT_BUTTON,self.OnStart)
        self.button_stop.Bind(wx.EVT_BUTTON, self.OnStop)

        # pack the buttons in the Sizer
        btnsizer = wx.BoxSizer(wx.HORIZONTAL)
        btnsizer.Add(self.button_start, 1, wx.LEFT)
        btnsizer.Add(self.button_stop, 1, wx.LEFT)

        sizer.Add(btnsizer, 0, wx.TOP)
        self.SetSizer(sizer)
        self.Fit()

        # initialize the data here
        self.el = FDTD()
        self.el.TIME_STEPS = 100
        self.el.initmatrix()
        a = self.fig.add_subplot(111)
        self.im = a.imshow( self.el.Ex[:,:,22], vmin=-0.002, vmax=0.002)
        
    def OnStop(self):
        pass
    
    def OnStart(self,event=None):
        for self.el.iteration in range(0, self.el.TIME_STEPS):
            self.el.currentSimulatedTime = self.el.dt*self.el.iteration
            print "#%d %E sec" %(self.el.iteration,self.el.currentSimulatedTime)
            if ( (self.el.iteration % self.el.PLOT_MODULUS) == 0):
                self.im.set_array(self.el.Ex[:,:,22])
                self.canvas.draw()
            self.el.pointsourceEx(45,20,22)
            self.el.calcHB()
            self.el.calcED()

if __name__ == "__main__":
    app = wx.PySimpleApp(0)
    frame = PlotFigure()
    frame.Show(True)
    app.MainLoop()

Svein-Erik,

I can't run your example because I don't have pyFDTF06:

from pyFDTD06 import *

But it seems you have a classic case of putting a resource
intensive loop inside a GUI (in this case, in the OnStart
method) and not allowing the GUI toolkit to respond to
other events.

As a first attempt to fix this, you probably want to add a
self.Refresh() in your loop in OnStart:

# if ( (self.el.iteration % self.el.PLOT_MODULUS) == 0):
# self.im.set_array(self.el.Ex[:,:,22])
# self.canvas.draw()
# self.Refresh() # <--- !!
# self.el.pointsource(45,20,22)

A better approach might be to replace your
   for self.el.iteration in range(0, self.el.TIME_STEPS)

loop with a timer loop.

Hope that helps,

--Matt

Matt,

Thank you for the reply.

I added in the self.Refresh() command. Then the window turns white when the programs comes to that point. I also tried to add a time.sleep(0.1) inside the for loop so that the GUI could respond to other events, but it had no effect.

Any other ideas?

Svein-Erik

···

From: Matt Newville [newville@...189...]
Sent: 2005-05-03 21:52:39 CEST
To: Svein-Erik Hamran [seh@...597...]
Cc: matplotlib-users@lists.sourceforge.net
Subject: Re: [Matplotlib-users] dynamic plot problem

Svein-Erik,

I can't run your example because I don't have pyFDTF06:
> from pyFDTD06 import *

But it seems you have a classic case of putting a resource
intensive loop inside a GUI (in this case, in the OnStart
method) and not allowing the GUI toolkit to respond to
other events.

As a first attempt to fix this, you probably want to add a
self.Refresh() in your loop in OnStart:

# if ( (self.el.iteration % self.el.PLOT_MODULUS) == 0):
# self.im.set_array(self.el.Ex[:,:,22])
# self.canvas.draw()
# self.Refresh() # <--- !!
# self.el.pointsource(45,20,22)

A better approach might be to replace your
   for self.el.iteration in range(0, self.el.TIME_STEPS)

loop with a timer loop.

Hope that helps,

--Matt

I added in the self.Refresh() command. Then the window turns
white when the programs comes to that point.

Like John said, it would be much easier to help if you could
post a simple example that we could run.

I also tried to add a time.sleep(0.1) inside the for loop so
that the GUI could respond to other events, but it had no
effect.

Inserting the time.sleep() will completely block the GUI from
responding during that time. I doubt that's what you want.

It's usually best to avoid long-running code that will blocak
GUI events inside a GUI program. Inserting something like
self.Refresh() or self.canvas.gui_repaint() may help, but won't
do anything while the loop is executing non-GUI code, such as
time.sleep(), or (I'm assuming) your self.el.calc**() methods.

I'd guess that you want to put your calculation into a different
thread and then generate a GUI event to redraw the data when
each iteration is ready.

Hope that helps,

--Matt