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()