Mastiff
Mastiff

Reputation: 2240

How to get matplotlib (pyplot) plots to update in loop?

I've read a bunch of similar posts, but nothing is working. I have a loop and am attempting to update 3 figures containing images with text overlays, kind of like this:

def updatePlot(data, fig):
  fig.clear()
  ax = fig.subplots()
  ax.imshow(...)
  ax.text(...)
  plt.show()
  plt.draw()
  plt.pause(0.0001)

fig1 = plt.figure()
fig2 = plt.figure()
fig3 = plt.figure()

while True:
  # do computation
  updatePlot(..., fig1)
  updatePlot(..., fig2)
  updatePlot(..., fig3)

The symptom is that only fig3 updates and the others stay static until I kill the program, then they refresh. I'm working in an ipython terminal (in Spyder).

Upvotes: 1

Views: 912

Answers (1)

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339062

The following should work. It's running in interactive mode (plt.ion()) and flushes the events on each figure.

import numpy as np
import matplotlib.pyplot as plt

plt.ion()

def updatePlot(data, fig):
  fig.clear()
  ax = fig.subplots()
  ax.imshow(data)
  ax.text(2,2, np.mean(data))

  plt.pause(0.1)
  fig.canvas.draw_idle()
  fig.canvas.flush_events()

fig1 = plt.figure()
fig2 = plt.figure()
fig3 = plt.figure()

while True:
  # do computation
  updatePlot(np.random.rand(4,4), fig1)
  updatePlot(np.random.rand(6,6), fig2)
  updatePlot(np.random.rand(10,10), fig3)

This is pretty unstable and inefficient though. Maybe consider using FuncAnimation.

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


def updatePlot(data, image, text):
    image.set_data(data)
    text.set_text(data.mean())

fig1, ax1 = plt.subplots()
image1 = ax1.imshow(np.random.rand(4,4))
text1 = ax1.text(2,2, "")

fig2, ax2 = plt.subplots()
image2 = ax2.imshow(np.random.rand(6,6))
text2 = ax2.text(2,2, "")

fig3, ax3 = plt.subplots()
text3 = ax3.text(2,2, "")
image3 = ax3.imshow(np.random.rand(10,10))

def update_plots(i):
    # do computation
    updatePlot(np.random.rand(4,4), image1, text1)
    updatePlot(np.random.rand(6,6), image2, text2)
    updatePlot(np.random.rand(10,10), image3, text3)
    fig2.canvas.draw_idle()
    fig3.canvas.draw_idle()

ani = matplotlib.animation.FuncAnimation(fig1, update_plots, interval=40)

plt.show()

Upvotes: 2

Related Questions