Matplotlib figure not updating on data change
I'm implementing an image viewer using matplotlib
. The idea is that changes being made to the image (such as filter application) will update automatically.
I create a Figure to show the inital image and have added a button using pyQt
to update the data. The data does change, I have checked, but the Figure does not. However, if after I've pressed the filter application button, I move the image using matplotlib
's standard tool bar, the image is then updated.
I assume I'm doing something wrong when updating the image, but since the fact of moving it actually forces the update, it then shows the data change. I would like for this to happen when I press the button, though.
Below is some of the code. This is the initial figure initialization, which shows the original image:
self.observableFig = Figure((4.0, 4.0), dpi=100)
self.canvas = FigureCanvas(self.observableFig)
self.canvas.setParent(self.observableWindow)
self.canvas.setFocusPolicy(Qt.StrongFocus)
self.canvas.setFocus()
self.canvas.mpl_connect('button_press_event', self.on_click)
# Showing initial data on Window
self.observableFig.clear()
self.observableAxes = self.observableFig.add_subplot(1, 1, 1)
min, max = self.min, self.max
self.observableAxes.imshow(
self.data,
vmin=min,
vmax=max,
origin='lower'
)
And this is the event for when the button that changes the data is pressed:
self.observableAxes.imshow(self.data/2, origin='lower')
# plt.clf()
# plt.draw()
# plt.show()
I have tried draw()
, show()
, basically anything I've found on pyplot
about this. I have also tried both with and without plt.ion()
at the beginning, but it hasn't made a difference in this.
Thanks in advance.
Solution 1:
The reason that nothing is updating is that you're trying to use pyplot
methods for a figure that's not a part of the pyplot state machine. plt.draw()
won't draw this figure, as plt
doesn't know the figure exists.
Use fig.canvas.draw()
instead.
Regardless, it's better to use fig.canvas.draw()
that plt.draw()
, as it's clear which figure you're drawing (the former draws one, the latter draws all, but only if they're tracked by pyplot
).
Try something along these lines:
import numpy as np
import matplotlib.pyplot as plt
data = np.random.random((10,10))
# To make a standalone example, I'm skipping initializing the
# `Figure` and `FigureCanvas` and using `plt.figure()` instead...
# `plt.draw()` would work for this figure, but the rest is identical.
fig, ax = plt.subplots()
ax.set(title='Click to update the data')
im = ax.imshow(data)
def update(event):
im.set_data(np.random.random((10,10)))
fig.canvas.draw()
fig.canvas.mpl_connect('button_press_event', update)
plt.show()