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()
解决方法
问题根源
- 循环中重复定义
update_data函数和FuncAnimation实例,后续迭代会覆盖之前的对象,最终仅最后一条Trace的动画生效 - 循环内的
animated_plot和tr变量会被后续循环覆盖,导致update_data只能访问最后一条Trace的数据 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
相关产品推荐
相关产品推荐

