Zeitachse in pyqtgraph

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
d.elm
User
Beiträge: 12
Registriert: Freitag 13. Januar 2023, 18:24

Hallo,
nachdem mir die Umstellung meines damaligen mit DELPHI erstellten Programmes zur Steuerung meiner Heizung gelungen ist, ist noch ein
Problem nicht geklärt.
Ich habe die GUI mit QT5 Designer erstellt und ein "graphWidget" zur Darstellung des Temperaturverlaufes integriert. Siehe Bild im Anhang.
Das Problem ist folgendes: Mir gelingt es nicht die aktuelle Uhrzeit "HH:MM" als x-Achse darzustellen. Alle bisherigen Versuche sind immer
gescheidert.
Das Update der Werte wollt ich so gestalten (die y-Werte funktionieren aber der x- Wert nicht)
def update_plot(self):
Uhrzeit=datetime.now().strftime("%H:%M")
#self.Zeit=self.Zeit[1:] #remove 1. Element
#self.Zeit.append(Uhrzeit)
self.Aussen=self.Aussen[1:]
self.Aussen.append(self.mErrech)
self.Vorlauf=self.Vorlauf[1:]
self.Vorlauf.append(self.mVl)
self.Ruecklauf=self.Ruecklauf[1:]
self.Ruecklauf.append(self.mRl)
self.Boiler=self.Boiler[1:]
self.Boiler.append(self.mSpi)
self.Brenner=self.Brenner[1:]
if self.aBrein or self.mBrein:
self.Brenner.append(100)
else:
self.Brenner.append(-20)
self.graphWidget.clear()
self.plot(self.Zeit, self.Aussen, "Außen", 'r')
self.plot(self.Zeit, self.Vorlauf, "Vorlauf", 'g')
self.plot(self.Zeit, self.Ruecklauf, "Rücklauf", 'm')
self.plot(self.Zeit, self.Boiler, "Boiler", 'b')
self.plot(self.Zeit, self.Brenner, "Brenner", 'k')

Für den x-Wert habe ich wie man sieht 0..59 fest eingestellt.

Hat Jemand einen Hinweis wie das zu machen ist?
Danke

Bild
Ernie1412
User
Beiträge: 161
Registriert: Freitag 10. Januar 2020, 20:38

Code: Alles auswählen

import datetime

# ...

self.Zeit = self.Zeit[1:]
self.Zeit.append(datetime.datetime.now()
Damit sollte die aktuelle Uhrzeit als x-Achse im Graphen angezeigt werden.

Du solltest möglicherweise die Anzahl der angezeigten Datenpunkte begrenzen oder eine scrollbare Ansicht implementieren.

P.S. beim Erstellen des Posts, verwende bitte der besseren Lesbarkeit "code ... "
und ein Bild einfügen per "img ... " Buttons dafür sind oben.
d.elm
User
Beiträge: 12
Registriert: Freitag 13. Januar 2023, 18:24

Danke für Deine Hilfe.
Dieses Konstrukt hatte ich im Vorfeld nebst anderen Varianten ausprobiert und es kommt der folgende Fehler!
================== RESTART: /home/elm/Heizung/Heizung_Dia_1.py =================
Traceback (most recent call last):
File "/home/elm/Heizung/Heizung_Dia_1.py", line 380, in timeout
self.update_plot()
File "/home/elm/Heizung/Heizung_Dia_1.py", line 385, in update_plot
self.Zeit.append(datetime.datetime.now())
AttributeError: type object 'datetime.datetime' has no attribute 'datetime'
[DEBUG ON]
>>>
Das scheint mir leider nicht so trivial zu sein.
In allen Quellen, die ich bemüht habe ist so ein Fall nicht dargestellt.
Viele Grüße
Detlef
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Es ist ein Ärgernis mit der Benamung dieser Typen, die solche Verwirrung herstellen. Trivial ist es trotzdem: du behandelst den Typ datetime als ob er das Modul datetime wäre. Einmal “dateime.” Am Anfang weglassen, und das Problem ist gelöst.
d.elm
User
Beiträge: 12
Registriert: Freitag 13. Januar 2023, 18:24

Der Hinweis ist sicher richtig. Das habe ich auch schon gemacht und es klapt nicht!!
Hier der Ausschnitt aus dem Code:
def update_plot(self): #Diagram aktualisieren
self.Zeit=self.Zeit[1:] #remove 1. Element
self.Zeit.append(datetime.now())
print(self.Zeit)
self.Aussen=self.Aussen[1:]
self.Aussen.append(self.mErrech)
self.Vorlauf=self.Vorlauf[1:]
self.Vorlauf.append(self.mVl)

Und hier die Fehlermeldung (der Komentar ist nachträglich eingebaut)

================== RESTART: /home/elm/Heizung/Heizung_Dia_1.py =================
================== RESTART: /home/elm/Heizung/Heizung_Dia_1.py =================
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
58, 59, datetime.datetime(2023, 3, 8, 8, 44, 18, 624647)]

