2

I'm new to Python matplotlib and want to make a figure updated in a loop. This is some simple test code. I want to draw 3 graphs, each for 2 seconds, with different slopes each time. Of course, I know I should read some more about matplotlib but I need to do something quick. What is wrong below? Thanks!

#!/usr/bin/env python

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

def demo(a):
    y = [xt*a+1 for xt in x]
    ax.plot(x,y)

if __name__ == '__main__':
    plt.ion()
    fig, ax = plt.subplots()
    ax.set_ylim([0,15])
    x = range(0,5)
    for a in range(1,4):
        demo(a)
        time.sleep(2)

I thought plt.ion() makes it interactive and ax.plot(x,y) take effect instantly (but guess not). I tried adding ax.draw() after ax.plot(x,y) but it requires some arguments like artist or something which I don't know yet :). Also, I have this error message coming (Ubuntu 14.04.LTS).

Xlib:  extension "XInputExtension" missing on display ":1.0".
X Error: BadDrawable (invalid Pixmap or Window parameter) 9
  Major opcode: 62 (X_CopyArea)
  Resource id:  0x0

EDIT : I add the correct code below. (according to Estilus's solution to which I modified a little for correct graph display.

#!/usr/bin/env python

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

def demo(a):
    plt.cla()
    y = [xt*a+1 for xt in x]
    ax.set_ylim([0,15])
    ax.plot(x,y)

if __name__ == '__main__':
    plt.ion()
    fig, ax = plt.subplots()
    x = range(5)
    for a in range(1,4):
        demo(a)
        plt.pause(3)
        plt.draw()
Chan Kim
  • 5,177
  • 12
  • 57
  • 112
  • Possible duplicate of [How to update a plot in matplotlib?](http://stackoverflow.com/questions/4098131/how-to-update-a-plot-in-matplotlib) – dot.Py Jul 19 '16 at 14:25
  • Possible duplicate of [Defining multiple plots to be animated with a for loop in matplotlib](http://stackoverflow.com/questions/21937976/defining-multiple-plots-to-be-animated-with-a-for-loop-in-matplotlib) – hashcode55 Jul 19 '16 at 14:31

3 Answers3

4

So plt.ion() needs to be paused for a short period of time for it to be interactive. Otherwise, you'll just run into a frozen white screen. Secondly you want to use draw() to update the figure. Therefore, your code would look something like this:

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

def demo(a):
    y = [xt*a+1 for xt in x]
    ax.plot(x,y)

if __name__ == '__main__':
    plt.ion()
    fig, ax = plt.subplots()
    ax.set_ylim([0,15])
    x = range(0,5)
    for a in range(1,4):
        demo(a)
        plt.pause(3)
        plt.draw()

I set the pause time to be 3 seconds, but it could be a pretty small number if you'd like (like 0.000001). Hope this helped!

LogCapy
  • 447
  • 7
  • 20
  • Hi, this works. except I moved ax.set_ylim([0,15]) to inside demo(). otherwise the ylim is not correctly set. Thanks! – Chan Kim Jul 19 '16 at 23:56
  • 1
    Be careful not to set the pause time too short. With 1e-9 I sometimes had the issue that the plot wasn't redrawn during every pause, I guess because it didn't have time to process everything in the event queue. With 1e-3 it's working fine – Max Klein Jul 15 '22 at 10:21
-1

It seems that you're trying to understand how to update a plot in matplotlib.

You should use this code to understand how to use fig1.canvas.draw() to update your charts data:

fig1 = figure()

for n in range(30):

    ## Clear the figure
    clf()

    # Do a plot that changes for each iteration
    plot(range(n))

    # Now set the xlimit so that it doesn’t change the plot
    xlim((0,30))
    ylim((0,30))

    ## Now the magic, we must update the canvas
    fig1.canvas.draw()
Community
  • 1
  • 1
dot.Py
  • 5,007
  • 5
  • 31
  • 52
-1

Here is a code which works. The key lines are:

  • plt.cla(): to clear the axis between each draw. Remove this line if you want to keep all graphs.
  • fig.canvas.draw(): to actually draw the plot into the canvas of the figure

#!/usr/bin/env python

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

def demo(a):
    plt.cla()
    y = [xt*a+1 for xt in x]
    ax.set_ylim([0,200])
    ax.plot(x,y)
    fig.canvas.draw()

if __name__ == '__main__':
    plt.ion()
    fig, ax = plt.subplots()
    x = range(5)
    for a in range(40):
        demo(a)
        time.sleep(0.1)
Frodon
  • 3,684
  • 1
  • 16
  • 33
  • I did exactly as you showed me but it gives me this error. (maybe not python related). and I see no figures excepts a short flashing figure window after a couple of seconds. Xlib: extension "XInputExtension" missing on display ":1.0". X Error: BadDrawable (invalid Pixmap or Window parameter) 9 Major opcode: 62 (X_CopyArea) Resource id: 0x0 – Chan Kim Jul 19 '16 at 14:49
  • @ChanKim this is not Python related. It's a problem with your graphic environment (virtual machine ?) – Frodon Jul 19 '16 at 14:51
  • I know, so I copied your code to my CentOS6.7 machine, but no picture window shows up. The script just ends after some seconds. What could be wrong? Are you sure your modified code runs ok in your machine? – Chan Kim Jul 19 '16 at 14:55