【问题标题】:Plotting of streaming data in matplotlib: The need for speed在 matplotlib 中绘制流数据:对速度的需求
【发布时间】:2016-10-28 10:23:31
【问题描述】:

我正在从我的 android 手机流式传输加速度计数据,并已使用 matplotlib 成功构建了一个实时绘图。我正在使用逗号运算符来动态更新绘图,但我想知道是否有更优雅/pythonic 的方式来做到这一点。要执行下面的代码,您必须使用应用程序Sensorstream IMU+GPS。下面的代码将获取加速度计值并实时绘制它们。我的绘图基于Can you plot live data in matplotlib?。就像我说的那样,它可以工作,但代码很笨拙。即使在matplotlib documentation 中提到了加速,我也以大约 25 FPS 的速度运行。该技术,如果我只使用一个简单的情节可以达到大约 90 FPS。可以证明,您可以在 why is plotting with Matplotlib so slow? 上实现更快的 ~200 FPS。我找不到我的瓶颈。那么,有没有更优雅的方式来编码所有的子图呢?第二,我可以加快绘图速度吗?

import socket, traceback
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
from scipy.signal import butter, lfilter,iirfilter,savgol_filter
import math
import pylab
from pylab import *
import time
import numpy as np


host = ''
port = 5555
 
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
s.bind((host, port))

# lists for plotting
Ax = [0.0] * 50
Ay = [0.0] * 50
Az = [0.0] * 50
G  = [0.0] * 50
x = [i for i in range(len(Ax))]
 
#used for debugging
 
fig = plt.figure(figsize=(16,10))

# raw data
ax = plt.subplot("311")
ax.set_xlim(0, 50)
ax.set_ylim(-2, 2)
ax.set_title("Raw acceleration data")
ax.set_ylabel("g$/m^2$",fontsize=18)
ax.hold(True)

line  = ax.plot(Ax,label='Acc x')[0]
line2 = ax.plot(Ay,label='Acc y')[0]
line3 = ax.plot(Az,label='Acc z')[0]

# filtered data
ax2 = plt.subplot("312")
ax2.set_xlim(0, 50)
ax2.set_ylim(-2, 2)
ax2.set_title(" acceleration data")
ax2.set_ylabel("g$/m^2$",fontsize=18)
ax2.hold(True)

f_line  = ax2.plot(Ax,label='Acc x')[0]
f_line2 = ax2.plot(Ay,label='Acc y')[0]
f_line3 = ax2.plot(Az,label='Acc z')[0]

# tilt angle plot
ax3 = plt.subplot("313")
ax3.set_ylim([-180,180])
ax3.set_title("Tilt Angles")
ax3.set_ylabel("degrees",fontsize=18)
t_line = ax3.plot(G)[0]

fig.suptitle('Three-axis accelerometer streamed from Sensorstream',fontsize=18)
plt.show(False)
plt.draw()

# cache the background
background = fig.canvas.copy_from_bbox(fig.bbox)

count = 0 
print("Success binding")
while 1:
    # time it
    tstart = time.time()
    message, address = s.recvfrom(8192)
    messageString = message.decode("utf-8")
    Acc = messageString.split(',')[2:5]
    Acc = [float(Acc[i])/10.0 for i in range(3)]
    
    # appending and deleting is order 10e-5 sec
    Ax.append(Acc[0])
    del Ax[0]
    Ay.append(Acc[1])
    del Ay[0]
    Az.append(Acc[2])
    del Az[0]
    G.append(np.sqrt(Ax[-1]**2 + Ay[-1]**2 + Az[-1]**2))
    del G[0]
    
    # filter
    acc_x_savgol = savgol_filter(Ax, window_length=5, polyorder=3)
    acc_y_savgol = savgol_filter(Ay, window_length=5, polyorder=3)
    acc_z_savgol = savgol_filter(Az, window_length=5, polyorder=3)
    
    tilt_angles = []
    for i,val in enumerate(G): 
        angle = math.atan2(Ax[i], -1*Ay[i]) * (180 / math.pi)
        if (math.isnan(angle)):
            tilt_angles.append(0)
        else:
            tilt_angles.append(angle)
            
    print(Ax[0],Ay[1],Az[2])   
    
    line.set_xdata(x)
    line.set_ydata(Ax)
    line2.set_xdata(x)
    line2.set_ydata(Ay)
    line3.set_xdata(x)
    line3.set_ydata(Az)
    ax.set_xlim(count, count+50)
    
    f_line.set_xdata(x)
    f_line.set_ydata(acc_x_savgol)
    f_line2.set_xdata(x)
    f_line2.set_ydata(acc_y_savgol)
    f_line3.set_xdata(x)
    f_line3.set_ydata(acc_z_savgol)
    ax2.set_xlim(count, count+50)

    t_line.set_xdata(x)
    t_line.set_ydata(tilt_angles)
    ax3.set_xlim(count, count+50)
    # restore background
    fig.canvas.restore_region(background)

    # redraw just the points
    ax.draw_artist(line)
    ax.draw_artist(line2)
    ax.draw_artist(line3)
    ax2.draw_artist(f_line)
    ax2.draw_artist(f_line2)
    ax2.draw_artist(f_line3)
    ax3.draw_artist(t_line)

    # fill in the axes rectangle
    fig.canvas.blit(fig.bbox)
    
    count+=1
    x = np.arange(count,count+50,1)
    
    # tops out at about 25 fps :|
    print "Total time for 1 plot is: ",(time.time() - tstart)

【问题讨论】:

    标签: python-2.7 matplotlib streaming accelerometer


    【解决方案1】:

    Matplotlib documentation 中所述,您需要在向当前图形添加新图之前plot 一个子图。它提到plt.figure(x) 是可选的,但建议这样做。我会附加以下代码来绘制多个子图。

    plt.figure(1)
    plt.subplot(211)
    plt.plot('''Data''')
    
    plt.subplot(212)
    plt.plot('''Data''')
    plt.draw()
    

    【讨论】:

    • 也许我遗漏了一些东西,但您能否更具体地说明一下这是如何回答问题的?
    • 我的意思是说你需要plot()draw()他们之前的结果。这样,解释器就知道画布上充满了子图。
    猜你喜欢
    • 1970-01-01
    • 2017-06-20
    • 2018-02-28
    • 1970-01-01
    • 1970-01-01
    • 2017-06-25
    • 2020-08-23
    • 1970-01-01
    • 2021-11-29
    相关资源
    最近更新 更多