pyobs-gui 2.0.0.dev6__tar.gz → 2.0.0.dev7__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/PKG-INFO +1 -1
  2. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/weatherwidget.py +51 -1
  3. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyproject.toml +7 -1
  4. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/uv.lock +1 -1
  5. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/.claude/skills/verify/SKILL.md +0 -0
  6. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/.github/dependabot.yml +0 -0
  7. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/.github/workflows/pypi.yml +0 -0
  8. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/.github/workflows/pyrefly.yml +0 -0
  9. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/.github/workflows/ruff.yml +0 -0
  10. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/.gitignore +0 -0
  11. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/.pre-commit-config.yaml +0 -0
  12. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/.readthedocs.yml +0 -0
  13. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/CHANGELOG.rst +0 -0
  14. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/LICENSE +0 -0
  15. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/README.md +0 -0
  16. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/bin/mypyuic5 +0 -0
  17. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/docs/Makefile +0 -0
  18. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/docs/make.bat +0 -0
  19. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/docs/requirements.txt +0 -0
  20. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/docs/source/_static/pyobs.gif +0 -0
  21. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/docs/source/conf.py +0 -0
  22. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/docs/source/index.rst +0 -0
  23. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/mypy.ini +0 -0
  24. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/__init__.py +0 -0
  25. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/__main__.py +0 -0
  26. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/_nuitka_astropy_patch.py +0 -0
  27. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/accounts.py +0 -0
  28. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/acquisitionwidget.py +0 -0
  29. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/autofocuswidget.py +0 -0
  30. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/autoguidingwidget.py +0 -0
  31. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/base.py +0 -0
  32. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/camerawidget.py +0 -0
  33. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/commandinputwidget.py +0 -0
  34. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/compassmovewidget.py +0 -0
  35. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/coolingwidget.py +0 -0
  36. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/datadisplaywidget.py +0 -0
  37. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/eventswidget.py +0 -0
  38. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/filterwidget.py +0 -0
  39. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/fitsheaderswidget.py +0 -0
  40. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/focuswidget.py +0 -0
  41. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/gui.py +0 -0
  42. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/login.py +0 -0
  43. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/loginwindow.py +0 -0
  44. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/logmodel.py +0 -0
  45. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/mainwindow.py +0 -0
  46. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/modewidget.py +0 -0
  47. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/modifiedmixin.py +0 -0
  48. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/modulegui.py +0 -0
  49. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/__init__.py +0 -0
  50. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/acquisitionwidget.ui +0 -0
  51. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/acquisitionwidget_ui.py +0 -0
  52. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/autofocuswidget.ui +0 -0
  53. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/autofocuswidget_ui.py +0 -0
  54. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/autoguidingwidget.ui +0 -0
  55. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/autoguidingwidget_ui.py +0 -0
  56. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/camerawidget.ui +0 -0
  57. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/camerawidget_ui.py +0 -0
  58. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/compassmoveplugin.py +0 -0
  59. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/compassmovewidget.py +0 -0
  60. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/compassmovewidget.ui +0 -0
  61. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/compassmovewidget_ui.py +0 -0
  62. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/compile.sh +0 -0
  63. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/coolingwidget.ui +0 -0
  64. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/coolingwidget_ui.py +0 -0
  65. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/datadisplayplugin.py +0 -0
  66. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/datadisplaywidget.ui +0 -0
  67. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/datadisplaywidget_ui.py +0 -0
  68. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/designer.sh +0 -0
  69. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/eventswidget.ui +0 -0
  70. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/eventswidget_ui.py +0 -0
  71. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/filterwidget.ui +0 -0
  72. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/filterwidget_ui.py +0 -0
  73. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/fitsheaderswidget.ui +0 -0
  74. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/fitsheaderswidget_ui.py +0 -0
  75. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/focuswidget.ui +0 -0
  76. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/focuswidget_ui.py +0 -0
  77. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/mainwindow.ui +0 -0
  78. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/mainwindow_ui.py +0 -0
  79. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/modewidget.ui +0 -0
  80. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/modewidget_ui.py +0 -0
  81. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/resources/arrow-alt-circle-down-solid.svg +0 -0
  82. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/resources/arrow-alt-circle-left-solid.svg +0 -0
  83. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/resources/arrow-alt-circle-right-solid.svg +0 -0
  84. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/resources/arrow-alt-circle-up-solid.svg +0 -0
  85. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/resources/arrow-up-right-from-square-solid.svg +0 -0
  86. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/resources/arrows-to-eye-solid.svg +0 -0
  87. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/resources/chart-line-solid.svg +0 -0
  88. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/resources/circle-question-solid.svg +0 -0
  89. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/resources/cloud-sun-solid.svg +0 -0
  90. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/resources/edit-solid.svg +0 -0
  91. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/resources/search-solid.svg +0 -0
  92. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/resources/undo-solid.svg +0 -0
  93. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/resources.qrc +0 -0
  94. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/resources_rc.py +0 -0
  95. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/roofwidget.ui +0 -0
  96. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/roofwidget_ui.py +0 -0
  97. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/shellwidget.ui +0 -0
  98. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/shellwidget_ui.py +0 -0
  99. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/spectrographwidget.ui +0 -0
  100. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/spectrographwidget_ui.py +0 -0
  101. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/telescopewidget.ui +0 -0
  102. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/telescopewidget_ui.py +0 -0
  103. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/temperaturesplotwidget.ui +0 -0
  104. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/temperaturesplotwidget_ui.py +0 -0
  105. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/temperatureswidget.ui +0 -0
  106. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/temperatureswidget_ui.py +0 -0
  107. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/videowidget.ui +0 -0
  108. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/videowidget_ui.py +0 -0
  109. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/weatherwidget.ui +0 -0
  110. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/qt/weatherwidget_ui.py +0 -0
  111. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/roofwidget.py +0 -0
  112. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/shellwidget.py +0 -0
  113. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/spectrographwidget.py +0 -0
  114. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/statuswidget.py +0 -0
  115. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/telescopewidget.py +0 -0
  116. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/temperaturesplotwidget.py +0 -0
  117. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/temperatureswidget.py +0 -0
  118. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/utils.py +0 -0
  119. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/videowidget.py +0 -0
  120. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pyobs_gui/watchedlabel.py +0 -0
  121. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/pysidedeploy.spec +0 -0
  122. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/specs/README.md +0 -0
  123. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/spike_standalone/main.py +0 -0
  124. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/spike_standalone/pysidedeploy.spec +0 -0
  125. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/test/acquisition.yaml +0 -0
  126. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/test/autofocus.yaml +0 -0
  127. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/test/camera.yaml +0 -0
  128. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/test/full.yaml +0 -0
  129. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/test/guiding.yaml +0 -0
  130. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/test/mode.yaml +0 -0
  131. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/test/roof.yaml +0 -0
  132. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/test/spectrograph.yaml +0 -0
  133. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/test/telescope.yaml +0 -0
  134. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/test/telescope_acl.yaml +0 -0
  135. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/test/telescope_acl_denied.yaml +0 -0
  136. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/test/video.yaml +0 -0
  137. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/tests/__init__.py +0 -0
  138. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/tests/conftest.py +0 -0
  139. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/tests/test_accounts.py +0 -0
  140. {pyobs_gui-2.0.0.dev6 → pyobs_gui-2.0.0.dev7}/tests/test_loginwindow.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyobs-gui
