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 @@
1
+
+ QListWidgetSelect
+ QListWidget
+
+
calc_edit