My code produces a number of plots from data using matplotib and I would like to be able to scroll forwards and backwards through them in a live demonstration (maybe by pressing the forwards and backwards keys or using the mouse). Currently I have to save each one as an image separately and then use a separate image viewer to scroll through them. Is there any way of doing this entirely from within python?
1 Answer
An easy way to achieve that is storing in a list a tuple of the x and y arrays and then use a handler event that picks the next (x,y) pair to be plotted:
import numpy as np import matplotlib.pyplot as plt # define your x and y arrays to be plotted t = np.linspace(start=0, stop=2*np.pi, num=100) y1 = np.cos(t) y2 = np.sin(t) y3 = np.tan(t) plots = [(t,y1), (t,y2), (t,y3)] # now the real code :) curr_pos = 0 def key_event(e): global curr_pos if e.key == "right": curr_pos = curr_pos + 1 elif e.key == "left": curr_pos = curr_pos - 1 else: return curr_pos = curr_pos % len(plots) ax.cla() ax.plot(plots[curr_pos][0], plots[curr_pos][1]) fig.canvas.draw() fig = plt.figure() fig.canvas.mpl_connect('key_press_event', key_event) ax = fig.add_subplot(111) ax.plot(t,y1) plt.show() In this code I choose the right and left arrows to iterate, but you can change them.
3 Comments
Mike O'Connor
Thanks much jabaldonedo--- your example is now in my project and so I can confirm for others that it works. In my case
key_event is a closure within a closure inside a decorator. I do not fathom the cause--- so help me it's not erroneous punctuation on the end of the previous line--- but I kept getting "global name curr_pos not defined", notwithstanding the fact it is clearly defined by curr_pos = 0. I opted for a solution in the form if not hasattr(key_event, "curr_pos"): key_event.curr_pos = 0 in place of global curr_pos. I would use key_event.__dict__={} to reset if needed.Tropilio
Thank you, this worked perfectly for me! I tried to comment out fig.canvas.draw() and it still works. Maybe it is not needed?
JeffP
I don't understand how the namespace works in this example. I understand why
curr_pos needs to be a global variable, but why then does key_event have access to the plots list and the ax axes instance?
press a button -> generate a plot -> show itand so on.