diff --git a/.gitea/workflows/build-appimage.yaml b/.gitea/workflows/build-appimage.yaml index 2c43c0b..1b69b69 100644 --- a/.gitea/workflows/build-appimage.yaml +++ b/.gitea/workflows/build-appimage.yaml @@ -29,10 +29,10 @@ jobs: env: GPG_KEYGRIP: ${{ vars.GPG_KEYGRIP }} GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} - GO_PIPELINE_LABEL: ${{ env.YEAR }}.${{ gitea.run_number }}_${{ env.SHA_SHORT }}_bookworm + GO_PIPELINE_LABEL: ${{ env.YEAR }}.${{ gitea.run_number }}_${{ env.SHA_SHORT }} - name: Upload AppImage run: ./tools/upload_gitea.sh env: - GO_PIPELINE_LABEL: ${{ env.YEAR }}.${{ gitea.run_number }}_${{ env.SHA_SHORT }}_bookworm + GO_PIPELINE_LABEL: ${{ env.YEAR }}.${{ gitea.run_number }}_${{ env.SHA_SHORT }} UPLOAD_TOKEN: ${{ secrets.UPLOAD_TOKEN }} UPLOAD_USER: ${{ vars.UPLOAD_USER }} diff --git a/src/gui_qt/_py/fcreader.py b/src/gui_qt/_py/fcreader.py index 766c641..041a46c 100644 --- a/src/gui_qt/_py/fcreader.py +++ b/src/gui_qt/_py/fcreader.py @@ -1,10 +1,11 @@ # -*- coding: utf-8 -*- -# Form implementation generated from reading ui file 'resources/_ui/fcreader.ui' +# Form implementation generated from reading ui file 'src/resources/_ui/fcreader.ui' # -# Created by: PyQt5 UI code generator 5.12.3 +# Created by: PyQt5 UI code generator 5.15.10 # -# WARNING! All changes made in this file will be lost! +# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# run again. Do not edit this file unless you know what you are doing. from PyQt5 import QtCore, QtGui, QtWidgets @@ -47,6 +48,7 @@ class Ui_FCEval_dialog(object): self.verticalLayout.addWidget(self.input_box) self.region_box = QtWidgets.QGroupBox(FCEval_dialog) self.region_box.setCheckable(True) + self.region_box.setChecked(False) self.region_box.setObjectName("region_box") self.horizontalLayout = QtWidgets.QHBoxLayout(self.region_box) self.horizontalLayout.setContentsMargins(3, 3, 3, 3) @@ -139,6 +141,7 @@ class Ui_FCEval_dialog(object): self.line.setObjectName("line") self.gridLayout.addWidget(self.line, 2, 0, 1, 2) self.graph_comboBox = QtWidgets.QComboBox(self.out_box) + self.graph_comboBox.setEnabled(False) self.graph_comboBox.setObjectName("graph_comboBox") self.gridLayout.addWidget(self.graph_comboBox, 3, 1, 1, 1) self.graph_checkbox = QtWidgets.QCheckBox(self.out_box) @@ -167,8 +170,8 @@ class Ui_FCEval_dialog(object): self.label_6.setBuddy(self.m0_cb) self.retranslateUi(FCEval_dialog) - self.buttonBox.accepted.connect(FCEval_dialog.accept) - self.buttonBox.rejected.connect(FCEval_dialog.reject) + self.buttonBox.accepted.connect(FCEval_dialog.accept) # type: ignore + self.buttonBox.rejected.connect(FCEval_dialog.reject) # type: ignore QtCore.QMetaObject.connectSlotsByName(FCEval_dialog) def retranslateUi(self, FCEval_dialog): @@ -178,7 +181,7 @@ class Ui_FCEval_dialog(object): self.file_pushbutton.setText(_translate("FCEval_dialog", "Add HDF files...")) self.dir_pushbutton.setText(_translate("FCEval_dialog", "Add directory...")) self.overwrite_cb.setText(_translate("FCEval_dialog", "Overwrite prev. data")) - self.region_box.setTitle(_translate("FCEval_dialog", "Evaluate region (empty values default to start/end)")) + self.region_box.setTitle(_translate("FCEval_dialog", "Evaluate region (empty values default to values of the script)")) self.start_lineedit.setPlaceholderText(_translate("FCEval_dialog", "start pos in µs")) self.stop_lineedit.setPlaceholderText(_translate("FCEval_dialog", "end pos in µs")) self.fit_box.setTitle(_translate("FCEval_dialog", "Fit equation")) diff --git a/src/gui_qt/_py/smoothdialog.py b/src/gui_qt/_py/smoothdialog.py index 634fde5..7d2d758 100644 --- a/src/gui_qt/_py/smoothdialog.py +++ b/src/gui_qt/_py/smoothdialog.py @@ -1,10 +1,11 @@ # -*- coding: utf-8 -*- -# Form implementation generated from reading ui file 'resources/_ui/smoothdialog.ui' +# Form implementation generated from reading ui file 'src/resources/_ui/smoothdialog.ui' # -# Created by: PyQt5 UI code generator 5.12.3 +# Created by: PyQt5 UI code generator 5.15.10 # -# WARNING! All changes made in this file will be lost! +# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# run again. Do not edit this file unless you know what you are doing. from PyQt5 import QtCore, QtGui, QtWidgets @@ -17,9 +18,37 @@ class Ui_SmoothDialog(object): self.gridLayout = QtWidgets.QGridLayout(SmoothDialog) self.gridLayout.setSpacing(3) self.gridLayout.setObjectName("gridLayout") + spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.gridLayout.addItem(spacerItem, 7, 0, 1, 1) self.frac_label = QtWidgets.QLabel(SmoothDialog) self.frac_label.setObjectName("frac_label") - self.gridLayout.addWidget(self.frac_label, 1, 0, 1, 1) + self.gridLayout.addWidget(self.frac_label, 2, 0, 1, 1) + self.line = QtWidgets.QFrame(SmoothDialog) + self.line.setFrameShape(QtWidgets.QFrame.HLine) + self.line.setFrameShadow(QtWidgets.QFrame.Sunken) + self.line.setObjectName("line") + self.gridLayout.addWidget(self.line, 5, 0, 1, 2) + self.widget = QtWidgets.QWidget(SmoothDialog) + self.widget.setObjectName("widget") + self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.widget) + self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_2.setSpacing(3) + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.label = QtWidgets.QLabel(self.widget) + self.label.setObjectName("label") + self.horizontalLayout_2.addWidget(self.label) + self.polynom_spinBox = QtWidgets.QSpinBox(self.widget) + self.polynom_spinBox.setMinimum(1) + self.polynom_spinBox.setMaximum(3) + self.polynom_spinBox.setObjectName("polynom_spinBox") + self.horizontalLayout_2.addWidget(self.polynom_spinBox) + self.gridLayout.addWidget(self.widget, 3, 0, 1, 2) + self.y_checkBox = QtWidgets.QCheckBox(SmoothDialog) + self.y_checkBox.setObjectName("y_checkBox") + self.gridLayout.addWidget(self.y_checkBox, 6, 1, 1, 1) + self.x_checkBox = QtWidgets.QCheckBox(SmoothDialog) + self.x_checkBox.setObjectName("x_checkBox") + self.gridLayout.addWidget(self.x_checkBox, 6, 0, 1, 1) self.widget_2 = QtWidgets.QWidget(SmoothDialog) self.widget_2.setObjectName("widget_2") self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.widget_2) @@ -35,37 +64,17 @@ class Ui_SmoothDialog(object): self.iter_spinBox.setProperty("value", 1) self.iter_spinBox.setObjectName("iter_spinBox") self.horizontalLayout_3.addWidget(self.iter_spinBox) - self.gridLayout.addWidget(self.widget_2, 3, 0, 1, 2) - self.line = QtWidgets.QFrame(SmoothDialog) - self.line.setFrameShape(QtWidgets.QFrame.HLine) - self.line.setFrameShadow(QtWidgets.QFrame.Sunken) - self.line.setObjectName("line") - self.gridLayout.addWidget(self.line, 4, 0, 1, 2) - self.buttonBox = QtWidgets.QDialogButtonBox(SmoothDialog) - self.buttonBox.setOrientation(QtCore.Qt.Horizontal) - self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Apply|QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok) - self.buttonBox.setObjectName("buttonBox") - self.gridLayout.addWidget(self.buttonBox, 7, 0, 1, 2) - self.widget = QtWidgets.QWidget(SmoothDialog) - self.widget.setObjectName("widget") - self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.widget) - self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0) - self.horizontalLayout_2.setSpacing(3) - self.horizontalLayout_2.setObjectName("horizontalLayout_2") - self.label = QtWidgets.QLabel(self.widget) - self.label.setObjectName("label") - self.horizontalLayout_2.addWidget(self.label) - self.polynom_spinBox = QtWidgets.QSpinBox(self.widget) - self.polynom_spinBox.setMinimum(1) - self.polynom_spinBox.setMaximum(3) - self.polynom_spinBox.setObjectName("polynom_spinBox") - self.horizontalLayout_2.addWidget(self.polynom_spinBox) - self.gridLayout.addWidget(self.widget, 2, 0, 1, 2) + self.gridLayout.addWidget(self.widget_2, 4, 0, 1, 2) self.frac_spinBox = QtWidgets.QSpinBox(SmoothDialog) self.frac_spinBox.setMinimum(1) self.frac_spinBox.setMaximum(999) self.frac_spinBox.setObjectName("frac_spinBox") - self.gridLayout.addWidget(self.frac_spinBox, 1, 1, 1, 1) + self.gridLayout.addWidget(self.frac_spinBox, 2, 1, 1, 1) + self.buttonBox = QtWidgets.QDialogButtonBox(SmoothDialog) + self.buttonBox.setOrientation(QtCore.Qt.Horizontal) + self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Apply|QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok) + self.buttonBox.setObjectName("buttonBox") + self.gridLayout.addWidget(self.buttonBox, 8, 0, 1, 2) self.comboBox = QtWidgets.QComboBox(SmoothDialog) self.comboBox.setObjectName("comboBox") self.comboBox.addItem("") @@ -77,22 +86,17 @@ class Ui_SmoothDialog(object): self.comboBox.addItem("") self.comboBox.addItem("") self.comboBox.addItem("") - self.gridLayout.addWidget(self.comboBox, 0, 0, 1, 2) - spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.gridLayout.addItem(spacerItem, 6, 0, 1, 1) - self.y_checkBox = QtWidgets.QCheckBox(SmoothDialog) - self.y_checkBox.setObjectName("y_checkBox") - self.gridLayout.addWidget(self.y_checkBox, 5, 1, 1, 1) - self.x_checkBox = QtWidgets.QCheckBox(SmoothDialog) - self.x_checkBox.setObjectName("x_checkBox") - self.gridLayout.addWidget(self.x_checkBox, 5, 0, 1, 1) + self.gridLayout.addWidget(self.comboBox, 1, 0, 1, 2) + self.label_2 = QtWidgets.QLabel(SmoothDialog) + self.label_2.setObjectName("label_2") + self.gridLayout.addWidget(self.label_2, 0, 0, 1, 2) self.frac_label.setBuddy(self.frac_spinBox) - self.label_3.setBuddy(self.iter_spinBox) self.label.setBuddy(self.polynom_spinBox) + self.label_3.setBuddy(self.iter_spinBox) self.retranslateUi(SmoothDialog) - self.buttonBox.accepted.connect(SmoothDialog.accept) - self.buttonBox.rejected.connect(SmoothDialog.reject) + self.buttonBox.accepted.connect(SmoothDialog.accept) # type: ignore + self.buttonBox.rejected.connect(SmoothDialog.reject) # type: ignore QtCore.QMetaObject.connectSlotsByName(SmoothDialog) SmoothDialog.setTabOrder(self.comboBox, self.frac_spinBox) SmoothDialog.setTabOrder(self.frac_spinBox, self.polynom_spinBox) @@ -104,9 +108,11 @@ class Ui_SmoothDialog(object): _translate = QtCore.QCoreApplication.translate SmoothDialog.setWindowTitle(_translate("SmoothDialog", "1D smoothing filter")) self.frac_label.setText(_translate("SmoothDialog", "Window length")) - self.label_3.setText(_translate("SmoothDialog", "Iterations")) self.label.setText(_translate("SmoothDialog", "Polynomial degree")) self.polynom_spinBox.setToolTip(_translate("SmoothDialog", "Deg")) + self.y_checkBox.setText(_translate("SmoothDialog", "y log-spaced?")) + self.x_checkBox.setText(_translate("SmoothDialog", "x log-spaced?")) + self.label_3.setText(_translate("SmoothDialog", "Iterations")) self.frac_spinBox.setToolTip(_translate("SmoothDialog", "

