wxpython中的动态绘图

时间:2009-07-25 06:29:51

标签: python wxpython matplotlib

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

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

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

4 个答案:

答案 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()