Messwerte jede Sekunde plotten

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
Tom Brady
User
Beiträge: 9
Registriert: Freitag 4. Dezember 2015, 07:13

Hallo,
ich möchte Werte, welche ich aus einer Textdatei auslesen will zeitlich darstellen.
Das heißt die y-Achse sind die Werte der Textdatei und die x-Achse ist die Zeit in Sekunden, welche den Plot jede Sekunde aktualisieren soll.
Dabei soll der Plot mittels Button gestartet und unterbrochen werden können (der Aufbau mit QtDesigner war kein Problem).

Leider kam ich mit meinen Versuchen mit “animation.FuncAnimation()“ nicht weiter.
Auch die Zeit mit timer.start(1000) – QtCore.Qtimer() - hab ich nicht zum laufen gebracht.

Könnt ihr mir bitte helfen?
Danke
Benutzeravatar
Sr4l
User
Beiträge: 1091
Registriert: Donnerstag 28. Dezember 2006, 20:02
Wohnort: Kassel
Kontaktdaten:

Dann zerleg dein Projekt doch erstmal in Teilaufgaben.

Ich denke die Messwerte bekommst du zuverlässig. Dann mach doch erstmal nur die Animation in matplotlib ohne das ganze gleich in QT einzubauen.

Hier findest du viele Beispiele (http://matplotlib.org/1.4.1/examples/an ... index.html). Meiner Meinung nach kommt das "random_data" Beispiel einem Messwerte plotten schon sehr nahe.
BlackJack

@Tom Brady: Ich gehe mal davon aus das wir von `matplotlib.animation` reden.

Laut Dokumentation ist `FuncAnimation` eine Unterklasse von `TimedAnimation`. Die Sekunde muss also beim erstellen vom `FuncAnimation`-Exemplar angegeben werden und nicht bei Qt. Das sieht man auch im `basic_example.py` in der Dokumentation.

Und für das stoppen/starten müsste man die entsprechenden Methoden auf dem `event_source`-Attribut des Animationsobjekts aufrufen können.
Tom Brady
User
Beiträge: 9
Registriert: Freitag 4. Dezember 2015, 07:13

Danke für eure Antworten.

@Sr4l:
Dieses Beispiel habe ich mir angeschaut, aber leider verstehe ich den Code nicht.
Wenn ich das so lesen kann, stammen die y-Daten aus:

Code: Alles auswählen

line, = ax.plot(np.random.rand(10))
und werden hier erneuert:

Code: Alles auswählen

def update(data):
    line.set_ydata(data)
    return line,
Aber was ist das "data"? und was hat die Funktion "data_gen()" zu tun?
Also an welcher Stelle füge ich mein "lese die Werte aus der Textdatei", also meinen y-Achsenwert ein?

@BlackJack:
ja, es geht um Matplotlip (wenn es nicht ein besseres Modul zum plotten gibt)
Wie oft er aktualisiert gebe ich bei "intervall" (1000 = 1 Sekunde) ein und das wäre dann auch schon mein x-Achsenwert?
Wo finde ich das "event_source"-Attribut? (Sorry für die dumme Frage)

Dankeschön.
BlackJack

@Tom Brady: Aus der Zeile stammen nur die ersten 10 Zufallswerte.

`data_gen()` generiert in jedem Schritt 10 neue Zufallsdaten und `update()` aktualisiert den Linienzug damit. Dein `data_gen()` müsste also bei jedem Aufruf die bisherigen Punkte und den nächsten aus der Datei liefern.

`event_source` ist ein Attribut das alle `Animation`-Unterklassen besitzen. Und `TimedAnimation` erzeugt dafür ein Objekt vom Typ `TimerBase` das `start()` und `stop()`-Methoden besitzt.
derhendrik
User
Beiträge: 17
Registriert: Donnerstag 15. Januar 2015, 16:39

Hey! Ich plotte zurzeit auch mit PyQt Messwerte und nutze dazu "pyqtgraph" statt matplotlib. Da sind unheimlich viele Beispiele drin enthalten, was mir den Einstieg sehr erleichtert hat ("scrollender" plot zum Beispiel). Vielleicht lohnt es sich auch für dich da mal reinzuschauen.

Viele Grüße

Hendrik
Tom Brady
User
Beiträge: 9
Registriert: Freitag 4. Dezember 2015, 07:13

Sieht vielversprechend aus.
Ich werde mich mal in beide Methoden einlesen und melde mich dann ggf. nochmal.
Danke euch beiden ertmal bis hierhin.
Grüße.
BlackJack

Das `random_example.py` in Qt mit einem Pause-Button:

Code: Alles auswählen

#!/usr/bin/env python
# coding: utf8
from __future__ import absolute_import, division, print_function
import sys
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.animation import FuncAnimation
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from PyQt4.QtGui import (
    QAction, QApplication, QHBoxLayout, QIcon, QMainWindow, QToolBar,
    QSizePolicy, QWidget
)


class AnimantionCanvas(FigureCanvas):

    def __init__(self, parent):
        figure, axes = plt.subplots()
        FigureCanvas.__init__(self, figure)
        self.setParent(parent)
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.updateGeometry()

        self.line, = axes.plot(np.random.rand(10))
        axes.set_ylim(0, 1)
        self.animation = FuncAnimation(
            figure, self.update_line, self.data_generator, interval=500
        )

    def update_line(self, data):
        self.line.set_ydata(data)
        return self.line,

    def data_generator(self):
        while True:
            yield np.random.rand(10)

    def set_pause(self, state):
        if state:
            self.animation.event_source.stop()
        else:
            self.animation.event_source.start()


class MainWindow(QMainWindow):

    def __init__(self):
        QMainWindow.__init__(self)
        self.setWindowTitle('Animation Pause Test')

        pause_action = QAction(
            QIcon.fromTheme('media-playback-pause'), 'pause', self
        )
        pause_action.setCheckable(True)

        tool_bar = QToolBar(self)
        self.addToolBar(tool_bar)
        tool_bar.addAction(pause_action)

        widget = QWidget(self)
        layout = QHBoxLayout(widget)

        canvas = AnimantionCanvas(widget)
        layout.addWidget(canvas)

        self.setCentralWidget(widget)

        pause_action.triggered.connect(canvas.set_pause)


def main():
    application = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(application.exec_())


if __name__ == '__main__':
    main()
Benutzeravatar
Sr4l
User
Beiträge: 1091
Registriert: Donnerstag 28. Dezember 2006, 20:02
Wohnort: Kassel
Kontaktdaten:

@BlackJack Jetzt noch ne deque als Speicher und du hast die Aufgabe für Tom Brady gelöst. :wink:
Tom Brady
User
Beiträge: 9
Registriert: Freitag 4. Dezember 2015, 07:13

Ich danke dir.
Habe es jetzt hinbekommen. Das Problem war, dass die Messwerte als Liste verarbeitet werden mussten.
Vielen Dank nochmal, dass du dir solche Mühe gemacht hast.
Grüße
Antworten