Number of data points used as smoothing window.

")) self.comboBox.setItemText(0, _translate("SmoothDialog", "Moving mean")) self.comboBox.setItemText(1, _translate("SmoothDialog", "Savitzky-Golay")) @@ -117,5 +123,4 @@ class Ui_SmoothDialog(object): self.comboBox.setItemText(6, _translate("SmoothDialog", "Moving maximum")) self.comboBox.setItemText(7, _translate("SmoothDialog", "Moving minimum")) self.comboBox.setItemText(8, _translate("SmoothDialog", "Moving sum")) - self.y_checkBox.setText(_translate("SmoothDialog", "y log-spaced?")) - self.x_checkBox.setText(_translate("SmoothDialog", "x log-spaced?")) + self.label_2.setText(_translate("SmoothDialog", "

Note: Sets must be sorted for correct results

")) diff --git a/src/gui_qt/io/fcbatchreader.py b/src/gui_qt/io/fcbatchreader.py index 4f678b5..c4bb80b 100644 --- a/src/gui_qt/io/fcbatchreader.py +++ b/src/gui_qt/io/fcbatchreader.py @@ -22,14 +22,16 @@ class QFCReader(QtWidgets.QDialog, Ui_FCEval_dialog): self.start_lineedit.setValidator(QtGui.QDoubleValidator()) self.stop_lineedit.setValidator(QtGui.QDoubleValidator()) - self.graph_checkbox.stateChanged.connect(lambda x: self.graph_comboBox.setEnabled(not bool(x))) + self.graph_checkbox.stateChanged.connect( + lambda x: self.graph_comboBox.setEnabled(x == QtCore.Qt.CheckState.Unchecked) + ) self.listWidget.installEventFilter(self) def eventFilter(self, src: QtCore.QObject, evt: QtCore.QEvent) -> bool: # intercept key press in listwidget to allow deletion with Del - if evt.type() == QtCore.QEvent.KeyPress: - if evt.key() == QtCore.Qt.Key_Delete: + if evt.type() == QtCore.QEvent.Type.KeyPress: + if evt.key() == QtCore.Qt.Key.Key_Delete: self.listWidget.takeItem(self.listWidget.currentRow()) return True @@ -41,21 +43,25 @@ class QFCReader(QtWidgets.QDialog, Ui_FCEval_dialog): @QtCore.pyqtSlot(int, name='on_region_checkBox_stateChanged') def use_region(self, state: int): - self.start_lineedit.setEnabled(state == QtCore.Qt.Checked) - self.stop_lineedit.setEnabled(state == QtCore.Qt.Checked) + self.start_lineedit.setEnabled(state == QtCore.Qt.CheckState.Checked) + self.stop_lineedit.setEnabled(state == QtCore.Qt.CheckState.Checked) @QtCore.pyqtSlot(name='on_file_pushbutton_clicked') @QtCore.pyqtSlot(name='on_dir_pushbutton_clicked') def get_input(self): if self.sender() == self.file_pushbutton: - infiles, _ = QtWidgets.QFileDialog.getOpenFileNames(caption='Select HDF files', - directory=str(self.path), - filter='HDF files (*.h5)') + infiles, _ = QtWidgets.QFileDialog.getOpenFileNames( + caption='Select HDF files', + directory=str(self.path), + filter='HDF files (*.h5)', + ) else: - infiles = QtWidgets.QFileDialog.getExistingDirectory(caption='Select input directory', - directory=str(self.path), - options=QtWidgets.QFileDialog.ShowDirsOnly) + infiles = QtWidgets.QFileDialog.getExistingDirectory( + caption='Select input directory', + directory=str(self.path), + options=QtWidgets.QFileDialog.ShowDirsOnly, + ) infiles = [infiles] if infiles else infiles if infiles: @@ -65,9 +71,12 @@ class QFCReader(QtWidgets.QDialog, Ui_FCEval_dialog): @QtCore.pyqtSlot(name='on_savebutton_clicked') def save_path(self): - outfile = QtWidgets.QFileDialog.getExistingDirectory(self, caption='Select directory', - directory=self.label.text(), - options=QtWidgets.QFileDialog.ShowDirsOnly) + outfile = QtWidgets.QFileDialog.getExistingDirectory( + self, + caption='Select directory', + directory=self.label.text(), + options=QtWidgets.QFileDialog.ShowDirsOnly, + ) if outfile: self.label.setText(outfile) @@ -110,6 +119,6 @@ class QFCReader(QtWidgets.QDialog, Ui_FCEval_dialog): grp = '' if not self.graph_checkbox.isChecked(): - grp = self.graph_comboBox.currentData(QtCore.Qt.UserRole) + grp = self.graph_comboBox.currentData(QtCore.Qt.ItemDataRole.UserRole) self.data_read.emit(ret_vals, grp) diff --git a/src/nmreval/math/smooth.py b/src/nmreval/math/smooth.py index 5207720..fc5997d 100644 --- a/src/nmreval/math/smooth.py +++ b/src/nmreval/math/smooth.py @@ -3,14 +3,21 @@ import numpy.polynomial.polynomial as poly from scipy import signal as signal -__all__ = ['smooth', 'loess', 'savgol', - 'running_max', 'running_min', - 'running_var', 'running_std', - 'running_median', 'running_mean', - 'running_sum'] +__all__ = [ + 'smooth', + 'loess', + 'savgol', + 'running_max', + 'running_min', + 'running_var', + 'running_std', + 'running_median', + 'running_mean', + 'running_sum', +] -def loess(x, y, window_size, it=0, deg=2): +def loess(x, y, window_size: int, it: int = 0, deg: int = 2): # ULTRA LANGSAM !!! it = max(it, 0) @@ -81,19 +88,19 @@ def savgol(x, y, window_size: int, deg: int = 2, mode: str = 'mirror'): return new_y -def running_mean(x, y, window_size): +def running_mean(x, y, window_size: int): return _running_func(np.nanmean, x, y, window_size) -def running_median(x, y, window_size): +def running_median(x, y, window_size: int): return _running_func(np.nanmedian, x, y, window_size) -def running_std(x, y, window_size): +def running_std(x, y, window_size: int): return _running_func(np.nanstd, x, y, window_size) -def running_var(x, y, window_size): +def running_var(x, y, window_size: int): return _running_func(np.nanvar, x, y, window_size) @@ -132,11 +139,27 @@ def _moving_window(arr, nn): return np.lib.stride_tricks.as_strided(arr, shapes, strides) -_funcs = {'loess': loess, 'savgol': savgol, 'mean': running_mean, 'median': running_median, - 'std': running_std, 'var': running_var, 'max': running_max, 'min': running_min, 'sum': running_sum} +_funcs = { + 'loess': loess, + 'savgol': savgol, + 'mean': running_mean, + 'median': running_median, + 'std': running_std, + 'var': running_var, + 'max': running_max, + 'min': running_min, + 'sum': running_sum, +} -def smooth(data, window_size, mode='mean', logx=False, logy=False, **kwargs): +def smooth( + data: 'Data', + window_size: int, + mode: str = 'mean', + logx: bool = False, + logy: bool = False, + **kwargs +): try: func = _funcs[mode] except KeyError: @@ -162,6 +185,6 @@ def smooth(data, window_size, mode='mean', logx=False, logy=False, **kwargs): new_y = 10**new_y new_data = data.copy() - new_data.set_data(x=new_x, y=new_y, y_err=None) + new_data.set_data(x=new_x, y=new_y, y_err=np.zeros_like(new_y)) return new_data diff --git a/src/resources/_ui/fcreader.ui b/src/resources/_ui/fcreader.ui index 7c818de..ff4695c 100644 --- a/src/resources/_ui/fcreader.ui +++ b/src/resources/_ui/fcreader.ui @@ -96,11 +96,14 @@ - Evaluate region (empty values default to start/end) + Evaluate region (empty values default to values of the script) true + + false + 3 @@ -311,7 +314,11 @@ - + + + false + + diff --git a/src/resources/_ui/smoothdialog.ui b/src/resources/_ui/smoothdialog.ui index e26b521..19e63ec 100644 --- a/src/resources/_ui/smoothdialog.ui +++ b/src/resources/_ui/smoothdialog.ui @@ -17,7 +17,20 @@ 3 - + + + + Qt::Vertical + + + + 20 + 40 + + + + + Window length @@ -27,68 +40,14 @@ - - - - - 3 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Iterations - - - iter_spinBox - - - - - - - 3 - - - 1 - - - 1 - - - - - - - + Qt::Horizontal - - - - Qt::Horizontal - - - QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - + @@ -132,7 +91,65 @@ - + + + + y log-spaced? + + + + + + + x log-spaced? + + + + + + + + 3 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Iterations + + + iter_spinBox + + + + + + + 3 + + + 1 + + + 1 + + + + + + + <html><head/><body><p>Number of data points used as smoothing window.</p></body></html> @@ -145,7 +162,17 @@ - + + + + Qt::Horizontal + + + QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + @@ -194,30 +221,13 @@ - - - - Qt::Vertical - - - - 20 - 40 - - - - - - + + - y log-spaced? + <html><head/><body><p><span style=" font-weight:600;">Note:</span> Sets must be sorted for correct results</p></body></html> - - - - - - x log-spaced? + + 3