2

I have the following code in python to convert a plot into an animation.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.animation import PillowWriter

fig,ax=plt.subplots(subplot_kw=dict(projection='3d'), figsize=(15,15))
l,=plt.plot([],[],'k-')
plt.xlim(-5,5)
plt.ylim(-5,5)
f=lambda x,t: np.cos(x*t)

xvec = np.arange(-5,5,0.1)
yvec = np.arange(-5,5,0.1)

u,v=np.meshgrid(xvec,yvec)
#xlist=np.cos(u)*np.sin(v)
#ylist=np.sin(u)*np.sin(v)
#zlist=np.cos(v)
fx=lambda u,v,t: (1+0.5*np.cos(u+t))*np.cos(v)
fy=lambda u,v,t: (1+0.5*np.cos(u+t))*np.sin(v)
fz=lambda v,t: 0.5*np.sin(u)

metadata=dict(title='Movie', artist='me')
writer=PillowWriter(fps=15,metadata=metadata)

with writer.saving(fig, "shakingtorus.gif", 100):
    for tval in np.arange(0,5,0.3):
        ax.set_zlim(-2,2)
        ax.set_xlim(-2,2)
        ax.set_ylim(-2,2)
        xlist=fx(u,v, tval) 
        ylist=fy(u,v, tval)
        zlist=fz(v,tval)
        ax.plot_surface(xlist,ylist,zlist, cmap=cm.viridis)
        writer.grab_frame()
        plt.cla()

Is there a way to rewrite this code such that fps is still high and without exporting the graph to a gif file. Also I want to keep surface plotting. I also know the matplotlib.animation.FuncAnimation function but I couldn't make it working without having a slow animation.

Surface animation

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158

1 Answers1

1

To use FuncAnimation with plot_surface you can clear the axes at every frame with ax.cla and draw the updated plot (see example here). To control the fps in your animation without saving it to a file, you can set the interval parameter fo FuncAnimation to whatever value you want in ms (see doc here).

Here what it looks like with your code and with 15 fps:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.animation import FuncAnimation

fig,ax=plt.subplots(subplot_kw=dict(projection='3d'), figsize=(15,15))

xvec = np.arange(-5,5,0.1)
yvec = np.arange(-5,5,0.1)
u,v=np.meshgrid(xvec,yvec)

fx=lambda u,v,t: (1+0.5*np.cos(u+t))*np.cos(v)
fy=lambda u,v,t: (1+0.5*np.cos(u+t))*np.sin(v)
fz=lambda v,t: 0.5*np.sin(u)
tval=np.arange(0,5,0.3)

def update(frame):
  ax.cla() #clearing previous axes
  ax.set_zlim(-2,2)
  ax.set_xlim(-2,2)
  ax.set_ylim(-2,2)
  xlist=fx(u,v, tval[frame]) 
  ylist=fy(u,v, tval[frame])
  zlist=fz(v,tval[frame])
  l=ax.plot_surface(xlist,ylist,zlist, cmap=cm.viridis)
  return l,

animation = FuncAnimation(fig, update,frames=len(tval),interval=(1/15)*1000)

enter image description here

jylls
  • 4,395
  • 2
  • 10
  • 21