From 6b71de82653df5e5ac549f5e8b70cfa76297d053 Mon Sep 17 00:00:00 2001 From: Dominik Demuth Date: Fri, 7 Apr 2023 13:45:28 +0000 Subject: [PATCH] bug-fixer (#40) fixes #32, #34, #39 Co-authored-by: Dominik Demuth Reviewed-on: https://gitea.pkm.physik.tu-darmstadt.de/IPKM/nmreval/pulls/40 --- .gitignore | 1 + src/gui_qt/_py/eval_expr_dialog.py | 14 +++++++------ .../data/signaledit/editsignalwidget.py | 2 +- src/gui_qt/lib/listwidget.py | 20 +++++++++++++++++++ src/gui_qt/main/mainwindow.py | 11 +++++----- src/nmreval/fit/minimizer.py | 19 +++++++++++++----- src/resources/_ui/eval_expr_dialog.ui | 11 +++++++--- 7 files changed, 58 insertions(+), 20 deletions(-) create mode 100644 src/gui_qt/lib/listwidget.py diff --git a/.gitignore b/.gitignore index 3a30800..581e7b2 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ AppDir NMReval*.zsync .idea *.zs-old +docs diff --git a/src/gui_qt/_py/eval_expr_dialog.py b/src/gui_qt/_py/eval_expr_dialog.py index d70a5ed..5bda16f 100644 --- a/src/gui_qt/_py/eval_expr_dialog.py +++ b/src/gui_qt/_py/eval_expr_dialog.py @@ -1,10 +1,11 @@ # -*- coding: utf-8 -*- -# Form implementation generated from reading ui file 'resources/_ui/eval_expr_dialog.ui' +# Form implementation generated from reading ui file 'src/resources/_ui/eval_expr_dialog.ui' # -# Created by: PyQt5 UI code generator 5.12.3 +# Created by: PyQt5 UI code generator 5.15.9 # -# 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 @@ -36,14 +37,14 @@ class Ui_CalcDialog(object): self.label_2 = QtWidgets.QLabel(self.page) self.label_2.setObjectName("label_2") self.verticalLayout_2.addWidget(self.label_2) - self.listWidget = QtWidgets.QListWidget(self.page) + self.listWidget = QListWidgetSelect(self.page) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.MinimumExpanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.listWidget.sizePolicy().hasHeightForWidth()) self.listWidget.setSizePolicy(sizePolicy) self.listWidget.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers) - self.listWidget.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection) + self.listWidget.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection) self.listWidget.setObjectName("listWidget") self.verticalLayout_2.addWidget(self.listWidget) self.overwrite_checkbox = QtWidgets.QCheckBox(self.page) @@ -202,7 +203,7 @@ class Ui_CalcDialog(object): self.label_8.setBuddy(self.line_doubleSpinBox) self.retranslateUi(CalcDialog) - self.stackedWidget.setCurrentIndex(2) + self.stackedWidget.setCurrentIndex(0) QtCore.QMetaObject.connectSlotsByName(CalcDialog) CalcDialog.setTabOrder(self.calc_edit, self.listWidget) CalcDialog.setTabOrder(self.listWidget, self.overwrite_checkbox) @@ -237,4 +238,5 @@ class Ui_CalcDialog(object): self.label_11.setText(_translate("CalcDialog", "Style")) self.label.setText(_translate("CalcDialog", "Expressions are evaluated line by line and change previous values")) from ..lib.delegates import ColorListEditor, LineStyleEditor, SymbolStyleEditor +from ..lib.listwidget import QListWidgetSelect from ..lib.namespace import QNamespaceWidget diff --git a/src/gui_qt/data/signaledit/editsignalwidget.py b/src/gui_qt/data/signaledit/editsignalwidget.py index 73571ea..980ea19 100644 --- a/src/gui_qt/data/signaledit/editsignalwidget.py +++ b/src/gui_qt/data/signaledit/editsignalwidget.py @@ -46,7 +46,7 @@ class EditSignalWidget(QtWidgets.QWidget, Ui_Form): stype = 'pts' else: try: - _nop = float(self.lineEdit.text()) + _nop = float(self.ls_lineEdit.text()) except ValueError: _nop = 0.0 stype = 'time' diff --git a/src/gui_qt/lib/listwidget.py b/src/gui_qt/lib/listwidget.py new file mode 100644 index 0000000..0686192 --- /dev/null +++ b/src/gui_qt/lib/listwidget.py @@ -0,0 +1,20 @@ +from ..Qt import QtWidgets, QtGui, QtCore + + +class QListWidgetSelect(QtWidgets.QListWidget): + """ + Extension of QListWidget to change the check state of all selected QListWidgetItems with space key + """ + + def __init__(self, parent=None): + super().__init__(parent=parent) + + def keyPressEvent(self, evt: QtGui.QKeyEvent): + if evt.key() == QtCore.Qt.Key.Key_Space: + for idx in self.selectedIndexes(): + item = self.itemFromIndex(idx) + cs = item.checkState() + item.setCheckState(QtCore.Qt.CheckState.Unchecked if cs == QtCore.Qt.CheckState.Checked + else QtCore.Qt.CheckState.Checked) + else: + super().keyPressEvent(evt) diff --git a/src/gui_qt/main/mainwindow.py b/src/gui_qt/main/mainwindow.py index a6cc098..fc2f079 100644 --- a/src/gui_qt/main/mainwindow.py +++ b/src/gui_qt/main/mainwindow.py @@ -76,8 +76,8 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow): self.look_for_update() self.__timer = QtCore.QTimer() - self.__savepath = config_paths() / f'{datetime.datetime.now().strftime("%Y-%m-%d_%H%M%S")}.nmr' - self.__timer.start(0.2*60*1000) # every three minutese + self.__backup_path = config_paths() / f'{datetime.datetime.now().strftime("%Y-%m-%d_%H%M%S")}.nmr' + self.__timer.start(3*60*1000) # every three minutese self.__timer.timeout.connect(self._autosave) def _init_gui(self): @@ -146,7 +146,7 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow): self.actionUndo.setIcon(icon) self.menuData.insertAction(self.actionRedo, self.actionUndo) - # # self.actionSave.triggered.connect(lambda: self.management.save('/autohome/dominik/nmreval/testdata/test.nmr', '')) + # self.actionSave.triggered.connect(lambda: self.management.save('/autohome/dominik/nmreval/testdata/test.nmr', '')) # self.actionSave.triggered.connect(self.save) self.action_save_fit_parameter.triggered.connect(self.save_fit_parameter) self.ac_group2.triggered.connect(self.change_fit_limits) @@ -269,6 +269,7 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow): selected_filter = save_dialog.selectedNameFilter() if savefile is not None: + self.path = savefile.parent use_underscore = save_dialog.checkBox.isChecked() self.management.save(savefile, selected_filter, strip_spaces=use_underscore) @@ -1028,7 +1029,7 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow): write_state({'History': {'recent path': str(self.path)}}) # remove backup file when closing - self.__savepath.unlink(missing_ok=True) + self.__backup_path.unlink(missing_ok=True) super().close() @@ -1056,5 +1057,5 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow): def _autosave(self): # TODO better separate thread may it takes some time to save self.status.setText('Autosave...') - NMRWriter(self.management.graphs, self.management.data).export(self.__savepath) + NMRWriter(self.management.graphs, self.management.data).export(self.__backup_path) self.status.setText('') diff --git a/src/nmreval/fit/minimizer.py b/src/nmreval/fit/minimizer.py index bde5a93..f157962 100644 --- a/src/nmreval/fit/minimizer.py +++ b/src/nmreval/fit/minimizer.py @@ -14,6 +14,8 @@ from .result import FitResultCreator __all__ = ['FitRoutine', 'FitAbortException'] +from ..lib.logger import logger + class FitAbortException(Exception): pass @@ -464,11 +466,18 @@ class FitRoutine(object): def _calc_error(jac, chi, nobs, nvars): # copy of scipy.curve_fit to calculate covariance # noinspection PyTupleAssignmentBalance - _, s, vt = la.svd(jac, full_matrices=False) - threshold = EPS * max(jac.shape) * s[0] - s = s[s > threshold] - vt = vt[:s.size] - pcov = np.dot(vt.T / s**2, vt) * chi / (nobs - nvars) + try: + _, s, vt = la.svd(jac, full_matrices=False) + except ValueError as e: + # this may be issue #39: On entry to DGESSD parameter had an illegal value + # catch this exception and ignore error calculation + logger.error(f'Error calculation failed with {e.args}') + pcov = None + else: + threshold = EPS * max(jac.shape) * s[0] + s = s[s > threshold] + vt = vt[:s.size] + pcov = np.dot(vt.T / s**2, vt) * chi / (nobs - nvars) if pcov is None: _err = np.zeros(nvars) diff --git a/src/resources/_ui/eval_expr_dialog.ui b/src/resources/_ui/eval_expr_dialog.ui index c3f7791..c483d3f 100644 --- a/src/resources/_ui/eval_expr_dialog.ui +++ b/src/resources/_ui/eval_expr_dialog.ui @@ -27,7 +27,7 @@ - 2 + 0 @@ -54,7 +54,7 @@ - + 0 @@ -65,7 +65,7 @@ QAbstractItemView::NoEditTriggers - QAbstractItemView::SingleSelection + QAbstractItemView::ExtendedSelection @@ -414,6 +414,11 @@
..lib.namespace
1 + + QListWidgetSelect + QListWidget +
..lib.listwidget
+
calc_edit