Dann erscheint dieser Eintrag in der Liste und es kommen jede Menge Fehlermeldungen!!!
Trivial scheint das doch nicht zu sein!!!

Traceback (most recent call last):
File "/usr/local/lib/python3.9/dist-packages/pyqtgraph/graphicsItems/GraphicsObject.py", line 36, in itemChange
self.changeParent()
File "/usr/local/lib/python3.9/dist-packages/pyqtgraph/graphicsItems/GraphicsItem.py", line 460, in changeParent
self._updateView()
File "/usr/local/lib/python3.9/dist-packages/pyqtgraph/graphicsItems/GraphicsItem.py", line 519, in _updateView
self.viewRangeChanged()
File "/usr/local/lib/python3.9/dist-packages/pyqtgraph/graphicsItems/PlotDataItem.py", line 1182, in viewRangeChanged
self.updateItems(styleUpdate=False)
File "/usr/local/lib/python3.9/dist-packages/pyqtgraph/graphicsItems/PlotDataItem.py", line 865, in updateItems
dataset = self._getDisplayDataset()
File "/usr/local/lib/python3.9/dist-packages/pyqtgraph/graphicsItems/PlotDataItem.py", line 1034, in _getDisplayDataset
data_range = self._datasetMapped.dataRect()
File "/usr/local/lib/python3.9/dist-packages/pyqtgraph/graphicsItems/PlotDataItem.py", line 84, in
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das ist ja auch ein anderes Problem. Nicht jedes Problem ist trivial, aber das letzte (oder vorletzte) war es. Und so wie es aussieht, mischst du Ganzzahlen mit einem Zeitstempel. Das geht nicht. Das muss schon homogen sein.
d.elm
User
Beiträge: 12
Registriert: Freitag 13. Januar 2023, 18:24

o.k.
Kannst Du mir bitte verraten, wie ich so eine Liste erstellen kann? Ich habe einiges versucht, aber ohne Erfolg.
Bitte nicht falsch verstehen. Wie man eine Liste erstellt ist mir schon klar.
Ich meine eine Liste, deren Werte auf der X-Achse die Uhrzeit "HH:MM" darstellen.
so wie unten:

[img]f:bild.bmp[/img]
funktioniert leider auch nicht! Naja schade

