Skip to content

Instantly share code, notes, and snippets.

@hugke729
Last active March 24, 2024 19:54
  • Star 14 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save hugke729/ac3cf36500f2f0574a6f4ffe40986b4f to your computer and use it in GitHub Desktop.
# Example animations using matplotlib's FuncAnimation
# Ken Hughes. 18 June 2016.
# For more detail, see
# https://brushingupscience.wordpress.com/2016/06/21/matplotlib-animations-the-easy-way/
# Examples include
# - line plot
# - pcolor plot
# - scatter plot
# - contour plot
# - quiver plot
# - plot with changing labels
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
# Use matplotlib ggplot stylesheet if available
try:
plt.style.use('ggplot')
except:
pass
# Set which type of animation will be plotted. One of:
# line, pcolor, scatter, contour, quiver, labels
animation_type = 'line'
# ----------------------------------------------------------------------------
# Create data to plot. F is 2D array. G is 3D array
# Create a two-dimensional array of data: F(x, t)
x = np.linspace(-3, 3, 91)
t = np.linspace(0, 25, 30)
X2, T2 = np.meshgrid(x, t)
sinT2 = np.sin(2*np.pi*T2/T2.max())
F = 0.9*sinT2*np.sinc(X2*(1 + sinT2))
# Create three-dimensional array of data G(x, z, t)
x = np.linspace(-3, 3, 91)
t = np.linspace(0, 25, 30)
y = np.linspace(-3, 3, 91)
X3, Y3, T3 = np.meshgrid(x, y, t)
sinT3 = np.sin(2*np.pi*T3 /
T3.max(axis=2)[..., np.newaxis])
G = (X3**2 + Y3**2)*sinT3
# ----------------------------------------------------------------------------
# Set up the figure and axis
fig, ax = plt.subplots(figsize=(4, 3))
if animation_type not in ['line', 'scatter']:
ax.set_aspect('equal')
# ----------------------------------------------------------------------------
if animation_type == 'line':
ax.set(xlim=(-3, 3), ylim=(-1, 1))
line = ax.plot(x, F[0, :], color='k', lw=2)[0]
def animate(i):
line.set_ydata(F[i, :])
# ----------------------------------------------------------------------------
if animation_type == 'pcolor':
cax = ax.pcolormesh(x, y, G[:-1, :-1, 0], vmin=-1, vmax=1, cmap='Blues')
fig.colorbar(cax)
def animate(i):
cax.set_array(G[:-1, :-1, i].flatten())
# ----------------------------------------------------------------------------
if animation_type == 'scatter':
ax.set(xlim=(-3, 3), ylim=(-1, 1))
scat = ax.scatter(x[::3], F[0, ::3])
def animate(i):
# Must pass scat.set_offsets an N x 2 array
y_i = F[i, ::3]
scat.set_offsets(np.c_[x[::3], y_i])
# ----------------------------------------------------------------------------
if animation_type == 'contour':
# Keyword options used in every call to contour
contour_opts = {'levels': np.linspace(-9, 9, 10), 'cmap':'RdBu', 'lw': 2}
cax = ax.contour(x, y, G[..., 0], **contour_opts)
def animate(i):
ax.collections = []
ax.contour(x, y, G[..., i], **contour_opts)
# ----------------------------------------------------------------------------
if animation_type == 'quiver':
ax.set(xlim=(-4, 4), ylim=(-4, 4))
# Plot every 20th arrow
step = 15
x_q, y_q = x[::step], y[::step]
# Create U and V vectors to plot
U = G[::step, ::step, :-1].copy()
V = np.roll(U, shift=4, axis=2)
qax = ax.quiver(x_q, y_q, U[..., 0], V[..., 0], scale=100)
def animate(i):
qax.set_UVC(U[..., i], V[..., i])
# ----------------------------------------------------------------------------
if animation_type == 'labels':
ax.set(xlim=(-1, 1), ylim=(-1, 1))
string_to_type = 'abcdefghijklmnopqrstuvwxyz0123'
label = ax.text(0, 0, string_to_type[0],
ha='center', va='center',
fontsize=12)
def animate(i):
label.set_text(string_to_type[:i+1])
ax.set_ylabel('Time (s): ' + str(i/10))
ax.set_title('Frame ' + str(i))
# ----------------------------------------------------------------------------
# Save the animation
anim = FuncAnimation(fig, animate, interval=100, frames=len(t)-1, repeat=True)
fig.show()
# anim.save(animation_type + '.gif', writer='imagemagick')
@lincolnfrias
Copy link

