From 585db909b16182fa200b36503dec6cb56f0387ea Mon Sep 17 00:00:00 2001 From: Tim-Oliver Husser Date: Sun, 7 Feb 2021 13:21:35 +0100 Subject: [PATCH 01/29] made binning a check box and added option for image format --- pyobs_gui/qt/widgetcamera.py | 39 ++++++++++++++-------------- pyobs_gui/qt/widgetcamera.ui | 50 +++++++++++++++++------------------- pyobs_gui/widgetcamera.py | 39 +++++++++++++++++++++++----- 3 files changed, 75 insertions(+), 53 deletions(-) diff --git a/pyobs_gui/qt/widgetcamera.py b/pyobs_gui/qt/widgetcamera.py index 472ab74..f59e4be 100644 --- a/pyobs_gui/qt/widgetcamera.py +++ b/pyobs_gui/qt/widgetcamera.py @@ -80,23 +80,25 @@ def setupUi(self, WidgetCamera): self.gridLayout_3 = QtWidgets.QGridLayout(self.groupBinning) self.gridLayout_3.setSpacing(0) self.gridLayout_3.setObjectName("gridLayout_3") - self.spinBinningY = QtWidgets.QSpinBox(self.groupBinning) - self.spinBinningY.setMinimum(1) - self.spinBinningY.setMaximum(3) - self.spinBinningY.setObjectName("spinBinningY") - self.gridLayout_3.addWidget(self.spinBinningY, 1, 1, 1, 1) - self.spinBinningX = QtWidgets.QSpinBox(self.groupBinning) - self.spinBinningX.setMinimum(1) - self.spinBinningX.setMaximum(3) - self.spinBinningX.setObjectName("spinBinningX") - self.gridLayout_3.addWidget(self.spinBinningX, 0, 1, 1, 1) - self.label_6 = QtWidgets.QLabel(self.groupBinning) - self.label_6.setObjectName("label_6") - self.gridLayout_3.addWidget(self.label_6, 1, 0, 1, 1) self.label_5 = QtWidgets.QLabel(self.groupBinning) self.label_5.setObjectName("label_5") self.gridLayout_3.addWidget(self.label_5, 0, 0, 1, 1) + self.comboBinning = QtWidgets.QComboBox(self.groupBinning) + self.comboBinning.setObjectName("comboBinning") + self.gridLayout_3.addWidget(self.comboBinning, 0, 1, 1, 1) self.verticalLayout.addWidget(self.groupBinning) + self.groupImageFormat = QtWidgets.QGroupBox(self.scrollAreaWidgetContents) + self.groupImageFormat.setObjectName("groupImageFormat") + self.gridLayout_6 = QtWidgets.QGridLayout(self.groupImageFormat) + self.gridLayout_6.setSpacing(0) + self.gridLayout_6.setObjectName("gridLayout_6") + self.label_10 = QtWidgets.QLabel(self.groupImageFormat) + self.label_10.setObjectName("label_10") + self.gridLayout_6.addWidget(self.label_10, 0, 0, 1, 1) + self.comboImageFormat = QtWidgets.QComboBox(self.groupImageFormat) + self.comboImageFormat.setObjectName("comboImageFormat") + self.gridLayout_6.addWidget(self.comboImageFormat, 0, 1, 1, 1) + self.verticalLayout.addWidget(self.groupImageFormat) self.groupExposure = QtWidgets.QGroupBox(self.scrollAreaWidgetContents) self.groupExposure.setObjectName("groupExposure") self.gridLayout_4 = QtWidgets.QGridLayout(self.groupExposure) @@ -508,9 +510,7 @@ def setupUi(self, WidgetCamera): WidgetCamera.setTabOrder(self.spinWindowTop, self.spinWindowWidth) WidgetCamera.setTabOrder(self.spinWindowWidth, self.spinWindowHeight) WidgetCamera.setTabOrder(self.spinWindowHeight, self.butFullFrame) - WidgetCamera.setTabOrder(self.butFullFrame, self.spinBinningX) - WidgetCamera.setTabOrder(self.spinBinningX, self.spinBinningY) - WidgetCamera.setTabOrder(self.spinBinningY, self.comboImageType) + WidgetCamera.setTabOrder(self.butFullFrame, self.comboImageType) WidgetCamera.setTabOrder(self.comboImageType, self.spinExpTime) WidgetCamera.setTabOrder(self.spinExpTime, self.spinCount) WidgetCamera.setTabOrder(self.spinCount, self.butExpose) @@ -532,9 +532,10 @@ def retranslateUi(self, WidgetCamera): self.label.setText(_translate("WidgetCamera", "Left:")) self.label_4.setText(_translate("WidgetCamera", "Height:")) self.butFullFrame.setText(_translate("WidgetCamera", "Full Frame")) - self.groupBinning.setTitle(_translate("WidgetCamera", "Binning:")) - self.label_6.setText(_translate("WidgetCamera", "Y:")) - self.label_5.setText(_translate("WidgetCamera", "X:")) + self.groupBinning.setTitle(_translate("WidgetCamera", "Binning")) + self.label_5.setText(_translate("WidgetCamera", "XxY:")) + self.groupImageFormat.setTitle(_translate("WidgetCamera", "Image format")) + self.label_10.setText(_translate("WidgetCamera", "Format:")) self.groupExposure.setTitle(_translate("WidgetCamera", "Exposure")) self.label_7.setText(_translate("WidgetCamera", "ExpTime:")) self.label_8.setText(_translate("WidgetCamera", "Count:")) diff --git a/pyobs_gui/qt/widgetcamera.ui b/pyobs_gui/qt/widgetcamera.ui index 1ddfb46..46322bb 100644 --- a/pyobs_gui/qt/widgetcamera.ui +++ b/pyobs_gui/qt/widgetcamera.ui @@ -131,46 +131,44 @@ - Binning: + Binning 0 - - - - 1 - - - 3 + + + + XxY: - - - 1 - - - 3 - - - - - - - Y: - - + + + + + + + + Image format + + + + 0 + - + - X: + Format: + + + @@ -1325,8 +1323,6 @@ spinWindowWidth spinWindowHeight butFullFrame - spinBinningX - spinBinningY comboImageType spinExpTime spinCount diff --git a/pyobs_gui/widgetcamera.py b/pyobs_gui/widgetcamera.py index fb69fb0..71bfd0a 100644 --- a/pyobs_gui/widgetcamera.py +++ b/pyobs_gui/widgetcamera.py @@ -7,8 +7,8 @@ from pyobs.events import ExposureStatusChangedEvent, NewImageEvent from pyobs.interfaces import ICamera, ICameraBinning, ICameraWindow, ICooling, IFilters, ITemperatures, \ - ICameraExposureTime, IImageType -from pyobs.utils.enums import ImageType + ICameraExposureTime, IImageType, IImageFormat +from pyobs.utils.enums import ImageType, ImageFormat from pyobs.vfs import VirtualFileSystem from pyobs_gui.basewidget import BaseWidget from pyobs_gui.widgetcooling import WidgetCooling @@ -52,6 +52,7 @@ def __init__(self, module, comm, vfs, parent=None): # hide groups, if necessary self.groupWindowing.setVisible(isinstance(self.module, ICameraWindow)) self.groupBinning.setVisible(isinstance(self.module, ICameraBinning)) + self.groupImageFormat.setVisible(isinstance(self.module, IImageFormat)) # add image panel self.imageLayout = QtWidgets.QVBoxLayout(self.tabImage) @@ -64,6 +65,7 @@ def __init__(self, module, comm, vfs, parent=None): # connect signals self.butFullFrame.clicked.connect(self.set_full_frame) + self.comboBinning.currentTextChanged.connect(self.binning_changed) self.comboImageType.currentTextChanged.connect(self.image_type_changed) self.butExpose.clicked.connect(self.expose) self.butAbort.clicked.connect(self.abort) @@ -89,9 +91,27 @@ def __init__(self, module, comm, vfs, parent=None): self.add_to_sidebar(WidgetTemperatures(module, comm)) def _init(self): - # get status and update gui + # get status self.exposure_status = ICamera.ExposureStatus(self.module.get_exposure_status().wait()) + + # get binnings + if isinstance(self.module, ICameraBinning): + binnings = ['1x1', '2x2', '3x3'] + self.comboBinning.clear() + self.comboBinning.addItems(binnings) + self.comboBinning.setCurrentIndex(0) + + # get image formats + if isinstance(self.module, IImageFormat): + image_formats = [ImageFormat(f) for f in self.module.list_image_formats().wait()] + self.comboImageFormat.clear() + self.comboImageFormat.addItems(list(image_formats.keys())) + self.comboImageFormat.setCurrentIndex(0) + + # set full frame self.set_full_frame() + + # update GUI self.signal_update_gui.emit() def set_full_frame(self): @@ -99,6 +119,9 @@ def set_full_frame(self): # get full frame left, top, width, height = self.module.get_full_frame().wait() + # get binning + binning = int(self.comboBinning.currentText()[0]) if isinstance(self.module, ICameraBinning) else 1 + # set it self.spinWindowLeft.setValue(left) self.spinWindowTop.setValue(top) @@ -115,21 +138,23 @@ def image_type_changed(self, image_type): def expose(self): # set binning if isinstance(self.module, ICameraBinning): - binx, biny = self.spinBinningX.value(), self.spinBinningY.value() + binning = int(self.comboBinning.currentText()[0]) + print(binning) try: - self.module.set_binning(binx, biny).wait() + self.module.set_binning(binning, binning).wait() except: + log.exception('bla') QMessageBox.information(self, 'Error', 'Could not set binning.') return else: - binx, biny = 1, 1 + binning = 1 # set window if isinstance(self.module, ICameraWindow): left, top = self.spinWindowLeft.value(), self.spinWindowTop.value() width, height = self.spinWindowWidth.value(), self.spinWindowHeight.value() try: - self.module.set_window(left, top, width * binx, height * biny).wait() + self.module.set_window(left, top, width * binning, height * binning).wait() except: QMessageBox.information(self, 'Error', 'Could not set window.') return From fda9fe07bde57c5d12338440fa30ca56528ecb5a Mon Sep 17 00:00:00 2001 From: Tim-Oliver Husser Date: Sun, 7 Feb 2021 13:22:15 +0100 Subject: [PATCH 02/29] set maximum values for window --- pyobs_gui/widgetcamera.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/pyobs_gui/widgetcamera.py b/pyobs_gui/widgetcamera.py index 71bfd0a..6dbb50a 100644 --- a/pyobs_gui/widgetcamera.py +++ b/pyobs_gui/widgetcamera.py @@ -125,8 +125,17 @@ def set_full_frame(self): # set it self.spinWindowLeft.setValue(left) self.spinWindowTop.setValue(top) - self.spinWindowWidth.setValue(width / self.spinBinningX.value()) - self.spinWindowHeight.setValue(height / self.spinBinningY.value()) + self.spinWindowWidth.setValue(width / binning) + self.spinWindowHeight.setValue(height / binning) + + # max values + self.spinWindowLeft.setMaximum(width / binning) + self.spinWindowTop.setMaximum(height / binning) + self.spinWindowWidth.setMaximum(width / binning) + self.spinWindowHeight.setMaximum(height / binning) + + def binning_changed(self, binning): + self.set_full_frame() def image_type_changed(self, image_type): if image_type == 'BIAS': From aeda5bec29f41e577824f6c018d67a8336444785 Mon Sep 17 00:00:00 2001 From: Tim-Oliver Husser Date: Sun, 7 Feb 2021 13:40:10 +0100 Subject: [PATCH 03/29] added combo box for setting image format --- pyobs_gui/widgetcamera.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/pyobs_gui/widgetcamera.py b/pyobs_gui/widgetcamera.py index 6dbb50a..787f487 100644 --- a/pyobs_gui/widgetcamera.py +++ b/pyobs_gui/widgetcamera.py @@ -103,10 +103,20 @@ def _init(self): # get image formats if isinstance(self.module, IImageFormat): + # get formats image_formats = [ImageFormat(f) for f in self.module.list_image_formats().wait()] + + # set it self.comboImageFormat.clear() - self.comboImageFormat.addItems(list(image_formats.keys())) - self.comboImageFormat.setCurrentIndex(0) + self.comboImageFormat.addItems([f.name for f in image_formats]) + + # find default value + if ImageFormat.INT16 in image_formats: + self.comboImageFormat.setCurrentText('INT16') + elif ImageFormat.INT8 in image_formats: + self.comboImageFormat.setCurrentText('INT8') + else: + self.comboImageFormat.setCurrentIndex(0) # set full frame self.set_full_frame() @@ -168,6 +178,11 @@ def expose(self): QMessageBox.information(self, 'Error', 'Could not set window.') return + # set image format + if isinstance(self.module, IImageFormat): + image_format = ImageFormat[self.comboImageFormat.currentText()] + self.module.set_image_format(image_format) + # set initial image count self.exposures_left = self.spinCount.value() From 1687d526c9e5e6c9badb4f4c91901cd11dcabbda Mon Sep 17 00:00:00 2001 From: Tim-Oliver Husser Date: Sun, 7 Feb 2021 20:13:13 +0100 Subject: [PATCH 04/29] fetching available binnings from module --- pyobs_gui/widgetcamera.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pyobs_gui/widgetcamera.py b/pyobs_gui/widgetcamera.py index 787f487..7477e86 100644 --- a/pyobs_gui/widgetcamera.py +++ b/pyobs_gui/widgetcamera.py @@ -96,9 +96,14 @@ def _init(self): # get binnings if isinstance(self.module, ICameraBinning): - binnings = ['1x1', '2x2', '3x3'] + # get binnings + binnings = ['%dx%d' % (b, b) for b in self.module.list_binnings().wait()] + + # set it self.comboBinning.clear() self.comboBinning.addItems(binnings) + + # set default value self.comboBinning.setCurrentIndex(0) # get image formats From f7c8b358d65f5960861a773514f8dd36ab353888 Mon Sep 17 00:00:00 2001 From: Tim-Oliver Husser Date: Mon, 8 Feb 2021 09:50:21 +0100 Subject: [PATCH 05/29] changed signature of ICameraBinning's list_binnings() to return list of X,Y tuples --- pyobs_gui/widgetcamera.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyobs_gui/widgetcamera.py b/pyobs_gui/widgetcamera.py index 7477e86..5d84282 100644 --- a/pyobs_gui/widgetcamera.py +++ b/pyobs_gui/widgetcamera.py @@ -97,7 +97,7 @@ def _init(self): # get binnings if isinstance(self.module, ICameraBinning): # get binnings - binnings = ['%dx%d' % (b, b) for b in self.module.list_binnings().wait()] + binnings = ['%dx%d' % tuple(binning) for binning in self.module.list_binnings().wait()] # set it self.comboBinning.clear() From 622716a33b21af3c266eb2befe572146c9a01301 Mon Sep 17 00:00:00 2001 From: Tim-Oliver Husser Date: Mon, 8 Feb 2021 10:19:20 +0100 Subject: [PATCH 06/29] hide controls if not required --- pyobs_gui/qt/widgetcamera.py | 20 +++++++++++--------- pyobs_gui/qt/widgetcamera.ui | 6 ++++-- pyobs_gui/widgetcamera.py | 6 ++++++ 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/pyobs_gui/qt/widgetcamera.py b/pyobs_gui/qt/widgetcamera.py index f59e4be..7bb8feb 100644 --- a/pyobs_gui/qt/widgetcamera.py +++ b/pyobs_gui/qt/widgetcamera.py @@ -104,9 +104,9 @@ def setupUi(self, WidgetCamera): self.gridLayout_4 = QtWidgets.QGridLayout(self.groupExposure) self.gridLayout_4.setSpacing(0) self.gridLayout_4.setObjectName("gridLayout_4") - self.label_7 = QtWidgets.QLabel(self.groupExposure) - self.label_7.setObjectName("label_7") - self.gridLayout_4.addWidget(self.label_7, 1, 0, 1, 1) + self.labelExpTime = QtWidgets.QLabel(self.groupExposure) + self.labelExpTime.setObjectName("labelExpTime") + self.gridLayout_4.addWidget(self.labelExpTime, 1, 0, 1, 1) self.comboImageType = QtWidgets.QComboBox(self.groupExposure) self.comboImageType.setObjectName("comboImageType") self.gridLayout_4.addWidget(self.comboImageType, 0, 1, 1, 1) @@ -118,9 +118,9 @@ def setupUi(self, WidgetCamera): self.spinCount.setMaximum(9999) self.spinCount.setObjectName("spinCount") self.gridLayout_4.addWidget(self.spinCount, 2, 1, 1, 1) - self.label_9 = QtWidgets.QLabel(self.groupExposure) - self.label_9.setObjectName("label_9") - self.gridLayout_4.addWidget(self.label_9, 0, 0, 1, 1) + self.labelImageType = QtWidgets.QLabel(self.groupExposure) + self.labelImageType.setObjectName("labelImageType") + self.gridLayout_4.addWidget(self.labelImageType, 0, 0, 1, 1) self.butExpose = QtWidgets.QPushButton(self.groupExposure) palette = QtGui.QPalette() brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) @@ -510,7 +510,9 @@ def setupUi(self, WidgetCamera): WidgetCamera.setTabOrder(self.spinWindowTop, self.spinWindowWidth) WidgetCamera.setTabOrder(self.spinWindowWidth, self.spinWindowHeight) WidgetCamera.setTabOrder(self.spinWindowHeight, self.butFullFrame) - WidgetCamera.setTabOrder(self.butFullFrame, self.comboImageType) + WidgetCamera.setTabOrder(self.butFullFrame, self.comboBinning) + WidgetCamera.setTabOrder(self.comboBinning, self.comboImageFormat) + WidgetCamera.setTabOrder(self.comboImageFormat, self.comboImageType) WidgetCamera.setTabOrder(self.comboImageType, self.spinExpTime) WidgetCamera.setTabOrder(self.spinExpTime, self.spinCount) WidgetCamera.setTabOrder(self.spinCount, self.butExpose) @@ -537,9 +539,9 @@ def retranslateUi(self, WidgetCamera): self.groupImageFormat.setTitle(_translate("WidgetCamera", "Image format")) self.label_10.setText(_translate("WidgetCamera", "Format:")) self.groupExposure.setTitle(_translate("WidgetCamera", "Exposure")) - self.label_7.setText(_translate("WidgetCamera", "ExpTime:")) + self.labelExpTime.setText(_translate("WidgetCamera", "ExpTime:")) self.label_8.setText(_translate("WidgetCamera", "Count:")) - self.label_9.setText(_translate("WidgetCamera", "Type:")) + self.labelImageType.setText(_translate("WidgetCamera", "Type:")) self.butExpose.setText(_translate("WidgetCamera", "Expose")) self.butAbort.setText(_translate("WidgetCamera", "Abort")) self.spinExpTime.setSuffix(_translate("WidgetCamera", "s")) diff --git a/pyobs_gui/qt/widgetcamera.ui b/pyobs_gui/qt/widgetcamera.ui index 46322bb..527b02d 100644 --- a/pyobs_gui/qt/widgetcamera.ui +++ b/pyobs_gui/qt/widgetcamera.ui @@ -182,7 +182,7 @@ 0 - + ExpTime: @@ -209,7 +209,7 @@ - + Type: @@ -1323,6 +1323,8 @@ spinWindowWidth spinWindowHeight butFullFrame + comboBinning + comboImageFormat comboImageType spinExpTime spinCount diff --git a/pyobs_gui/widgetcamera.py b/pyobs_gui/widgetcamera.py index 5d84282..572888f 100644 --- a/pyobs_gui/widgetcamera.py +++ b/pyobs_gui/widgetcamera.py @@ -54,6 +54,12 @@ def __init__(self, module, comm, vfs, parent=None): self.groupBinning.setVisible(isinstance(self.module, ICameraBinning)) self.groupImageFormat.setVisible(isinstance(self.module, IImageFormat)) + # and single controls + self.labelImageType.setVisible(isinstance(self.module, IImageType)) + self.comboImageType.setVisible(isinstance(self.module, IImageType)) + self.labelExpTime.setVisible(isinstance(self.module, ICameraExposureTime)) + self.spinExpTime.setVisible(isinstance(self.module, ICameraExposureTime)) + # add image panel self.imageLayout = QtWidgets.QVBoxLayout(self.tabImage) self.imageView = QFitsWidget() From 96a357cd5f6786840b4ab124d325e4157e845db8 Mon Sep 17 00:00:00 2001 From: Tim-Oliver Husser Date: Mon, 8 Feb 2021 16:18:08 +0100 Subject: [PATCH 07/29] added new checkbox to avoid broadcasting new images --- pyobs_gui/qt/widgetcamera.py | 74 +++++++++++++----------- pyobs_gui/qt/widgetcamera.ui | 107 +++++++++++++++++++---------------- pyobs_gui/widgetcamera.py | 15 ++++- 3 files changed, 111 insertions(+), 85 deletions(-) diff --git a/pyobs_gui/qt/widgetcamera.py b/pyobs_gui/qt/widgetcamera.py index 7bb8feb..899319d 100644 --- a/pyobs_gui/qt/widgetcamera.py +++ b/pyobs_gui/qt/widgetcamera.py @@ -13,7 +13,7 @@ class Ui_WidgetCamera(object): def setupUi(self, WidgetCamera): WidgetCamera.setObjectName("WidgetCamera") - WidgetCamera.resize(967, 657) + WidgetCamera.resize(1269, 810) self.horizontalLayout_2 = QtWidgets.QHBoxLayout(WidgetCamera) self.horizontalLayout_2.setObjectName("horizontalLayout_2") self.scrollArea = QtWidgets.QScrollArea(WidgetCamera) @@ -26,7 +26,7 @@ def setupUi(self, WidgetCamera): self.scrollArea.setWidgetResizable(True) self.scrollArea.setObjectName("scrollArea") self.scrollAreaWidgetContents = QtWidgets.QWidget() - self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 183, 641)) + self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 183, 794)) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) @@ -104,23 +104,6 @@ def setupUi(self, WidgetCamera): self.gridLayout_4 = QtWidgets.QGridLayout(self.groupExposure) self.gridLayout_4.setSpacing(0) self.gridLayout_4.setObjectName("gridLayout_4") - self.labelExpTime = QtWidgets.QLabel(self.groupExposure) - self.labelExpTime.setObjectName("labelExpTime") - self.gridLayout_4.addWidget(self.labelExpTime, 1, 0, 1, 1) - self.comboImageType = QtWidgets.QComboBox(self.groupExposure) - self.comboImageType.setObjectName("comboImageType") - self.gridLayout_4.addWidget(self.comboImageType, 0, 1, 1, 1) - self.label_8 = QtWidgets.QLabel(self.groupExposure) - self.label_8.setObjectName("label_8") - self.gridLayout_4.addWidget(self.label_8, 2, 0, 1, 1) - self.spinCount = QtWidgets.QSpinBox(self.groupExposure) - self.spinCount.setMinimum(1) - self.spinCount.setMaximum(9999) - self.spinCount.setObjectName("spinCount") - self.gridLayout_4.addWidget(self.spinCount, 2, 1, 1, 1) - self.labelImageType = QtWidgets.QLabel(self.groupExposure) - self.labelImageType.setObjectName("labelImageType") - self.gridLayout_4.addWidget(self.labelImageType, 0, 0, 1, 1) self.butExpose = QtWidgets.QPushButton(self.groupExposure) palette = QtGui.QPalette() brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) @@ -269,7 +252,26 @@ def setupUi(self, WidgetCamera): palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.PlaceholderText, brush) self.butExpose.setPalette(palette) self.butExpose.setObjectName("butExpose") - self.gridLayout_4.addWidget(self.butExpose, 3, 0, 1, 2) + self.gridLayout_4.addWidget(self.butExpose, 4, 0, 1, 2) + self.spinCount = QtWidgets.QSpinBox(self.groupExposure) + self.spinCount.setMinimum(1) + self.spinCount.setMaximum(9999) + self.spinCount.setObjectName("spinCount") + self.gridLayout_4.addWidget(self.spinCount, 2, 1, 1, 1) + self.spinExpTime = QtWidgets.QDoubleSpinBox(self.groupExposure) + self.spinExpTime.setMaximum(99999.0) + self.spinExpTime.setProperty("value", 1.0) + self.spinExpTime.setObjectName("spinExpTime") + self.gridLayout_4.addWidget(self.spinExpTime, 1, 1, 1, 1) + self.comboImageType = QtWidgets.QComboBox(self.groupExposure) + self.comboImageType.setObjectName("comboImageType") + self.gridLayout_4.addWidget(self.comboImageType, 0, 1, 1, 1) + self.labelImageType = QtWidgets.QLabel(self.groupExposure) + self.labelImageType.setObjectName("labelImageType") + self.gridLayout_4.addWidget(self.labelImageType, 0, 0, 1, 1) + self.labelExpTime = QtWidgets.QLabel(self.groupExposure) + self.labelExpTime.setObjectName("labelExpTime") + self.gridLayout_4.addWidget(self.labelExpTime, 1, 0, 1, 1) self.butAbort = QtWidgets.QPushButton(self.groupExposure) palette = QtGui.QPalette() brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) @@ -418,12 +420,14 @@ def setupUi(self, WidgetCamera): palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.PlaceholderText, brush) self.butAbort.setPalette(palette) self.butAbort.setObjectName("butAbort") - self.gridLayout_4.addWidget(self.butAbort, 4, 0, 1, 2) - self.spinExpTime = QtWidgets.QDoubleSpinBox(self.groupExposure) - self.spinExpTime.setMaximum(99999.0) - self.spinExpTime.setProperty("value", 1.0) - self.spinExpTime.setObjectName("spinExpTime") - self.gridLayout_4.addWidget(self.spinExpTime, 1, 1, 1, 1) + self.gridLayout_4.addWidget(self.butAbort, 5, 0, 1, 2) + self.label_8 = QtWidgets.QLabel(self.groupExposure) + self.label_8.setObjectName("label_8") + self.gridLayout_4.addWidget(self.label_8, 2, 0, 1, 1) + self.checkBroadcast = QtWidgets.QCheckBox(self.groupExposure) + self.checkBroadcast.setChecked(True) + self.checkBroadcast.setObjectName("checkBroadcast") + self.gridLayout_4.addWidget(self.checkBroadcast, 3, 1, 1, 1) self.verticalLayout.addWidget(self.groupExposure) spacerItem = QtWidgets.QSpacerItem(20, 26, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) self.verticalLayout.addItem(spacerItem) @@ -515,15 +519,16 @@ def setupUi(self, WidgetCamera): WidgetCamera.setTabOrder(self.comboImageFormat, self.comboImageType) WidgetCamera.setTabOrder(self.comboImageType, self.spinExpTime) WidgetCamera.setTabOrder(self.spinExpTime, self.spinCount) - WidgetCamera.setTabOrder(self.spinCount, self.butExpose) + WidgetCamera.setTabOrder(self.spinCount, self.checkBroadcast) + WidgetCamera.setTabOrder(self.checkBroadcast, self.butExpose) WidgetCamera.setTabOrder(self.butExpose, self.butAbort) - WidgetCamera.setTabOrder(self.butAbort, self.tabWidget) - WidgetCamera.setTabOrder(self.tabWidget, self.checkAutoUpdate) + WidgetCamera.setTabOrder(self.butAbort, self.checkAutoUpdate) WidgetCamera.setTabOrder(self.checkAutoUpdate, self.checkAutoSave) WidgetCamera.setTabOrder(self.checkAutoSave, self.textAutoSavePath) WidgetCamera.setTabOrder(self.textAutoSavePath, self.butAutoSave) WidgetCamera.setTabOrder(self.butAutoSave, self.butSaveTo) - WidgetCamera.setTabOrder(self.butSaveTo, self.tableFitsHeader) + WidgetCamera.setTabOrder(self.butSaveTo, self.tabWidget) + WidgetCamera.setTabOrder(self.tabWidget, self.tableFitsHeader) def retranslateUi(self, WidgetCamera): _translate = QtCore.QCoreApplication.translate @@ -539,12 +544,13 @@ def retranslateUi(self, WidgetCamera): self.groupImageFormat.setTitle(_translate("WidgetCamera", "Image format")) self.label_10.setText(_translate("WidgetCamera", "Format:")) self.groupExposure.setTitle(_translate("WidgetCamera", "Exposure")) - self.labelExpTime.setText(_translate("WidgetCamera", "ExpTime:")) - self.label_8.setText(_translate("WidgetCamera", "Count:")) - self.labelImageType.setText(_translate("WidgetCamera", "Type:")) self.butExpose.setText(_translate("WidgetCamera", "Expose")) - self.butAbort.setText(_translate("WidgetCamera", "Abort")) self.spinExpTime.setSuffix(_translate("WidgetCamera", "s")) + self.labelImageType.setText(_translate("WidgetCamera", "Type:")) + self.labelExpTime.setText(_translate("WidgetCamera", "ExpTime:")) + self.butAbort.setText(_translate("WidgetCamera", "Abort")) + self.label_8.setText(_translate("WidgetCamera", "Count:")) + self.checkBroadcast.setText(_translate("WidgetCamera", "Broadcast")) self.labelStatus.setText(_translate("WidgetCamera", "IDLE")) self.labelExposuresLeft.setText(_translate("WidgetCamera", "IDLE")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabImage), _translate("WidgetCamera", "Image")) diff --git a/pyobs_gui/qt/widgetcamera.ui b/pyobs_gui/qt/widgetcamera.ui index 527b02d..760ad9e 100644 --- a/pyobs_gui/qt/widgetcamera.ui +++ b/pyobs_gui/qt/widgetcamera.ui @@ -6,8 +6,8 @@ 0 0 - 967 - 657 + 1269 + 810 @@ -34,7 +34,7 @@ 0 0 183 - 641 + 794 @@ -181,41 +181,7 @@ 0 - - - - ExpTime: - - - - - - - - - - Count: - - - - - - - 1 - - - 9999 - - - - - - - Type: - - - - + @@ -664,7 +630,47 @@ - + + + + 1 + + + 9999 + + + + + + + s + + + 99999.000000000000000 + + + 1.000000000000000 + + + + + + + + + + Type: + + + + + + + ExpTime: + + + + @@ -1113,16 +1119,20 @@ - - - - s + + + + Count: - - 99999.000000000000000 + + + + + + Broadcast - - 1.000000000000000 + + true @@ -1328,14 +1338,15 @@ comboImageType spinExpTime spinCount + checkBroadcast butExpose butAbort - tabWidget checkAutoUpdate checkAutoSave textAutoSavePath butAutoSave butSaveTo + tabWidget tableFitsHeader diff --git a/pyobs_gui/widgetcamera.py b/pyobs_gui/widgetcamera.py index 572888f..48f8cef 100644 --- a/pyobs_gui/widgetcamera.py +++ b/pyobs_gui/widgetcamera.py @@ -24,6 +24,7 @@ class WidgetCamera(BaseWidget, Ui_WidgetCamera): signal_update_gui = pyqtSignal() + signal_new_image = pyqtSignal(NewImageEvent, str) def __init__(self, module, comm, vfs, parent=None): BaseWidget.__init__(self, parent=parent, update_func=self._update) @@ -76,6 +77,7 @@ def __init__(self, module, comm, vfs, parent=None): self.butExpose.clicked.connect(self.expose) self.butAbort.clicked.connect(self.abort) self.signal_update_gui.connect(self.update_gui) + self.signal_new_image.connect(self._on_new_image) self.butAutoSave.clicked.connect(self.select_autosave_path) self.butSaveTo.clicked.connect(self.save_image) self.checkAutoSave.stateChanged.connect(lambda x: self.textAutoSavePath.setEnabled(x)) @@ -169,7 +171,6 @@ def expose(self): # set binning if isinstance(self.module, ICameraBinning): binning = int(self.comboBinning.currentText()[0]) - print(binning) try: self.module.set_binning(binning, binning).wait() except: @@ -206,16 +207,24 @@ def _expose_thread_func(self): # do exposure(s) while self.exposures_left > 0: - # set exposure time and expose + # set exposure time and image type if isinstance(self.module, ICameraExposureTime): self.module.set_exposure_time(self.spinExpTime.value()).wait() if isinstance(self.module, IImageType): self.module.set_image_type(image_type) - self.module.expose().wait() + + # expose + broadcast = self.checkBroadcast.isChecked() + filename = self.module.expose(broadcast=broadcast).wait() # decrement number of exposures left self.exposures_left -= 1 + # if we're not broadcasting the filename, we need to signal it manually + if not broadcast: + ev = NewImageEvent(filename, image_type) + self.signal_new_image.emit(ev, self.module.name) + # signal GUI update self.signal_update_gui.emit() From a92a0dcb4f4998b4e6ea72dbdb88bbd577e12d79 Mon Sep 17 00:00:00 2001 From: Tim-Oliver Husser Date: Mon, 8 Feb 2021 16:20:22 +0100 Subject: [PATCH 08/29] changed order of setting max and current values --- pyobs_gui/widgetcamera.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pyobs_gui/widgetcamera.py b/pyobs_gui/widgetcamera.py index 48f8cef..a5f8355 100644 --- a/pyobs_gui/widgetcamera.py +++ b/pyobs_gui/widgetcamera.py @@ -145,18 +145,18 @@ def set_full_frame(self): # get binning binning = int(self.comboBinning.currentText()[0]) if isinstance(self.module, ICameraBinning) else 1 - # set it - self.spinWindowLeft.setValue(left) - self.spinWindowTop.setValue(top) - self.spinWindowWidth.setValue(width / binning) - self.spinWindowHeight.setValue(height / binning) - # max values self.spinWindowLeft.setMaximum(width / binning) self.spinWindowTop.setMaximum(height / binning) self.spinWindowWidth.setMaximum(width / binning) self.spinWindowHeight.setMaximum(height / binning) + # set it + self.spinWindowLeft.setValue(left) + self.spinWindowTop.setValue(top) + self.spinWindowWidth.setValue(width / binning) + self.spinWindowHeight.setValue(height / binning) + def binning_changed(self, binning): self.set_full_frame() From d9dfc0f27b08c9cac96d89f53aad6b7a6cba3d54 Mon Sep 17 00:00:00 2001 From: Tim-Oliver Husser Date: Mon, 8 Feb 2021 16:28:43 +0100 Subject: [PATCH 09/29] show security question when disabling broadcast --- pyobs_gui/widgetcamera.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/pyobs_gui/widgetcamera.py b/pyobs_gui/widgetcamera.py index a5f8355..adcde15 100644 --- a/pyobs_gui/widgetcamera.py +++ b/pyobs_gui/widgetcamera.py @@ -2,7 +2,7 @@ import os import threading from PyQt5 import QtWidgets, QtGui -from PyQt5.QtCore import pyqtSignal +from PyQt5.QtCore import pyqtSignal, pyqtSlot from PyQt5.QtWidgets import QMessageBox from pyobs.events import ExposureStatusChangedEvent, NewImageEvent @@ -160,6 +160,15 @@ def set_full_frame(self): def binning_changed(self, binning): self.set_full_frame() + @pyqtSlot(int, name='on_checkBroadcast_stateChanged') + def broadcast_changed(self, state): + if state == 0: + r = QMessageBox.question(self, 'pyobs', 'When disabling the broadcast, new images will not processed (and ' + 'saved) within the pyobs network. Continue?', + QMessageBox.Yes | QMessageBox.No, QMessageBox.No) + if r == QMessageBox.No: + self.checkBroadcast.setChecked(True) + def image_type_changed(self, image_type): if image_type == 'BIAS': self.spinExpTime.setValue(0) From 7b697eecd5af13a20d775ee81791361ff3d89d0e Mon Sep 17 00:00:00 2001 From: Tim-Oliver Husser Date: Mon, 8 Feb 2021 16:32:45 +0100 Subject: [PATCH 10/29] instead of manually connection signals/slot, use pyqtSlot() --- pyobs_gui/widgetcamera.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pyobs_gui/widgetcamera.py b/pyobs_gui/widgetcamera.py index adcde15..9762a9b 100644 --- a/pyobs_gui/widgetcamera.py +++ b/pyobs_gui/widgetcamera.py @@ -71,15 +71,8 @@ def __init__(self, module, comm, vfs, parent=None): self.tableFitsHeader.setHorizontalHeaderLabels(['Key', 'Value', 'Comment']) # connect signals - self.butFullFrame.clicked.connect(self.set_full_frame) - self.comboBinning.currentTextChanged.connect(self.binning_changed) - self.comboImageType.currentTextChanged.connect(self.image_type_changed) - self.butExpose.clicked.connect(self.expose) - self.butAbort.clicked.connect(self.abort) self.signal_update_gui.connect(self.update_gui) self.signal_new_image.connect(self._on_new_image) - self.butAutoSave.clicked.connect(self.select_autosave_path) - self.butSaveTo.clicked.connect(self.save_image) self.checkAutoSave.stateChanged.connect(lambda x: self.textAutoSavePath.setEnabled(x)) # initial values @@ -137,6 +130,7 @@ def _init(self): # update GUI self.signal_update_gui.emit() + @pyqtSlot(name='on_butFullFrame_clicked') def set_full_frame(self): if isinstance(self.module, ICameraWindow): # get full frame @@ -157,6 +151,7 @@ def set_full_frame(self): self.spinWindowWidth.setValue(width / binning) self.spinWindowHeight.setValue(height / binning) + @pyqtSlot(str, name='on_comboBinning_currentTextChanged') def binning_changed(self, binning): self.set_full_frame() @@ -169,6 +164,7 @@ def broadcast_changed(self, state): if r == QMessageBox.No: self.checkBroadcast.setChecked(True) + @pyqtSlot(str, name='on_comboImageType_currentTextChanged') def image_type_changed(self, image_type): if image_type == 'BIAS': self.spinExpTime.setValue(0) @@ -176,6 +172,7 @@ def image_type_changed(self, image_type): else: self.spinExpTime.setEnabled(True) + @pyqtSlot(name='on_butExpose_clicked') def expose(self): # set binning if isinstance(self.module, ICameraBinning): @@ -240,7 +237,8 @@ def _expose_thread_func(self): def plot(self): """Show image.""" self.imageView.display(self.image) - + + @pyqtSlot(name='on_butAbort_clicked') def abort(self): """Abort exposure.""" @@ -399,6 +397,7 @@ def _on_new_image(self, event: NewImageEvent, sender: str): # update GUI self.signal_update_gui.emit() + @pyqtSlot(name='on_butAutoSave_clicked') def select_autosave_path(self): """Select path for auto-saving.""" @@ -411,6 +410,7 @@ def select_autosave_path(self): else: self.textAutoSavePath.clear() + @pyqtSlot(name='on_butSaveTo_clicked') def save_image(self): """Save image.""" From ebe6f6b11d1de06324fdcb156088c4f4b18998f2 Mon Sep 17 00:00:00 2001 From: Tim-Oliver Husser Date: Tue, 9 Feb 2021 10:43:15 +0100 Subject: [PATCH 11/29] size of page selector --- pyobs_gui/qt/mainwindow.py | 7 +++++++ pyobs_gui/qt/mainwindow.ui | 24 ++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/pyobs_gui/qt/mainwindow.py b/pyobs_gui/qt/mainwindow.py index da307c7..d3b0872 100644 --- a/pyobs_gui/qt/mainwindow.py +++ b/pyobs_gui/qt/mainwindow.py @@ -74,9 +74,16 @@ def setupUi(self, MainWindow): sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.listPages.sizePolicy().hasHeightForWidth()) self.listPages.setSizePolicy(sizePolicy) + self.listPages.setMinimumSize(QtCore.QSize(100, 0)) self.listPages.setMaximumSize(QtCore.QSize(100, 16777215)) self.listPages.setFrameShape(QtWidgets.QFrame.NoFrame) + self.listPages.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) + self.listPages.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers) + self.listPages.setProperty("showDropIndicator", False) + self.listPages.setDragDropMode(QtWidgets.QAbstractItemView.NoDragDrop) + self.listPages.setDefaultDropAction(QtCore.Qt.IgnoreAction) self.listPages.setIconSize(QtCore.QSize(64, 64)) + self.listPages.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel) self.listPages.setViewMode(QtWidgets.QListView.IconMode) self.listPages.setObjectName("listPages") self.horizontalLayout.addWidget(self.listPages) diff --git a/pyobs_gui/qt/mainwindow.ui b/pyobs_gui/qt/mainwindow.ui index c72c5ee..cc4666f 100644 --- a/pyobs_gui/qt/mainwindow.ui +++ b/pyobs_gui/qt/mainwindow.ui @@ -153,6 +153,12 @@ 0 + + + 100 + 0 + + 100 @@ -162,12 +168,30 @@ QFrame::NoFrame + + Qt::ScrollBarAlwaysOff + + + QAbstractItemView::NoEditTriggers + + + false + + + QAbstractItemView::NoDragDrop + + + Qt::IgnoreAction + 64 64 + + QAbstractItemView::ScrollPerPixel + QListView::IconMode From 7629c9327ba9b48e8427a980cee8f5ebea76d0de Mon Sep 17 00:00:00 2001 From: Tim-Oliver Husser Date: Tue, 9 Feb 2021 10:44:56 +0100 Subject: [PATCH 12/29] catch exception --- pyobs_gui/widgetfocus.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/pyobs_gui/widgetfocus.py b/pyobs_gui/widgetfocus.py index b08dc1a..4a2b163 100644 --- a/pyobs_gui/widgetfocus.py +++ b/pyobs_gui/widgetfocus.py @@ -60,10 +60,17 @@ def _set_focus(self, offset: bool = False): self.run_async(setter, new_value) def _init(self): - # get current filter - self._focus = self.module.get_focus().wait() - self._focus_offset = self.module.get_focus_offset().wait() - self._motion_status = self.module.get_motion_status().wait() + # get status + try: + self._focus = self.module.get_focus().wait() + self._focus_offset = self.module.get_focus_offset().wait() + self._motion_status = self.module.get_motion_status().wait() + except: + self._focus = None + self._focus_offset = None + self._motion_status = IMotion.Status.UNKNOWN + + # update GUI self.signal_update_gui.emit() def update_gui(self): From 9b59174dab185f8a4d1efc71f8dc806de397a572 Mon Sep 17 00:00:00 2001 From: Tim-Oliver Husser Date: Tue, 9 Feb 2021 11:01:34 +0100 Subject: [PATCH 13/29] sorting page icons --- pyobs_gui/mainwindow.py | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/pyobs_gui/mainwindow.py b/pyobs_gui/mainwindow.py index dabe062..e21664b 100644 --- a/pyobs_gui/mainwindow.py +++ b/pyobs_gui/mainwindow.py @@ -20,6 +20,29 @@ from pyobs_gui.widgetweather import WidgetWeather +class PagesListWidgetItem(QtWidgets.QListWidgetItem): + """ListWidgetItem for the pages list. Always sorts Shell and Events first""" + def __lt__(self, other): + """Compare two items.""" + + # special cases? + if self.text() == 'Shell': + # if self is 'Shell', it always goes first + return True + elif other.text() == 'Shell': + # if other is 'Shell', it always goes later + return False + elif self.text() == 'Events': + # if self is 'Events', it only goes first if other is not 'Shell' + return other.text() != 'Shell' + elif other.text() == 'Events': + # if other is 'Events', self always goes later, since case of 'Shell' as self has always been dealt with + return False + else: + # default case + return QtWidgets.QListWidgetItem.__lt__(self, other) + + class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): add_log = pyqtSignal(list) add_command_log = pyqtSignal(str) @@ -109,12 +132,13 @@ def _add_client(self, client: str, icon: QtGui.QIcon, widget: QtWidgets.QWidget) """ # add list item - item = QtWidgets.QListWidgetItem() + item = PagesListWidgetItem() item.setIcon(icon) item.setText(client) - # add to list + # add to list and sort self.listPages.addItem(item) + self.listPages.sortItems() # add widget self.stackedWidget.addWidget(widget) From d427e182fa524a1b7726ef52287cb12e159158db Mon Sep 17 00:00:00 2001 From: Tim-Oliver Husser Date: Tue, 16 Feb 2021 15:45:32 +0100 Subject: [PATCH 14/29] download images in thread --- pyobs_gui/widgetcamera.py | 86 +++++++++++++++++++++++++++++++-------- 1 file changed, 68 insertions(+), 18 deletions(-) diff --git a/pyobs_gui/widgetcamera.py b/pyobs_gui/widgetcamera.py index 9762a9b..596311f 100644 --- a/pyobs_gui/widgetcamera.py +++ b/pyobs_gui/widgetcamera.py @@ -1,7 +1,7 @@ import logging import os import threading -from PyQt5 import QtWidgets, QtGui +from PyQt5 import QtWidgets, QtGui, QtCore from PyQt5.QtCore import pyqtSignal, pyqtSlot from PyQt5.QtWidgets import QMessageBox @@ -9,6 +9,7 @@ from pyobs.interfaces import ICamera, ICameraBinning, ICameraWindow, ICooling, IFilters, ITemperatures, \ ICameraExposureTime, IImageType, IImageFormat from pyobs.utils.enums import ImageType, ImageFormat +from pyobs.utils.images import Image from pyobs.vfs import VirtualFileSystem from pyobs_gui.basewidget import BaseWidget from pyobs_gui.widgetcooling import WidgetCooling @@ -22,6 +23,48 @@ log = logging.getLogger(__name__) +class DownloadThread(QtCore.QThread): + """Worker thread for downloading images.""" + + """Signal emitted when the image is downloaded.""" + imageReady = pyqtSignal(Image, str) + + def __init__(self, vfs: VirtualFileSystem, filename: str, autosave: str = None, *args, **kwargs): + """Init a new worker thread. + + Args: + vfs: VFS to use for download + filename: File to download + autosave: Path for autosave or None. + """ + QtCore.QThread.__init__(self, *args, **kwargs) + self.vfs = vfs + self.filename = filename + self.autosave = autosave + + def run(self): + """Run method in thread.""" + + # download image + image = self.vfs.read_image(self.filename) + + # auto save? + if self.autosave is not None: + # get path and check + path = self.autosave + if not os.path.exists(path): + log.warning('Invalid path for auto-saving.') + + else: + # save image + filename = os.path.join(path, os.path.basename(self.image_filename.replace('.fits.gz', '.fits'))) + log.info('Saving image as %s...', filename) + self.image.writeto(filename, overwrite=True) + + # update GUI + self.imageReady.emit(image, self.filename) + + class WidgetCamera(BaseWidget, Ui_WidgetCamera): signal_update_gui = pyqtSignal() signal_new_image = pyqtSignal(NewImageEvent, str) @@ -42,6 +85,7 @@ def __init__(self, module, comm, vfs, parent=None): self.exposures_left = 0 self.exposure_time_left = 0 self.exposure_progress = 0 + self.download_threads = [] # set exposure types image_types = ['OBJECT', 'BIAS', 'DARK'] @@ -376,26 +420,32 @@ def _on_new_image(self, event: NewImageEvent, sender: str): if not self.checkAutoUpdate.isChecked(): return - # download image - self.image = self.vfs.read_image(event.filename) - self.image_filename = event.filename - self.new_image = True + # autosave? + autosave = self.textAutoSavePath.text() if self.checkAutoSave.isChecked() else None - # auto save? - if self.checkAutoSave.isChecked(): - # get path and check - path = self.textAutoSavePath.text() - if not os.path.exists(path): - log.warning('Invalid path for auto-saving.') + # create thread for download + thread = DownloadThread(self.vfs, event.filename, autosave) + thread.imageReady.connect(self._image_downloaded) + thread.start() - else: - # save image - filename = os.path.join(path, os.path.basename(self.image_filename.replace('.fits.gz', '.fits'))) - log.info('Saving image as %s...', filename) - self.image.writeto(filename, overwrite=True) + self.download_threads.append(thread) - # update GUI - self.signal_update_gui.emit() + def _image_downloaded(self, image, filename): + """Called, when image is downloaded. + """ + + # store image and filename + self.image = image + self.image_filename = filename + self.new_image = True + + # find finished threads and delete them + finished_threads = [t for t in self.download_threads if not t.isRunning()] + for t in finished_threads: + self.download_threads.remove(t) + + # show image + self.update_gui() @pyqtSlot(name='on_butAutoSave_clicked') def select_autosave_path(self): From f320ea183fa795be8a5018523fd0d54083abffd7 Mon Sep 17 00:00:00 2001 From: Tim-Oliver Husser Date: Fri, 19 Feb 2021 10:32:16 +0100 Subject: [PATCH 15/29] Moved "images" module to top-level --- pyobs_gui/widgetcamera.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyobs_gui/widgetcamera.py b/pyobs_gui/widgetcamera.py index 596311f..99cb325 100644 --- a/pyobs_gui/widgetcamera.py +++ b/pyobs_gui/widgetcamera.py @@ -1,7 +1,7 @@ import logging import os import threading -from PyQt5 import QtWidgets, QtGui, QtCore +from PyQt5 import QtWidgets, QtCore from PyQt5.QtCore import pyqtSignal, pyqtSlot from PyQt5.QtWidgets import QMessageBox @@ -9,7 +9,7 @@ from pyobs.interfaces import ICamera, ICameraBinning, ICameraWindow, ICooling, IFilters, ITemperatures, \ ICameraExposureTime, IImageType, IImageFormat from pyobs.utils.enums import ImageType, ImageFormat -from pyobs.utils.images import Image +from pyobs.images import Image from pyobs.vfs import VirtualFileSystem from pyobs_gui.basewidget import BaseWidget from pyobs_gui.widgetcooling import WidgetCooling From 9bbf8794e2d16e7828de97d16ab6fea8c3facc34 Mon Sep 17 00:00:00 2001 From: Tim-Oliver Husser Date: Fri, 26 Feb 2021 10:42:27 +0100 Subject: [PATCH 16/29] allow for negative offsets in dialog --- pyobs_gui/widgettelescope.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyobs_gui/widgettelescope.py b/pyobs_gui/widgettelescope.py index 5d59384..90daec8 100644 --- a/pyobs_gui/widgettelescope.py +++ b/pyobs_gui/widgettelescope.py @@ -396,7 +396,7 @@ def _set_offset(self): self.run_async(self.module.set_radec_offsets, self._off_ra, 0.) else: # now the sets, ask for value - new_value, ok = QtWidgets.QInputDialog.getDouble(self, 'Set offset', 'New offset ["]', 0, 0, 999) + new_value, ok = QtWidgets.QInputDialog.getDouble(self, 'Set offset', 'New offset ["]', 0, -999, 999) if ok: if self.sender() == self.buttonSetAltOffset: self.run_async(self.module.set_altaz_offsets, new_value / 3600., self._off_az) From 48df0e4ff5677c5a495a42ea0ccdf7166f87400a Mon Sep 17 00:00:00 2001 From: Tim-Oliver Husser Date: Wed, 3 Mar 2021 17:05:25 +0100 Subject: [PATCH 17/29] fixed bug when auto-saving --- pyobs_gui/widgetcamera.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyobs_gui/widgetcamera.py b/pyobs_gui/widgetcamera.py index 99cb325..9572139 100644 --- a/pyobs_gui/widgetcamera.py +++ b/pyobs_gui/widgetcamera.py @@ -57,9 +57,9 @@ def run(self): else: # save image - filename = os.path.join(path, os.path.basename(self.image_filename.replace('.fits.gz', '.fits'))) + filename = os.path.join(path, os.path.basename(self.filename.replace('.fits.gz', '.fits'))) log.info('Saving image as %s...', filename) - self.image.writeto(filename, overwrite=True) + image.writeto(filename, overwrite=True) # update GUI self.imageReady.emit(image, self.filename) From 1c442805a1d2f94ed71424f6328774024fbd9150 Mon Sep 17 00:00:00 2001 From: Karl Wessel Date: Mon, 22 Mar 2021 10:04:39 +0100 Subject: [PATCH 18/29] add warning to logger when GUIs update_func fails --- pyobs_gui/basewidget.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pyobs_gui/basewidget.py b/pyobs_gui/basewidget.py index d93325d..753b2fe 100644 --- a/pyobs_gui/basewidget.py +++ b/pyobs_gui/basewidget.py @@ -75,8 +75,9 @@ def _update_loop_thread(self): try: # call update function self._update_func() - except: - pass + except Exception as e: + log.warning("Exception during GUIs update function: %s", + str(e)) # sleep a little self._update_thread_event.wait(self._update_interval) From d564ab0c63784829b821a43a98cbb97bc22d1295 Mon Sep 17 00:00:00 2001 From: Tim-Oliver Husser Date: Wed, 24 Mar 2021 10:44:36 +0100 Subject: [PATCH 19/29] added combo box for exposure time unit --- pyobs_gui/qt/widgetcamera.py | 32 ++++++++++++++------ pyobs_gui/qt/widgetcamera.ui | 58 ++++++++++++++++++++++++++---------- pyobs_gui/widgetcamera.py | 17 +++++++++-- 3 files changed, 81 insertions(+), 26 deletions(-) diff --git a/pyobs_gui/qt/widgetcamera.py b/pyobs_gui/qt/widgetcamera.py index 899319d..4d05a7b 100644 --- a/pyobs_gui/qt/widgetcamera.py +++ b/pyobs_gui/qt/widgetcamera.py @@ -26,7 +26,7 @@ def setupUi(self, WidgetCamera): self.scrollArea.setWidgetResizable(True) self.scrollArea.setObjectName("scrollArea") self.scrollAreaWidgetContents = QtWidgets.QWidget() - self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 183, 794)) + self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 264, 794)) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) @@ -258,11 +258,6 @@ def setupUi(self, WidgetCamera): self.spinCount.setMaximum(9999) self.spinCount.setObjectName("spinCount") self.gridLayout_4.addWidget(self.spinCount, 2, 1, 1, 1) - self.spinExpTime = QtWidgets.QDoubleSpinBox(self.groupExposure) - self.spinExpTime.setMaximum(99999.0) - self.spinExpTime.setProperty("value", 1.0) - self.spinExpTime.setObjectName("spinExpTime") - self.gridLayout_4.addWidget(self.spinExpTime, 1, 1, 1, 1) self.comboImageType = QtWidgets.QComboBox(self.groupExposure) self.comboImageType.setObjectName("comboImageType") self.gridLayout_4.addWidget(self.comboImageType, 0, 1, 1, 1) @@ -428,6 +423,24 @@ def setupUi(self, WidgetCamera): self.checkBroadcast.setChecked(True) self.checkBroadcast.setObjectName("checkBroadcast") self.gridLayout_4.addWidget(self.checkBroadcast, 3, 1, 1, 1) + self.horizontalLayout_3 = QtWidgets.QHBoxLayout() + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + self.spinExpTime = QtWidgets.QDoubleSpinBox(self.groupExposure) + self.spinExpTime.setSuffix("") + self.spinExpTime.setDecimals(3) + self.spinExpTime.setMaximum(999.0) + self.spinExpTime.setProperty("value", 1.0) + self.spinExpTime.setObjectName("spinExpTime") + self.horizontalLayout_3.addWidget(self.spinExpTime) + self.comboExpTimeUnit = QtWidgets.QComboBox(self.groupExposure) + self.comboExpTimeUnit.setMinimumContentsLength(2) + self.comboExpTimeUnit.setObjectName("comboExpTimeUnit") + self.comboExpTimeUnit.addItem("") + self.comboExpTimeUnit.addItem("") + self.comboExpTimeUnit.addItem("") + self.horizontalLayout_3.addWidget(self.comboExpTimeUnit) + self.horizontalLayout_3.setStretch(0, 1) + self.gridLayout_4.addLayout(self.horizontalLayout_3, 1, 1, 1, 1) self.verticalLayout.addWidget(self.groupExposure) spacerItem = QtWidgets.QSpacerItem(20, 26, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) self.verticalLayout.addItem(spacerItem) @@ -517,8 +530,7 @@ def setupUi(self, WidgetCamera): WidgetCamera.setTabOrder(self.butFullFrame, self.comboBinning) WidgetCamera.setTabOrder(self.comboBinning, self.comboImageFormat) WidgetCamera.setTabOrder(self.comboImageFormat, self.comboImageType) - WidgetCamera.setTabOrder(self.comboImageType, self.spinExpTime) - WidgetCamera.setTabOrder(self.spinExpTime, self.spinCount) + WidgetCamera.setTabOrder(self.comboImageType, self.spinCount) WidgetCamera.setTabOrder(self.spinCount, self.checkBroadcast) WidgetCamera.setTabOrder(self.checkBroadcast, self.butExpose) WidgetCamera.setTabOrder(self.butExpose, self.butAbort) @@ -545,12 +557,14 @@ def retranslateUi(self, WidgetCamera): self.label_10.setText(_translate("WidgetCamera", "Format:")) self.groupExposure.setTitle(_translate("WidgetCamera", "Exposure")) self.butExpose.setText(_translate("WidgetCamera", "Expose")) - self.spinExpTime.setSuffix(_translate("WidgetCamera", "s")) self.labelImageType.setText(_translate("WidgetCamera", "Type:")) self.labelExpTime.setText(_translate("WidgetCamera", "ExpTime:")) self.butAbort.setText(_translate("WidgetCamera", "Abort")) self.label_8.setText(_translate("WidgetCamera", "Count:")) self.checkBroadcast.setText(_translate("WidgetCamera", "Broadcast")) + self.comboExpTimeUnit.setItemText(0, _translate("WidgetCamera", "s")) + self.comboExpTimeUnit.setItemText(1, _translate("WidgetCamera", "ms")) + self.comboExpTimeUnit.setItemText(2, _translate("WidgetCamera", "µs")) self.labelStatus.setText(_translate("WidgetCamera", "IDLE")) self.labelExposuresLeft.setText(_translate("WidgetCamera", "IDLE")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabImage), _translate("WidgetCamera", "Image")) diff --git a/pyobs_gui/qt/widgetcamera.ui b/pyobs_gui/qt/widgetcamera.ui index 760ad9e..b85e56a 100644 --- a/pyobs_gui/qt/widgetcamera.ui +++ b/pyobs_gui/qt/widgetcamera.ui @@ -33,7 +33,7 @@ 0 0 - 183 + 264 794 @@ -640,19 +640,6 @@ - - - - s - - - 99999.000000000000000 - - - 1.000000000000000 - - - @@ -1136,6 +1123,48 @@ + + + + + + + + + 3 + + + 999.000000000000000 + + + 1.000000000000000 + + + + + + + 2 + + + + s + + + + + ms + + + + + µs + + + + + + @@ -1336,7 +1365,6 @@ comboBinning comboImageFormat comboImageType - spinExpTime spinCount checkBroadcast butExpose diff --git a/pyobs_gui/widgetcamera.py b/pyobs_gui/widgetcamera.py index 9572139..6391f2b 100644 --- a/pyobs_gui/widgetcamera.py +++ b/pyobs_gui/widgetcamera.py @@ -104,6 +104,7 @@ def __init__(self, module, comm, vfs, parent=None): self.comboImageType.setVisible(isinstance(self.module, IImageType)) self.labelExpTime.setVisible(isinstance(self.module, ICameraExposureTime)) self.spinExpTime.setVisible(isinstance(self.module, ICameraExposureTime)) + self.comboExpTimeUnit.setVisible(isinstance(self.module, ICameraExposureTime)) # add image panel self.imageLayout = QtWidgets.QVBoxLayout(self.tabImage) @@ -257,9 +258,21 @@ def _expose_thread_func(self): # do exposure(s) while self.exposures_left > 0: - # set exposure time and image type + # set exposure time if isinstance(self.module, ICameraExposureTime): - self.module.set_exposure_time(self.spinExpTime.value()).wait() + # get exp_time + exp_time = self.spinExpTime.value() + + # unit + if self.comboExpTimeUnit.currentText() == 'ms': + exp_time /= 1e3 + elif self.comboExpTimeUnit.currentText() == 'µs': + exp_time /= 1e6 + + # set it + self.module.set_exposure_time(exp_time).wait() + + # set image type if isinstance(self.module, IImageType): self.module.set_image_type(image_type) From ee15fbc89463840065a516dae2286aee74c6bdd3 Mon Sep 17 00:00:00 2001 From: Tim-Oliver Husser Date: Fri, 9 Apr 2021 16:04:13 +0200 Subject: [PATCH 20/29] fixed type hints --- pyobs_gui/basewidget.py | 3 ++- pyobs_gui/gui.py | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/pyobs_gui/basewidget.py b/pyobs_gui/basewidget.py index 753b2fe..f7e5cb3 100644 --- a/pyobs_gui/basewidget.py +++ b/pyobs_gui/basewidget.py @@ -1,5 +1,6 @@ import threading import logging +from typing import List, Dict, Tuple, Any from PyQt5 import QtWidgets, QtGui, QtCore from PyQt5.QtCore import pyqtSignal @@ -108,7 +109,7 @@ def show_error(self, message): def enable_buttons(self, widgets, enable): [w.setEnabled(enable) for w in widgets] - def get_fits_headers(self, namespaces: list = None, *args, **kwargs) -> dict: + def get_fits_headers(self, namespaces: List[str] = None, *args, **kwargs) -> Dict[str, Tuple[Any, str]]: """Returns FITS header for the current status of this module. Args: diff --git a/pyobs_gui/gui.py b/pyobs_gui/gui.py index bcf782c..e1fd215 100644 --- a/pyobs_gui/gui.py +++ b/pyobs_gui/gui.py @@ -1,3 +1,5 @@ +from typing import List, Dict, Tuple, Any + from PyQt5 import QtWidgets from pyobs.interfaces import IFitsHeaderProvider @@ -21,7 +23,7 @@ def main(self): # run app.exec() - def get_fits_headers(self, namespaces: list = None, *args, **kwargs) -> dict: + def get_fits_headers(self, namespaces: List[str] = None, *args, **kwargs) -> Dict[str, Tuple[Any, str]]: """Returns FITS header for the current status of this module. Args: From eaf9510525ecdc61b66ff4dfcb63f26834fc812e Mon Sep 17 00:00:00 2001 From: Tim-Oliver Husser Date: Fri, 9 Apr 2021 16:05:13 +0200 Subject: [PATCH 21/29] fixed types to make mypy happy --- pyobs_gui/basewidget.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/pyobs_gui/basewidget.py b/pyobs_gui/basewidget.py index f7e5cb3..f7da8bb 100644 --- a/pyobs_gui/basewidget.py +++ b/pyobs_gui/basewidget.py @@ -24,11 +24,11 @@ def __init__(self, update_func=None, update_interval: float = 1, *args, **kwargs # update thread self._update_func = update_func self._update_interval = update_interval - self._update_thread = None - self._update_thread_event = None + self._update_thread = threading.Thread() + self._update_thread_event = threading.Event() # sidebar - self.sidebar_widgets = [] + self.sidebar_widgets: List[BaseWidget] = [] self.sidebar_layout = None # has it been initialized? @@ -68,8 +68,6 @@ def hideEvent(self, event: QtGui.QHideEvent) -> None: # wait for it if self._update_thread is not None: self._update_thread.join() - self._update_thread = None - self._update_thread_event = None def _update_loop_thread(self): while not self._update_thread_event.is_set(): From bcd9d94f4072a421db1b5086519de59074824b67 Mon Sep 17 00:00:00 2001 From: Tim-Oliver Husser Date: Fri, 9 Apr 2021 21:00:00 +0200 Subject: [PATCH 22/29] fixed bug (_update_thread is never None) --- pyobs_gui/basewidget.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyobs_gui/basewidget.py b/pyobs_gui/basewidget.py index f7da8bb..ee556c4 100644 --- a/pyobs_gui/basewidget.py +++ b/pyobs_gui/basewidget.py @@ -66,7 +66,7 @@ def hideEvent(self, event: QtGui.QHideEvent) -> None: self._update_thread_event.set() # wait for it - if self._update_thread is not None: + if self._update_thread.is_alive(): self._update_thread.join() def _update_loop_thread(self): From e4af37d92f7726ecaef91a2e71d46c57617c61d6 Mon Sep 17 00:00:00 2001 From: Tim-Oliver Husser Date: Wed, 14 Apr 2021 15:38:26 +0200 Subject: [PATCH 23/29] moved ExposureStatus to utils.enums --- pyobs_gui/widgetcamera.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/pyobs_gui/widgetcamera.py b/pyobs_gui/widgetcamera.py index 6391f2b..f769f88 100644 --- a/pyobs_gui/widgetcamera.py +++ b/pyobs_gui/widgetcamera.py @@ -8,7 +8,7 @@ from pyobs.events import ExposureStatusChangedEvent, NewImageEvent from pyobs.interfaces import ICamera, ICameraBinning, ICameraWindow, ICooling, IFilters, ITemperatures, \ ICameraExposureTime, IImageType, IImageFormat -from pyobs.utils.enums import ImageType, ImageFormat +from pyobs.utils.enums import ImageType, ImageFormat, ExposureStatus from pyobs.images import Image from pyobs.vfs import VirtualFileSystem from pyobs_gui.basewidget import BaseWidget @@ -81,7 +81,7 @@ def __init__(self, module, comm, vfs, parent=None): self.image_filename = None self.image = None self.status = None - self.exposure_status = ICamera.ExposureStatus.IDLE + self.exposure_status = ExposureStatus.IDLE self.exposures_left = 0 self.exposure_time_left = 0 self.exposure_progress = 0 @@ -138,7 +138,7 @@ def __init__(self, module, comm, vfs, parent=None): def _init(self): # get status - self.exposure_status = ICamera.ExposureStatus(self.module.get_exposure_status().wait()) + self.exposure_status = ExposureStatus(self.module.get_exposure_status().wait()) # get binnings if isinstance(self.module, ICameraBinning): @@ -312,7 +312,7 @@ def abort(self): def _update(self): # are we exposing? - if self.exposure_status == ICamera.ExposureStatus.EXPOSING: + if self.exposure_status == ExposureStatus.EXPOSING: # get camera status exposure_time_left = self.module.get_exposure_time_left() exposure_progress = self.module.get_exposure_progress() @@ -336,8 +336,8 @@ def update_gui(self): self.setEnabled(True) # enable/disable buttons - self.butExpose.setEnabled(self.exposure_status == ICamera.ExposureStatus.IDLE) - self.butAbort.setEnabled(self.exposure_status != ICamera.ExposureStatus.IDLE) + self.butExpose.setEnabled(self.exposure_status == ExposureStatus.IDLE) + self.butAbort.setEnabled(self.exposure_status != ExposureStatus.IDLE) # set abort text if self.exposures_left > 1: @@ -347,13 +347,13 @@ def update_gui(self): # set progress msg = '' - if self.exposure_status == ICamera.ExposureStatus.IDLE: + if self.exposure_status == ExposureStatus.IDLE: self.progressExposure.setValue(0) msg = 'IDLE' - elif self.exposure_status == ICamera.ExposureStatus.EXPOSING: + elif self.exposure_status == ExposureStatus.EXPOSING: self.progressExposure.setValue(self.exposure_progress) msg = 'EXPOSING %.1fs' % self.exposure_time_left - elif self.exposure_status == ICamera.ExposureStatus.READOUT: + elif self.exposure_status == ExposureStatus.READOUT: self.progressExposure.setValue(100) msg = 'READOUT' From 109fce9a679d9a1d2dcb2448e651a3387baa8ae2 Mon Sep 17 00:00:00 2001 From: Tim-Oliver Husser Date: Wed, 14 Apr 2021 15:48:57 +0200 Subject: [PATCH 24/29] moved IMotion.Status to utils.enums.MotionStatus --- pyobs_gui/widgetfilter.py | 7 ++++--- pyobs_gui/widgetfocus.py | 9 +++++---- pyobs_gui/widgettelescope.py | 15 ++++++++------- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/pyobs_gui/widgetfilter.py b/pyobs_gui/widgetfilter.py index dd99768..7c93fc4 100644 --- a/pyobs_gui/widgetfilter.py +++ b/pyobs_gui/widgetfilter.py @@ -5,6 +5,7 @@ from pyobs.comm import Comm from pyobs.events import FilterChangedEvent, MotionStatusChangedEvent from pyobs.interfaces import IFilters, IMotion +from pyobs.utils.enums import MotionStatus from pyobs_gui.basewidget import BaseWidget from .qt.widgetfilter import Ui_WidgetFilter @@ -20,7 +21,7 @@ def __init__(self, module: IFilters, comm: Comm, parent=None): # variables self._filter = None - self._motion_status = IMotion.Status.UNKNOWN + self._motion_status = MotionStatus.UNKNOWN # connect signals self.signal_update_gui.connect(self.update_gui) @@ -45,8 +46,8 @@ def update_gui(self): self.setEnabled(True) self.textStatus.setText(self._motion_status.name) self.textFilter.setText('' if self._filter is None else self._filter) - initialized = self._motion_status in [IMotion.Status.SLEWING, IMotion.Status.TRACKING, - IMotion.Status.IDLE, IMotion.Status.POSITIONED] + initialized = self._motion_status in [MotionStatus.SLEWING, MotionStatus.TRACKING, + MotionStatus.IDLE, MotionStatus.POSITIONED] self.buttonSetFilter.setEnabled(initialized) def _on_filter_changed(self, event: FilterChangedEvent, sender: str): diff --git a/pyobs_gui/widgetfocus.py b/pyobs_gui/widgetfocus.py index 4a2b163..bc50fac 100644 --- a/pyobs_gui/widgetfocus.py +++ b/pyobs_gui/widgetfocus.py @@ -5,6 +5,7 @@ from pyobs.events import MotionStatusChangedEvent from pyobs.interfaces import IFocuser, IMotion +from pyobs.utils.enums import MotionStatus from pyobs_gui.basewidget import BaseWidget from .qt.widgetfocus import Ui_WidgetFocus @@ -24,7 +25,7 @@ def __init__(self, module, comm, parent=None): # variables self._focus = None self._focus_offset = None - self._motion_status = IMotion.Status.UNKNOWN + self._motion_status = MotionStatus.UNKNOWN # connect signals self.signal_update_gui.connect(self.update_gui) @@ -68,7 +69,7 @@ def _init(self): except: self._focus = None self._focus_offset = None - self._motion_status = IMotion.Status.UNKNOWN + self._motion_status = MotionStatus.UNKNOWN # update GUI self.signal_update_gui.emit() @@ -81,8 +82,8 @@ def update_gui(self): self.labelCurFocusOffset.setText('' if self._focus_offset is None else '%.3f' % self._focus_offset) self.labelCurFocus.setText('' if self._focus is None or self._focus_offset is None else '%.3f' % (self._focus + self._focus_offset,)) - initialized = self._motion_status in [IMotion.Status.SLEWING, IMotion.Status.TRACKING, - IMotion.Status.IDLE, IMotion.Status.POSITIONED] + initialized = self._motion_status in [MotionStatus.SLEWING, MotionStatus.TRACKING, + MotionStatus.IDLE, MotionStatus.POSITIONED] self.buttonResetFocusOffset.setEnabled(initialized) self.butSetFocusOffset.setEnabled(initialized) self.butSetFocusBase.setEnabled(initialized) diff --git a/pyobs_gui/widgettelescope.py b/pyobs_gui/widgettelescope.py index 90daec8..bbc68e8 100644 --- a/pyobs_gui/widgettelescope.py +++ b/pyobs_gui/widgettelescope.py @@ -12,6 +12,7 @@ from pyobs.comm import Comm from pyobs.events import MotionStatusChangedEvent from pyobs.interfaces import ITelescope, IFilters, IFocuser, ITemperatures, IMotion, IAltAzOffsets, IRaDecOffsets +from pyobs.utils.enums import MotionStatus from pyobs.utils.time import Time from pyobs_gui.widgetfilter import WidgetFilter from pyobs_gui.widgetfocus import WidgetFocus @@ -34,7 +35,7 @@ def __init__(self, module, comm, observer, parent=None): self.observer = observer # type: Observer # variables - self._motion_status = IMotion.Status.UNKNOWN + self._motion_status = MotionStatus.UNKNOWN self._ra_dec = None self._alt_az = None self._off_ra = None @@ -158,12 +159,12 @@ def update_gui(self): self.labelStatus.setText(self._motion_status.value.upper()) # (de)activate buttons - self.buttonInit.setEnabled(self._motion_status == IMotion.Status.PARKED) - self.buttonPark.setEnabled(self._motion_status not in [IMotion.Status.PARKED, IMotion.Status.ERROR, - IMotion.Status.PARKING, IMotion.Status.INITIALIZING]) - self.buttonStop.setEnabled(self._motion_status in [IMotion.Status.SLEWING, IMotion.Status.TRACKING]) - initialized = self._motion_status in [IMotion.Status.SLEWING, IMotion.Status.TRACKING, - IMotion.Status.IDLE, IMotion.Status.POSITIONED] + self.buttonInit.setEnabled(self._motion_status == MotionStatus.PARKED) + self.buttonPark.setEnabled(self._motion_status not in [MotionStatus.PARKED, MotionStatus.ERROR, + MotionStatus.PARKING, MotionStatus.INITIALIZING]) + self.buttonStop.setEnabled(self._motion_status in [MotionStatus.SLEWING, MotionStatus.TRACKING]) + initialized = self._motion_status in [MotionStatus.SLEWING, MotionStatus.TRACKING, + MotionStatus.IDLE, MotionStatus.POSITIONED] self.buttonMove.setEnabled(initialized) self.buttonOffsetNorth.setEnabled(initialized) self.buttonOffsetSouth.setEnabled(initialized) From 509a14e07b74555da6d03744fad70d2ebaa1204f Mon Sep 17 00:00:00 2001 From: Tim-Oliver Husser Date: Wed, 14 Apr 2021 15:54:14 +0200 Subject: [PATCH 25/29] moved IMotion.Status to utils.enums.MotionStatus --- pyobs_gui/widgetfilter.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pyobs_gui/widgetfilter.py b/pyobs_gui/widgetfilter.py index 7c93fc4..68a95d4 100644 --- a/pyobs_gui/widgetfilter.py +++ b/pyobs_gui/widgetfilter.py @@ -1,10 +1,9 @@ from PyQt5 import QtWidgets, QtCore from PyQt5.QtCore import pyqtSignal, pyqtSlot -import threading from pyobs.comm import Comm from pyobs.events import FilterChangedEvent, MotionStatusChangedEvent -from pyobs.interfaces import IFilters, IMotion +from pyobs.interfaces import IFilters from pyobs.utils.enums import MotionStatus from pyobs_gui.basewidget import BaseWidget from .qt.widgetfilter import Ui_WidgetFilter From f8662d0299947bcf44f3d0bac1e6b72675816e9a Mon Sep 17 00:00:00 2001 From: Tim-Oliver Husser Date: Fri, 16 Apr 2021 11:13:23 +0200 Subject: [PATCH 26/29] updated docstrings --- pyobs_gui/__init__.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pyobs_gui/__init__.py b/pyobs_gui/__init__.py index 80f3ae3..eb433a8 100644 --- a/pyobs_gui/__init__.py +++ b/pyobs_gui/__init__.py @@ -1 +1,8 @@ +""" +GUI (pyobs_gui) +----------------------- + +TODO: write doc +""" + from .gui import GUI From 43cf0a85db2590d8dfc92f3edf2d6bb7a2071329 Mon Sep 17 00:00:00 2001 From: Tim-Oliver Husser Date: Sat, 17 Apr 2021 16:16:01 +0200 Subject: [PATCH 27/29] added __module__ --- pyobs_gui/gui.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyobs_gui/gui.py b/pyobs_gui/gui.py index e1fd215..c8eb4b0 100644 --- a/pyobs_gui/gui.py +++ b/pyobs_gui/gui.py @@ -8,6 +8,8 @@ class GUI(Module, IFitsHeaderProvider): + __module__ = 'pyobs_gui' + def __init__(self, *args, **kwargs): Module.__init__(self, *args, **kwargs) self._window = None From 9f3c667c9401ff442d9aaf4097f5407563bb9fe7 Mon Sep 17 00:00:00 2001 From: Tim-Oliver Husser Date: Sun, 18 Apr 2021 17:26:57 +0200 Subject: [PATCH 28/29] documentation --- pyobs_gui/__init__.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pyobs_gui/__init__.py b/pyobs_gui/__init__.py index eb433a8..537153b 100644 --- a/pyobs_gui/__init__.py +++ b/pyobs_gui/__init__.py @@ -1,8 +1,6 @@ """ -GUI (pyobs_gui) ------------------------ - TODO: write doc """ +__title__ = 'GUI' from .gui import GUI From 76683761acb48f01896bfc83d47fe006525f1d56 Mon Sep 17 00:00:00 2001 From: Tim-Oliver Husser Date: Fri, 30 Apr 2021 13:45:53 +0200 Subject: [PATCH 29/29] v0.13 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 4267aff..c851758 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ setup( name='pyobs-gui', - version='0.12.2', + version='0.13', description='GUI for pyobs', author='Tim-Oliver Husser', author_email='thusser@uni-goettingen.de',