CL. Wang
CL. Wang

Reputation: 168

How to refresh images of axes of Matplotlib figure

I want to draw a 3D volume using Matplotlib, slice by slice. Mouse scroll to change the index. My program is given below:

#Mouse scroll event.
def mouse_scroll(event):
fig = event.canvas.figure
  ax = fig.axes[0]
  if event.button == 'down':
    next_slice(ax)
  fig.canvas.draw()

#Next slice func.
def previous_slice(ax):
  volume = ax.volume
  ax.index = (ax.index - 1) % volume.shape[0]
  #ax.imshow(volume[ax.index])
  ax.images[0].set_array(volume[ax.index])

Figure is initialized in the main function. like:

 fig, ax = plt.subplots()
 ax.volume = volume # volume is a 3D data, a 3d np array.
 ax.index = 1
 ax.imshow(volume[ax.index])
 fig.canvas.mpl_connect('scroll_event', mouse_scroll)

Everything worked pretty well even I don't understand what is the ax.images. However, problem occurred when I replace the ax.volume with a new volume data. It suddenly stop to render! Debug into the code, the ax.image[0] is correctly set at each event callback.

But, if change the image set_array method to ax.show(). Figure begins to render again. But axes imshow function is really slow comparing to the ax.images[0].set_array() method.

How can I fix this problem? really want to use set_array() method. Thank you very much.

A simple executable script is attached. plot.py@googledrive

Upvotes: 2

Views: 2828

Answers (1)

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339705

You need to work on the same image all the time. Best give this a name

img = ax.imshow(volume[ax.index])

You can then set the data for it using set_data.

import numpy as np
import matplotlib.pyplot as plt

#Mouse scroll event.
def mouse_scroll(event):
    fig = event.canvas.figure
    ax = fig.axes[0]
    if event.button == 'down':
        next_slice(ax)
    fig.canvas.draw()

#Next slice func.
def next_slice(ax):
    volume = ax.volume
    ax.index = (ax.index - 1) % volume.shape[0]
    img.set_array(volume[ax.index])

def mouse_click(event):
    fig = event.canvas.figure
    ax = fig.axes[0]
    volume = np.random.rand(10, 10, 10)
    ax.volume = volume
    ax.index = (ax.index - 1) % volume.shape[0]              
    img.set_array(volume[ax.index])
    fig.canvas.draw_idle()

if __name__ == '__main__':
    fig, ax = plt.subplots()
    volume = np.random.rand(40, 40, 40)
    ax.volume = volume # volume is a 3D data, a 3d np array.
    ax.index = 1
    img = ax.imshow(volume[ax.index])
    fig.canvas.mpl_connect('scroll_event', mouse_scroll)
    fig.canvas.mpl_connect('button_press_event', mouse_click)
    plt.show()

Upvotes: 2

Related Questions