图例不适用于实时数据和 while 循环配置
Legend not working for live data and while loop configuration
我的代码从 raspberry pi 获取不断更新的输入,然后将其绘制到图表上。我正在尝试使用图例来显示当前频率(y_data 的最新输出),但我似乎无法显示它。将 plt.legend()
放在 plt.show()
之前会导致显示,但会冻结图形。任何帮助将不胜感激。
import matplotlib
matplotlib.use('qt5agg')
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
import RPi.GPIO as GPIO
import time
import numpy as np
x_data = []
y_data = []
GPIO.setmode(GPIO.BCM)
INPUT_PIN = 26
GPIO.setup(INPUT_PIN, GPIO.IN)
fig, ax = plt.subplots()
line, = plt.plot([],[], 'k-',label = 'data', drawstyle = 'steps')
avr, = plt.plot([],[], 'g--',label = 'mean')
plt.show(block = False)
def update(x_data, y_data, average):
line.set_ydata(y_data)
line.set_xdata(x_data)
avr.set_xdata(x_data)
avr.set_ydata([average]*len(x_data))
fig.canvas.draw()
ax.draw_artist(ax.patch)
ax.draw_artist(line)
ax.draw_artist(avr)
ax.relim()
ax.autoscale_view()
data = round(y_data[-1], 1)
ax.legend((line, avr), (data, 'mean'))
fig.canvas.update()
fig.canvas.flush_events()
while True: #Begin continuous loop
NUM_CYCLES = 10 #Loops to be averaged over
start = time.time()
for impulse_count in range(NUM_CYCLES):
GPIO.wait_for_edge(INPUT_PIN, GPIO.FALLING)
duration = time.time() - start #seconds to run for loop
frequency = NUM_CYCLES / duration #Frequency in Hz
bpm = (frequency/1000)*60 #Frequency / no. of cogs per breath * min
x_data.append(time.time()) #add new data to data lists
y_data.append(bpm)
average = sum(y_data)/float(len(y_data))
update(x_data,y_data, average) #call function to update graph contents
在 update
的末尾添加 plt.draw()
(或 fig.canvas.draw_idle()
以获得更面向对象的方法)。
我认为你应该在更新函数的末尾调用 fig.canvas.draw()
,而不是在它的中间。我不确定为什么要在更新功能中再次添加所有艺术家,所以您可以忽略它。关于图例,最好在开始时创建一次,在更新函数中只更新相关文本。
注释掉所有 GPIO 的东西,这是一个适合我的版本:
import matplotlib
#matplotlib.use('qt5agg')
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
#import RPi.GPIO as GPIO
import time
import numpy as np
x_data = []
y_data = []
#GPIO.setmode(GPIO.BCM)
#INPUT_PIN = 26
#GPIO.setup(INPUT_PIN, GPIO.IN)
fig, ax = plt.subplots()
line, = plt.plot([],[], 'k-',label = 'data', drawstyle = 'steps')
avr, = plt.plot([],[], 'g--',label = 'mean')
# add legend already at the beginning
legend = ax.legend((line, avr), (0.0, 'mean'))
plt.show(block = False)
def update(x_data, y_data, average):
line.set_ydata(y_data)
line.set_xdata(x_data)
avr.set_xdata(x_data)
avr.set_ydata([average]*len(x_data))
#fig.canvas.draw() <- use this at the end
#ax.draw_artist(ax.patch) # useless?
#ax.draw_artist(line) # useless?
#ax.draw_artist(avr) # useless?
ax.relim()
ax.autoscale_view()
data = round(y_data[-1], 1)
# only update legend here
legend.get_texts()[0].set_text(str(data))
#fig.canvas.update() # <- what is this one needed for?
fig.canvas.draw()
fig.canvas.flush_events()
while True: #Begin continuous loop
NUM_CYCLES = 10 #Loops to be averaged over
start = time.time()
#for impulse_count in range(NUM_CYCLES):
# GPIO.wait_for_edge(INPUT_PIN, GPIO.FALLING)
a = np.random.rand(700,800) # <- just something that takes a little time
duration = time.time() - start #seconds to run for loop
frequency = NUM_CYCLES / duration #Frequency in Hz
bpm = (frequency/1000)*60 #Frequency / no. of cogs per breath * min
x_data.append(time.time()) #add new data to data lists
y_data.append(bpm)
average = sum(y_data)/float(len(y_data))
update(x_data,y_data, average) #call function to update graph contents
我的代码从 raspberry pi 获取不断更新的输入,然后将其绘制到图表上。我正在尝试使用图例来显示当前频率(y_data 的最新输出),但我似乎无法显示它。将 plt.legend()
放在 plt.show()
之前会导致显示,但会冻结图形。任何帮助将不胜感激。
import matplotlib
matplotlib.use('qt5agg')
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
import RPi.GPIO as GPIO
import time
import numpy as np
x_data = []
y_data = []
GPIO.setmode(GPIO.BCM)
INPUT_PIN = 26
GPIO.setup(INPUT_PIN, GPIO.IN)
fig, ax = plt.subplots()
line, = plt.plot([],[], 'k-',label = 'data', drawstyle = 'steps')
avr, = plt.plot([],[], 'g--',label = 'mean')
plt.show(block = False)
def update(x_data, y_data, average):
line.set_ydata(y_data)
line.set_xdata(x_data)
avr.set_xdata(x_data)
avr.set_ydata([average]*len(x_data))
fig.canvas.draw()
ax.draw_artist(ax.patch)
ax.draw_artist(line)
ax.draw_artist(avr)
ax.relim()
ax.autoscale_view()
data = round(y_data[-1], 1)
ax.legend((line, avr), (data, 'mean'))
fig.canvas.update()
fig.canvas.flush_events()
while True: #Begin continuous loop
NUM_CYCLES = 10 #Loops to be averaged over
start = time.time()
for impulse_count in range(NUM_CYCLES):
GPIO.wait_for_edge(INPUT_PIN, GPIO.FALLING)
duration = time.time() - start #seconds to run for loop
frequency = NUM_CYCLES / duration #Frequency in Hz
bpm = (frequency/1000)*60 #Frequency / no. of cogs per breath * min
x_data.append(time.time()) #add new data to data lists
y_data.append(bpm)
average = sum(y_data)/float(len(y_data))
update(x_data,y_data, average) #call function to update graph contents
在 update
的末尾添加 plt.draw()
(或 fig.canvas.draw_idle()
以获得更面向对象的方法)。
我认为你应该在更新函数的末尾调用 fig.canvas.draw()
,而不是在它的中间。我不确定为什么要在更新功能中再次添加所有艺术家,所以您可以忽略它。关于图例,最好在开始时创建一次,在更新函数中只更新相关文本。
注释掉所有 GPIO 的东西,这是一个适合我的版本:
import matplotlib
#matplotlib.use('qt5agg')
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
#import RPi.GPIO as GPIO
import time
import numpy as np
x_data = []
y_data = []
#GPIO.setmode(GPIO.BCM)
#INPUT_PIN = 26
#GPIO.setup(INPUT_PIN, GPIO.IN)
fig, ax = plt.subplots()
line, = plt.plot([],[], 'k-',label = 'data', drawstyle = 'steps')
avr, = plt.plot([],[], 'g--',label = 'mean')
# add legend already at the beginning
legend = ax.legend((line, avr), (0.0, 'mean'))
plt.show(block = False)
def update(x_data, y_data, average):
line.set_ydata(y_data)
line.set_xdata(x_data)
avr.set_xdata(x_data)
avr.set_ydata([average]*len(x_data))
#fig.canvas.draw() <- use this at the end
#ax.draw_artist(ax.patch) # useless?
#ax.draw_artist(line) # useless?
#ax.draw_artist(avr) # useless?
ax.relim()
ax.autoscale_view()
data = round(y_data[-1], 1)
# only update legend here
legend.get_texts()[0].set_text(str(data))
#fig.canvas.update() # <- what is this one needed for?
fig.canvas.draw()
fig.canvas.flush_events()
while True: #Begin continuous loop
NUM_CYCLES = 10 #Loops to be averaged over
start = time.time()
#for impulse_count in range(NUM_CYCLES):
# GPIO.wait_for_edge(INPUT_PIN, GPIO.FALLING)
a = np.random.rand(700,800) # <- just something that takes a little time
duration = time.time() - start #seconds to run for loop
frequency = NUM_CYCLES / duration #Frequency in Hz
bpm = (frequency/1000)*60 #Frequency / no. of cogs per breath * min
x_data.append(time.time()) #add new data to data lists
y_data.append(bpm)
average = sum(y_data)/float(len(y_data))
update(x_data,y_data, average) #call function to update graph contents