16

There are a lot of questions about matplotlib, pylab, pyplot, ipython, so I'm sorry if you're sick of seeing this asked. I'll try to be as specific as I can, because I've been looking through people's questions and looking at documentation for pyplot and pylab, and I still am not sure what I'm doing wrong. On with the code:

Goal: plot a figure every .5 seconds, and update the figure as soon as the plot command is called.

My attempt at coding this follows (running on ipython -pylab):


import time
ion()
x=linspace(-1,1,51)
plot(sin(x))
for i in range(10):
    plot([sin(i+j) for j in x])
    #see **
    print i
    time.sleep(1)
print 'Done'

It correctly plots each line, but not until it has exited the for loop. I have tried forcing a redraw by putting draw() where ** is, but that doesn't seem to work either. Ideally, I'd like to have it simply add each line, instead of doing a full redraw. If redrawing is required however, that's fine.

Additional attempts at solving:
just after ion(), tried adding hold(True) to no avail.
for kicks tried show() for **
The closest answer I've found to what I'm trying to do was at plotting lines without blocking execution, but show() isn't doing anything.

I apologize if this is a straightforward request, and I'm looking past something so obvious. For what it's worth, this came up while I was trying to convert matlab code from class to some python for my own use. The original matlab (initializations removed) which I have been trying to convert follows:


for i=1:time
    plot(u)
    hold on
    pause(.01)
    for j=2:n-1
        v(j)=u(j)-2*u(j-1)
    end
    v(1)= pi
    u=v
end

Any help, even if it's just "look up this_method" would be excellent, so I can at least narrow my efforts to figuring out how to use that method. If there's any more information that would be useful, let me know.

Community
  • 1
  • 1
  • 1
    [You should use `pyplot.pause` rather than `time.sleep`.](http://stackoverflow.com/questions/12822762/pylab-ion-in-python-2-matplotlib-1-1-1-and-updating-of-the-plot-while-the-pro) – Mechanical snail Jun 05 '13 at 23:36
  • I had the same problem using the QT4Agg backend on Windows, I believe it is related to this [github issue](https://github.com/matplotlib/matplotlib/issues/1646), using pyplot.pause() fixed it. – seumas Aug 12 '13 at 11:13

4 Answers4

10
from pylab import *
import time
ion()
tstart = time.time()               # for profiling
x = arange(0,2*pi,0.01)            # x-array
line, = plot(x,sin(x))
for i in arange(1,200):
    line.set_ydata(sin(x+i/10.0))  # update the data
    draw()                         # redraw the canvas
    pause(0.01)
print 'FPS:' , 200/(time.time()-tstart)
ioff()
show()

######################## The above worked for me nicely. I ran it in spyder editor in pythonxy2.7.3 under win7 OS.
Note the pause() statement following draw() followed by ioff() and show().

Zephyr
  • 11,891
  • 53
  • 45
  • 80
9

The second answer to the question you linked provides the answer: call draw() after every plot() to make it appear immediately; for example:

import time
ion()
x = linspace(-1,1,51)
plot(sin(x))
for i in range(10):
    plot([sin(i+j) for j in x])
    # make it appear immediately
    draw()
    time.sleep(1)

If that doesn't work... try what they do on this page: http://www.scipy.org/Cookbook/Matplotlib/Animations

import time

ion()

tstart = time.time()               # for profiling
x = arange(0,2*pi,0.01)            # x-array
line, = plot(x,sin(x))
for i in arange(1,200):
    line.set_ydata(sin(x+i/10.0))  # update the data
    draw()                         # redraw the canvas

print 'FPS:' , 200/(time.time()-tstart)

The page mentions that the line.set_ydata() function is the key part.

Daniel G
  • 67,224
  • 7
  • 42
  • 42
  • 2
    For some reason this is not working for me. I have no doubt it's right, I'm just not sure why it's not working for me. As soon as the first one prints, I see a blank window for 10 seconds; after which all of the graphs appear. But draw() doesn't seem to be forcing an update until it's out of the for loop. I've just started (trying) to use matplotlib- could this be related to the "backend" I've heard about? (I have no idea what that is =/) –  Apr 09 '10 at 00:03
  • 1
    @NumberOverZero - what platform are you using? (Windows/Mac/Linux...) – Daniel G Apr 09 '10 at 00:11
  • Weird... it works for me on 7. Okay, I'll update the answer with something else to try. – Daniel G Apr 09 '10 at 00:23
  • Looked promising, but no such luck. Getting around 77fps. I threw a pause in the main loop afterward to see if it was doing each piece at a time, using "trashvar=raw_input(":")" to pause each time for input. Same thing, still a blank screen until the loop finishes. –  Apr 09 '10 at 00:34
  • :( I'm sorry - both methods work for me, I don't have any idea what's going on. – Daniel G Apr 09 '10 at 00:58
  • No problem, I'll keep looking and if nothing comes up, go for a fresh install when I can get my hands on another computer. Thank you for the help, I'm sure it will work for (most) someone(s). –  Apr 09 '10 at 01:09
5

had the exact same problem with ipython running on my mac. (Enthought Distribution of python 2.7 32bit on Macbook pro running snow leopard).

Got a tip from a friend at work. Run ipython from the terminal with the following arguments:

ipython -wthread -pylab

This works for me. The above python code from "Daniel G" runs without incident, whereas previously it didn't update the plot.

According to the ipython documentation:

[-gthread, -qthread, -q4thread, -wthread, -pylab:...] They provide threading support for the GTK, Qt (versions 3 and 4) and WXPython toolkits, and for the matplotlib library.

I don't know why that is important, but it works.

hope that is helpful, labjunky

Zephyr
  • 11,891
  • 53
  • 45
  • 80
labjunky
  • 831
  • 1
  • 13
  • 22
  • 1
    this -wthread flag fixed a similar issue for me , with figure windows locking up on closure. thanks! – wim Jun 14 '11 at 04:51
  • sadly -wthread was [removed in ipython 0.11](http://ipython.org/ipython-doc/stable/interactive/reference.html#eventloop-integration). Is there any other way to get this to work? – Jim Garrison Jul 12 '13 at 07:46
0

Please see the answer I posted here to a similar question. I could generate your animation without problems using only the GTKAgg backend. To do this, you need to add this line to your script (I think before importing pylab):

matplotlib.use('GTkAgg')

and also install PyGTK.

Community
  • 1
  • 1
Carlos Cordoba
  • 33,273
  • 10
  • 95
  • 124