3
- Version: 2.0.0.dev6
3
+ Version: 2.0.0.dev7
4
4
  Summary: A remote GUI for pyobs
5
5
  Author-email: Tim-Oliver Husser <thusser@uni-goettingen.de>
6
6
  License-Expression: MIT
@@ -1,7 +1,14 @@
1
- from typing import Any, Dict, TYPE_CHECKING
1
+ import os
2
+ from collections import deque
3
+ from typing import Any, Deque, Dict, Tuple, TYPE_CHECKING
2
4
  from PySide6 import QtWidgets, QtGui, QtCore # type: ignore
3
5
  import logging
4
6
 
7
+ os.environ["QT_API"] = "PySide6"
8
+ from matplotlib import pyplot as plt
9
+ from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg as FigureCanvas
10
+ from matplotlib.dates import DateFormatter
11
+
5
12
  from pyobs.interfaces import IWeather, WeatherState, WeatherSensorReading
6
13
  from pyobs.utils.enums import WeatherSensors
7
14
  from .qt.weatherwidget_ui import Ui_WeatherWidget
@@ -13,6 +20,9 @@ if TYPE_CHECKING:
13
20
 
14
21
  log = logging.getLogger(__name__)
15
22
 
23
+ # how many samples to keep per sensor for the history plot
24
+ _HISTORY_LENGTH = 200
25
+
16
26
 
17
27
  # label and display order for known sensors; anything else reported by the module is ignored
