0

I have a simple animation I'm trying to make with MatPlotLib FuncAnimation and a contour plot. Here's what I'm trying so far:

# Create Figure and Axes
figure, ax = plot.subplots()

# Draw new contour with new data from u
def animate(i):
    a = u[:, :, int(i)]
    CS = ax.contourf(x.flatten(), y.flatten(), a, colors=['blue', 'white'], levels=0)
    return CS,

# create animation using the animate() function
myAnimation = FuncAnimation(figure, animate, frames=np.arange(0.0, t, t), interval=10, blit=True)

figure.show()

Where u[:, :, i] contains the new Z data I want to plot in my contour.

This works for the very first frame, but then I immediately get the error: AttributeError: 'QuadContourSet' object has no attribute 'get_zorder' from the line CS = ax.contourf(...) for every iteration after that. I do have a crude animation working which is shown below:

figure, ax = plot.subplots()
for i in range(0, t):
        a = u[:, :, i]
        CS = ax.contourf(x.flatten(), y.flatten(), a, colors=['blue', 'white'], levels=0)
        figure.show()
        sleep(0.01)

but this implementation creates a new graph for each step and thus is not efficient which is why I'm looking at FuncAnimation. If anyone knows why my FuncAnimation isn't working or if theres another way to animate all my data on one graph I'd be grateful! I've tried plotting it all on one graph using clf(), pause(), and draw() as well but to no avail!

Pecans
  • 307
  • 5
  • 16

1 Answers1

0

Another option is to use ArtistAnimation. You can use celluloid (disclaimer: I wrote it), to easily capture plots and then animate them. It uses ArtistAnimation under the hood. The basic idea is that you capture the figure each time you want an image in your animation. Then when you ask celluloid to create the animation it can handle the rest.

Please keep in mind is that while this method may be fewer lines of code it can take much longer to run depending on the length of your animation. It has to keep all those plots in memory unlike FuncAnimation.

import matplotlib.pyplot as plt
import numpy as np
from celluloid import Camera

X, Y = np.meshgrid(np.linspace(0, 10, 100), np.linspace(0, 10, 100))
fig, ax = plt.subplots()
camera = Camera(fig)
for i in np.linspace(0, 2 * np.pi, 30, endpoint=False):
    ax.contourf(np.sin(X + i) + np.sin(Y - i))
    camera.snap()
anim = camera.animate()
anim.save('contours.mp4')

enter image description here

Jacques Kvam
  • 2,856
  • 1
  • 26
  • 31