Skip to content

Instantly share code, notes, and snippets.

@ussserrr
Created January 31, 2019 20:59
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ussserrr/a5088966ed0cca0207bf7c1a7bea314e to your computer and use it in GitHub Desktop.
Save ussserrr/a5088966ed0cca0207bf7c1a7bea314e to your computer and use it in GitHub Desktop.
Simple example of how to use matplotlib animation to visualize 24 real-time channels simultaneously
import matplotlib.pyplot as plt, matplotlib.animation as animation, numpy as np
# use oscilloscope-like style and hide matplotlib toolbar for more space
from matplotlib import rcParams
plt.style.use('dark_background'); rcParams['toolbar']='None'
N_ROWS = 12; N_COLS = 2
N_POINTS = 250 # number of points in each line
interval = 50 # in ms, interval of updating plots for FuncAnimation
N_XTICKLABELS = 10
# axes: 2D numpy.ndarray of axes instances
fig, axes = plt.subplots(nrows=N_ROWS, ncols=N_COLS, sharex=True)
# reduce white space around the plots, hspace=0 for no vertical gap between plots
fig.subplots_adjust(left=0.025, bottom=0.025, right=0.99, top=0.99, wspace=0.1, hspace=0)
# toggle run/pause by mouse clicks anywhere on the figure
run = True
def onClick(event):
global run; run^=True
fig.canvas.mpl_connect('button_press_event', onClick)
# plot initial data (zeros) to get lines instances and pack them into
# 1) numpy.ndarray to match axes array shape
# 2) tuple to 'blit' redraw functionality of FuncAnimation
# also make some visual settings
lines = np.zeros_like(axes); lines_tuple = ()
for i in range(N_ROWS):
for j in range(N_COLS):
line, = axes[i][j].plot(range(N_POINTS), np.zeros(N_POINTS), color='yellow', linewidth=0.75)
axes[i][j].set_ylim(0, 1)
axes[i][j].grid(color='gray', linestyle=':', linewidth=0.5)
plt.setp([axes[i][j].get_xticklabels()], visible=False) # remove all xticks ...
lines[i][j] = line; lines_tuple += (line,)
# ... except lower xticks. Also set xticks to reflect actual time stamps of points.
# Note that you can't get real time stamps if updating of figure takes more time than
# updating interval
for ax in axes[-1]:
plt.setp([ax.get_xticklabels()], visible=True)
ax.set_xticks(np.arange(0, N_POINTS+0.01, N_POINTS/(N_XTICKLABELS-1)))
ax.set_xticklabels([ '{0:.2f}'.format(interval*N_POINTS*i/(N_XTICKLABELS-1)/1000) for i in range(N_XTICKLABELS) ])
# update function. Replace random number by your new data point. This function must return
# iterable of artists that need to be redrawn at each call (lines tuple in our case)
def update(frame):
if run:
for i in range(N_ROWS):
for j in range(N_COLS):
lines[i][j].set_ydata(np.append(lines[i][j].get_ydata()[1:], np.random.rand()))
return lines_tuple
# in our case init function is simple { def init(): return lines_tuple } so we replace it by lambda
ani = animation.FuncAnimation(fig, update, init_func=lambda: lines_tuple, interval=interval, blit=True)
# you need this, otherwise your PC doesn't draw anything
plt.show()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment