Plotting in a non-blocking way with Matplotlib Plotting in a non-blocking way with Matplotlib python python

Plotting in a non-blocking way with Matplotlib


I spent a long time looking for solutions, and found this answer.

It looks like, in order to get what you (and I) want, you need the combination of plt.ion(), plt.show() (not with block=False) and, most importantly, plt.pause(.001) (or whatever time you want). The pause is needed because the GUI events happen while the main code is sleeping, including drawing. It's possible that this is implemented by picking up time from a sleeping thread, so maybe IDEs mess with that—I don't know.

Here's an implementation that works for me on python 3.5:

import numpy as npfrom matplotlib import pyplot as pltdef main():    plt.axis([-50,50,0,10000])    plt.ion()    plt.show()    x = np.arange(-50, 51)    for pow in range(1,5):   # plot x^1, x^2, ..., x^4        y = [Xi**pow for Xi in x]        plt.plot(x, y)        plt.draw()        plt.pause(0.001)        input("Press [enter] to continue.")if __name__ == '__main__':    main()



A simple trick that works for me is the following:

  1. Use the block = False argument inside show: plt.show(block = False)
  2. Use another plt.show() at the end of the .py script.

Example:

import matplotlib.pyplot as pltplt.imshow(add_something)plt.xlabel("x")plt.ylabel("y")plt.show(block=False)#more code here (e.g. do calculations and use print to see them on the screenplt.show()

Note: plt.show() is the last line of my script.


You can avoid blocking execution by writing the plot to an array, then displaying the array in a different thread. Here is an example of generating and displaying plots simultaneously using pf.screen from pyformulas 0.2.8:

import pyformulas as pfimport matplotlib.pyplot as pltimport numpy as npimport timefig = plt.figure()canvas = np.zeros((480,640))screen = pf.screen(canvas, 'Sinusoid')start = time.time()while True:    now = time.time() - start    x = np.linspace(now-2, now, 100)    y = np.sin(2*np.pi*x) + np.sin(3*np.pi*x)    plt.xlim(now-2,now+1)    plt.ylim(-3,3)    plt.plot(x, y, c='black')    # If we haven't already shown or saved the plot, then we need to draw the figure first...    fig.canvas.draw()    image = np.fromstring(fig.canvas.tostring_rgb(), dtype=np.uint8, sep='')    image = image.reshape(fig.canvas.get_width_height()[::-1] + (3,))    screen.update(image)#screen.close()

Result:

Sine animation

Disclaimer: I'm the maintainer for pyformulas.

Reference: Matplotlib: save plot to numpy array