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
In Matplotlib, we can draw multiple graphs in a single plot in two ways. One is by using subplot() function and other by superimposition of second graph on the first i.e, all graphs will appear on the same plot.
The easiest way to display multiple images in one figure is use figure(), add_subplot(), and imshow() methods of Matplotlib. The approach which is used to follow is first initiating fig object by calling fig=plt. figure() and then add an axes object to the fig by calling add_subplot() method.
MatPlotLib with PythonCreate random data using numpy. Add a subplot to the current figure, nrows=1, ncols=4 and at index=1. Display data as an image, i.e., on a 2D regular raster, using imshow() method with cmap="Blues_r". Add a subplot to the current figure, nrows=1, ncols=4 and at index=2.
Sometimes it is natural to have more than one distinct group of Axes grids, in which case Matplotlib has the concept of SubFigure : SubFigure. A virtual figure within a figure.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With