Really helpful, thanks a lot!

@fullpotato
Copy link

Exactly what I was looking for. Many thanks!

@syelluru
Copy link

syelluru commented Feb 2, 2018

Thanks hugke!

@Boud811
Copy link

Boud811 commented Oct 28, 2018

I have copied the code and pasted it in PyCharm, all what i got was a still plot :(
I have also tried Jupyter, it didn't work
image

@hugke729
Copy link
Author

hugke729 commented Nov 1, 2018

@Boud811: are your standard figure windows (ie not animations) in PyCharm or Jupyter interactive (as in there are buttons for zoom, pan, save etc). If not, then animation will not work.

@xy994
Copy link

xy994 commented Dec 5, 2019

Thank you! This helps me a lot.

@Kiruthika65
Copy link

Im trying this using a dataset,buut it doesnt display

@hugke729
Copy link
Author

hugke729 commented Jan 7, 2020

Kiruthika65, you need to provide more detail. How are you applying the method? What's not working?

@dbiersach
Copy link

Hi - I copied your code straight into a new Python file and tried to run it - the plot window appears for a blip, then disappears and the program ends. I am using Python 3.9 and mplotlib 3.3.3

@hugke729
Copy link
Author

hugke729 commented Dec 8, 2020

@dbiersach Any error messages? There's multiple reasons for what you describe happening

@dbiersach
Copy link

dbiersach commented Dec 9, 2020 via email

@hugke729
Copy link
Author

hugke729 commented Dec 9, 2020

Glad it's fixed. This sounds like on of those issues that depends on the exact configuration of the Python / IPython / Jupyter set up

@engsbk
Copy link

engsbk commented Feb 19, 2021

Thanks for the wonderful tutorial!
I tried pcolor. This is my code:

import matplotlib
x = np.linspace(-3, 3, 91)
t = np.linspace(0, 25, 30)
y = np.linspace(-3, 3, 91)
X3, Y3, T3 = np.meshgrid(x, y, t)
sinT3 = np.sin(2*np.pi*T3 /
               T3.max(axis=2)[..., np.newaxis])
G = (X3**2 + Y3**2)*sinT3

fig, ax = plt.subplots(figsize=(4, 3))
ax.set_aspect('equal')

cax = ax.pcolormesh(x, y, G[:-1, :-1, 0], vmin=-1, vmax=1, cmap='Blues')
fig.colorbar(cax)

def animate(i):
    cax.set_array(G[:-1, :-1, i].flatten())
    
# Save the animation
anim = FuncAnimation(fig, animate, interval=100, frames=len(t)-1, repeat=True)
matplotlib.use('module://ipykernel.pylab.backend_inline')

#fig.canvas.draw()
fig.show()
# anim.save(animation_type + '.gif', writer='imagemagick')

I got this error:

<ipython-input-26-94ea5fa97086>:24: UserWarning: Matplotlib is currently using module://ipykernel.pylab.backend_inline, which is a non-GUI backend, so cannot show the figure.
  fig.show()

Do you have an idea on how to fix this?

@hugke729
Copy link
Author

@engsk As the error message states, you're trying to show something that can't be shown given your choice of backend. Your choice of the inline backend is something for generating static images like a PNG file. You need to use something else like Agg, Qt5Agg, or notebook. It'll depend on your set up.

Also, put the matplotlib.use statement at the top.

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