Assume we want to track the centre of a tropical cyclone from the sea-level pressure data in longitude–latitude grid.
This notebook shows how to animate shades or contours, and a point at the same time.
Shades, contours and points are termed Artists
in matplotlib.
To find how to find the minimum value interpolated between grid points see pytrack.
To focus on plotting a simpler example is used here.
Define a function for cosine bell, which is used as the sea-level pressure field with a ‘tropical cyclone’.
%matplotlib inline
import numpy as np
lon = np.linspace(120, 150, 31)
lat = np.linspace(20, 50, 31)
X, Y = np.meshgrid(lon, lat)
def cosbel(x, y, height = -1, radius = 5):
r = np.sqrt(x**2 + y**2)
z = 0.5 * height * (1 +np.cos(np.pi * r / radius))
z[r > radius] = 0
return z
It is straightforward to draw contours and a point.
import matplotlib.pyplot as plt
plt.rcParams['font.size'] = 18
fig, ax = plt.subplots(figsize=(11,11))
ax.set_aspect('equal')
ax.set_xlabel("longitude")
ax.set_ylabel("latitude")
ax.set_title("FT=0")
lonc = 130
latc = 25
Z = 1000 + cosbel(X - lonc, Y - latc, height=-40)
im = ax.contourf(X, Y, Z)
ax.scatter(lonc, latc, c='white')
cbar = fig.colorbar(im)
To animate Artists
pass figure
and a list of Artists
to animation.ArtistsAnimation
. Use save()
to save the animation to a file. imagemagick
is required to create GIF and ffmpeg
for MPEG-4. The script below animates QuadContourSet
(return value of contourf
).
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation
plt.rcParams['animation.html'] = 'html5'
plt.rcParams['font.size'] = 18
fig, ax = plt.subplots(figsize=(11,11))
ax.set_aspect('equal')
ims = []
for i in range(30):
lonc = 130 + 0.03*i**2
latc = 25 + i
Z = 1000 + cosbel(X - lonc, Y - latc, height=-40)
im = ax.contourf(X, Y, Z)
ims.append(im.collections) # use collections for QuadContourSet (return value of contourf)
ani = animation.ArtistAnimation(fig, ims)
#ani.save("tc.gif", writer="imagemagick")
#ani.save("tc.mp4", writer="ffmpeg")
plt.close() # suppress plot
ani
To animate QuadMesh
(return value of pcolormesh
) build the list by appending [im]
.
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation
plt.rcParams['animation.html'] = 'html5'
plt.rcParams['font.size'] = 18
fig, ax = plt.subplots(figsize=(11,11))
ax.set_aspect('equal')
ims = []
for i in range(30):
lonc = 130 + 0.03*i**2
latc = 25 + i
Z = 1000 + cosbel(X - lonc, Y - latc, height=-40)
im = ax.pcolormesh(X, Y, Z, shading='gouraud') # shading for smoothing
ims.append([im]) # pass im as list
ani = animation.ArtistAnimation(fig, ims)
plt.close()
ani
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation
plt.rcParams['animation.html'] = 'html5'
plt.rcParams['font.size'] = 18
fig, ax = plt.subplots(figsize=(11,11))
ax.set_aspect('equal')
ax.set_xlim(120, 150)
ax.set_ylim(20, 50)
ims = []
for i in range(30):
lonc = 130 + 0.03*i**2
latc = 25 + i
Z = 1000 + cosbel(X - lonc, Y - latc, height=-40)
ax.scatter(lonc, latc, c="white")
im = ax.contourf(X, Y, Z)
ims.append(im.collections)
ani = animation.ArtistAnimation(fig, ims)
plt.close()
ani
To draw both shades and a point at the same time, an alternative approach is used: animation.Funcanimation
.
Axes
. Supply what changes between frames.FuncAnimation
with Figure
, the update function, and the number of frames (or an iterable).%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation
plt.rcParams['animation.html'] = 'html5'
plt.rcParams['font.size'] = 18
fig, ax = plt.subplots(figsize=(11,11))
ax.set_aspect('equal')
ax.set_xlim(120, 150)
ax.set_ylim(20, 50)
ti = ax.set_title("FT=0")
lon0 = 130
lat0 = 25
p0 = 1000
dp = 40
Z = p0 + cosbel(X - lon0, Y - lat0, height=-dp)
sc = ax.scatter(lonc, latc, c="white")
pm = ax.pcolormesh(X, Y, Z, shading='gouraud')
cbar = fig.colorbar(pm)
cbar.set_clim(p0-dp, p0)
cbar.set_ticks(np.linspace(p0-dp, p0, 11))
cbar.set_label('slp hPa')
def update(i):
lonc = lon0 + 0.03*i**2
latc = lat0 + i
Z = p0 + cosbel(X - lonc, Y - latc, height = -dp + 2 * i)
sc.set_offsets((lonc, latc))
pm.set_array(Z.ravel()) # convert array to 1d with ravel()
sc.set_zorder(1) # need to set drawing order with pcolormesh
pm.set_zorder(0)
ti.set_text("FT={}".format(i * 6))
ani = animation.FuncAnimation(fig, update, frames=30)
plt.close()
ani