python 如何创建随时间变化的MatPlotLib或类似图形?

myzjeezk  于 9个月前  发布在  Python
关注(0)|答案(1)|浏览(162)

我试图做的是使用Matplotlib绘制轨道模拟的数据;下面是我试图实现的一个例子。x1c 0d1x
我有行星的数据,以及航天器在X,Y,Z,时间坐标(或者如果必要的话,我可以在其他坐标系中获得它)相对于太阳。
我怎么能做一个这样的GIF?
我试着只使用x,y的pyplot,但不是移动GIF,我只得到一个平面图像。(正如预期的那样,因为PyPlot只能制作静态图)。任何帮助/指针,我可以看非常感谢。

efzxgjgh

efzxgjgh1#

可以使用matplotlib FuncAnimation工具根据matplotlib中的数据创建动画。其思想是将动画视为帧的集合,并根据帧号定义每帧的图形/内容(假设这些帧是按升序排列的)。更多关于matplotlib动画的详细信息可以在官方网站的这个页面上找到:Matplotlib Animations。答案的其余部分专门针对该问题提供了一些指导。

最终结果

下面是我用matplotlib FuncAnimation创建的一个虚拟动画,它是基于问题的思想(虽然有虚拟数据)。
x1c 0d1x的数据

代码

下面是生成上述动画的代码-

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.创建数据。您可以从任何数据库中计算或加载数据。在上面的代码中,我们正在计算数据。在创建帧时,更新函数中也会计算一些数据。此外,代码中还有一些额外的方便参数,如fpstotal_timetime_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(),因为我们不想指定动画运行的时间。我们希望它在我们查看时就运行。

相关问题