plot not updating in snow leopard

Hello,

I am trying to do some simple calculations in a loop, and draw a plot periodically within the loop, and the drawing is not updating. I'm using the Enthought Python Distribution which is using Matplotlib 0.99.3 with python 2.6.5 on Snow Leopard, OSX 10.6.4, and am running it in ipython with the -pylab flag (and I've tried with the -wthread flag too). A sample piece of code below. It is actually drawing, because when I control-C to stop, it shows the plot.

from pylab import *
from numpy import *
import sys

def dot():
    sys.stdout.write('.')
    sys.stdout.flush()
    
def busy_loop():

    for i in range(1000):
        r=rand(100,100)
        
    return r
    
for t in range(1000):

    r=busy_loop()
    
    clf()
    imshow(r,interpolation='nearest',cmap=cm.gray)
    draw()
    show()
    
    dot()
    
and I've set in my matplotlibrc - backend : TkAgg, but it doesn't work with WxAgg either.

Am I missing something? Is this an idiom that needs to be avoided/replaced?

Any help would be great!

    thanks,

      Brian Blais

···

--
Brian Blais
bblais@...1129...
http://web.bryant.edu/~bblais
http://bblais.blogspot.com/

Hello,

I am trying to do some simple calculations in a loop, and draw a plot periodically within the loop, and the drawing is not updating. I’m using the Enthought Python Distribution which is using Matplotlib 0.99.3 with python 2.6.5 on Snow Leopard, OSX 10.6.4, and am running it in ipython with the -pylab flag (and I’ve tried with the -wthread flag too). A sample piece of code below. It is actually drawing, because when I control-C to stop, it shows the plot.

from pylab import *

from numpy import *

import sys

def dot():

sys.stdout.write('.')

sys.stdout.flush()

def busy_loop():

for i in range(1000):

    r=rand(100,100)



return r

for t in range(1000):

r=busy_loop()



clf()

imshow(r,interpolation='nearest',cmap=cm.gray)

draw()

show()



dot()

and I’ve set in my matplotlibrc - backend : TkAgg, but it doesn’t work with WxAgg either.

Am I missing something? Is this an idiom that needs to be avoided/replaced?

Any help would be great!

            thanks,



                    Brian Blais

Brian,

First, I would suggest using time.sleep() to do your busy loop:

import time
time.sleep(0.1)

to sleep for a tenth of a second.

Second, you have the show() function within the loop. Call the show() function only once (in interactive mode), and draw() can be used to update the graph. Also note that some plotting functions return objects that have a function like “update_data” that would allow you to modify the plot without having to call clf().

Some of these examples in the given link might be overkill for your needs:

http://matplotlib.sourceforge.net/examples/animation/index.html

but they may be useful to better understand how animations can be done. Also note that the next release of matplotlib will include a much easier to use module to create animations (of course, if you are daring, you could install the latest matplotlib from source).

I hope this helps!
Ben Root

···

On Mon, Sep 20, 2010 at 5:12 PM, Brian Blais <bblais@…1129…> wrote:

I am trying to do some simple calculations in a loop, and draw a plot periodically within the loop, and the drawing is not updating. I'm using the Enthought Python Distribution which is using Matplotlib 0.99.3 with python 2.6.5 on Snow Leopard, OSX 10.6.4, and am running it in ipython with the -pylab flag (and I've tried with the -wthread flag too). A sample piece of code below. It is actually drawing, because when I control-C to stop, it shows the plot.

from pylab import *
from numpy import *
import sys

def dot():
   sys.stdout.write('.')
   sys.stdout.flush()

def busy_loop():

   for i in range(1000):
       r=rand(100,100)

   return r

for t in range(1000):

   r=busy_loop()

   clf()
   imshow(r,interpolation='nearest',cmap=cm.gray)
   draw()
   show()

   dot()

First, I would suggest using time.sleep() to do your busy loop:

>>> import time
>>> time.sleep(0.1)

I tried that before (even upping to 1 second)...no dice.

Second, you have the show() function within the loop. Call the show() function only once (in interactive mode), and draw() can be used to update the graph.

also done...no effect.

Also note that some plotting functions return objects that have a function like "update_data" that would allow you to modify the plot without having to call clf().

sure, but that take more effort, and I don't really care about a slow down, because most of my time is spent in the busy loop. I do care about it displaying *at all*, which is the problem. I am familiar with the efficient way of animating, but for most things I want to focus on the computation and then display here and there, so I want the shortest, clearest plotting code without any optimizations. if I call plot commands, and then a draw, I expect it to actually pause right there until it is done drawing, and then continue...it's not doing that.

another wrinkle: If I run ipython -pylab, and then run my script like:

run do_my_script

