2016-06-26 29 views
0

Ich stream Beschleunigungsmesser Daten von meinem Android-Handy und haben erfolgreich ein Live-Plot mit Matplotlib gebaut. Ich verwende den Komma-Operator, um den Plot dynamisch zu aktualisieren, aber ich frage mich, ob es eine elegantere/pythischere Art gibt, es zu tun. Um den folgenden Code auszuführen, müssen Sie die App Sensorstream IMU+GPS verwenden. Der folgende Code erfasst die Beschleunigungsmesserwerte und zeichnet sie live auf. Ich basierte das Plotten auf Can you plot live data in matplotlib?. Wie ich schon sagte, es funktioniert, aber der Code ist ungeschickt. Auch bei den in der matplotlib documentation genannten Beschleunigungen liege ich bei ca. 25 FPS. Die Technik, wenn ich nur eine einfache Grafik verwende, kann bis zu 90 FPS erreichen. Es kann gezeigt werden, dass Sie ~ 200 FPS schneller hier erreichen können why is plotting with Matplotlib so slow?. Ich kann meinen Engpass nicht finden. Gibt es also eine elegantere Methode, um alle Subplots zu kodieren? Zweitens, kann ich das Plotten beschleunigen?Plotten von Streaming-Daten in Matplotlib: Die Notwendigkeit für die Geschwindigkeit

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) 

Antwort

0

Wie in der Matplotlib documentation erwähnt benötigen Sie einen subplot zu plot bevor ein neues Grundstück auf die aktuelle Zahl hinzugefügt wird. Es erwähnt plt.figure(x) ist optional, aber es wird empfohlen, dies zu tun. Ich würde den folgenden Code anhängen, um mehrere Sub-Plots zu plotten.

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

plt.subplot(212) 
plt.plot('''Data''') 
plt.draw() 
+0

Vielleicht vermisse ich etwas, aber könnten Sie ein wenig genauer sein, wie dies die Fragen beantwortet? – superhero

+0

Ich wollte sagen, Sie müssen die Ergebnisse vor dem Zeichnen() 'plotten()'. Auf diese Weise weiß der Interpreter, dass die Leinwand mit Unterparzellen gefüllt ist. –