Skip to content

Instantly share code, notes, and snippets.

@Seanny123
Created February 21, 2017 05:15
Controllable animation in matplotlib
import numpy as np
from collections import deque
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib.widgets import Button, Slider
class AnalogPlot:
def __init__(self, data, display_len):
self.buff = deque(np.zeros(display_len))
self.display_len = display_len
self.data = data
# set up the plot
self.fig = plt.figure()
self.ax = self.fig.add_subplot(111, xlim=(0, t_max), ylim=(-1, 1))
self.ax.set_xticks((0,t_max))
self.lines = self.ax.plot([], [])
# setup the animation
self.cur_frame = 0
self.anim = animation.FuncAnimation(self.fig, self._update,
interval=1.0)
# setup the animation control
self.anim_running = True
def _add_to_buff(self, buf, val):
if len(buf) < self.display_len:
buf.appendLeft(val)
else:
buf.popleft()
buf.append(val)
def _update(self, frame):
frame = self.cur_frame
self._add_to_buff(self.buff, self.data[frame:frame+1])
self.lines[0].set_data(range(self.display_len), self.buff)
self.ax.set_xticklabels((str(frame), str(frame+self.display_len)))
self.time_slider.eventson = False
self.time_slider.set_val(frame)
self.time_slider.eventson = True
self.cur_frame += 1
return self.lines
def _pause(self, event):
if self.anim_running:
self.anim.event_source.stop()
self.anim_running = False
else:
self.anim.event_source.start()
self.anim_running = True
def _reset(self, event):
self._set_val(0)
def _set_val(self, frame=0):
frame = int(frame)
self.cur_frame = frame
new_start = frame - self.display_len
if new_start >= 0:
self.buff = deque(self.data[new_start:frame])
else:
self.buff = deque(np.concatenate((np.zeros(np.abs(new_start)), self.data[:frame])))
self.anim.event_source.stop()
self.anim = animation.FuncAnimation(self.fig, self._update,
interval=1.0)
self.anim_running = True
def animate(self):
pause_ax = self.fig.add_axes((0.7, 0.025, 0.1, 0.04))
pause_button = Button(pause_ax, 'pause', hovercolor='0.975')
pause_button.on_clicked(self._pause)
reset_ax = self.fig.add_axes((0.8, 0.025, 0.1, 0.04))
reset_button = Button(reset_ax, 'reset', hovercolor='0.975')
reset_button.on_clicked(self._reset)
slider_ax = self.fig.add_axes((0.1, 0.025, 0.5, 0.04))
self.time_slider = Slider(slider_ax, label='Time',
valmin=0, valmax=self.data.shape[0],
valinit=0.0)
self.time_slider.on_changed(self._set_val)
plt.show()
t_max = 100
lin_sig = np.linspace(0, 1, 1000)
analog_plot = AnalogPlot(lin_sig, t_max)
analog_plot.animate()
@AI-noobie
Copy link

when I run this I get "AttributeError: AnalogPlot instance has no attribute 'time_slider'"

@fgoroncy
Copy link

Hi, when the animation reaches the end, I get an "RuntimeError: xdata and ydata must be the same length". The code was still a good reference for me :)

@zhuyali2018
Copy link

I try to set up title, and the title goes to Slider bar: plt.title("My Title"). How to set title on the top of the big graph ?

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment