matplotlib sequence of figures in the same window

matplotlib, python, python-3.x

Solution

The most general approach is to create a sequence of axes in the same figure, and only display one at a time.

Here's an example of that (The left and right arrow keys control which plot is displayed):

import matplotlib.pyplot as plt
import numpy as np

def main():
    x = np.linspace(0, 10, 100)
    axes = AxesSequence()
    for i, ax in zip(range(3), axes):
        ax.plot(x, np.sin(i * x))
        ax.set_title('Line {}'.format(i))
    for i, ax in zip(range(5), axes):
        ax.imshow(np.random.random((10,10)))
        ax.set_title('Image {}'.format(i))
    axes.show()

class AxesSequence(object):
    """Creates a series of axes in a figure where only one is displayed at any
    given time. Which plot is displayed is controlled by the arrow keys."""
    def __init__(self):
        self.fig = plt.figure()
        self.axes = []
        self._i = 0 # Currently displayed axes index
        self._n = 0 # Last created axes index
        self.fig.canvas.mpl_connect('key_press_event', self.on_keypress)

    def __iter__(self):
        while True:
            yield self.new()

    def new(self):
        # The label needs to be specified so that a new axes will be created
        # instead of "add_axes" just returning the original one.
        ax = self.fig.add_axes([0.15, 0.1, 0.8, 0.8], 
                               visible=False, label=self._n)
        self._n += 1
        self.axes.append(ax)
        return ax

    def on_keypress(self, event):
        if event.key == 'right':
            self.next_plot()
        elif event.key == 'left':
            self.prev_plot()
        else:
            return
        self.fig.canvas.draw()

    def next_plot(self):
        if self._i < len(self.axes):
            self.axes[self._i].set_visible(False)
            self.axes[self._i+1].set_visible(True)
            self._i += 1

    def prev_plot(self):
        if self._i > 0:
            self.axes[self._i].set_visible(False)
            self.axes[self._i-1].set_visible(True)
            self._i -= 1

    def show(self):
        self.axes[0].set_visible(True)
        plt.show()

if __name__ == '__main__':
    main()

If they're all the same type of plot, you could just update the data of the artists involved. This is especially easy if you have the same number of items in each plot. I'll leave out an example for the moment, but if the example above is too memory-hungry, just updating the data of the artists will be considerably lighter.

Problem

I'm testing an algorithm and I'd like to produce a sequence of figures displaying intermediate results using matplotlib. I'm not needing animations, nor multiple figures all on the screens, nor subplots. I'd just like to produce a sequence of figures (possibly using pyplot), and when I'm done, a single window is shown. Then I'd like to navigate in the sequence of figures using the arrows. How can I do something like that? I tried to search, but I can only find subplot or multiple figures on the screen. Thanks

Original source