diff --git a/AppImageBuilder.yml b/AppImageBuilder.yml
index 084c2e8..ffd4159 100644
--- a/AppImageBuilder.yml
+++ b/AppImageBuilder.yml
@@ -32,7 +32,7 @@ AppDir:
arch: amd64
allow_unauthenticated: true
sources:
- - sourceline: 'deb [arch=amd64] http://mirror.infra.pkm/ bullseye main contrib non-free'
+ - sourceline: 'deb [arch=amd64] http://ftp.uni-mainz.de/debian bullseye main contrib non-free'
include:
# for /usr/bin/env
@@ -42,7 +42,7 @@ AppDir:
# - hicolor-icon-theme
- libatlas3-base
- gnuplot-nox
- - python3.9-minimal
+ - python3-minimal
- python3-numpy
- python3-scipy
- python3-bsddb3
diff --git a/src/gui_qt/_py/apod_dialog.py b/src/gui_qt/_py/apod_dialog.py
index 3c985d9..6a40632 100644
--- a/src/gui_qt/_py/apod_dialog.py
+++ b/src/gui_qt/_py/apod_dialog.py
@@ -1,10 +1,11 @@
# -*- coding: utf-8 -*-
-# Form implementation generated from reading ui file '_ui/apod_dialog.ui'
+# Form implementation generated from reading ui file 'src/resources/_ui/apod_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
@@ -23,7 +24,7 @@ class Ui_ApodEdit(object):
self.gridLayout.setContentsMargins(3, 3, 3, 3)
self.gridLayout.setSpacing(3)
self.gridLayout.setObjectName("gridLayout")
- self.graphicsView = PlotWidget(ApodEdit)
+ self.graphicsView = NMRPlotWidget(ApodEdit)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
@@ -31,7 +32,7 @@ class Ui_ApodEdit(object):
self.graphicsView.setSizePolicy(sizePolicy)
self.graphicsView.setObjectName("graphicsView")
self.gridLayout.addWidget(self.graphicsView, 2, 0, 1, 1)
- self.graphicsView_2 = PlotWidget(ApodEdit)
+ self.graphicsView_2 = NMRPlotWidget(ApodEdit)
self.graphicsView_2.setObjectName("graphicsView_2")
self.gridLayout.addWidget(self.graphicsView_2, 2, 1, 1, 1)
self.apodcombobox = QtWidgets.QComboBox(ApodEdit)
@@ -63,12 +64,12 @@ class Ui_ApodEdit(object):
self.gridLayout.addWidget(self.eqn_label, 0, 1, 1, 1)
self.retranslateUi(ApodEdit)
- self.buttonBox.accepted.connect(ApodEdit.accept)
- self.buttonBox.rejected.connect(ApodEdit.close)
+ self.buttonBox.accepted.connect(ApodEdit.accept) # type: ignore
+ self.buttonBox.rejected.connect(ApodEdit.close) # type: ignore
QtCore.QMetaObject.connectSlotsByName(ApodEdit)
def retranslateUi(self, ApodEdit):
_translate = QtCore.QCoreApplication.translate
ApodEdit.setWindowTitle(_translate("ApodEdit", "Apodization"))
self.eqn_label.setText(_translate("ApodEdit", "TextLabel"))
-from pyqtgraph import PlotWidget
+from ..lib.graph_items import NMRPlotWidget
diff --git a/src/gui_qt/_py/baseline_dialog.py b/src/gui_qt/_py/baseline_dialog.py
index ca67fe7..6c632f7 100644
--- a/src/gui_qt/_py/baseline_dialog.py
+++ b/src/gui_qt/_py/baseline_dialog.py
@@ -1,10 +1,11 @@
# -*- coding: utf-8 -*-
-# Form implementation generated from reading ui file '_ui/baseline_dialog.ui'
+# Form implementation generated from reading ui file 'src/resources/_ui/baseline_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
@@ -44,7 +45,7 @@ class Ui_SignalEdit(object):
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
self.buttonBox.setObjectName("buttonBox")
self.gridLayout.addWidget(self.buttonBox, 1, 0, 1, 3)
- self.graphicsView = PlotWidget(SignalEdit)
+ self.graphicsView = NMRPlotWidget(SignalEdit)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
@@ -54,11 +55,11 @@ class Ui_SignalEdit(object):
self.gridLayout.addWidget(self.graphicsView, 0, 2, 1, 1)
self.retranslateUi(SignalEdit)
- self.buttonBox.accepted.connect(SignalEdit.accept)
- self.buttonBox.rejected.connect(SignalEdit.close)
+ self.buttonBox.accepted.connect(SignalEdit.accept) # type: ignore
+ self.buttonBox.rejected.connect(SignalEdit.close) # type: ignore
QtCore.QMetaObject.connectSlotsByName(SignalEdit)
def retranslateUi(self, SignalEdit):
_translate = QtCore.QCoreApplication.translate
SignalEdit.setWindowTitle(_translate("SignalEdit", "Dialog"))
-from pyqtgraph import PlotWidget
+from ..lib.graph_items import NMRPlotWidget
diff --git a/src/gui_qt/_py/dscfile_dialog.py b/src/gui_qt/_py/dscfile_dialog.py
index a0f3242..1e84afc 100644
--- a/src/gui_qt/_py/dscfile_dialog.py
+++ b/src/gui_qt/_py/dscfile_dialog.py
@@ -166,7 +166,7 @@ class Ui_Dialog(object):
self.gridLayout = QtWidgets.QGridLayout(self.layoutWidget)
self.gridLayout.setContentsMargins(0, 0, 0, 0)
self.gridLayout.setObjectName("gridLayout")
- self.raw_graph = PlotWidget(self.layoutWidget)
+ self.raw_graph = NMRPlotWidget(self.layoutWidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
@@ -175,7 +175,7 @@ class Ui_Dialog(object):
self.raw_graph.setMinimumSize(QtCore.QSize(300, 200))
self.raw_graph.setObjectName("raw_graph")
self.gridLayout.addWidget(self.raw_graph, 0, 0, 1, 1)
- self.calib_graph = PlotWidget(self.layoutWidget)
+ self.calib_graph = NMRPlotWidget(self.layoutWidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
@@ -184,7 +184,7 @@ class Ui_Dialog(object):
self.calib_graph.setMinimumSize(QtCore.QSize(300, 200))
self.calib_graph.setObjectName("calib_graph")
self.gridLayout.addWidget(self.calib_graph, 1, 0, 1, 1)
- self.baseline_graph = PlotWidget(self.layoutWidget)
+ self.baseline_graph = NMRPlotWidget(self.layoutWidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
@@ -193,7 +193,7 @@ class Ui_Dialog(object):
self.baseline_graph.setMinimumSize(QtCore.QSize(300, 200))
self.baseline_graph.setObjectName("baseline_graph")
self.gridLayout.addWidget(self.baseline_graph, 0, 1, 1, 1)
- self.end_graph = PlotWidget(self.layoutWidget)
+ self.end_graph = NMRPlotWidget(self.layoutWidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
@@ -228,4 +228,4 @@ class Ui_Dialog(object):
self.cp_checkBox.setText(_translate("Dialog", "Use reference to convert to heat capacity"))
self.ref_add_pushButton.setText(_translate("Dialog", "Add reference"))
self.ref_remove_pushButton.setText(_translate("Dialog", "Remove reference"))
-from pyqtgraph import PlotWidget
+from ..lib.graph_items import NMRPlotWidget
diff --git a/src/gui_qt/_py/fitdialog.py b/src/gui_qt/_py/fitdialog.py
index cf7d7f6..70ae70a 100644
--- a/src/gui_qt/_py/fitdialog.py
+++ b/src/gui_qt/_py/fitdialog.py
@@ -38,7 +38,6 @@ class Ui_FitDialog(object):
self.weight_combobox.addItem("")
self.weight_combobox.addItem("")
self.weight_combobox.addItem("")
- self.weight_combobox.addItem("")
self.gridLayout_2.addWidget(self.weight_combobox, 6, 1, 1, 1)
self.newmodel_button = QtWidgets.QPushButton(self.scrollAreaWidgetContents_2)
self.newmodel_button.setEnabled(False)
@@ -144,7 +143,6 @@ class Ui_FitDialog(object):
self.weight_combobox.setItemText(1, _translate("FitDialog", "y"))
self.weight_combobox.setItemText(2, _translate("FitDialog", "y²"))
self.weight_combobox.setItemText(3, _translate("FitDialog", "Δy"))
- self.weight_combobox.setItemText(4, _translate("FitDialog", "log(y)"))
self.newmodel_button.setText(_translate("FitDialog", "New model"))
self.deletemodel_button.setText(_translate("FitDialog", "Delete model"))
self.label_3.setText(_translate("FitDialog", "Weight"))
diff --git a/src/gui_qt/_py/graph.py b/src/gui_qt/_py/graph.py
index 8ecac0b..62feba0 100644
--- a/src/gui_qt/_py/graph.py
+++ b/src/gui_qt/_py/graph.py
@@ -210,7 +210,7 @@ class Ui_GraphWindow(object):
self.checkBox.setChecked(True)
self.checkBox.setObjectName("checkBox")
self.gridLayout.addWidget(self.checkBox, 0, 1, 1, 1)
- self.graphic = PlotWidget(GraphWindow)
+ self.graphic = NMRPlotWidget(GraphWindow)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
@@ -274,5 +274,5 @@ class Ui_GraphWindow(object):
self.label_6.setText(_translate("GraphWindow", "X Axis"))
self.label_7.setText(_translate("GraphWindow", "Y Axis"))
self.checkBox.setText(_translate("GraphWindow", "Show legend"))
+from ..lib.graph_items import NMRPlotWidget
from ..lib.listwidget import QListWidgetSelect
-from pyqtgraph import PlotWidget
diff --git a/src/gui_qt/_py/phase_corr_dialog.py b/src/gui_qt/_py/phase_corr_dialog.py
index a8c9c51..b0f12fe 100644
--- a/src/gui_qt/_py/phase_corr_dialog.py
+++ b/src/gui_qt/_py/phase_corr_dialog.py
@@ -1,8 +1,8 @@
# -*- coding: utf-8 -*-
-# Form implementation generated from reading ui file 'resources/_ui/phase_corr_dialog.ui'
+# Form implementation generated from reading ui file 'src/resources/_ui/phase_corr_dialog.ui'
#
-# Created by: PyQt5 UI code generator 5.15.4
+# Created by: PyQt5 UI code generator 5.15.9
#
# 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.
@@ -24,7 +24,7 @@ class Ui_SignalEdit(object):
self.gridLayout.setContentsMargins(6, 6, 6, 6)
self.gridLayout.setSpacing(3)
self.gridLayout.setObjectName("gridLayout")
- self.graphicsView = PlotWidget(SignalEdit)
+ self.graphicsView = NMRPlotWidget(SignalEdit)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
@@ -83,8 +83,8 @@ class Ui_SignalEdit(object):
self.gridLayout.addItem(spacerItem1, 1, 5, 1, 1)
self.retranslateUi(SignalEdit)
- self.buttonBox.accepted.connect(SignalEdit.accept)
- self.buttonBox.rejected.connect(SignalEdit.close)
+ self.buttonBox.accepted.connect(SignalEdit.accept) # type: ignore
+ self.buttonBox.rejected.connect(SignalEdit.close) # type: ignore
QtCore.QMetaObject.connectSlotsByName(SignalEdit)
def retranslateUi(self, SignalEdit):
@@ -94,4 +94,4 @@ class Ui_SignalEdit(object):
self.label_8.setText(_translate("SignalEdit", "Pivot"))
self.label_6.setText(_translate("SignalEdit", "Phase 1"))
self.label.setText(_translate("SignalEdit", "Phase 0"))
-from pyqtgraph import PlotWidget
+from ..lib.graph_items import NMRPlotWidget
diff --git a/src/gui_qt/_py/shift_scale_dialog.py b/src/gui_qt/_py/shift_scale_dialog.py
index 7997c30..fbb01ed 100644
--- a/src/gui_qt/_py/shift_scale_dialog.py
+++ b/src/gui_qt/_py/shift_scale_dialog.py
@@ -1,10 +1,11 @@
# -*- coding: utf-8 -*-
-# Form implementation generated from reading ui file 'resources/_ui/shift_scale_dialog.ui'
+# Form implementation generated from reading ui file 'src/resources/_ui/shift_scale_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
@@ -162,7 +163,7 @@ class Ui_shift_dialog(object):
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.verticalFrame_2)
self.verticalLayout_2.setSpacing(3)
self.verticalLayout_2.setObjectName("verticalLayout_2")
- self.graphicsView = PlotWidget(self.verticalFrame_2)
+ self.graphicsView = NMRPlotWidget(self.verticalFrame_2)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.MinimumExpanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
@@ -267,8 +268,8 @@ class Ui_shift_dialog(object):
self.retranslateUi(shift_dialog)
self.tabWidget.setCurrentIndex(0)
- self.buttonBox.accepted.connect(shift_dialog.accept)
- self.buttonBox.rejected.connect(shift_dialog.reject)
+ self.buttonBox.accepted.connect(shift_dialog.accept) # type: ignore
+ self.buttonBox.rejected.connect(shift_dialog.reject) # type: ignore
QtCore.QMetaObject.connectSlotsByName(shift_dialog)
shift_dialog.setTabOrder(self.tabWidget, self.shift_table)
shift_dialog.setTabOrder(self.shift_table, self.x_shift_spinbox)
@@ -310,5 +311,5 @@ class Ui_shift_dialog(object):
self.overwrite_checkbox.setText(_translate("shift_dialog", "Overwrite data"))
self.data_newgraph.setText(_translate("shift_dialog", "New graph"))
self.values_newgraph.setText(_translate("shift_dialog", "New graph"))
+from ..lib.graph_items import NMRPlotWidget
from ..lib.spinboxes import SciSpinBox
-from pyqtgraph import PlotWidget
diff --git a/src/gui_qt/_py/t1dialog.py b/src/gui_qt/_py/t1dialog.py
index 7f6c421..f277459 100644
--- a/src/gui_qt/_py/t1dialog.py
+++ b/src/gui_qt/_py/t1dialog.py
@@ -1,10 +1,11 @@
# -*- coding: utf-8 -*-
-# Form implementation generated from reading ui file 'resources/_ui/t1dialog.ui'
+# Form implementation generated from reading ui file 'src/resources/_ui/t1dialog.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
@@ -160,6 +161,7 @@ class Ui_t1dialog(object):
self.tau_combox.addItem("")
self.gridLayout_4.addWidget(self.tau_combox, 1, 0, 1, 2)
self.checkBox_interpol = QtWidgets.QCheckBox(self.groupBox_3)
+ self.checkBox_interpol.setEnabled(False)
self.checkBox_interpol.setObjectName("checkBox_interpol")
self.gridLayout_4.addWidget(self.checkBox_interpol, 2, 0, 1, 2)
self.graph_checkbox = QtWidgets.QCheckBox(self.groupBox_3)
diff --git a/src/gui_qt/_py/tnmh_dialog.py b/src/gui_qt/_py/tnmh_dialog.py
index 7581c52..f683f18 100644
--- a/src/gui_qt/_py/tnmh_dialog.py
+++ b/src/gui_qt/_py/tnmh_dialog.py
@@ -59,7 +59,7 @@ class Ui_DSCEvalDialog(object):
self.tg_tree.headerItem().setText(0, "1")
self.tg_tree.header().setVisible(False)
self.gridLayout_2.addWidget(self.tg_tree, 2, 0, 1, 1)
- self.dsc_plot = PlotWidget(self.page)
+ self.dsc_plot = NMRPlotWidget(self.page)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
@@ -89,10 +89,10 @@ class Ui_DSCEvalDialog(object):
self.label_4 = QtWidgets.QLabel(self.page_2)
self.label_4.setObjectName("label_4")
self.gridLayout_3.addWidget(self.label_4, 2, 0, 1, 1)
- self.tghodge_graph = PlotWidget(self.page_2)
+ self.tghodge_graph = NMRPlotWidget(self.page_2)
self.tghodge_graph.setObjectName("tghodge_graph")
self.gridLayout_3.addWidget(self.tghodge_graph, 1, 0, 1, 1)
- self.tau_plot = PlotWidget(self.page_2)
+ self.tau_plot = NMRPlotWidget(self.page_2)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.MinimumExpanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
@@ -155,7 +155,7 @@ class Ui_DSCEvalDialog(object):
self.page_3.setObjectName("page_3")
self.gridLayout_6 = QtWidgets.QGridLayout(self.page_3)
self.gridLayout_6.setObjectName("gridLayout_6")
- self.tnmh_graphics = PlotWidget(self.page_3)
+ self.tnmh_graphics = NMRPlotWidget(self.page_3)
self.tnmh_graphics.setObjectName("tnmh_graphics")
self.gridLayout_6.addWidget(self.tnmh_graphics, 1, 0, 1, 2)
self.tnmh_tree = QtWidgets.QTreeWidget(self.page_3)
@@ -249,5 +249,5 @@ class Ui_DSCEvalDialog(object):
self.back_button.setText(_translate("DSCEvalDialog", "Back"))
self.next_button.setText(_translate("DSCEvalDialog", "Next"))
self.close_button.setText(_translate("DSCEvalDialog", "Close"))
+from ..lib.graph_items import NMRPlotWidget
from ..lib.listwidget import QListWidgetSelect
-from pyqtgraph import PlotWidget
diff --git a/src/gui_qt/data/container.py b/src/gui_qt/data/container.py
index 82dabc6..913ad7e 100644
--- a/src/gui_qt/data/container.py
+++ b/src/gui_qt/data/container.py
@@ -463,6 +463,16 @@ class ExperimentContainer(QtCore.QObject):
return offset
+ @plot_update
+ def shift_scale(self, shift_factor: tuple[float, float], scaling_factor: tuple[float, float]):
+ scale_x, scale_y = scaling_factor
+ shift_x, shift_y = shift_factor
+ self.data.x = self.data.x * scale_x + shift_x
+ self.data.y = self.data.y * scale_y + shift_y
+ self.data.y_err = self.data.y_err * scale_y
+
+ self.update({'shift': scaling_factor, 'scale': shift_factor})
+
def get_namespace(self, i: int = None, j: int = None) -> dict:
if (i is None) and (j is None):
prefix = ''
diff --git a/src/gui_qt/data/shift_graphs.py b/src/gui_qt/data/shift_graphs.py
index 61dc918..f436989 100644
--- a/src/gui_qt/data/shift_graphs.py
+++ b/src/gui_qt/data/shift_graphs.py
@@ -1,7 +1,7 @@
import numpy as np
from itertools import cycle
-from pyqtgraph import mkColor, mkPen
+from pyqtgraph import mkColor, mkPen, mkBrush
from nmreval.lib.colors import Tab10
@@ -42,11 +42,17 @@ class QShift(QtWidgets.QDialog, Ui_shift_dialog):
def add_item(self, idx, name, x, y):
color = mkColor(next(self._colors).rgb())
- if np.iscomplexobj(y):
- pl = [PlotItem(x=x, y=y.real, name=name, pen=mkPen(color=color)),
- PlotItem(x=x, y=y.imag, name=name, pen=mkPen(color=color))]
+
+ if len(y) == 1:
+ sym_kwds = {'symbol': 'o', 'symbolBrush': mkBrush(color=color), 'symbolPen': mkPen(color=color)}
else:
- pl = [PlotItem(x=x, y=y, name=name, pen=mkPen(color=color))]
+ sym_kwds = {'symbol': None, 'symbolBrush': mkBrush(color=color), 'symbolPen': mkPen(color=color)}
+
+ if np.iscomplexobj(y):
+ pl = [PlotItem(x=x, y=y.real, name=name, pen=mkPen(color=color), **sym_kwds),
+ PlotItem(x=x, y=y.imag, name=name, pen=mkPen(color=color), **sym_kwds)]
+ else:
+ pl = [PlotItem(x=x, y=y, name=name, pen=mkPen(color=color), **sym_kwds)]
self.data[idx] = (pl, x, y)
diff --git a/src/gui_qt/fit/fit_forms.py b/src/gui_qt/fit/fit_forms.py
index 0a4179f..2d5f85c 100644
--- a/src/gui_qt/fit/fit_forms.py
+++ b/src/gui_qt/fit/fit_forms.py
@@ -6,12 +6,14 @@ from ..Qt import QtCore, QtWidgets, QtGui
from .._py.fitmodelwidget import Ui_FitParameter
from .._py.save_fitmodel_dialog import Ui_SaveDialog
from ..lib.iconloading import get_icon
+from ..lib.tables import TableWidget
class FitModelWidget(QtWidgets.QWidget, Ui_FitParameter):
value_requested = QtCore.pyqtSignal(object)
value_changed = QtCore.pyqtSignal(str)
state_changed = QtCore.pyqtSignal()
+ replace_single_value = QtCore.pyqtSignal(object)
def __init__(self, label: str = 'Fitparameter', parent=None, fixed: bool = False):
super().__init__(parent)
@@ -30,6 +32,7 @@ class FitModelWidget(QtWidgets.QWidget, Ui_FitParameter):
self.global_checkbox.stateChanged.connect(lambda: self.state_changed.emit())
self.parameter_line.editingFinished.connect(self.update_parameter)
self.parameter_line.values_requested.connect(lambda: self.value_requested.emit(self))
+ self.parameter_line.replace_single_values.connect(lambda: self.replace_single_value.emit(None))
self.parameter_line.editingFinished.connect(lambda: self.value_changed.emit(self.parameter_line.text()))
self.fixed_check.toggled.connect(self.set_fixed)
@@ -311,7 +314,7 @@ class FitModelTree(QtWidgets.QTreeWidget):
return funcs
-class FitTableWidget(QtWidgets.QTableWidget):
+class FitTableWidget(TableWidget):
def __init__(self, parent=None):
super().__init__(parent=parent)
diff --git a/src/gui_qt/fit/fit_parameter.py b/src/gui_qt/fit/fit_parameter.py
index ae41510..f4894f0 100644
--- a/src/gui_qt/fit/fit_parameter.py
+++ b/src/gui_qt/fit/fit_parameter.py
@@ -78,6 +78,7 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
widgt.state_changed.connect(self.make_global)
widgt.value_requested.connect(self.look_for_value)
widgt.value_changed.connect(self.change_global_parameter)
+ widgt.replace_single_value.connect(self.delete_single_parameter)
self.global_parameter.append(widgt)
self.scrollwidget.layout().addWidget(widgt)
@@ -150,6 +151,13 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
if value is None:
self.change_data(self.comboBox.currentIndex())
+ def delete_single_parameter(self):
+ idx = self.global_parameter.index(self.sender())
+ for i in range(self.comboBox.count()):
+ set_id = self.comboBox.itemData(i)
+ self.data_values[set_id][idx] = None
+ self.change_data(self.comboBox.currentIndex())
+
def change_single_choice(self, _, value, sender=None):
if sender is None:
sender = self.sender()
@@ -298,7 +306,8 @@ class ParameterSingleWidget(QtWidgets.QWidget):
self._name = name
self.label.setText(convert(name))
- self.label.setToolTip('IIf this is bold then this parameter is only for this data. otherwise the general parameter is used and displayed')
+ self.label.setToolTip('If this is bold then this parameter is only for this data. '
+ 'Otherwise, the general parameter is used and displayed')
# self.value_line.setValidator(QtGui.QDoubleValidator())
self.value_line.textChanged.connect(lambda: self.valueChanged.emit(self.value) if self.value is not None else 0)
diff --git a/src/gui_qt/fit/function_creation_dialog.py b/src/gui_qt/fit/function_creation_dialog.py
index b63ee29..41d9363 100644
--- a/src/gui_qt/fit/function_creation_dialog.py
+++ b/src/gui_qt/fit/function_creation_dialog.py
@@ -14,7 +14,7 @@ from gui_qt.lib.namespace import QNamespaceWidget
__all__ = ['QUserFitCreator']
-validator = QtGui.QRegExpValidator(QtCore.QRegExp('[A-Za-z]\S*'))
+validator = QtGui.QRegExpValidator(QtCore.QRegExp('[_A-Za-z][_A-Za-z0-9]*'))
pattern = re.compile(r'def func\(.*\):', flags=re.MULTILINE)
@@ -145,6 +145,7 @@ class QUserFitCreator(QtWidgets.QDialog, Ui_Dialog):
self.classCreated.emit()
super().accept()
+
class KwargsWidget(QtWidgets.QWidget):
Changed = QtCore.pyqtSignal()
@@ -209,7 +210,7 @@ class KwargsWidget(QtWidgets.QWidget):
def get_strings(self) -> str:
kwargs = []
if self.use_nuclei.isChecked():
- kwargs.append("(r'\gamma', 'nucleus', gamma)")
+ kwargs.append(r"(r'\gamma', 'nucleus', gamma)")
for i in range(self.choices.count()):
kwargs.append(self.choices.widget(i).get_strings())
@@ -300,7 +301,7 @@ class ChoiceWidget(QtWidgets.QWidget):
def get_strings(self) -> str:
opts = []
for i in range(self.table.rowCount()):
- name = self.table.item(i, 0).text()
+ name = self.table.cellWidget(i, 0).text()
val = self._make_value(i)
opts.append(f'{name!r}: {val!r}')
diff --git a/src/gui_qt/fit/result.py b/src/gui_qt/fit/result.py
index 6a820ed..a7e77f7 100644
--- a/src/gui_qt/fit/result.py
+++ b/src/gui_qt/fit/result.py
@@ -3,6 +3,7 @@ from math import isnan
from pyqtgraph import mkBrush, mkPen
from nmreval.utils.text import convert
+from ..lib.graph_items import logTickValues
from ..lib.utils import RdBuCMap
from ..Qt import QtWidgets, QtGui, QtCore
@@ -33,8 +34,12 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
self.graph_opts = {}
self.last_idx = None
- self.resid_plot = self.graphicsView.addPlot(row=0, col=0, title='Residual')
self.fit_plot = self.graphicsView.addPlot(row=1, col=0, title='Fit')
+ self.resid_plot = self.graphicsView.addPlot(row=0, col=0, title='Residual')
+
+ for orient in ['top', 'bottom', 'left', 'right']:
+ self.fit_plot.getAxis(orient).logTickValues = logTickValues
+ self.resid_plot.getAxis(orient).logTickValues = logTickValues
self.graphicsView.ci.layout.setRowStretchFactor(0, 1)
self.graphicsView.ci.layout.setRowStretchFactor(1, 2)
diff --git a/src/gui_qt/graphs/graphwindow.py b/src/gui_qt/graphs/graphwindow.py
index 134a6cc..ce40d71 100644
--- a/src/gui_qt/graphs/graphwindow.py
+++ b/src/gui_qt/graphs/graphwindow.py
@@ -4,7 +4,7 @@ import itertools
import os
import uuid
-from math import isnan
+from math import isfinite
from pathlib import Path
import numpy as np
@@ -45,7 +45,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
self.id = str(uuid.uuid4())
self.sets = []
- self.active = []
+ self._active = []
self.real_plots = {}
self.imag_plots = {}
@@ -75,6 +75,8 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
self.scene.contextMenu[0].disconnect()
self.scene.contextMenu[0].triggered.connect(self.export_dialog)
+ self.bwbutton.toggled.connect(self.change_background)
+
def _init_gui(self):
self.setWindowTitle('Graph ' + str(next(QGraphWindow.counter)))
@@ -114,11 +116,11 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
return iter(self.active)
def __len__(self):
- return len(self.active)
+ return len(self._active)
def curves(self) -> tuple:
for set_id in self.sets:
- if set_id in self.active:
+ if set_id in self._active:
if self.real_button.isChecked():
if self.error_plots[set_id] is not None:
yield self.real_plots[set_id], self.error_plots[set_id]
@@ -144,7 +146,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
tmp = [np.nan, np.nan]
for j, x in enumerate(r[i]):
try:
- tmp[j] = 10**x
+ tmp[j] = 10**min(x, 199)
except OverflowError:
pass
r[i] = tuple(tmp)
@@ -153,6 +155,14 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
return tuple(r)
+ @property
+ def active(self) -> list:
+ return [set_id for set_id in self.sets if set_id in self._active]
+
+ @active.setter
+ def active(self, value: list):
+ self._active = value
+
def block(self, state: bool):
self._block = state
@@ -201,8 +211,8 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
for plot in [self.real_plots, self.imag_plots, self.error_plots]:
self.graphic.removeItem(plot[n])
- if n in self.active:
- self.active.remove(n)
+ if n in self._active:
+ self._active.remove(n)
# remove from label list
self.listWidget.blockSignals(True)
@@ -246,8 +256,8 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
return
for a in idlist:
- if a not in self.active:
- self.active.append(a)
+ if a not in self._active:
+ self._active.append(a)
for (bttn, plot_dic) in [
(self.real_button, self.real_plots),
@@ -266,8 +276,8 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
return
for r in idlist:
- if r in self.active:
- self.active.remove(r)
+ if r in self._active:
+ self._active.remove(r)
for plt in [self.real_plots, self.imag_plots, self.error_plots]:
item = plt[r]
@@ -289,7 +299,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
else:
func = self.graphic.removeItem
- for a in self.active:
+ for a in self._active:
item = plots[a]
if item is not None:
func(item)
@@ -306,12 +316,12 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
return
if visible:
- for a in self.active:
+ for a in self._active:
item = self.error_plots[a]
if (item is not None) and (item not in self.graphic.items()):
self.graphic.addItem(item)
else:
- for a in self.active:
+ for a in self._active:
item = self.error_plots[a]
if (item is not None) and (item in self.graphic.items()):
self.graphic.removeItem(item)
@@ -423,6 +433,9 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
def set_logmode(self, xmode: bool = None, ymode: bool = None):
r = self.ranges
+ self.plotItem.setXRange(*r[0])
+ self.plotItem.setYRange(*r[1])
+
if xmode is None:
xmode = self.plotItem.ctrl.logXCheck.isChecked()
else:
@@ -439,6 +452,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
item.logmode[0] = self.log[:]
self.plotItem.updateLogMode()
+ self.set_range(x=r[0], y=r[1])
self.plotItem.enableAutoRange()
@@ -481,9 +495,9 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
with errstate(all='ignore'):
xy = [log10(val) for val in xy]
- if isnan(xy[1]):
+ if not isfinite(xy[1]):
xy = [-1, 1]
- elif isnan(xy[0]):
+ elif not isfinite(xy[0]):
xy[0] = xy[1]-4
func(xy[0], xy[1], padding=0)
@@ -669,7 +683,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
'legend': self.legend.isVisible(),
'plots': (self.real_button.isChecked(), self.imag_button.isChecked(), self.error_button.isChecked()),
'children': self.sets,
- 'active': self.active,
+ 'active': self._active,
}
in_legend = []
@@ -760,8 +774,8 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
if y is not None:
self.plotItem.setLabel('left', y, **{'font-size': '10pt', 'color': self._fgcolor.name()})
- @QtCore.pyqtSlot(bool, name='on_bwbutton_toggled')
def change_background(self, _):
temp = self._fgcolor, self._bgcolor
self.set_color(foreground=self._prev_colors[0], background=self._prev_colors[1])
self._prev_colors = temp
+
diff --git a/src/gui_qt/io/gracereader.py b/src/gui_qt/io/gracereader.py
index be3d62a..ca1e414 100644
--- a/src/gui_qt/io/gracereader.py
+++ b/src/gui_qt/io/gracereader.py
@@ -4,6 +4,7 @@ from nmreval.lib.lines import LineStyle
from nmreval.lib.symbols import SymbolStyle
from nmreval.data.points import Points
from nmreval.io.graceeditor import GraceEditor
+from nmreval.utils.text import convert
from ..Qt import QtCore, QtWidgets, QtGui
from .._py.gracereader import Ui_Dialog
@@ -55,7 +56,7 @@ class QGraceReader(QtWidgets.QDialog, Ui_Dialog):
if ds is None:
continue
- item_2 = QtWidgets.QTreeWidgetItem([f'Set {gset.idx} (Label: {gset.get_property("legend")}, '
+ item_2 = QtWidgets.QTreeWidgetItem([f'Set {gset.idx} (Label: {convert(gset.get_property("legend"), old="agr", new="str")}, '
f'shape: {ds.shape})'])
item_2.setCheckState(0, QtCore.Qt.Checked)
item_2.setData(0, QtCore.Qt.UserRole, (graphs.idx, gset.idx))
@@ -94,6 +95,7 @@ class QGraceReader(QtWidgets.QDialog, Ui_Dialog):
label = ''
else:
label = label.replace('"', '')
+ label = convert(label, old='agr', new='str')
sd = s.data
sd = np.atleast_2d(sd)
if s.type == 'xydy':
diff --git a/src/gui_qt/lib/codeeditor.py b/src/gui_qt/lib/codeeditor.py
index 245a9e1..1b80d4d 100644
--- a/src/gui_qt/lib/codeeditor.py
+++ b/src/gui_qt/lib/codeeditor.py
@@ -237,7 +237,7 @@ class CodeEditor(QtWidgets.QPlainTextEdit):
if block.isVisible() and (bottom >= evt.rect().top()):
number = str(block_number + 1)
painter.setPen(QtCore.Qt.black)
- painter.drawText(0, top, self.current_linenumber.width() - 3, height,
+ painter.drawText(0, int(top), self.current_linenumber.width() - 3, height,
QtCore.Qt.AlignRight, number)
block = block.next()
diff --git a/src/gui_qt/lib/forms.py b/src/gui_qt/lib/forms.py
index c0b73aa..ab20ce3 100644
--- a/src/gui_qt/lib/forms.py
+++ b/src/gui_qt/lib/forms.py
@@ -52,19 +52,24 @@ class QDelayWidget(QtWidgets.QWidget):
class LineEdit(QtWidgets.QLineEdit):
values_requested = QtCore.pyqtSignal()
+ replace_single_values = QtCore.pyqtSignal()
def __init__(self, parent=None):
super().__init__(parent=parent)
def contextMenuEvent(self, evt):
menu = self.createStandardContextMenu()
- request_action = menu.addAction('Use value of sets')
+ request_action = menu.addAction('Use numeric value of sets')
+ set_value_action = menu.addAction('Replace single set values')
action = menu.exec(evt.globalPos())
if action == request_action:
self.values_requested.emit()
+ elif action == set_value_action:
+ self.replace_single_values.emit()
+
class LineEditPost(QtWidgets.QLineEdit):
values_requested = QtCore.pyqtSignal()
diff --git a/src/gui_qt/lib/graph_items.py b/src/gui_qt/lib/graph_items.py
new file mode 100644
index 0000000..85e826c
--- /dev/null
+++ b/src/gui_qt/lib/graph_items.py
@@ -0,0 +1,53 @@
+from numpy import log10, arange, floor, ceil
+from pyqtgraph import PlotWidget, PlotItem
+
+
+__all__ = ['NMRPlotWidget', 'logTickValues']
+
+
+class NMRPlotWidget(PlotWidget):
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+
+ for orient in ['top', 'bottom', 'left', 'right']:
+ # BAD HACK!!! but seems to work, see function for explanation
+ self.plotItem.getAxis(orient).logTickValues = logTickValues
+
+
+class NMRPlotItem(PlotItem):
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+
+ for orient in ['top', 'bottom', 'left', 'right']:
+ self.plotItem.getAxis(orient).logTickValues = logTickValues
+
+
+def logTickValues(minVal, maxVal, size, stdTicks):
+ # TODO FIND A BETTER SOLUTION!!!
+ # Sometimes minVal and maxVal are not log-scaled values and the loop from v1 to v2 is humongous,
+ # The minor list then fills the RAM completely and freezes everything
+ # Until there is a better solution, we overwrite this function for every AxesItem
+ # and do not draw minor ticks at all if there are too many
+
+ # start with the tick spacing given by tickValues().
+ # Any level whose spacing is < 1 needs to be converted to log scale
+ ticks = []
+ for (spacing, t) in stdTicks:
+ if spacing >= 1.0:
+ ticks.append((spacing, t))
+
+ if len(ticks) < 3:
+ v1 = int(floor(minVal))
+ v2 = int(ceil(maxVal))
+ # major = list(range(v1+1, v2))
+ minor = []
+
+ if v2 - v1 < 400:
+ for v in range(v1, v2):
+ minor.extend(v + log10(arange(1, 10)))
+ minor = [x for x in minor if minVal < x < maxVal]
+ ticks.append((None, minor))
+ return ticks
+
diff --git a/src/gui_qt/lib/pg_objects.py b/src/gui_qt/lib/pg_objects.py
index 9978031..923ca88 100644
--- a/src/gui_qt/lib/pg_objects.py
+++ b/src/gui_qt/lib/pg_objects.py
@@ -375,9 +375,6 @@ class PlotItem(PlotDataItem):
class RegionItem(LinearRegionItem):
def __init__(self, *args, **kwargs):
self.mode = kwargs.pop('mode', 'half')
-
- print(args, kwargs)
-
super().__init__(*args, **kwargs)
self.logmode = False
@@ -475,11 +472,18 @@ class LegendItemBlock(LegendItem):
def mouseDragEvent(self, ev):
if ev.button() == QtCore.Qt.LeftButton:
ev.accept()
+
dpos = ev.pos() - ev.lastPos()
+
+ upper_left = self.pos()
+ lower_right = self.pos()
+ lower_right.setX(lower_right.x() + self.width())
+ lower_right.setY(lower_right.y() + self.height())
+
vb_rect = self.parentItem().rect()
- pos = self.pos()
- # upper left corner and a point a little more to the bottom right must be inside
- if vb_rect.contains(pos+dpos) and vb_rect.contains(pos+dpos+QtCore.QPointF(20., 20.)):
- self.autoAnchor(pos + dpos)
+
+ # upper left and lower right corner must be inside viewbox
+ if vb_rect.contains(upper_left + dpos) and vb_rect.contains(lower_right + dpos):
+ self.autoAnchor(upper_left + dpos)
else:
- self.autoAnchor(pos)
+ self.autoAnchor(upper_left)
diff --git a/src/gui_qt/lib/tables.py b/src/gui_qt/lib/tables.py
index 15195c4..a7b6ef1 100644
--- a/src/gui_qt/lib/tables.py
+++ b/src/gui_qt/lib/tables.py
@@ -28,4 +28,17 @@ class TreeWidget(QtWidgets.QTreeWidget):
continue
it.setCheckState(0, QtCore.Qt.Unchecked if it.checkState(0) == QtCore.Qt.Checked else QtCore.Qt.Checked)
else:
- super().keyPressEvent(evt)
\ No newline at end of file
+ super().keyPressEvent(evt)
+
+
+class TableWidget(QtWidgets.QTableWidget):
+ 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 6973141..6f1c47b 100644
--- a/src/gui_qt/main/mainwindow.py
+++ b/src/gui_qt/main/mainwindow.py
@@ -211,7 +211,6 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
self.ptsselectwidget.points_selected.connect(self.management.extract_points)
- self.t1tauwidget.newData.connect(self.management.add_new_data)
self.t1tauwidget.newData.connect(self.management.add_new_data)
self.editsignalwidget.do_something.connect(self.management.apply)
@@ -917,10 +916,12 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
self.action_odr_fit: 'odr'
}[self.ac_group.checkedAction()]
- self.fit_dialog.fit_button.setEnabled(False)
- self.management.start_fit(parameter, links, fit_options)
- self.status.setText('Fit running...'.format(self.management.fitter.step))
- self.fit_timer.start(500)
+ fit_is_ready = self.management.prepare_fit(parameter, links, fit_options)
+ if fit_is_ready:
+ self.management.start_fit()
+ self.fit_dialog.fit_button.setEnabled(False)
+ self.status.setText('Fit running...'.format(self.management.fitter.step))
+ self.fit_timer.start(500)
@QtCore.pyqtSlot(dict, int, bool)
def show_fit_preview(self, funcs: dict, num: int, show: bool):
diff --git a/src/gui_qt/main/management.py b/src/gui_qt/main/management.py
index dfc98d7..e4a0dc4 100644
--- a/src/gui_qt/main/management.py
+++ b/src/gui_qt/main/management.py
@@ -58,11 +58,18 @@ class GraphDict(OrderedDict):
def list(self):
return [(k, v.title) for k, v in self.items()]
- def active(self, key: str):
- if key:
- return [(self._data[i].id, self._data[i].name) for i in self[key]]
- else:
+ def active(self, key: str, return_val: str = 'both'):
+ if not key:
return []
+ else:
+ if return_val == 'both':
+ return [(self._data[i].id, self._data[i].name) for i in self[key]]
+ elif return_val == 'id':
+ return [self._data[i].id for i in self[key]]
+ elif return_val == 'name':
+ return [self._data[i].name for i in self[key]]
+ else:
+ raise ValueError(f'return_val got wrong value {return_val!r}')
def current_sets(self, key: str):
if key:
@@ -148,6 +155,10 @@ class UpperManagement(QtCore.QObject):
def active_sets(self):
return self.graphs.active(self.current_graph)
+ @property
+ def active_id(self):
+ return self.graphs.active(self.current_graph, return_val='id')
+
def get_attributes(self, graph_id: str, attr: str) -> dict[str, Any]:
return {self.data[i].id: getattr(self.data[i], attr) for i in self.graphs[graph_id].sets}
@@ -413,9 +424,9 @@ class UpperManagement(QtCore.QObject):
for d in self.data.values():
d.mask = np.ones_like(d.mask, dtype=bool)
- def start_fit(self, parameter: dict, links: list, fit_options: dict):
+ def prepare_fit(self, parameter: dict, links: list, fit_options: dict) -> bool:
if self._fit_active:
- return
+ return False
self.__fit_options = (parameter, links, fit_options)
@@ -423,60 +434,84 @@ class UpperManagement(QtCore.QObject):
models = {}
fit_limits = fit_options['limits']
fit_mode = fit_options['fit_mode']
- we = fit_options['we']
+ we_option = fit_options['we']
- for model_id, model_p in parameter.items():
- m = Model(model_p['func'])
- models[model_id] = m
+ self.fitter.fitmethod = fit_mode
- m_complex = model_p['complex']
+ # all-encompassing error catch
+ try:
+ for model_id, model_p in parameter.items():
+ m = Model(model_p['func'])
+ models[model_id] = m
- for set_id, set_params in model_p['parameter'].items():
- data_i = self.data[set_id]
- if we.lower() == 'deltay':
- we = data_i.y_err**2
+ m_complex = model_p['complex']
- if m_complex is None or m_complex == 1:
- _y = data_i.y.real
- elif m_complex == 2 and np.iscomplexobj(data_i.y):
- _y = data_i.y.imag
- else:
- _y = data_i.y
+ # sets are not in active order but in order they first appeared in fit dialog
+ # iterate over order of set id in active order and access parameter inside loop
+ # instead of directly looping
+ list_ids = list(model_p['parameter'].keys())
+ set_order = [self.active_id.index(i) for i in list_ids]
+ for pos in set_order:
+ set_id = list_ids[pos]
- _x = data_i.x
+ data_i = self.data[set_id]
+ set_params = model_p['parameter'][set_id]
- if fit_limits == 'none':
- inside = slice(None)
- elif fit_limits == 'x':
- x_lim, _ = self.graphs[self.current_graph].ranges
- inside = np.where((_x >= x_lim[0]) & (_x <= x_lim[1]))
- else:
- inside = np.where((_x >= fit_limits[0]) & (_x <= fit_limits[1]))
+ if we_option.lower() == 'deltay':
+ we = data_i.y_err**2
+ else:
+ we = we_option
- if isinstance(we, str):
- d = fit_d.Data(_x[inside], _y[inside], we=we, idx=set_id)
- else:
- d = fit_d.Data(_x[inside], _y[inside], we=we[inside], idx=set_id)
+ if m_complex is None or m_complex == 1:
+ _y = data_i.y.real
+ elif m_complex == 2 and np.iscomplexobj(data_i.y):
+ _y = data_i.y.imag
+ else:
+ _y = data_i.y
- d.set_model(m)
- d.set_parameter(set_params[0], var=model_p['var'],
- lb=model_p['lb'], ub=model_p['ub'],
- fun_kwargs=set_params[1])
+ _x = data_i.x
- self.fitter.add_data(d)
+ if fit_limits == 'none':
+ inside = slice(None)
+ elif fit_limits == 'x':
+ x_lim, _ = self.graphs[self.current_graph].ranges
+ inside = np.where((_x >= x_lim[0]) & (_x <= x_lim[1]))
+ else:
+ inside = np.where((_x >= fit_limits[0]) & (_x <= fit_limits[1]))
- model_globs = model_p['glob']
- if model_globs:
- for parameter_args in zip(*model_globs.values()):
- m.set_global_parameter(**{k: v for k, v in zip(model_globs.keys(), parameter_args)})
- # m.set_global_parameter(**model_p['glob'])
+ if isinstance(we, str):
+ d = fit_d.Data(_x[inside], _y[inside], we=we, idx=set_id)
+ else:
+ d = fit_d.Data(_x[inside], _y[inside], we=we[inside], idx=set_id)
- for links_i in links:
- self.fitter.set_link_parameter((models[links_i[0]], links_i[1]),
- (models[links_i[2]], links_i[3]))
+ d.set_model(m)
+ d.set_parameter(set_params[0], var=model_p['var'],
+ lb=model_p['lb'], ub=model_p['ub'],
+ fun_kwargs=set_params[1])
+ self.fitter.add_data(d)
+
+ model_globs = model_p['glob']
+ if model_globs:
+ for parameter_args in zip(*model_globs.values()):
+ m.set_global_parameter(**{k: v for k, v in zip(model_globs.keys(), parameter_args)})
+ # m.set_global_parameter(**model_p['glob'])
+
+ for links_i in links:
+ self.fitter.set_link_parameter((models[links_i[0]], links_i[1]),
+ (models[links_i[2]], links_i[3]))
+ return True
+
+ except Exception as e:
+ logger.error('Fit preparation failed', *e.args)
+ QtWidgets.QMessageBox.warning(QtWidgets.QWidget(),
+ 'Fit prep failed',
+ f'Fit preparation failed with message\n{e.args}')
+ return False
+
+ def start_fit(self):
with busy_cursor():
- self.fit_worker = FitWorker(self.fitter, fit_mode)
+ self.fit_worker = FitWorker(self.fitter)
self.fit_thread = QtCore.QThread()
self.fit_worker.moveToThread(self.fit_thread)
@@ -512,7 +547,8 @@ class UpperManagement(QtCore.QObject):
for set_id, set_parameter in parameter.items():
new_values = [v.value for v in res[set_id].parameter.values()]
parameter[set_id] = (new_values, set_parameter[1])
- self.start_fit(*self.__fit_options)
+ if self.prepare_fit(*self.__fit_options):
+ self.start_fit()
def make_fits(self, res: dict, opts: list, param_graph: str, show_fit: bool, parts: bool, extrapolate: list) -> None:
"""
@@ -637,7 +673,7 @@ class UpperManagement(QtCore.QObject):
def save_fit_parameter(self, fname: str | pathlib.Path, fit_sets: list[str] = None):
if fit_sets is None:
- fit_sets = [s for (s, _) in self.active_sets]
+ fit_sets = [s for s in self.active_id]
for set_id in fit_sets:
data = self.data[set_id]
@@ -843,13 +879,10 @@ class UpperManagement(QtCore.QObject):
d_k = self.data[k]
if copy_data is None:
- d_k.x = d_k.x*v[1][0] + v[0][0]
- d_k.y = d_k.y*v[1][1] + v[0][1]
+ d_k.shift_scale(v[0], v[1])
else:
new_data = d_k.copy(full=True)
- new_data.update({'shift': v[0], 'scale': v[1]})
- new_data.data.x = new_data.x*v[1][0] + v[0][0]
- new_data.y = new_data.y*v[1][1] + v[0][1]
+ new_data.shift_scale(v[0], v[1])
sid = self.add(new_data)
sid_list.append(sid)
@@ -1009,7 +1042,7 @@ class UpperManagement(QtCore.QObject):
def show_statistics(self, mode):
x, y, = [], []
- for i, _ in self.active_sets:
+ for i in self.active_id:
_temp = self.data[i]
try:
x.append(float(_temp.name))
@@ -1020,7 +1053,7 @@ class UpperManagement(QtCore.QObject):
@QtCore.pyqtSlot()
def calc_magn(self):
new_id = []
- for k, _ in self.active_sets:
+ for k in self.active_id:
dataset = self.data[k]
if isinstance(dataset, SignalContainer):
new_value = dataset.copy(full=True)
@@ -1032,7 +1065,7 @@ class UpperManagement(QtCore.QObject):
@QtCore.pyqtSlot()
def center(self):
new_id = []
- for k, _ in self.active_sets:
+ for k in self.active_id:
new_value = self.data[k].copy(full=True)
new_value.x -= new_value.x[np.argmax(new_value.y.real)]
new_id.append(self.add(new_value))
@@ -1071,7 +1104,7 @@ class UpperManagement(QtCore.QObject):
def bds_deriv(self):
new_sets = []
- for (set_id, _) in self.active_sets:
+ for set_id in self.active_id:
data_i = self.data[set_id]
diff = data_i.data.diff(log=True)
new_data = Points(x=diff.x, y=-np.pi/2*diff.y.real)
@@ -1098,7 +1131,7 @@ class UpperManagement(QtCore.QObject):
self.newData.emit(new_sets, kwargs['graph'])
def skip_points(self, offset: int, step: int, invert: bool = False, copy: bool = False):
- for k, _ in self.active_sets:
+ for k in self.active_id:
src = self.data[k]
if invert:
mask = np.mod(np.arange(offset, src.x.size+offset), step) != 0
@@ -1253,16 +1286,15 @@ class UpperManagement(QtCore.QObject):
class FitWorker(QtCore.QObject):
finished = QtCore.pyqtSignal(list, bool)
- def __init__(self, fitter, mode):
+ def __init__(self, fitter):
super().__init__()
self.fitter = fitter
- self.mode = mode
@QtCore.pyqtSlot()
def run(self):
try:
- res = self.fitter.run(mode=self.mode)
+ res = self.fitter.run()
success = True
except Exception as e:
res = [e]
diff --git a/src/gui_qt/nmr/t1_from_tau.py b/src/gui_qt/nmr/t1_from_tau.py
index 00e1f18..261e0aa 100644
--- a/src/gui_qt/nmr/t1_from_tau.py
+++ b/src/gui_qt/nmr/t1_from_tau.py
@@ -19,7 +19,7 @@ class QRelaxCalc(QtWidgets.QDialog, Ui_Dialog):
self.graphs = {}
- self.specdens = [ColeCole, ColeDavidson, HavriliakNegami, KWW]
+ self.specdens = [ColeCole, ColeDavidson, HavriliakNegami, KWW, LogGaussian]
self.coupling = [Quadrupolar, HomoDipolar, Czjzek]
self.tau_parameter = []
@@ -199,3 +199,9 @@ class QRelaxCalc(QtWidgets.QDialog, Ui_Dialog):
def accept(self):
self.calc_relaxation()
super().accept()
+
+ @QtCore.pyqtSlot(QtWidgets.QAbstractButton)
+ def on_buttonBox_clicked(self, button: QtWidgets.QAbstractButton):
+ role = self.buttonBox.buttonRole(button)
+ if role == self.buttonBox.ApplyRole:
+ self.calc_relaxation()
diff --git a/src/gui_qt/nmr/t1widget.py b/src/gui_qt/nmr/t1widget.py
index 2521224..a4c9228 100644
--- a/src/gui_qt/nmr/t1widget.py
+++ b/src/gui_qt/nmr/t1widget.py
@@ -61,6 +61,8 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
self.freq_combox.currentIndexChanged.connect(lambda x: self.update_model())
self.freq_spinbox.valueChanged.connect(lambda x: self.update_model())
+ self.checkBox_interpol.setVisible(False)
+
self.update_specdens(0)
self.update_coupling(0)
diff --git a/src/nmreval/distributions/colecole.py b/src/nmreval/distributions/colecole.py
index b8551a8..b1a5a66 100644
--- a/src/nmreval/distributions/colecole.py
+++ b/src/nmreval/distributions/colecole.py
@@ -54,6 +54,9 @@ class ColeCole(Distribution):
tau (array_like):
alpha (float):
"""
+ if alpha == 1:
+ return tau / (1 + omega**2 * tau**2)
+
omtau = (omega*tau)**alpha
return np.sin(alpha*np.pi/2) * omtau / (1 + omtau**2 + 2*np.cos(alpha*np.pi/2)*omtau) / omega
diff --git a/src/nmreval/distributions/loggaussian.py b/src/nmreval/distributions/loggaussian.py
index 10c3615..8979750 100644
--- a/src/nmreval/distributions/loggaussian.py
+++ b/src/nmreval/distributions/loggaussian.py
@@ -5,6 +5,7 @@ from typing import Callable
import numpy as np
from scipy import LowLevelCallable
+from scipy.special import erf
from nmreval.lib.utils import ArrayLike
@@ -32,7 +33,7 @@ class LogGaussian(Distribution):
return np.exp(-0.5*(np.log(tau/tau0)/sigma)**2)/np.sqrt(2*np.pi)/sigma
@staticmethod
- def correlation(t, tau0, sigma: float):
+ def correlation(t: ArrayLike, tau0: ArrayLike, sigma: float):
_t = np.atleast_1d(t)
_tau = np.atleast_1d(tau0)
@@ -44,7 +45,7 @@ class LogGaussian(Distribution):
return res.squeeze()
@staticmethod
- def susceptibility(omega, tau0, sigma: float):
+ def susceptibility(omega: ArrayLike, tau0: ArrayLike, sigma: float):
_omega = np.atleast_1d(omega)
_tau = np.atleast_1d(tau0)
@@ -68,6 +69,7 @@ class LogGaussian(Distribution):
ret_val = _integration_parallel(_omega, _tau, sigma, _integrate_process_imag)
ret_val /= _omega[:, None]
+ ret_val[_omega == 0, :] = tau[None, :] * np.exp(sigma**2 / 2)
return ret_val.squeeze()
@@ -113,18 +115,16 @@ def _integrate_susc_c(lowfunc, highfunc, omega, tau, sigma):
return res
-def _integrate_process_imag(args):
- omega_i, tau_j, sigma = args
- area = quad(_integrand_freq_imag_high, 0, 50, args=(omega_i, tau_j, sigma), epsabs=1e-12, epsrel=1e-12)[0]
- area += quad(_integrand_freq_imag_low, -50, 0, args=(omega_i, tau_j, sigma), epsabs=1e-12, epsrel=1e-12)[0]
+def _integrate_process_imag(omega, tau, sigma):
+ area = quad(_integrand_freq_imag_high, 0, 50, args=(omega, tau, sigma), epsabs=1e-12, epsrel=1e-12)[0]
+ area += quad(_integrand_freq_imag_low, -50, 0, args=(omega, tau, sigma), epsabs=1e-12, epsrel=1e-12)[0]
return area
-def _integrate_process_real(args):
- omega_i, tau_j, sigma = args
- area = quad(_integrand_freq_real_high, 0, 50, args=(omega_i, tau_j, sigma))[0]
- area += quad(_integrand_freq_real_low, -50, 0, args=(omega_i, tau_j, sigma))[0]
+def _integrate_process_real(omega: float, tau: float, sigma: float):
+ area = quad(_integrand_freq_real_high, 0, 50, args=(omega, tau, sigma))[0]
+ area += quad(_integrand_freq_real_low, -50, 0, args=(omega, tau, sigma))[0]
return area
@@ -145,9 +145,8 @@ def _integrate_correlation_c(t, tau, sigma):
return res
-def _integrate_process_time(args):
- omega_i, tau_j, sigma = args
- return quad(_integrand_time, -50, 50, args=(omega_i, tau_j, sigma), epsabs=1e-12, epsrel=1e-12)[0]
+def _integrate_process_time(omega, tau, sigma):
+ return quad(_integrand_time, -50, 50, args=(omega, tau, sigma), epsabs=1e-12, epsrel=1e-12)[0]
def _integrand_time(u, t, tau, sigma):
diff --git a/src/nmreval/fit/_meta.py b/src/nmreval/fit/_meta.py
index 9fe9c34..889cc57 100644
--- a/src/nmreval/fit/_meta.py
+++ b/src/nmreval/fit/_meta.py
@@ -24,9 +24,10 @@ class ModelFactory:
param_len.append(len(func['func'].params))
if func['children']:
- right, _, _ = ModelFactory.create_from_list(func['children'], left=func['func'], left_cnt=func['pos'],
+ right, _, _ = ModelFactory.create_from_list(func['children'], left_cnt=func['pos'],
func_order=func_order, param_len=param_len)
right_cnt = None
+ right = MultiModel(func['func'], right, func['children'][0]['op'], left_idx=func['cnt'], right_idx=None)
else:
right = func['func']
right_cnt = func['cnt']
@@ -46,7 +47,13 @@ class MultiModel:
str_op = {'+': operator.add, '*': operator.mul, '-': operator.sub, '/': operator.truediv}
int_op = {0: operator.add, 1: operator.mul, 2: operator.sub, 3: operator.truediv}
- def __init__(self, left: Any, right: Any, op: str | Callable | int = '+', left_idx=0, right_idx=1):
+ def __init__(self,
+ left: Any,
+ right: Any,
+ op: str | Callable | int = '+',
+ left_idx: int | None = 0,
+ right_idx: int | None = 1,
+ ):
self._left = left
self._right = right
diff --git a/src/nmreval/fit/minimizer.py b/src/nmreval/fit/minimizer.py
index bc07df9..50fa4e4 100644
--- a/src/nmreval/fit/minimizer.py
+++ b/src/nmreval/fit/minimizer.py
@@ -82,7 +82,7 @@ def _update_parameter(data: Data, varied_keys: list[str], parameter: list[float]
class FitRoutine(object):
def __init__(self, mode='lsq'):
- self._fitmethod = mode
+ self.fitmethod = mode
self.data = []
self.fit_model = None
self._no_own_model = []
@@ -220,9 +220,12 @@ class FitRoutine(object):
logger.info('Fit aborted by user')
self._abort = True
- def run(self, mode: str = 'lsq'):
+ def run(self, mode: str=None):
self._abort = False
+ if mode is None:
+ mode = self.fitmethod
+
fit_groups, linked_parameter = self.prepare_links()
for data_groups in fit_groups:
if len(data_groups) == 1 and not self.linked:
diff --git a/src/nmreval/io/asciireader.py b/src/nmreval/io/asciireader.py
index f8232b1..dddf87d 100644
--- a/src/nmreval/io/asciireader.py
+++ b/src/nmreval/io/asciireader.py
@@ -15,7 +15,7 @@ NUMBERRE = re.compile(r'[0-9]\.*[0-9]*[Ee]*[+-]*[0-9]*')
class AsciiReader:
- delimiters = ['\t', ' ', ',']
+ # delimiters = ['\t', ' ', ',']
def __init__(self, fname):
self.fname = None
@@ -49,7 +49,8 @@ class AsciiReader:
with self.fname.open('r') as f:
for i, line in enumerate(islice(f, len(self.header)+len(self.lines), num_lines)):
line = line.rstrip('\n\t\r, ')
- line = re.split(r'[\s,;]', line)
+ line = re.sub(r'[\t ;,] *', ';', line)
+ line = line.split(';')
try:
comment_start = line.index('#')
diff --git a/src/nmreval/io/dsc.py b/src/nmreval/io/dsc.py
index 2be1fa4..b531bd4 100644
--- a/src/nmreval/io/dsc.py
+++ b/src/nmreval/io/dsc.py
@@ -292,7 +292,7 @@ class DSCCalibrator:
empty_y = empty_data[1]
if self.sample.length(idx) != self.empty.length(idx_empty):
with np.errstate(all='ignore'):
- empty_y = interp1d(empty_data[2], empty_data[1], fill_value='extrapolate')(sample_data[2])
+ empty_y = interp1d(empty_data[2]-empty_data[2, 0], empty_data[1], fill_value='extrapolate')(sample_data[2, 0])
sample_data[1] -= empty_y
drift_value = sample_data.copy()[(2, 1), :]
diff --git a/src/nmreval/math/interpol.py b/src/nmreval/math/interpol.py
index 81a5b31..7d139cd 100644
--- a/src/nmreval/math/interpol.py
+++ b/src/nmreval/math/interpol.py
@@ -24,8 +24,8 @@ def interpolate(data, new_x, xlog=False, ylog=False, kind='cubic', extrapolate=T
new_y = f(new_x)
if ylog:
- ret_val.set_data(x=new_x, y=10**new_y, y_err=None)
+ ret_val.set_data(x=new_x, y=10**new_y, y_err=0)
else:
- ret_val.set_data(x=new_x, y=new_y, y_err=None)
+ ret_val.set_data(x=new_x, y=new_y, y_err=0)
return ret_val
diff --git a/src/nmreval/models/bds.py b/src/nmreval/models/bds.py
index 137c5ab..7e770e7 100644
--- a/src/nmreval/models/bds.py
+++ b/src/nmreval/models/bds.py
@@ -54,14 +54,35 @@ class HavriliakNegamiBDS(_AbstractBDS):
name = 'Havriliak-Negami'
equation = r'\Delta\epsilon / [1-(i\omega\tau)^{\gamma}]^{\alpha}'
params = _AbstractBDS.params + [r'\alpha', r'\gamma']
- bounds = _AbstractBDS.bounds + [(0, 1), (0, 1)]
+ bounds = _AbstractBDS.bounds + [(0, 1), (0, None)]
susceptibility = HavriliakNegami.susceptibility
+class HavriliakNegamiAlphaGammaBDS:
+ type = 'Dielectric Spectroscopy'
+ name = 'Havriliak-Negami (ind. slopes)'
+ equation = r'\Delta\epsilon / [1-(i\omega\tau)^{\gamma}]^{\alpha}'
+ params = [r'\Delta\epsilon', r'\tau_{0}', r'\alpha', r'\alpha\gamma']
+ bounds = [(0, None), (0, None), (0, 1), (0, 1)]
+ iscomplex = True
+
+ @staticmethod
+ def func(x, deps, tau, alpha, alphagamma, complex_mode: int = 0, **kwargs):
+ chi = deps * HavriliakNegami.susceptibility(2*np.pi*x, tau, alpha, alphagamma/alpha, **kwargs)
+ if complex_mode == 0:
+ return chi
+ elif complex_mode == 1:
+ return chi.real
+ elif complex_mode == 2:
+ return chi.imag
+ else:
+ raise ValueError(f'{complex_mode!r} is not 0, 1, 2')
+
+
class KWWBDS(_AbstractBDS):
name = 'KWW'
params = _AbstractBDS.params + [r'\beta']
- bounds = _AbstractBDS.bounds + [(0, 1)]
+ bounds = _AbstractBDS.bounds + [(0.1, 1)]
susceptibility = KWW.susceptibility
diff --git a/src/nmreval/models/diffusion.py b/src/nmreval/models/diffusion.py
index 32dba92..f99e97a 100644
--- a/src/nmreval/models/diffusion.py
+++ b/src/nmreval/models/diffusion.py
@@ -149,7 +149,6 @@ class DiffusionGradients:
else:
tm = t2
tp = x
- # T2 decay happens twice
q2 = (g1**2 - g2**2) * (nucleus * tp)**2
t_eff = (2 * tp) / 3 + tm
diff --git a/src/nmreval/models/fieldcycling.py b/src/nmreval/models/fieldcycling.py
index 4d5221e..a1082d9 100644
--- a/src/nmreval/models/fieldcycling.py
+++ b/src/nmreval/models/fieldcycling.py
@@ -66,7 +66,7 @@ class HavriliakNegamiFC(_AbstractFC):
class KWWFC(_AbstractFC):
name = 'KWW'
params = _AbstractFC.params + [r'\beta']
- bounds = _AbstractFC.bounds + [(0, 1)]
+ bounds = _AbstractFC.bounds + [(0.1, 1)]
relax = Relaxation(distribution=KWW)
diff --git a/src/nmreval/utils/text.py b/src/nmreval/utils/text.py
index 57ff30a..7a8e8ba 100644
--- a/src/nmreval/utils/text.py
+++ b/src/nmreval/utils/text.py
@@ -80,6 +80,10 @@ def _replace_delims(text, src, dest):
return text
+def _replace_agr_controls(text: str):
+ return re.sub(r'\\[hvzfx]\{(\d*.?\d+.?)?\}', '', text)
+
+
def convert(text: str, old: str = 'tex', new: str = 'html', brackets: bool = True):
t = {'latex': 0, 'tex': 0, 'html': 1,
'agr': 2, 'plain': 3, 'str': 3}
@@ -101,5 +105,8 @@ def convert(text: str, old: str = 'tex', new: str = 'html', brackets: bool = Tru
if idx_out == 3 and not brackets:
text = text.replace('{', '').replace('}', '')
+ if idx_in == 2:
+ text = _replace_agr_controls(text)
+
return text
diff --git a/src/resources/_ui/apod_dialog.ui b/src/resources/_ui/apod_dialog.ui
index 03c5c1b..5585d7b 100644
--- a/src/resources/_ui/apod_dialog.ui
+++ b/src/resources/_ui/apod_dialog.ui
@@ -36,7 +36,7 @@
3
-
-
+
0
@@ -46,7 +46,7 @@
-
-
+
-
@@ -98,9 +98,9 @@
- PlotWidget
+ NMRPlotWidget
QGraphicsView
-
+
diff --git a/src/resources/_ui/baseline_dialog.ui b/src/resources/_ui/baseline_dialog.ui
index f047d0f..6bfaec6 100644
--- a/src/resources/_ui/baseline_dialog.ui
+++ b/src/resources/_ui/baseline_dialog.ui
@@ -53,7 +53,7 @@
-
-
+
0
@@ -66,9 +66,9 @@
- PlotWidget
+ NMRPlotWidget
QGraphicsView
-
+
diff --git a/src/resources/_ui/dscfile_dialog.ui b/src/resources/_ui/dscfile_dialog.ui
index c3ead1a..50af594 100644
--- a/src/resources/_ui/dscfile_dialog.ui
+++ b/src/resources/_ui/dscfile_dialog.ui
@@ -378,7 +378,7 @@
-
-
+
0
@@ -394,7 +394,7 @@
-
-
+
0
@@ -410,7 +410,7 @@
-
-
+
0
@@ -426,7 +426,7 @@
-
-
+
0
@@ -449,9 +449,9 @@
- PlotWidget
+ NMRPlotWidget
QGraphicsView
-
+
diff --git a/src/resources/_ui/graph.ui b/src/resources/_ui/graph.ui
index 02f573f..a433365 100644
--- a/src/resources/_ui/graph.ui
+++ b/src/resources/_ui/graph.ui
@@ -538,7 +538,7 @@
-
-
+
0
@@ -552,16 +552,16 @@
-
- PlotWidget
- QGraphicsView
-
-
QListWidgetSelect
QListWidget
+
+ NMRPlotWidget
+ QGraphicsView
+
+
logx_button
diff --git a/src/resources/_ui/phase_corr_dialog.ui b/src/resources/_ui/phase_corr_dialog.ui
index caec699..227d063 100644
--- a/src/resources/_ui/phase_corr_dialog.ui
+++ b/src/resources/_ui/phase_corr_dialog.ui
@@ -36,7 +36,7 @@
3
-
-
+
0
@@ -160,9 +160,9 @@
- PlotWidget
+ NMRPlotWidget
QGraphicsView
-
+
diff --git a/src/resources/_ui/shift_scale_dialog.ui b/src/resources/_ui/shift_scale_dialog.ui
index 6f7939b..defeb9c 100644
--- a/src/resources/_ui/shift_scale_dialog.ui
+++ b/src/resources/_ui/shift_scale_dialog.ui
@@ -317,7 +317,7 @@
3
-
-
+
0
@@ -503,9 +503,9 @@
- PlotWidget
+ NMRPlotWidget
QGraphicsView
-
+
SciSpinBox
diff --git a/src/resources/_ui/t1dialog.ui b/src/resources/_ui/t1dialog.ui
index e0438c1..b406232 100644
--- a/src/resources/_ui/t1dialog.ui
+++ b/src/resources/_ui/t1dialog.ui
@@ -451,6 +451,9 @@
-
+
+ false
+
Use minimon interpolation
diff --git a/src/resources/_ui/tnmh_dialog.ui b/src/resources/_ui/tnmh_dialog.ui
index 7345efc..1961825 100644
--- a/src/resources/_ui/tnmh_dialog.ui
+++ b/src/resources/_ui/tnmh_dialog.ui
@@ -100,7 +100,7 @@
-
-
+
0
@@ -145,10 +145,10 @@
-
-
+
-
-
+
0
@@ -277,7 +277,7 @@
-
-
+
-
@@ -427,16 +427,16 @@
-
- PlotWidget
- QGraphicsView
-
-
QListWidgetSelect
QListWidget
+
+ NMRPlotWidget
+ QGraphicsView
+
+