8

I have a 3D array that represents density values over cartesian space. To get a 2D image I just sum over one of the axes using sum(array,2) and then use the matplotlib function imshow(array2D) to obtain the 2D image.

What I want to do is use imshow() to display only one slice of the 3D array at a time so that I can 'page' through the 3D array to see different points of the image.

The slice command is simple: array[:,:,x] but I see no way to display every slice one at a time at least. Does anyone have suggestions other than manually changing the program file each time? Can this be done interactively somehow?

1 Answer 1

4

I actually wrote code to do exactly what I think you are looking for, see if this helps:

import numpy as np
import pylab

class plotter:
    def __init__(self, im, i=0):
        self.im = im
        self.i = i
        self.vmin = im.min()
        self.vmax = im.max()
        self.fig = pylab.figure()
        pylab.gray()
        self.ax = self.fig.add_subplot(111)
        self.draw()
        self.fig.canvas.mpl_connect('key_press_event',self)

    def draw(self):
        if self.im.ndim is 2:
            im = self.im
        if self.im.ndim is 3:
            im = self.im[...,self.i]
            self.ax.set_title('image {0}'.format(self.i))

        pylab.show()

        self.ax.imshow(im, vmin=self.vmin, vmax=self.vmax, interpolation=None)


    def __call__(self, event):
        old_i = self.i
        if event.key=='right':
            self.i = min(self.im.shape[2]-1, self.i+1)
        elif event.key == 'left':
            self.i = max(0, self.i-1)
        if old_i != self.i:
            self.draw()
            self.fig.canvas.draw()


def slice_show(im, i=0):
    plotter(im, i)

Just call the show function on your 3d array, i will tell it what slice to displaying. You can step through slices with arrow keys as long as you have the plot selected.

Note, this expects arrays with shape (x, y, z), you could for example get such an array from a series of 2d arrays with np.dstack((im1, im2, ...)).

See also Interactive matplotlib plot with two sliders for a code example of doing it with gui sliders

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for this, I was looking for something like this too. Just fyi, every time you call imshow it stacks another image onto a pile of images, you might want to do something like self.ax.images.pop() before you do the imshow in order to avoid a memory leak.
hey cool, I have suspected a memory leak, I will give ax.images.pop() a try

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.