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

如何在Python/Octave/Julia中制作带非静态轨迹的动态参数图

动态参数轨迹绘图说明

标注后的绘图截图

使用背景

  • 使用的应用:everycircuit
  • 示例电路(左侧边栏书本图标):"LED Array"、"RC step response"

绘图特性

  • 这是一张参数图,纵轴为若干物理量(图中#3标注的图例),横轴为一个物理量(图中#2标注的图例)
  • 所有数值随单一参数(时间)变化
  • 绘图轨迹会保留一段时间后自动清除:保留轨迹便于查看系统稳定状态,清除则能在系统特性变化时简化绘图,聚焦新的相关区域

问题

如何在Python、Octave、Julia等代码类数据分析软件中实现此类动画?

动画需满足的要求

  • 数值随参数动态更新(常规绘图的动态更新)
  • 轨迹仅保留一段时间(非静态轨迹)
  • 支持调整参数并查看对应的数据点(即“追踪”绘图)

Python 实现示例

用matplotlib的FuncAnimation实现,通过固定长度的缓冲区控制轨迹保留时长,结合滑块可实时调整参数:

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

# 轨迹保留点数(对应时长)
max_points = 100
t = 0.0
x_data, y1_data, y2_data = [], [], []

# 初始化绘图
fig, ax = plt.subplots()
line1, = ax.plot([], [], label='物理量1')
line2, = ax.plot([], [], label='物理量2')
ax.set_xlabel('横轴物理量')
ax.set_ylabel('纵轴物理量')
ax.legend()
ax.set_xlim(0, 10)
ax.set_ylim(-1.5, 1.5)

# 动态更新函数
def update(frame):
    global t
    # 模拟随时间变化的物理量(可替换为真实计算逻辑)
    x = t
    y1 = np.sin(t)
    y2 = np.cos(t)
    
    # 添加新数据
    x_data.append(x)
    y1_data.append(y1)
    y2_data.append(y2)
    
    # 超过长度则删除旧数据,实现轨迹清除
    if len(x_data) > max_points:
        x_data.pop(0)
        y1_data.pop(0)
        y2_data.pop(0)
    
    # 更新线条
    line1.set_data(x_data, y1_data)
    line2.set_data(x_data, y2_data)
    
    # 自动跟随横轴最新数据
    ax.set_xlim(max(0, x - 10), x)
    
    t += 0.1
    return line1, line2

# 启动动画
ani = FuncAnimation(fig, update, interval=50, blit=True)
plt.show()

如果需要实时调整参数,可结合ipywidgets在Jupyter环境中添加滑块:

import ipywidgets as widgets
from IPython.display import display

freq_slider = widgets.FloatSlider(min=0.5, max=2.0, value=1.0, description='频率:')
display(freq_slider)

def update_with_param(frame):
    global t
    freq = freq_slider.value
    x = t
    y1 = np.sin(freq * t)
    y2 = np.cos(freq * t)
    
    x_data.append(x)
    y1_data.append(y1)
    y2_data.append(y2)
    
    if len(x_data) > max_points:
        x_data.pop(0)
        y1_data.pop(0)
        y2_data.pop(0)
    
    line1.set_data(x_data, y1_data)
    line2.set_data(x_data, y2_data)
    ax.set_xlim(max(0, x - 10), x)
    
    t += 0.1
    return line1, line2

ani = FuncAnimation(fig, update_with_param, interval=50, blit=True)
plt.show()

Octave 实现示例

利用Octave的animatedline和定时器实现,通过控制数据点数量限制轨迹时长:

max_points = 100;
t = 0.0;

fig = figure();
ax = axes('XLabel', '横轴物理量', 'YLabel', '纵轴物理量');
line1 = animatedline('Color', 'b', 'DisplayName', '物理量1');
line2 = animatedline('Color', 'r', 'DisplayName', '物理量2');
legend(ax);
xlim(ax, [0, 10]);
ylim(ax, [-1.5, 1.5]);

% 更新绘图的回调函数
function update_plot(obj, event)
    global t max_points line1 line2 ax;
    freq = 1.0;
    x = t;
    y1 = sin(freq * t);
    y2 = cos(freq * t);
    
    % 添加新数据点
    addpoints(line1, x, y1);
    addpoints(line2, x, y2);
    
    % 清除超出长度的旧数据
    if numpoints(line1) > max_points
        removepoints(line1, 1);
        removepoints(line2, 1);
    end
    
    % 跟随横轴最新数据
    xlim(ax, [max(0, x-10), x]);
    t += 0.1;
end

% 启动定时器,固定间隔更新
timer_obj = timer('ExecutionMode', 'fixedRate', 'Period', 0.05, 'TimerFcn', @update_plot);
start(timer_obj);

% 停止动画:stop(timer_obj); delete(timer_obj);

添加参数调整滑块:

freq_slider = uicontrol('Style', 'slider', 'Min', 0.5, 'Max', 2.0, 'Value', 1.0, ...
                        'Position', [20, 20, 120, 20]);

% 修改update_plot中的freq为:
freq = get(freq_slider, 'Value');

Julia 实现示例

用Plots.jl结合循环维护数据缓冲区,实现实时轨迹更新:

using Plots
gr()

max_points = 100
t = 0.0
x_data = Float64[]
y1_data = Float64[]
y2_data = Float64[]

# 初始化绘图
plt = plot(xlabel="横轴物理量", ylabel="纵轴物理量", legend=true, xlims=(0,10), ylims=(-1.5,1.5))
line1 = plot!(plt, [], [], label="物理量1", linecolor=:blue)[1]
line2 = plot!(plt, [], [], label="物理量2", linecolor=:red)[1]

# 实时更新循环
while true
    freq = 1.0
    x = t
    y1 = sin(freq * t)
    y2 = cos(freq * t)
    
    push!(x_data, x)
    push!(y1_data, y1)
    push!(y2_data, y2)
    
    # 清除旧数据
    if length(x_data) > max_points
        popfirst!(x_data)
        popfirst!(y1_data)
        popfirst!(y2_data)
    end
    
    # 更新线条数据
    line1[:x] = x_data
    line1[:y] = y1_data
    line2[:x] = x_data
    line2[:y] = y2_data
    
    # 跟随横轴最新数据
    xlims!(plt, max(0, x-10), x)
    
    display(plt)
    sleep(0.05)
    t += 0.1
end

添加参数调整滑块(需Interact.jl):

using Interact

freq_slider = slider(0.5:0.1:2.0, value=1.0, label="频率")

@manipulate for freq in freq_slider
    # 替换循环中的freq变量,其余逻辑同上
end

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 17:45:49