这个问题实际上是建立在我上周发布的问题之上的(How to partial fill_between in matplotlib, as in different colors for different values)
我试着在CAN总线上记录每秒的数据量,并将其绘制在图表上。我为这么多代码提前道歉,但是我尝试的三种方法有些相似
这是一种静态情况,有效:
import matplotlib
matplotlib.use('Qt5Agg')
from matplotlib import pyplot as plt
import sys
from collections import deque
import logging
import time
logging.basicConfig(level=logging.INFO)
buffer_size = 120
lvl = buffer_size * [100]
llvl = buffer_size * [95]
t = [t for t in range(buffer_size)]
bitthrough = deque(buffer_size*[0], buffer_size)
y = [107, 108, 105, 109, 107, 106, 107, 109, 106, 106, 94, 93, 94, 93, 93, 94, 95, 106, 108, 109, 107, 107, 106, 108, 105, 108, 107, 106, 107, 97, 93, 96, 94, 96, 95, 94, 104, 107, 106, 108, 107, 107, 106, 107, 105, 107, 108, 105, 107, 100, 93, 94, 93, 95, 104, 107, 107, 108, 108, 107, 107, 107, 107, 104, 94, 96, 95, 96, 94, 95, 94, 100, 107, 107, 105, 107, 107, 109, 107, 108, 107, 105, 108, 108, 106, 97, 94, 94, 94, 94, 95, 94, 94, 94, 96, 108, 108, 107, 106, 107, 107, 108, 107, 106, 95, 95, 95, 94, 94, 96, 105, 108, 107, 106, 106, 108, 107, 108, 106, 107]
bitthrough = y
fig, ax = plt.subplots()
ax.set_ylim(0, 120)
ax.set_xlim(0, 120)
ln, = plt.plot([], color='black')
plt.ion()
plt.show()
while True:
plt.pause(1)
ln.set_xdata(range(buffer_size))
ln.set_ydata(bitthrough)
wh_green = [a <= b for a,b in zip(bitthrough, llvl)]
wh_orange = [a > b and a <= c for a, b, c in zip(bitthrough, llvl, lvl)]
wh_red = [a > b for a, b, in zip(bitthrough, lvl)]
ax.fill_between(t, 0, bitthrough, where=wh_red, color='red', interpolate=True)
ax.fill_between(t, 0, bitthrough, where=wh_orange, color='orange', interpolate=True)
ax.fill_between(t, 0, bitthrough, where=wh_green, color='green', interpolate=True)
fig.canvas.draw_idle()
但是,当我想使用线程实时更新图形时,情况就不一样了。这是我的密码canbus
是我用来监视can总线的模块PCAN.throughput()
是一个asyncio协程函数,它统计一秒钟内的消息数。在传递第二个之后,它返回它在总线上接收到的千字节数。终端显示bitthrough
的内容,该内容被填充到一个单独的线程中
from canbus import PCAN
import matplotlib
matplotlib.use('Qt5Agg')
from matplotlib import pyplot as plt
import sys
import asyncio
from collections import deque
import logging
import time
import threading
from matplotlib.figure import Figure
logging.basicConfig(level=logging.INFO)
buffer_size = 120
lvl = buffer_size * [100]
llvl = buffer_size * [95]
t = [t for t in range(buffer_size)]
loop = asyncio.get_event_loop()
cn = PCAN()
loop.run_until_complete(cn.poll_ids())
loop.run_until_complete(cn.get_names())
print(cn.names)
bitthrough = deque(buffer_size*[0], buffer_size)
def get_bt(loop):
asyncio.set_event_loop(loop)
while True:
task = loop.run_until_complete(cn.throughput())
bitthrough.append(task[0] / 33. * 100.)
print(bitthrough)
thread = threading.Thread(target=get_bt, args=(loop,))
thread.daemon = True
thread.start()
fig, ax = plt.subplots()
ax.set_ylim(0, 120)
ax.set_xlim(0, 120)
ln, = plt.plot([], color='black')
plt.ion()
plt.show()
while True:
plt.pause(1)
ln.set_xdata(range(buffer_size))
ln.set_ydata(bitthrough)
wh_green = [a <= b for a,b in zip(bitthrough, llvl)]
wh_orange = [a > b and a <= c for a, b, c in zip(bitthrough, llvl, lvl)]
wh_red = [a > b for a, b, in zip(bitthrough, lvl)]
ax.fill_between(t, 0, bitthrough, where=wh_red, color='red', interpolate=True)
ax.fill_between(t, 0, bitthrough, where=wh_orange, color='orange', interpolate=True)
ax.fill_between(t, 0, bitthrough, where=wh_green, color='green', interpolate=True)
fig.canvas.draw_idle()
此代码产生以下结果:
注意红色是如何保持在以前的最高水平的
我还尝试用matplotlib的Qt后端实现它。然而,我只是得到了一个无法更新的空图(如果没有线程,这个方法是有效的,但它使我的计算机陷入困境,使我无法做其他事情)
from canbus import PCAN
# import numpy as np
import matplotlib
matplotlib.use('Qt5Agg')
from matplotlib import pyplot as plt
from matplotlib.animation import FuncAnimation
import sys
import asyncio
from collections import deque
import logging
import time
import threading
import datetime
from matplotlib.backends.qt_compat import QtCore, QtWidgets
from matplotlib.backends.backend_qt5agg import (
FigureCanvas, NavigationToolbar2QT as NavigationToolbar)
from matplotlib.figure import Figure
logging.basicConfig(level=logging.INFO)
buffer_size = 120
lvl = buffer_size * [100]
llvl = buffer_size * [95]
t = [t for t in range(buffer_size)]
loop = asyncio.get_event_loop()
cn = PCAN()
loop.run_until_complete(cn.poll_ids())
loop.run_until_complete(cn.get_names())
print(cn.names)
bitthrough = deque(buffer_size*[0], buffer_size)
def get_bt(loop):
asyncio.set_event_loop(loop)
while True:
task = loop.run_until_complete(cn.throughput())
bitthrough.append(task[0] / 33. * 100.)
print(bitthrough)
thread = threading.Thread(target=get_bt, args=(loop,))
thread.daemon = True
thread.start()
class ApplicationWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self._main = QtWidgets.QWidget()
self.setCentralWidget(self._main)
layout = QtWidgets.QVBoxLayout(self._main)
dynamic_canvas = FigureCanvas(Figure(figsize=(5, 3)))
layout.addWidget(dynamic_canvas)
self._dynamic_ax = dynamic_canvas.figure.subplots()
self._update_canvas()
def _update_canvas(self):
# p = loop.run_until_complete(cn.throughput())[0] / 500. * 100.
# bitthrough.append(p)
wh_green = [a <= b for a,b in zip(bitthrough, llvl)]
wh_orange = [a > b and a <= c for a, b, c in zip(bitthrough, llvl, lvl)]
wh_red = [a > b for a, b, in zip(bitthrough, lvl)]
self._dynamic_ax.clear()
self._dynamic_ax.fill_between(t, 0, bitthrough, where=wh_red, color='red', interpolate=True)
self._dynamic_ax.fill_between(t, 0, bitthrough, where=wh_orange,color='orange', interpolate=True)
self._dynamic_ax.fill_between(t, 0, bitthrough, where=wh_green, color='green', interpolate=True)
self._dynamic_ax.plot(t, bitthrough, color="black")
self._dynamic_ax.set_ylim(0, 120)
logging.info("redrawing graph")
self._dynamic_ax.figure.canvas.draw()
if __name__ == "__main__":
qapp = QtWidgets.QApplication(sys.argv)
app = ApplicationWindow()
app.show()
qapp.exec_()
while True:
app._update_canvas()
time.sleep(1)
也不太好,我现在有点迷路了
我发现这个问题是我的最后一个解决方案(使用matplotlib的Qt后端)。我打电话来了
在Qt应用程序之外。所以这个图没有被更新,因此,一个空的图。将
app._update_canvas()
移动到类内部并使用QTimer
周期性地调用它,可以正确地绘制图形添加到
ApplicationWindow
的__init__
函数:相关问题 更多 >
编程相关推荐