Python:matplotlib带缓冲区的livedata绘图,更高效的方式



我试图编写从真实对象绘制实时数据的脚本,但我需要更有效的方法。我认为问题是要始终存储相同数量的样本来绘制,并同时收集和绘制。我有一些代码,但我并不完全满意。

import time
from math import sin, cos
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
x_value = 0
x_list = []
y1_list = []
y2_list = []
props = dict(boxstyle='round', facecolor='wheat', alpha=0.5)
plt.rcParams['animation.html'] = 'jshtml'
fig, (ax1, ax2) = plt.subplots(2,1)
ax1.set_title("Power supply parameters")
ax1.set(ylabel='Voltage [V]')
ax2.set(xlabel='sample [n]', ylabel='Current [A]')
ax1.set_ylim(-1.5, 1.5)
ax2.set_ylim(-1.5,1.5)
ax1.grid(1)
ax2.grid(1)
box1 = ax1.text(.87, 0.95, str(0), transform=ax1.transAxes, fontsize=14,
verticalalignment='top', bbox=props)
box2 = ax2.text(0.87, 0.95, str(0), transform=ax2.transAxes, fontsize=14,
verticalalignment='top', bbox=props)
def annotate(last_y1, last_y2):
box1.set_text(str(round(last_y1,3)))
box2.set_text(str(round(last_y2,3)))
def data_gen(x_value):
x_value += 0.2
x_value = round(x_value,3)
total_1 = round(sin(x_value),3)
total_2 = round(cos(x_value),3)
time.sleep(0.1)
return (x_value,total_1,total_2)
def run(i):
global x_value ,x_list,y1_list, y2_list
x, y1, y2 = data_gen(x_value)
x_value += 0.2

if len(x_list) <=20:
x_list.append(x)
y1_list.append(y1)
y2_list.append(y2)
else:
x_list.append(x)
x_list.pop(0)
y1_list.append(y1)
y1_list.pop(0)
y2_list.append(y2)
y2_list.pop(0)
ax1.plot(x_list, y1_list, color='b')
ax2.plot(x_list, y2_list, color='r')  
ax1.set_xlim(left=max(0, x_list[-1] - 50), right=x_list[-1] + 10)
ax2.set_xlim(left=max(0, x_list[-1] - 50), right=x_list[-1] + 10)

annotate(y1_list[-1], y2_list[-1])
ani = FuncAnimation(fig, run, interval=10)
plt.show()

我想知道是否使用memoryview()为样本创建某种缓冲区,因为从列表中一次又一次地添加和弹出似乎太慢了,但我不知道如何使用它。

我很乐意为您提供建议:(

[编辑]以下为未来的固定版本:(

import time
from math import sin, cos
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from matplotlib.lines import Line2D      
x_value = 0
x_list = []
y1_list = []
y2_list = []
props = dict(boxstyle='round', facecolor='wheat', alpha=0.5)
plt.rcParams['animation.html'] = 'jshtml'
fig, (ax1, ax2) = plt.subplots(2,1)
ax1.set_title("Power supply parameters")
ax1.set(ylabel='Voltage [V]')
ax2.set(xlabel='sample [n]', ylabel='Current [A]')
ax1.set_ylim(-1.5, 1.5)
ax2.set_ylim(-1.5,1.5)
ax1.grid(1)
ax2.grid(1)
line1 = Line2D([0],[0.0],color='blue')
ax1.add_line(line1)
line2 = Line2D([0],[0.0],color='red')
ax2.add_line(line2)

box1 = ax1.text(.87, 0.95, str(0), transform=ax1.transAxes, fontsize=14,
verticalalignment='top', bbox=props)
box2 = ax2.text(0.87, 0.95, str(0), transform=ax2.transAxes, fontsize=14,
verticalalignment='top', bbox=props)
def annotate(last_y1, last_y2):
box1.set_text(str(round(last_y1,3)))
box2.set_text(str(round(last_y2,3)))
def data_gen(x_value):
x_value = round(x_value,3)
total_1 = round(sin(x_value),3)
total_2 = round(cos(x_value),3)
return (x_value,total_1,total_2)
def run(i):
global x_value ,x_list,y1_list, y2_list
x, y1, y2 = data_gen(x_value)
x_value += 0.2

if len(x_list) <=200:
x_list.append(x)
y1_list.append(y1)
y2_list.append(y2)
else:
x_list.append(x)
x_list.pop(0)
y1_list.append(y1)
y1_list.pop(0)
y2_list.append(y2)
y2_list.pop(0) 
ax1.set_xlim(left=max(0, x_list[-1] - 20), right=x_list[-1] + 10)
ax2.set_xlim(left=max(0, x_list[-1] - 20), right=x_list[-1] + 10)
line1.set_data(x_list,y1_list)
line2.set_data(x_list,y2_list)
annotate(y1_list[-1], y2_list[-1])
ani = FuncAnimation(fig, run, interval=1)
plt.show()

我要冒险说,存储数据的方式可能是代码中耗时最少的部分。

一个主要问题是,在每次迭代时都要创建新行,而应该创建2个Line2D对象并更新它们的数据(使用Line2D.set_data()(。请参见示例https://matplotlib.org/gallery/animation/unchained.html

最新更新