I'm failing to find the most efficient way to generate a simple animation of a spinning globe with a filled contour using cartopy. The following code yields a static gif, probably because the figure is not redrawing itself? Is there a way for the animation function to just change the geographic projection, without calling a contourf()
again (which is computationally expensive)?
from pylab import *
import cartopy.crs as ccrs
from matplotlib.animation import FuncAnimation
lon, lat = meshgrid(
(linspace(-180,180,361)+0.5)[::4],
(linspace(-90,90,181)+0.5)[::4],
)
h = (abs(lon)<20).astype(int) * (abs(lat)<10).astype(int)
fig = figure(figsize=(3,3))
ax = fig.add_subplot(1, 1, 1, projection = ccrs.Orthographic())
ax.contourf(lon, lat, h, transform=ccrs.PlateCarree())
def update_fig(t):
ax.projection = ccrs.Orthographic(t)
ani = FuncAnimation(
fig,
update_fig,
frames = linspace(0,360,13)[:-1],
interval = 100,
blit = False,
)
ani.save('mwe.gif')
It's worth noting that your code does not actually produce a static gif. If you add borders to your axis (with ax.coastlines()
) then you'll see that the globe is being updated each frame, your data is just not updating to match the new projection.
This problem can be solved if you're using ax.pcolormesh()
as follows:
from pylab import *
import cartopy.crs as ccrs
from matplotlib.animation import FuncAnimation
lon, lat = meshgrid(
(linspace(-180,180,361)+0.5)[::4],
(linspace(-90,90,181)+0.5)[::4],
)
h = (abs(lon)<20).astype(int) * (abs(lat)<10).astype(int)
fig = figure(figsize=(3,3))
ax = fig.add_subplot(1, 1, 1, projection = ccrs.Orthographic())
ax.coastlines()
mesh = ax.pcolormesh(lon, lat, h, transform=ccrs.PlateCarree())
def update_fig(t):
ax.projection = ccrs.Orthographic(t)
mesh.set(transform=ccrs.PlateCarree())
ani = FuncAnimation(
fig,
update_fig,
frames = linspace(0,360,13)[:-1],
interval = 200)
Unfortunately, the object produced by ax.contourf
doesn't seem to work in this way. The closest I could find was mesh.set_array()
, which is used in the cartopy documentation for pcolormesh
but also works for contourf
. There is no .set_transform()
or .set()
for the object produced by contourf
.