matplotlib制作核素衰变动画首帧即显示完整曲线问题求助
代码核心问题
- 初始化
line1、line2两条曲线时,你直接传入了全量的N_I、N_Xe数据作为y值,即使后续修改x轴参数,y轴始终是完整的所有时间步结果,所以第一帧就会显示整条曲线。 animate函数逻辑错误:你没有随时间步截断y轴数据,反而把固定长度的x数据拉伸到0到j的区间,完全不符合逐步展示的需求。- 冗余计算问题:用循环迭代调用
odeint求解完全没有必要,odeint本身支持传入完整时间序列直接输出所有时间步的结果,循环写法不仅运行效率低,还容易引入计算误差。 - 原始绘图未指定x轴参数,默认x轴是数据点索引,不是实际的时间值,和你设置的x轴范围逻辑不符。
优化后的修正代码
# I135 Xe135 decay. """ EQUATIONS: dIdt = (-Lambda_I * N_I) dXedt = ((-Lambda_Xe * N_Xe) + (Lambda_I * N_I)) """ import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animation from scipy.integrate import odeint def model(z,t): """ INITIAL CONDITIONS: I(0) = 1e8 atoms Xe(0) = 0 atom PARAMETERS: Lambda_I Lambda_Xe """ Lambda_I = (np.log(2) / 6.57) Lambda_Xe = (np.log(2) / 9.2) N_I = z[0] N_Xe = z[1] dIdt = (-Lambda_I * N_I) dXedt = ((-Lambda_Xe * N_Xe) + (Lambda_I * N_I)) return [dIdt,dXedt] z0 = [1e8, 0.0] # initial conditions for N_Xe and N_I n = 10000 max_time = 100 t = np.linspace(0,max_time,n) # 一次调用odeint得到全量结果,无需循环迭代 z = odeint(model, z0, t) N_I = z[:, 0] N_Xe = z[:, 1] # 绘图初始化 fig, ax = plt.subplots(figsize=(8,8)) ax.set_ylim(0, 1e8) ax.set_xlim(0, max_time) # 初始化线条时传入空数据,后续动画逐步填充 line1, = ax.plot([], [], 'b-', linewidth=2, label='I-135') line2, = ax.plot([], [], 'g-.', linewidth=2, label='Xe-135') plt.rcParams['font.size'] = '14' plt.minorticks_on() plt.tick_params(axis="both", which="major", length=12, labelsize=12, width=1, color="black") plt.tick_params(axis="both", which="minor", length=6, labelsize=10, width=0.8, color="black") plt.title('I-135 Xe-135 Decay Sim.', fontsize=18) plt.xlabel('Time (h)', fontsize=16) plt.ylabel('N', fontsize=16) plt.legend(prop={'size': 12}) plt.grid(color = 'black', linestyle = '--', linewidth = 0.6) # 计算每帧对应的数据点数 step_per_frame = n // max_time def animate(j): # 只取到当前时间步对应的数据做展示 current_idx = j * step_per_frame line1.set_xdata(t[:current_idx]) line1.set_ydata(N_I[:current_idx]) line2.set_xdata(t[:current_idx]) line2.set_ydata(N_Xe[:current_idx]) return [line1, line2] ani = animation.FuncAnimation(fig, animate, frames=max_time, blit=True, interval=20, save_count=max_time) plt.show() # 保存路径请根据本地目录修改 f = r"C://Users/USER_NAME/Desktop/animation.gif" writergif = animation.PillowWriter(fps=30) ani.save(f, writer=writergif)
额外优化建议
- 可以在动画中添加当前时间的文本标注,更直观展示时间进度
- 如果觉得动画太快来不及观察,可适当调大
FuncAnimation的interval参数值(单位为毫秒) - 若需要更高清的GIF,可调整
PillowWriter的dpi参数
内容的提问来源于stack exchange,提问作者Said
相关产品推荐
相关产品推荐

