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

问题描述 投票:0回答:1

我想做的是使用 Matplotlib 绘制轨道模拟的数据;下面附有我想要实现的目标的示例。

我有行星以及航天器相对于太阳的 X、Y、Z、时间坐标的数据(或者如果需要,我可以重新运行以获取其他坐标系中的数据)。

如何制作这样的 GIF?

我尝试只使用 x,y 的 pyplot,但我只得到一个平面图像,而不是移动的 GIF。(正如预期的那样,因为 PyPlot 只能制作静态图)。非常感谢任何帮助/指向我可以查看的地方。

python matplotlib animated-gif astronomy
1个回答
0
投票

可以使用

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


最终结果

这是我使用 matplotlib

FuncAnimation
创建的虚拟动画。它基于问题的想法(尽管使用虚拟数据)。

代码

这是生成上述动画的代码 -

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. 创建数据。您可以从任何数据库计算或加载数据。在上面的代码中,我们正在计算数据。创建帧时,还会在更新函数中计算一些数据。此外,代码中还有一些额外的方便参数,例如
    fps
    total_time
    time_ratio
  2. 初始化 matplotlib 图形和轴 (
    fig, ax = plt.subplots()
    ),然后定义
    update
    函数,该函数将帧号作为输入并为该帧号创建图形。
  3. 使用
    FuncAnimation
    创建动画。在代码中,我们使用
    FuncAnimation(fig, update, frames = range(total_frames), interval = interval*1000)
    来完成此操作。我们指定帧来匹配我们想要的时间,指定间隔来匹配我们想要的动画 FPS。
  4. 最后,查看/保存动画。如需查看,请致电
    plt.show()
    。要保存,请调用
    anim.save()
    ,在其中指定输出文件的路径以及文件名和 fps 以计算我们想要的 FPS。

注意:

anim.save()
指定的文件名中的扩展名用于决定导出格式。在
ffmpeg
的帮助下支持其他格式。要获得对其他格式的支持,请安装
ffmpeg
并在
writer='ffmpeg'
中指定
anim.save()

© www.soinside.com 2019 - 2024. All rights reserved.