I'd like to create a Matplotlib heatmap animation with at least 200*300 resolution, and 500 frames. The problem is the standard approach for the animation I took has a huge memory leak (as discussed in this question*). When the animation starts to draw, or to write out, the RAM begins to be filled up, to the point the system freezes until the script is killed. It's so bad that even my 4gb RAM and 4gb swap together is not enough. Is there any way to make that animation, besides creating smaller chunks and editing there together?
This is my code, with a bit of simplification. (Note: it'd take minutes to run and probably will fill up your memory completely, causing freezes.)
import numpy as np
from matplotlib import pyplot as plt
import matplotlib.animation as animation
def waveanim(frames, trange, xbounds, ybounds, xnum, ynum, fps):
xpoints = np.linspace(*xbounds, xnum)
ypoints = np.linspace(*ybounds, ynum)
tmin, tmax = trange
# this part is a complicated calculation in my actual code; point is I have all the
# values for all the time points in an array that I calculate like this ready before
# I even start animating. (Since the calculation involves an inverse FFT, I can't just use NumPy's cool array managing abilities as ImportanceOfBeingErnest's answer suggests.)
result = np.empty((xnum, ynum, frames), dtype="float64")
for i, x in enumerate(xpoints):
print("calculating: {} out of {}".format(i, len(xpoints)), end='\r')
for j, y in enumerate(ypoints):
arr = np.array([np.sin(x+t) + np.cos(x-y-2*t) for t in np.linspace(tmin, tmax, frames)])
result[i,j] = arr
print('\n')
def animate(i):
print("animating: {} out of {}".format(i, frames), end='\r')
val = result[:,:,i].transpose()
pc = plt.pcolor(xpoints, ypoints, val, cmap='jet')
return pc,
fig, ax = plt.subplots()
im_ani = animation.FuncAnimation(fig, animate, frames=frames, interval=1000/fps, repeat_delay=0, blit=True)
plt.show()
def main():
trange = (-10.0, 10.0)
xbounds = (-20.0, 20.0)
ybounds = (-20.0, 20.0)
frames = 100
xnum = 300
ynum = 300
fps = 25
waveanim(frames, trange, xbounds, ybounds, xnum, ynum, fps)
if __name__ == '__main__':
main()
I also tried generating the plots individually, putting them in an array and that array to ArtistAnimation, like in this example, but the result is the same.
*Mine is not a dupe since a) I work on Kubuntu, not on iOS, and the fix was OS-specific, and b) because I don't limit the solutions to solve the leak bug.