Created
January 31, 2019 20:59
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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