wxpython 中的动态绘图

发布于 2024-07-29 05:59:05 字数 450 浏览 1 评论 0原文

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

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

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

I have been developing a GUI for reading continuous data from a serial port. After reading the data, some calculations are made and the results will be plotted and refreshed (aka dynamic plotting). I use the wx backend provided in the matplotlib for this purposes. To do this, I basically use an array to store my results, in which I keep appending it to, after each calculation, and replot the whole graph. To make it "dynamic", I just set the x-axis lower and upper limits for each iteration. Something like found in:

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

The problem, however, is that since the data is continuous, and if I keep plotting it, eventually the system memory will run out and system will crash. Is there any other way I can plot my result continuously?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

眼趣 2024-08-05 05:59:05

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

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

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

To do this, I basically use an array
to store my results, in which I keep
appending it to

Try limiting the size of this array, either by deleting old data or by deleting every n-th entry (the screen resolution will prevent all entries to be displayed anyway). I assume you write all the data to disk so you won't lose anything.

Also, analise your code for memory leaks. Stuff you use and don't need anymore but that doesn't get garbage-collected because you still have a reference to it.

诗酒趁年少 2024-08-05 05:59:05

我用 pythons Tkinter 创建了这样一个组件。 来源位于此处

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

I have created such a component with pythons Tkinter. The source is here.

Basically, you have to keep the plotted data somewhere. You cannot keep an infinite amount of data points in memory, so you either have to save it to disk or you have to overwrite old data points.

半﹌身腐败 2024-08-05 05:59:05

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

Data and representation of data are two different things. You might want to store your data to disk if it's important data to be analyzed later, but only keep a fixed period of time or the last N points for display purposes. You could even let the user pick the time frame to be displayed.

ㄖ落Θ余辉 2024-08-05 05:59:05

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

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

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

为了实现实时日志,我首先想使用deque类,但由于数据是元组模式(x,y坐标),我放弃了,只是尝试重写元组的整个参数列表:请参阅_update_坐标。

它非常适合跟踪最后 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()

I actually ran into this problem (more of a mental block, actually...).

First of all I copy-pasted some wx Plot code from wx Demo Code.

What I do is keep a live log of a value, and compare it to two markers (min and max, shown as red and green dotted lines) (but I will make these 2 markers optional - hence the optional parameters).

In order to implement the live log, I first wanted to use the deque class, but since the data is in tuple mode (x,y coordinates) I gave up and just tried to rewrite the entire parameter list of tuples: see _update_coordinates.

It works just fine for keeping track of the last 100-10,000 plots. Would have also included a printscreen, but I'm too much of a noob at stackoverflow to be allowed :))

My live parameter is updated every 0.25 seconds over a 115kbps UART.

The trick is at the end, in the custom refresh method!

Here is most of the code:

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()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文