How to pyplot pause() for zero time?

Timothy Swan picture Timothy Swan · Nov 19, 2015 · Viewed 8.6k times · Source

I'm plotting an animation of circles. It looks and works great as long as speed is set to a positive number. However, I want to set speed to 0.0. When I do that, something changes and it no longer animates. Instead, I have to click the 'x' on the window after each frame. I tried using combinations of plt.draw() and plt.show() to get the same effect as plt.pause(), but the frames don't show up. How do I replicate the functionality of plt.pause() precisely either without the timer involved or with it set to 0.0?

speed = 0.0001
plt.ion()
for i in range(timesteps):
    fig, ax = plt.subplots()
    for j in range(num):
        circle = plt.Circle(a[j], b[j]), r[j], color='b')
        fig.gca().add_artist(circle)
    plt.pause(speed)
    #plt.draw()
    #plt.show()
    plt.clf()
    plt.close()

Answer

titusjan picture titusjan · Nov 20, 2015

I've copied the code of pyplot.pause() here:

def pause(interval):
    """
    Pause for *interval* seconds.

    If there is an active figure it will be updated and displayed,
    and the GUI event loop will run during the pause.

    If there is no active figure, or if a non-interactive backend
    is in use, this executes time.sleep(interval).

    This can be used for crude animation. For more complex
    animation, see :mod:`matplotlib.animation`.

    This function is experimental; its behavior may be changed
    or extended in a future release.

    """
    backend = rcParams['backend']
    if backend in _interactive_bk:
        figManager = _pylab_helpers.Gcf.get_active()
        if figManager is not None:
            canvas = figManager.canvas
            canvas.draw()
            show(block=False)
            canvas.start_event_loop(interval)
            return

    # No on-screen figure is active, so sleep() is all we need.
    import time
    time.sleep(interval)

As you can see, it calls start_event_loop, which starts a separate crude event loop for interval seconds. What happens if interval == 0 seems backend-dependend. For instance, for the WX backend a value of 0 means that this loop is blocking and never ends (I had to look in the code here, it doesn't show up in the documentation. See line 773).

In short, 0 is a special case. Can't you set it to a small value, e.g. 0.1 seconds?

The pause docstring above says that it can only be used for crude anmiations, you may have to resort to the animation module if you want something more sophisticated.