2009-07-25 12 views
2

Ich habe eine GUI entwickelt, um kontinuierliche Daten von einer seriellen Schnittstelle zu lesen. Nach dem Lesen der Daten werden einige Berechnungen durchgeführt und die Ergebnisse werden geplottet und aktualisiert (aka dynamisches Plotten). Ich benutze das Wx-Backend, das zu diesem Zweck in der Matplotlib zur Verfügung gestellt wird. Um dies zu tun, benutze ich im Grunde ein Array, um meine Ergebnisse zu speichern, in denen ich es nach jeder Berechnung anhängt, und den gesamten Graphen neu zu plotten. Um es "dynamisch" zu machen, setze ich einfach die untere und obere Grenze der X-Achse für jede Iteration. So etwas wie in gefunden:dynamisches Plotten in wxpython

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

Das Problem besteht jedoch darin, dass, da die Daten kontinuierlich ist, und wenn ich behalte es Plotten, schließlich der Systemspeicher zur Neige gehen und System zum Absturz bringen. Gibt es eine andere Möglichkeit, wie ich mein Ergebnis kontinuierlich darstellen kann?

Antwort

3

Um dies zu tun, verwende ich im Grunde ein Array meine Ergebnisse zu speichern, in dem ich halten es

anhängt

Versuchen Sie, die eine Größe von Array zu begrenzen, sei es durch alte Daten zu löschen oder durch Löschen jedes n-ten Eintrags (die Bildschirmauflösung verhindert, dass alle Einträge trotzdem angezeigt werden). Ich nehme an, Sie schreiben alle Daten auf die Festplatte, damit Sie nichts verlieren.

Analysieren Sie auch Ihren Code auf Speicherlecks. Dinge, die Sie verwenden und nicht mehr benötigen, aber die nicht gesammelt werden, weil Sie immer noch einen Verweis darauf haben.

+0

Ich habe von ähnlicher Sache zu denken; Löschen/Beschränken der Größe des Arrays. Sie haben Recht, abgesehen von Plot werden die Daten in einer Datei auf der Festplatte gespeichert. Trotzdem möchte ich, wenn möglich, ein Feature erstellen, in dem der Benutzer den gesamten/bestimmten Bereich des Plottings anzeigen kann (zusätzlich zum dynamischen Plotten, bei dem ich die X-Achsen-Grenze festlege). – teonghan

1

Ich habe eine solche Komponente mit Pythons Tkinter erstellt. Die Quelle ist here.

Grundsätzlich müssen Sie die geplotteten Daten irgendwo halten. Sie können nicht unendlich viele Datenpunkte im Speicher behalten, Sie müssen sie entweder auf der Festplatte speichern oder alte Datenpunkte überschreiben.

+0

Ja, ich stimme zu, Endlosschleife/Anhängen ist eine Katastrophe. Vielen Dank für die Freigabe des Codes, wir werden es uns ansehen. – teonghan

1

Daten und Darstellung von Daten sind zwei verschiedene Dinge. Vielleicht möchten Sie Ihre Daten auf Festplatte speichern, wenn es wichtig ist, dass Daten später analysiert werden, aber nur einen festen Zeitraum oder die letzten N Punkte für Anzeigezwecke behalten. Sie können den Benutzer sogar den anzuzeigenden Zeitraum auswählen lassen.

+0

Vielleicht so etwas? 1. Dynamisches Plotten: fester x-Bereich, begrenzen Sie die Größe des Arrays durch Löschen nicht verwendeter Werte. 2. Alle Daten werden in eine Datei auf der Festplatte geschrieben 3. Benutzerdefiniertes Plotten: Aus den zuvor gespeicherten Daten in der Festplatte lesen und grafisch darstellen – teonghan

+0

So ähnlich. In Punkt 1 meinst du wahrscheinlich "älteste" und nicht "unbenutzt" :) – Mathieu

0

Ich lief tatsächlich in dieses Problem (eher eine mentale Blockade, eigentlich ...).

Zuerst kopierte ich einige wx Plot-Code von wx Demo Code.

Was ich mache, ist ein Live-Log von einem Wert, und vergleichen Sie es mit zwei Marker (min und max, als rote und grüne gepunktete Linien angezeigt) (aber ich werde diese 2 Marker optional - daher die optionalen Parameter) .

Um das Live-Log zu implementieren, wollte ich zuerst die Deque-Klasse verwenden, aber da die Daten im Tupel-Modus (x, y-Koordinaten) sind, gab ich auf und versuchte die gesamte Parameterliste der Tupel neu zu schreiben: siehe _update_coordinates.

Es funktioniert gut für die Verfolgung der letzten 100-10.000 Grundstücke. Wäre auch ein printscreen enthalten, aber ich bin zu viel noob bei stackoverflow erlaubt :))

Mein Live-Parameter wird alle 0,25 Sekunden über einen 115kbps UART aktualisiert.

Der Trick ist am Ende, in der benutzerdefinierten Refresh-Methode!

ist hier die meiste 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()