2

我一直在开发一个用于从串行端口读取连续数据的 GUI。读取数据后,会进行一些计算并绘制和刷新结果(也称为动态绘图)。为此,我使用 matplotlib 中提供的 wx 后端。为此,我基本上使用一个数组来存储我的结果,在每次计算之后,我一直将其附加到其中,并重新绘制整个图表。为了使其“动态”,我只是为每次迭代设置了 x 轴的下限和上限。类似于在以下位置找到的东西:

http://eli.thegreenplace.net/2008/08/01/matplotlib-with-wxpython-guis/

然而,问题在于,由于数据是连续的,如果我继续绘制它,最终系统内存将耗尽,系统将崩溃。有没有其他方法可以连续绘制我的结果?

4

4 回答 4

3

为此,我基本上使用一个数组来存储我的结果,并在其中不断将其附加到

尝试通过删除旧数据或删除每个第 n 个条目来限制此数组的大小(屏幕分辨率将阻止显示所有条目)。我假设您将所有数据写入磁盘,这样您就不会丢失任何东西。

此外,请分析您的代码是否存在内存泄漏。您使用并且不再需要的东西,但不会被垃圾收集,因为您仍然有对它的引用。

于 2009-07-25T07:01:02.243 回答
1

我用 pythons Tkinter 创建了这样一个组件。来源在这里

基本上,您必须将绘制的数据保存在某处。您不能在内存中保留无限数量的数据点,因此您必须将其保存到磁盘或覆盖旧数据点。

于 2009-07-25T12:00:36.633 回答
1

数据和数据的表示是两个不同的东西。如果数据是稍后分析的重要数据,您可能希望将数据存储到磁盘,但仅保留固定时间段或最后 N 个点以用于显示目的。您甚至可以让用户选择要显示的时间范围。

于 2009-07-25T12:23:40.653 回答
0

我实际上遇到了这个问题(实际上更多的是精神障碍......)。

首先,我从wx Demo Code复制粘贴了一些 wx Plot 代码。

我所做的是保留一个值的实时日志,并将其与两个标记(最小值和最大值,显示为红色和绿色虚线)进行比较(但我会将这两个标记设为可选 - 因此是可选参数)。

为了实现实时日志,我首先想使用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()
于 2011-10-19T15:19:34.707 回答