我一直在开发一个用于从串口读取连续数据的GUI。在读取数据之后,进行一些计算并且将绘制和刷新结果(也称为动态绘图)。为此,我使用matplotlib中提供的wx后端。为此,我基本上使用一个数组来存储我的结果,在每次计算之后我会继续将其附加到其中,并重新绘制整个图形。为了使其“动态”,我只为每次迭代设置x轴下限和上限。有点像:
http://eli.thegreenplace.net/2008/08/01/matplotlib-with-wxpython-guis/
然而,问题在于,由于数据是连续的,并且如果我一直在绘制它,最终系统内存将耗尽并且系统将崩溃。还有其他方法可以连续绘制我的结果吗?
答案 0 :(得分:3)
为此,我基本上使用一个数组 存储我的结果,我保留 将其附加到
尝试通过删除旧数据或删除每个第n个条目来限制此数组的大小(屏幕分辨率将阻止所有条目的显示)。我假设您将所有数据写入磁盘,这样您就不会丢失任何东西。
另外,分析代码是否存在内存泄漏。你使用的东西,不再需要,但不会被垃圾收集,因为你仍然有一个参考。
答案 1 :(得分:1)
我用pythons Tkinter创建了这样一个组件。来源是here。
基本上,您必须将绘制的数据保留在某处。您无法在内存中保留大量数据点,因此您必须将其保存到磁盘或者必须覆盖旧数据点。
答案 2 :(得分:1)
数据和数据表示是两回事。如果要在以后分析重要数据,您可能希望将数据存储到磁盘,但只能保留固定的时间段或最后N个点用于显示目的。您甚至可以让用户选择要显示的时间范围。
答案 3 :(得分:0)
我实际上遇到了这个问题(更多的是心理障碍,实际上......)。
首先,我从wx Demo Code复制粘贴了一些wx Plot代码。
我所做的是保存一个值的实时日志,并将其与两个标记(min和max,显示为红色和绿色虚线)进行比较(但我将使这两个标记可选 - 因此是可选参数)。
为了实现实时日志,我首先想要使用deque类,但由于数据处于元组模式(x,y坐标),我放弃了,只是尝试重写元组的整个参数列表:请参阅_update_coordinates。
它可以很好地跟踪最后100-10,000个地块。本来也会包含一个版画屏幕,但我在stackoverflow上做的太多了不允许:))
我的实时参数在115kbps UART上每0.25秒更新一次。
诀窍在最后,在自定义刷新方法中!
以下是大部分代码:
class DefaultPlotFrame(wx.Frame):
def __init__(self, ymin=0, ymax=MAXIMUM_PLOTS, minThreshold=None,
maxThreshold=None, plotColour='blue',
title="Default Plot Frame",
position=(10,10),
backgroundColour="yellow", frameSize=(400,300)):
self.minThreshold = minThreshold
self.maxThreshold = maxThreshold
self.frame1 = wx.Frame(None, title="wx.lib.plot", id=-1, size=(410, 340), pos=position)
self.panel1 = wx.Panel(self.frame1)
self.panel1.SetBackgroundColour(backgroundColour)
self.ymin = ymin
self.ymax = ymax
self.title = title
self.plotColour = plotColour
self.lines = [None, None, None]
# mild difference between wxPython26 and wxPython28
if wx.VERSION[1] < 7:
self.plotter = plot.PlotCanvas(self.panel1, size=frameSize)
else:
self.plotter = plot.PlotCanvas(self.panel1)
self.plotter.SetInitialSize(size=frameSize)
# enable the zoom feature (drag a box around area of interest)
self.plotter.SetEnableZoom(False)
# list of (x,y) data point tuples
self.coordinates = []
for x_item in range(MAXIMUM_PLOTS):
self.coordinates.append((x_item, (ymin+ymax)/2))
self.queue = deque(self.coordinates)
if self.maxThreshold!=None:
self._update_max_threshold()
#endif
if self.lockThreshold!=None:
self._update_min_threshold()
#endif
self.line = plot.PolyLine(self.coordinates, colour=plotColour, width=1)
self.lines[0] = (self.line)
self.gc = plot.PlotGraphics(self.lines, title, 'Time', 'Value')
self.plotter.Draw(self.gc, xAxis=(0, MAXIMUM_PLOTS), yAxis=(ymin, ymax))
self.frame1.Show(True)
def _update_max_threshold(self):
if self.maxThreshold!=None:
self.maxCoordinates = []
for x_item in range(MAXIMUM_PLOTS):
self.maxCoordinates.append((x_item, self.maxThreshold))
#endfor
self.maxLine = plot.PolyLine(self.maxCoordinates, colour="green", width=1)
self.maxMarker = plot.PolyMarker(self.maxCoordinates, colour="green", marker='dot')
self.lines[1] = self.maxMarker
#endif
def _update_live_param(self, liveParam, minParam, maxParam):
if minParam!=None:
self.minThreshold = int(minParam)
self._update_min_threshold()
#endif
if maxParam!=None:
self.maxThreshold = int(maxParam)
self._update_max_threshold()
#endif
if liveParam!=None:
self._update_coordinates(int(liveParam))
#endif
def _update_coordinates(self, newValue):
newList = []
for x,y in self.coordinates[1:]:
newList.append((x-1, y))
#endfor
newList.append((x, newValue))
print "New list", newList
self.line = (plot.PolyLine(newList, colour=self.plotColour, width=1))
self.lines[0] = self.line
self.coordinates = newList
def _MyLIVE_MAGIC_refresh__(self, liveParam=None, minParam=None, maxParam=None):
self._update_live_param(liveParam, minParam, maxParam)
self.gc = plot.PlotGraphics(self.lines, self.title, 'Time', 'Value')
self.plotter.Draw(self.gc, xAxis=(0, MAXIMUM_PLOTS), yAxis=(self.ymin, self.ymax))
self.plotter.Refresh()
self.frame1.Refresh()