18
28
  SENSOR_LABELS: Dict[WeatherSensors, str] = {
@@ -92,6 +102,14 @@ class WeatherWidget(BaseWidget, Ui_WeatherWidget):
92
102
  self._good: bool | None = None
93
103
  self._readings: Dict[WeatherSensors, WeatherSensorReading] = {}
94
104
  self._current_widgets: Dict[str, WidgetCurrentSensor] = {}
105
+ self._history: Dict[WeatherSensors, "Deque[Tuple[Time, float]]"] = {}
106
+
107
+ # add plot
108
+ self.figure = plt.figure()
109
+ layout = QtWidgets.QVBoxLayout(self.framePlot)
110
+ self.canvas = FigureCanvas(self.figure)
111
+ layout.addWidget(self.canvas)
112
+ self.framePlot.setLayout(layout)
95
113
 
96
114
  # before first update, disable myself
97
115
  self.setEnabled(False)
@@ -106,6 +124,11 @@ class WeatherWidget(BaseWidget, Ui_WeatherWidget):
106
124
  self._time = state.time
107
125
  self._good = state.good
108
126
  self._readings = {r.sensor: r for r in state.readings}
127
+ for reading in state.readings:
128
+ if reading.value is not None:
129
+ self._history.setdefault(reading.sensor, deque(maxlen=_HISTORY_LENGTH)).append(
130
+ (reading.time, reading.value)
131
+ )
109
132
  self.signal_update_gui.emit()
110
133
 
111
134
  def update_gui(self) -> None:
@@ -150,5 +173,32 @@ class WeatherWidget(BaseWidget, Ui_WeatherWidget):
150
173
  widget.set_value(s)
151
174
  widget.set_good(self._good)
152
175
 
176
+ self._plot_history()
177
+
178
+ def _plot_history(self) -> None:
179
+ # one stacked subplot per sensor that has history, in the same order as the current-value
180
+ # tiles; the sensor set (and therefore the subplot count) can change at runtime, so the
181
+ # figure is rebuilt from scratch rather than reusing fixed axes
182
+ sensors = [s for s in SENSOR_LABELS if self._history.get(s)]
183
+
184
+ self.figure.clear()
185
+ if not sensors:
186
+ self.canvas.draw()
187
+ return
188
+
189
+ axes = self.figure.subplots(len(sensors), 1, sharex=True)
190
+ if len(sensors) == 1:
191
+ axes = [axes]
192
+ for ax, sensor in zip(axes, sensors, strict=True):
193
+ times, values = zip(*self._history[sensor], strict=True)
194
+ ax.plot([t.to_datetime() for t in times], values, color="tab:blue")
195
+ ax.set_ylabel(SENSOR_LABELS[sensor], fontsize="small")
196
+ ax.grid(linestyle=":", alpha=0.5)
197
+ ax.set_axisbelow(True)
198
+ axes[-1].xaxis.set_major_formatter(DateFormatter("%H:%M:%S"))
199
+ self.figure.autofmt_xdate()
200
+ self.figure.tight_layout()
201
+ self.canvas.draw()
202
+
153
203
 
154
204
  __all__ = ["WeatherWidget"]
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pyobs-gui"
3
- version = "2.0.0.dev6"
3
+ version = "2.0.0.dev7"
4
4
  description = "A remote GUI for pyobs"
5
5
  authors = [{ name = "Tim-Oliver Husser", email = "thusser@uni-goettingen.de" }]
6
6
  requires-python = ">=3.11,<3.14"
@@ -59,6 +59,12 @@ ignore = ["E203", "E266", "E501", "F403", "E722"]
59
59
 
60
60
  [tool.ruff.lint.per-file-ignores]
61
61
  "__init__.py" = ["F401"]
62
+ # The astropy/Nuitka patch must run before any other pyobs_gui import (see its own docstring).
63
+ "pyobs_gui/__init__.py" = ["E402"]
64
+ # _build_generic_grammar_namespace is a verbatim transcription of astropy's own PLY grammar,
65
+ # deliberately mirroring astropy's structure for easy diffing -- splitting it up to satisfy
66
+ # mccabe would work against that goal.
67
+ "pyobs_gui/_nuitka_astropy_patch.py" = ["C901"]
62
68
 
63
69
  [tool.ruff.lint.mccabe]
64
70
  max-complexity = 30
@@ -2375,7 +2375,7 @@ wheels = [
2375
2375
 
2376
2376
  [[package]]
2377
2377
  name = "pyobs-gui"
2378
- version = "2.0.0.dev6"
2378
+ version = "2.0.0.dev7"
2379
2379
  source = { editable = "." }
2380
2380
  dependencies = [
2381
2381
  { name = "astroplan" },
File without changes
File without changes
File without changes