Danke
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du nimmst dir die Zeit jetzt (mit now(), wie du es schon machst. Und dann mit einer for-Schleife von -59 bis 0 inklusive(!), rechnest du deine Werte aus:

Code: Alles auswählen

jetzt = datetime.now()
values = [jetzt+ timedelta(minutes=i) for i in range(-59, 1)]
timedelta ist auch aus dem datetime-Modul(!)
d.elm
User
Beiträge: 12
Registriert: Freitag 13. Januar 2023, 18:24

Danke für Deine Tips. Ich gebe resigniert auf!
Has Du das einmal ausprobiert?
Gruß Detlef
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Nein, weil ich gerade am Mobiltelefon tippe. Darum war das ohne Gewähr. Aber der Ansatz muss an sich schon funktionieren, zumindest für die Liste der Zeitstempel. Was das mit der visualisierung macht kann ich von hier aus nicht einschätzen.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich habe meinen Code getestet, der produziert zumindest mal die letzten 60 Minuten als Zeitstempel. War also korrekt. Ob und wie sich das in deinen Graphen integrieren laesst, weiss ich nicht. Das hat ja Ernie1412 behauptet, das ginge. Wenn es nur um die Formatierung als HH:MM geht, ist das natuerlich einfach:

Code: Alles auswählen

from datetime import datetime, timedelta

jetzt = datetime.now()
values = [(jetzt+ timedelta(minutes=i)).strftime("%H:%M") for i in range(-59, 1)]
print(values)
Benutzeravatar
Axel-WAK
User
Beiträge: 62
Registriert: Dienstag 29. November 2022, 11:52

Warum nimmst Du nicht QChart von PyQt5?

Das ist ein altes Beispiel.

Bild

Code: Alles auswählen

import datetime
from PyQt5.QtWidgets import QMainWindow, QApplication
from PyQt5.QtChart import (QChart, QChartView, QLineSeries, 
                            QDateTimeAxis, QValueAxis)
from PyQt5.QtCore import QDateTime

class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.plot = QChart()
        self.chart_view = QChartView(self.plot)
        self.setCentralWidget(self.chart_view)

        self.series = QLineSeries()
        self.series.setName("Test")
        self.plot.addSeries(self.series)

        # Setting X-axis
        self.axis_x = QDateTimeAxis()
        self.axis_x.setTickCount(11)
        self.axis_x.setLabelsAngle(70)
        self.axis_x.setFormat("dd.MM.yyyy <br><b>h:mm</b>")
        self.axis_x.setTitleText("Datum / Zeit")
        self.axis_x.setMax(datetime.datetime.strptime('202005071345','%Y%m%d%H%M'))
        self.axis_x.setMin(datetime.datetime.strptime('202005070845','%Y%m%d%H%M'))
        
        # Setting Y-axis
        self.axis_y = QValueAxis()
        self.axis_y.setTickCount(7)
        self.axis_y.setLabelFormat("%i")
        self.axis_y.setTitleText("Temperatur °C")
        self.axis_y.setMax(60)
        self.axis_y.setMin(10)
        self.plot.setAxisX(self.axis_x, self.series)
        self.plot.setAxisY(self.axis_y, self.series)
        
        self.series.append(
            QDateTime.fromString(
                "202005070849", "yyyyMMddhhmm"
            ).toMSecsSinceEpoch(),
            22,
        )
        self.series.append(
            QDateTime.fromString(
                "202005070950", "yyyyMMddhhmm"
            ).toMSecsSinceEpoch(),
            20,
        )
        self.series.append(
            QDateTime.fromString(
                "202005071051", "yyyyMMddhhmm"
            ).toMSecsSinceEpoch(),
            38,
        )
        self.series.append(
            QDateTime.fromString(
                "202005071141", "yyyyMMddhhmm"
            ).toMSecsSinceEpoch(),
            28,
        )
        self.series.append(
            QDateTime.fromString(
                "202005071235", "yyyyMMddhhmm"
            ).toMSecsSinceEpoch(),
            48,
        )
        self.series.append(
            QDateTime.fromString(
                "202005071319", "yyyyMMddhhmm"
            ).toMSecsSinceEpoch(),
            40,
        )
        self.series.append(
            QDateTime.fromString(
                "202005071339", "yyyyMMddhhmm"
            ).toMSecsSinceEpoch(),
            33,
        )
        
if __name__ == "__main__":
    import sys

    app = QApplication(sys.argv)
    window = MainWindow()
    window.resize(800, 480)
    window.show()
    sys.exit(app.exec_())
OS: LMDE5 *** Homepage *** Github Seite
d.elm
User
Beiträge: 12
Registriert: Freitag 13. Januar 2023, 18:24

Danke für Deine Mühe,
ich hatte das auch schon auf eine andere Art so erzeugt.
Wenn man vor das "timedelta()" noch "i*" schreibt, erhält man dann eine fortlaufende Folge von Strings 'HH:MM'.
Beim updaten laufen zig. Fehlermeldungen ein und auf im Diagram tut sich garnichts.
Vieleicht muß die X-Achsenvariable ein INTEGER sein? Nur so eine Vermutung.
Nochmals danke
Detlef
Benutzeravatar
Axel-WAK
User
Beiträge: 62
Registriert: Dienstag 29. November 2022, 11:52

Es hängt davon ab was Du als Achse verwendest, es gibt ja QDateTimeAxis QValueAxis ...
OS: LMDE5 *** Homepage *** Github Seite
d.elm
User
Beiträge: 12
Registriert: Freitag 13. Januar 2023, 18:24

Durch Zufall bin ich heute auf eine Aussage in einem Forum gestoßen:
As you have found, pyqtgraph does not support plotting with datetime objects. You need to convert these to numerical value before plotting.

Wie Sie festgestellt haben, unterstützt Pyqtgraph das Zeichnen mit Datetime-Objekten nicht. Sie müssen diese vor dem Plotten in numerische Werte umwandeln.

Oh mein Gott! Das ist doch mal eine Ansage. Nun brauche ich nicht länger nach der Lösung zu suchen. Komisch, dass das noch niemand gemacht hat und noch keinen aufgefallen ist. Eigendlich dachte ich eine ZEIT-Werte_Darstellung ist ein "normaler" Anwendungsfall. Naja.
Ich weiss nicht was ich morgens einnehmen muß um PYTHON gut zu finden. Bei anderen Programmiesprachen funktioniert das (und vieles andere auch). Python kommt mir vor wie ein Tool für "JUGEND FORSCHT".
Viele Grüße und Tschüss
Detlef
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Na dann benutz doch die vielen anderen Programmiersprachen, bei denen das besser geht. Es zwingt dich doch keiner, Python zu benutzen 🤷‍♂️

Abgesehen mal davon hat Axel doch einen Weg gezeigt, wie es geht. Zu behaupten, es geht nicht, obwohl einem das Gegenteil bewiesen wurde, muss man auch erstmal drauf kommen.
Benutzeravatar
grubenfox
User
Beiträge: 612
Registriert: Freitag 2. Dezember 2022, 15:49

aus der Doku: DateAxisItem
An AxisItem that displays dates from unix timestamps.
Benutzeravatar
__blackjack__
User
Beiträge: 14057
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Was hat das überhaupt mit Python oder der Programmiersprache zu tun? Das ist die API von einer externen Bibliothek, die wiederum auf ein externes GUI-Rahmenwerk aufsetzt, das in C++ geschrieben ist. Das kann einem also mit jeder anderen Bibliothek in jeder anderen Programmiersprache genau so gehen.

Wenn dann in der Dokumentation auch noch deutlich steht das die Zeit als Unix-Zeitstempel erwartet wird, dann sehe ich auch überhaupt gar kein Problem mit der API. Das ist nämlich nicht wirklich ungewöhnlich und wird auch von anderen Bibliotheken und in anderen Programmiersprachen so gehandhabt.

Das Problem sitzt *vor* dem Rechner wenn einfach so Daten auf eine API geworfen werden, in der Hoffnung das wird schon funktionieren, und im Fall das es das nicht tut, im Netz gesucht und in Foren gefragt wird, statt *erst* einmal einen Blick in die Dokumentation zu werfen was die API denn konkret erwartet.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten