【问题标题】:dynamic plotting in wxpythonwxpython中的动态绘图
【发布时间】:2010-11-13 23:05:02
【问题描述】:

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

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

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

【问题讨论】:

    标签: python wxpython matplotlib


    【解决方案1】:

    为此,我基本上使用数组 存储我的结果,我保存在其中 将其附加到

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

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

    【讨论】:

    • 我一直在想类似的事情;删除/限制数组的大小。你是对的,除了绘图之外,数据将被保存到磁盘中的一个文件中。不过,如果可能的话,我想创建一个功能,用户可以在其中查看整个/特定范围的绘图(除了我设置 x 轴限制的动态绘图)。
    【解决方案2】:

    我已经用 pythons Tkinter 创建了这样一个组件。来源是here

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

    【讨论】:

    • 是的,我同意,无限循环/追加是一场灾难。感谢分享代码,去看看。
    【解决方案3】:

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

    【讨论】:

    • 可能是这样的? 1.动态绘图:固定x-range,通过删除未使用的值来限制数组的大小。 2. 每个数据都写入磁盘中的文件 3. 用户定义绘图:从先前保存在磁盘中的数据中读取并绘制它
    • 类似的东西。在第 1 点中,您的意思可能是“最旧的”而不是“未使用的”:)
    【解决方案4】:

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

    首先,我从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()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多