You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Matplotlib多Trace动画异常:仅单次绘制单条Trace问题求助

问题

尝试使用Matplotlib Animation对多Trace数据制作动画,期望同时绘制Stream中的所有Trace,但当前代码每次运行仅能绘制一条Trace。以下是我的代码:

from obspy import read
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

st = read('300/*')
st = st.select(component='Z')
tr0 = st[0]
seed_ids = {tr.stats.station for tr in st}
t1 = np.arange(0, tr0.stats.npts/tr0.stats.sampling_rate, tr0.stats.delta)

fig, axis = plt.subplots(nrows=len(st))

# anim=[]
for ax, seed_id, tr in zip(axis, seed_ids, st):
    ax.set_xlim([min(t1), max(t1)])
    ax.set_ylim([min(tr.data), max(tr.data)])
    ax.set_xlabel('time[S]')
    ax.set_ylabel(f'{seed_id}')
    animated_plot, = ax.plot([],[])

    def update_data(frame):
        animated_plot.set_data(t1[:frame], tr.data[:frame])
        return animated_plot,

animation = FuncAnimation(fig=fig,
                         func=update_data,
                         frames=len(t1),
                         interval=10,
                         blit=True,
                         repeat_delay=1000,
)

plt.show()
解决方法

问题根源

  1. 循环中重复定义update_data函数和FuncAnimation实例,后续迭代会覆盖之前的对象,最终仅最后一条Trace的动画生效
  2. 循环内的animated_plot和tr变量会被后续循环覆盖,导致update_data只能访问最后一条Trace的数据
  3. seed_ids用集合存储是无序的,可能导致子图站点标注和对应Trace不匹配

修改后的完整代码

from obspy import read
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

st = read('300/*')
st = st.select(component='Z')
tr0 = st[0]
seed_ids = [tr.stats.station for tr in st]  # 改用列表保证顺序匹配
t1 = np.arange(0, tr0.stats.npts/tr0.stats.sampling_rate, tr0.stats.delta)

fig, axis = plt.subplots(nrows=len(st))
if len(st) == 1:  # 处理单Trace边界情况,避免axis不是数组
    axis = [axis]

# 存储所有动画线条和对应Trace数据
plots = []
traces = []

for ax, seed_id, tr in zip(axis, seed_ids, st):
    ax.set_xlim([min(t1), max(t1)])
    ax.set_ylim([min(tr.data), max(tr.data)])
    ax.set_xlabel('time[S]')
    ax.set_ylabel(f'{seed_id}')
    animated_plot, = ax.plot([], [])
    plots.append(animated_plot)
    traces.append(tr)

def update_all(frame):
    # 遍历所有线条和数据,逐个更新
    for plot, tr in zip(plots, traces):
        plot.set_data(t1[:frame], tr.data[:frame])
    # 返回所有需要更新的对象
    return plots

animation = FuncAnimation(fig=fig,
                         func=update_all,
                         frames=len(t1),
                         interval=10,
                         blit=True,
                         repeat_delay=1000,
)

plt.show()

关键改动说明

  • 把seed_ids改为列表,确保子图的站点标注和对应Trace顺序一致
  • 新增plots和traces列表,保存每个子图的动画线条和对应数据,避免变量被循环覆盖
  • 定义统一的update_all函数,一次性更新所有子图的动画线条
  • 处理单Trace的边界情况,避免axis不是数组导致循环报错
  • update_all返回所有动画线条对象,确保Matplotlib能正确更新所有子图的内容

内容的提问来源于stack exchange,提问作者yaser

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 01:33:17