I get no plot showing (an empty figure window shows, with a busy process "rainbow spiral). Now, I control-C and the plots come up and my script stops. I then type again:

run do_my_script

it works! once the figure is drawn once, it seems to work just fine. the *first* time it doesn't display, and requires a control-C. weird!

can anyone reproduce this?

      bb

···

On Sep 20, 2010, at 7:43 PM, Benjamin Root wrote:

On Mon, Sep 20, 2010 at 5:12 PM, Brian Blais <bblais@...1129...> wrote:

--
Brian Blais
bblais@...1129...
http://web.bryant.edu/~bblais
http://bblais.blogspot.com/

I am trying to do some simple calculations in a loop, and draw a plot periodically within the loop, and the drawing is not updating. I’m using the Enthought Python Distribution which is using Matplotlib 0.99.3 with python 2.6.5 on Snow Leopard, OSX 10.6.4, and am running it in ipython with the -pylab flag (and I’ve tried with the -wthread flag too). A sample piece of code below. It is actually drawing, because when I control-C to stop, it shows the plot.

from pylab import *

from numpy import *

import sys

def dot():

sys.stdout.write(’.’)

sys.stdout.flush()

def busy_loop():

for i in range(1000):

   r=rand(100,100)

return r

for t in range(1000):

r=busy_loop()

clf()

imshow(r,interpolation=‘nearest’,cmap=cm.gray)

draw()

show()

dot()

First, I would suggest using time.sleep() to do your busy loop:

import time

time.sleep(0.1)

I tried that before (even upping to 1 second)…no dice.

When you say ‘no dice’, do you mean that it didn’t pause execution at all, or that it didn’t solve your problem? Note that I wasn’t implying that it would solve your problem, only that it was probably a cleaner way to write code and it gives you explicit control over how long to wait regardless of which computer you are on.

Second, you have the show() function within the loop. Call the show() function only once (in interactive mode), and draw() can be used to update the graph.

also done…no effect.

Well, in any case, you should only have a single show() call for this use case. draw() is used by show() to actually perform the rendering. Whatever issue you are having, it isn’t from you calling show() only once.

Also note that some plotting functions return objects that have a function like “update_data” that would allow you to modify the plot without having to call clf().

sure, but that take more effort, and I don’t really care about a slow down, because most of my time is spent in the busy loop. I do care about it displaying at all, which is the problem. I am familiar with the efficient way of animating, but for most things I want to focus on the computation and then display here and there, so I want the shortest, clearest plotting code without any optimizations. if I call plot commands, and then a draw, I expect it to actually pause right there until it is done drawing, and then continue…it’s not doing that.

And that’s the way it is supposed to work.

another wrinkle: If I run ipython -pylab, and then run my script like:

run do_my_script

I get no plot showing (an empty figure window shows, with a busy process "rainbow spiral). Now, I control-C and the plots come up and my script stops. I then type again:

run do_my_script

it works! once the figure is drawn once, it seems to work just fine. the first time it doesn’t display, and requires a control-C. weird!

can anyone reproduce this?

                    bb

This might be an issue with the somewhat older version of matplotlib that is with EPD. I know there have been some significant fixes with the interactivity of plots. But I haven’t seen this much of an issue.

Give this a shot… run ipython -pylab and create some figure by hand, call .show(), and then do something else to the plot. No calls to draw() and only one initial call to show() to get the figure window up, I am just curious if the figure updates itself on its own.

Ben Root

···

On Mon, Sep 20, 2010 at 8:14 PM, Brian Blais <bblais@…1129…> wrote:

On Sep 20, 2010, at 7:43 PM, Benjamin Root wrote:

On Mon, Sep 20, 2010 at 5:12 PM, Brian Blais <bblais@…1129…> wrote:

It might be more effort, but what you're doing now plays havoc with
GUI event loops. Now, granted, until EPD upgrades to Matplotlib 1.0.0
this won't work for you (unless you're willing to install your own),
but this is how IMHO is best to approach this problem:

import matplotlib.pyplot as plt
import numpy as np
import sys

def dot():
   sys.stdout.write('.')
   sys.stdout.flush()

def busy_loop():
   for i in range(1000):
       r = np.random.rand(100,100)
   return r

def update_plot():
    update_plot.count += 1
    r = busy_loop()
    plt.clf()
    plt.imshow(r, interpolation='nearest', cmap=plt.get_cmap('gray'))
    plt.draw()
    dot()
    # Automatically stops after 10
    return update_plot.count < 10
update_plot.count = 0

fig = plt.figure()
# Creates a new timer that fires every 250 ms
timer = fig.canvas.new_timer(interval=250)
timer.add_callback(update_plot)
timer.start()
plt.show()

This, to me, isn't any more complex than your original (the most
complex part comes from getting it to stop after a fixed number of
iterations). The benefit is that the timed updates integrate into the
GUI event loop and don't fight it. The other benefit is that this
works with any of the interactive backends and you don't end up
debugging weird draw problems. Even when I've gotten your style of
animation to work in the past, I've still had problems where resizing
the figure, etc. don't work.

Hope this helps (at least in the future),

Ryan

···

On Mon, Sep 20, 2010 at 8:14 PM, Brian Blais <bblais@...1129...> wrote:

sure, but that take more effort, and I don't really care about a slow down, because most of my time is spent in the busy loop. I do
care about it displaying *at all*, which is the problem. I am familiar with the efficient way of animating, but for most things I want to
focus on the computation and then display here and there, so I want the shortest, clearest plotting code without any optimizations. if I
call plot commands, and then a draw, I expect it to actually pause right there until it is done drawing, and then continue...it's not doing
that.

