from matplotlib.animation import FuncAnimation
import matplotlib.pyplot as plt
import math
# dummy parameters, replace them with your own
sun_x, sun_y = 0, 0
voyager1_theta, voyager1_speed, voyager1_radius = 0, 0.003*math.pi, 40
planet1_theta, planet1_speed, planet1_radius = 0, 0.002*math.pi, 40
planet2_theta, planet2_speed, planet2_radius = 0, 0.001*math.pi, 90
fps = 10 # frames per second in animation
total_time = 5 # in seconds, total time of animation
time_ratio = 100 # in seconds, how many seconds in reality for every second on animation
# extra calculations
interval = 1/fps # in seconds
total_frames = total_time * fps
voyager_x_data = []
voyager_y_data = []
fig, ax = plt.subplots()
def update(frame):
# this function accepts the frame-number as frame and creates the figure for it
global ax
# dummy calculations, replace them with your own calculations
time = frame*interval*time_ratio # in seconds
voyager_x = (voyager1_radius+time/20) * math.cos(voyager1_speed*time + voyager1_theta)
voyager_y = (voyager1_radius+time/20) * math.sin(voyager1_speed*time + voyager1_theta)
voyager_x_data.append(voyager_x)
voyager_y_data.append(voyager_y)
planet1_x = planet1_radius * math.cos(planet1_speed*time + planet1_theta)
planet1_y = planet1_radius * math.sin(planet1_speed*time + planet1_theta)
planet2_x = planet2_radius * math.cos(planet2_speed*time + planet2_theta)
planet2_y = planet2_radius * math.sin(planet2_speed*time + planet2_theta)
# plotting
ax.clear() # clear the figure (to remove the contents of last frame)
ax.set_ylim(-100,100)
ax.set_xlim(-100,100)
ax.set_aspect('equal')
ax.set_title('Time = {:.3f} sec'.format(time))
ax.scatter(sun_x, sun_y, color = 'yellow', marker = 'o') #, label='Sun')
ax.scatter(planet1_x, planet1_y, color = 'blue', marker = 'o') #, label = 'Planet1')
ax.scatter(planet2_x, planet2_y, color = 'green', marker = 'o') #, label = 'Planet2')
ax.plot(voyager_x_data, voyager_y_data, color = 'red')
ax.scatter(voyager_x, voyager_y, color = 'red', label = 'Voyager')
ax.legend()
anim = FuncAnimation(fig, update, frames = range(total_frames), interval = interval*1000) # multiplying by 1000 to convert sec into milli-sec
anim.save('result.gif', fps = fps) # replace the name of file with your own path and name
#plt.show() # uncomment this line and comment out the second-last line to see in realtime instead of saving
1条答案
按热度按时间efzxgjgh1#
可以使用
matplotlib FuncAnimation
工具根据matplotlib中的数据创建动画。其思想是将动画视为帧的集合,并根据帧号定义每帧的图形/内容(假设这些帧是按升序排列的)。更多关于matplotlib动画的详细信息可以在官方网站的这个页面上找到:Matplotlib Animations。答案的其余部分专门针对该问题提供了一些指导。最终结果
下面是我用matplotlib
FuncAnimation
创建的一个虚拟动画,它是基于问题的思想(虽然有虚拟数据)。x1c 0d1x的数据
代码
下面是生成上述动画的代码-
字符串
解释说明
代码中的注解包含了阅读和使用代码时所需的所有辅助信息。本节包含了整体说明。
1.创建数据。您可以从任何数据库中计算或加载数据。在上面的代码中,我们正在计算数据。在创建帧时,更新函数中也会计算一些数据。此外,代码中还有一些额外的方便参数,如
fps
、total_time
、time_ratio
。1.初始化matplotlib图形和轴(
fig, ax = plt.subplots()
),然后定义update
函数,该函数将帧编号作为输入并创建该帧编号的图形。1.使用
FuncAnimation
创建动画。在代码中,我们使用FuncAnimation(fig, update, frames = range(total_frames), interval = interval*1000)
创建动画。我们指定帧以匹配我们想要的时间,并指定间隔以匹配我们想要的动画中的FPS。1.最后,查看/保存动画。要查看,请调用
plt.show()
。要保存,请调用anim.save()
,其中指定输出文件的路径沿着文件名和fps,以匹配我们想要的FPS。备注
1.指定给
anim.save()
的文件名扩展名用于确定导出格式。在ffmpeg
的帮助下,还支持其他格式。要获得对其他格式的支持,请安装ffmpeg
并在anim.save()
中指定writer='ffmpeg'
。1.在实时查看动画时,例如使用
plt.show()
,将frames=None
设置为FuncAnimation()
,因为我们不想指定动画运行的时间。我们希望它在我们查看时就运行。