--
Ryan May
Graduate Research Assistant
School of Meteorology
University of Oklahoma

sure, but that take more effort, and I don't really care about a slow down, because most of my time is spent in the busy loop.

It might be more effort, but what you're doing now plays havoc with
GUI event loops. Now, granted, until EPD upgrades to Matplotlib 1.0.0
this won't work for you (unless you're willing to install your own),
but this is how IMHO is best to approach this problem:

...

def busy_loop():
  for i in range(1000):
      r = np.random.rand(100,100)
  return r

def update_plot():
   update_plot.count += 1
   r = busy_loop()
   plt.clf()
   plt.imshow(r, interpolation='nearest', cmap=plt.get_cmap('gray'))
   plt.draw()
   dot()
   # Automatically stops after 10
   return update_plot.count < 10
update_plot.count = 0

fig = plt.figure()
# Creates a new timer that fires every 250 ms
timer = fig.canvas.new_timer(interval=250)
timer.add_callback(update_plot)
timer.start()
plt.show()

This, to me, isn't any more complex than your original (the most
complex part comes from getting it to stop after a fixed number of
iterations).

actually, I think the workflow that I use doesn't lend itself well to this. usually what I do is write code in the local space, in a if __name__=="__main__" block, so that after things run I can easily inspect variables, test the results, rerun, etc... It's only after things work that I box it into a nice function that can be called with an event callback. this is one of the reasons I use python, so that I can easily interact with my data.

why does the way I wrote things play havoc with GUI event loops? it shouldn't care, or at worst the GUI parts of the window (menus, buttons) should be unresponsive when the plots are drawn but the plots should at least be drawn!

The benefit is that the timed updates integrate into the
GUI event loop and don't fight it. The other benefit is that this
works with any of the interactive backends and you don't end up
debugging weird draw problems. Even when I've gotten your style of
animation to work in the past, I've still had problems where resizing
the figure, etc. don't work.

perhaps I can write things this way, and have the function inject into locals(), just to make it easier to debug the results, but that seems to me to be a bit of a hack. I'm not really interested in an animation, as much as easily visualizing my data every so often.

when people come from using matlab, and then hit odd draw problems like this, it is disconcerting.

      bb

···

On Sep 20, 2010, at 9:58 PM, Ryan May wrote:

On Mon, Sep 20, 2010 at 8:14 PM, Brian Blais <bblais@...1129...> wrote:

--
Brian Blais
bblais@...1129...
http://web.bryant.edu/~bblais
http://bblais.blogspot.com/

2010/9/21 Brian Blais <bblais@...1129...>:

actually, I think the workflow that I use doesn't lend itself well to this. usually what I do is write code in the local space, in a if __name__=="__main__" block, so that after things run I can easily inspect variables, test the results, rerun, etc... It's only after things work that I box it into a nice function that can be called with an event callback. this is one of the reasons I use python, so that I can easily interact with my data.

why does the way I wrote things play havoc with GUI event loops? it shouldn't care, or at worst the GUI parts of the window (menus, buttons) should be unresponsive when the plots are drawn but the plots should at least be drawn!

You must be with Tkinter extremely careful when having no mainloop()
call. There is no separate thread keeping the GUI mainloop poll
running when you import Tkinter (or matplotlib does). I.e., you have
two options, at least:

1) You implement your own mainloop, like calling the main widget's
.update() method repeatedly

2) You use Tkinter .after(), what I guess the Timer object will do.

What you should definitely avoid, just in case, is calling Tkinter
methods from *another* thread than those which imported Tkinter (this
is those which imported matplotlib in your case). Not adhering to
this rule will lead to unpredictable behaviour, especially on OS X (I
went through it, and it's painful). You don't do this atm, just don't
do it in future too.

The normal-users usecase of TkAgg is an interactive Python session.
For some reason I don't understand myself, it works there. Obviously
the Tkinter update poll is done when you enter the prompt or something
like that. In a script, you have no prompt, so you have no update, I
could imagine, but though, draw() should do that.

Friedrich

The benefit is that the timed updates integrate into the
GUI event loop and don't fight it. The other benefit is that this
works with any of the interactive backends and you don't end up
debugging weird draw problems. Even when I've gotten your style of
animation to work in the past, I've still had problems where resizing
the figure, etc. don't work.

perhaps I can write things this way, and have the function inject into locals(), just to make it easier to debug the results, but that seems to me to be a bit of a hack. I'm not really interested in an animation, as much as easily visualizing my data every so often.

I don't like that local() approach too, it really sounds hackish. You
can use a bound class method (i.e., a method of some instance of some
class coded by you), and this will have access to self.*. Do you like
this? The method would be the timer target.

when people come from using matlab, and then hit odd draw problems like this, it is disconcerting.

Maybe; maybe Python is just not the same as Matlab? To argument, the
graphical backend is not embedded into Python, Tkinter is a package,
although it ships with Python.

Brian, Do you, by chance, use interactive mode? Maybe ipython -pylab
(if this does)? Just a shot into the dark ...