1
0
forked from IPKM/nmreval

Merge branch 'main' into dsc

# Conflicts:
#	src/gui_qt/main/mainwindow.py
This commit is contained in:
Dominik Demuth
2023-06-20 18:07:52 +02:00
34 changed files with 646 additions and 389 deletions

View File

@ -1,13 +1,16 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'resources/_ui/bdsdialog.ui'
# Form implementation generated from reading ui file 'src/resources/_ui/bdsdialog.ui'
#
# Created by: PyQt5 UI code generator 5.9.2
# 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
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
@ -16,12 +19,13 @@ class Ui_Dialog(object):
self.gridLayout.setContentsMargins(3, 3, 3, 3)
self.gridLayout.setSpacing(3)
self.gridLayout.setObjectName("gridLayout")
self.listWidget = QtWidgets.QListWidget(Dialog)
self.listWidget = QListWidgetSelect(Dialog)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.MinimumExpanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.listWidget.sizePolicy().hasHeightForWidth())
self.listWidget.setSizePolicy(sizePolicy)
self.listWidget.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
self.listWidget.setObjectName("listWidget")
self.gridLayout.addWidget(self.listWidget, 1, 0, 2, 1)
self.groupBox_2 = QtWidgets.QGroupBox(Dialog)
@ -93,8 +97,8 @@ class Ui_Dialog(object):
self.gridLayout.addWidget(self.label, 0, 0, 1, 2)
self.retranslateUi(Dialog)
self.buttonBox.accepted.connect(Dialog.accept)
self.buttonBox.rejected.connect(Dialog.reject)
self.buttonBox.accepted.connect(Dialog.accept) # type: ignore
self.buttonBox.rejected.connect(Dialog.reject) # type: ignore
QtCore.QMetaObject.connectSlotsByName(Dialog)
Dialog.setTabOrder(self.freq_button, self.temp_button)
Dialog.setTabOrder(self.temp_button, self.eps_checkBox)
@ -117,4 +121,4 @@ class Ui_Dialog(object):
self.temp_checkBox.setText(_translate("Dialog", "Meas. temperature"))
self.time_checkBox.setText(_translate("Dialog", "Meas. time"))
self.label.setText(_translate("Dialog", "Found entries"))
from ..lib.listwidget import QListWidgetSelect

View File

@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'src/resources/_ui/fitresult.ui'
#
# Created by: PyQt5 UI code generator 5.15.2
# 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.
@ -14,37 +14,28 @@ from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(864, 649)
Dialog.resize(969, 974)
self.gridLayout = QtWidgets.QGridLayout(Dialog)
self.gridLayout.setObjectName("gridLayout")
self.sets_comboBox = ElideComboBox(Dialog)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.sets_comboBox.sizePolicy().hasHeightForWidth())
self.sets_comboBox.setSizePolicy(sizePolicy)
self.sets_comboBox.setMaximumSize(QtCore.QSize(400, 16777215))
self.sets_comboBox.setBaseSize(QtCore.QSize(200, 0))
self.sets_comboBox.setSizeAdjustPolicy(QtWidgets.QComboBox.AdjustToMinimumContentsLength)
self.sets_comboBox.setObjectName("sets_comboBox")
self.gridLayout.addWidget(self.sets_comboBox, 0, 0, 1, 1)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setSpacing(3)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.reject_fit_checkBox = QtWidgets.QCheckBox(Dialog)
self.reject_fit_checkBox.setObjectName("reject_fit_checkBox")
self.horizontalLayout_2.addWidget(self.reject_fit_checkBox)
self.del_prev_checkBox = QtWidgets.QCheckBox(Dialog)
self.del_prev_checkBox.setObjectName("del_prev_checkBox")
self.horizontalLayout_2.addWidget(self.del_prev_checkBox)
self.gridLayout.addLayout(self.horizontalLayout_2, 2, 0, 1, 2)
self.line = QtWidgets.QFrame(Dialog)
self.line.setFrameShape(QtWidgets.QFrame.HLine)
self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
self.line.setObjectName("line")
self.gridLayout.addWidget(self.line, 3, 0, 1, 2)
self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok|QtWidgets.QDialogButtonBox.Retry)
self.buttonBox.setObjectName("buttonBox")
self.gridLayout.addWidget(self.buttonBox, 6, 0, 1, 2)
self.param_tableWidget = QtWidgets.QTableWidget(Dialog)
self.param_tableWidget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
self.param_tableWidget.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustIgnored)
self.param_tableWidget.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.param_tableWidget.setAlternatingRowColors(True)
self.param_tableWidget.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
self.param_tableWidget.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectColumns)
self.param_tableWidget.setShowGrid(False)
self.param_tableWidget.setColumnCount(0)
self.param_tableWidget.setObjectName("param_tableWidget")
self.param_tableWidget.setRowCount(0)
self.param_tableWidget.horizontalHeader().setStretchLastSection(False)
self.gridLayout.addWidget(self.param_tableWidget, 1, 0, 1, 1)
self.groupBox = QtWidgets.QGroupBox(Dialog)
self.groupBox.setObjectName("groupBox")
self.gridLayout_2 = QtWidgets.QGridLayout(self.groupBox)
@ -113,21 +104,34 @@ class Ui_Dialog(object):
self.horizontalLayout.addWidget(self.partial_checkBox)
self.gridLayout_2.addLayout(self.horizontalLayout, 0, 0, 1, 4)
self.gridLayout.addWidget(self.groupBox, 5, 0, 1, 2)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setSpacing(3)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.reject_fit_checkBox = QtWidgets.QCheckBox(Dialog)
self.reject_fit_checkBox.setObjectName("reject_fit_checkBox")
self.horizontalLayout_2.addWidget(self.reject_fit_checkBox)
self.del_prev_checkBox = QtWidgets.QCheckBox(Dialog)
self.del_prev_checkBox.setObjectName("del_prev_checkBox")
self.horizontalLayout_2.addWidget(self.del_prev_checkBox)
self.gridLayout.addLayout(self.horizontalLayout_2, 2, 0, 1, 1)
self.line = QtWidgets.QFrame(Dialog)
self.line.setFrameShape(QtWidgets.QFrame.HLine)
self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
self.line.setObjectName("line")
self.gridLayout.addWidget(self.line, 3, 0, 1, 2)
self.param_tableWidget = QtWidgets.QTableWidget(Dialog)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.param_tableWidget.sizePolicy().hasHeightForWidth())
self.param_tableWidget.setSizePolicy(sizePolicy)
self.param_tableWidget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
self.param_tableWidget.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustIgnored)
self.param_tableWidget.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.param_tableWidget.setAlternatingRowColors(True)
self.param_tableWidget.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
self.param_tableWidget.setColumnCount(1)
self.param_tableWidget.setObjectName("param_tableWidget")
self.param_tableWidget.setRowCount(0)
self.param_tableWidget.horizontalHeader().setVisible(False)
self.param_tableWidget.horizontalHeader().setStretchLastSection(True)
self.gridLayout.addWidget(self.param_tableWidget, 1, 0, 1, 1)
self.sets_comboBox = ElideComboBox(Dialog)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.sets_comboBox.sizePolicy().hasHeightForWidth())
self.sets_comboBox.setSizePolicy(sizePolicy)
self.sets_comboBox.setMaximumSize(QtCore.QSize(400, 16777215))
self.sets_comboBox.setBaseSize(QtCore.QSize(200, 0))
self.sets_comboBox.setSizeAdjustPolicy(QtWidgets.QComboBox.AdjustToMinimumContentsLength)
self.sets_comboBox.setObjectName("sets_comboBox")
self.gridLayout.addWidget(self.sets_comboBox, 0, 0, 1, 1)
self.stack = QtWidgets.QTabWidget(Dialog)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
@ -194,7 +198,7 @@ class Ui_Dialog(object):
self.corr_tableWidget.verticalHeader().setVisible(False)
self.verticalLayout_3.addWidget(self.corr_tableWidget)
self.stack.addTab(self.stackPage3, "")
self.gridLayout.addWidget(self.stack, 0, 1, 3, 1)
self.gridLayout.addWidget(self.stack, 0, 1, 2, 1)
self.retranslateUi(Dialog)
self.stack.setCurrentIndex(0)
@ -203,6 +207,8 @@ class Ui_Dialog(object):
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Fit results"))
self.reject_fit_checkBox.setText(_translate("Dialog", "Reject this fit"))
self.del_prev_checkBox.setText(_translate("Dialog", "Delete previous fits"))
self.groupBox.setTitle(_translate("Dialog", "Output"))
self.extrapolate_box.setToolTip(_translate("Dialog", "Extrapolates only main function"))
self.extrapolate_box.setText(_translate("Dialog", "Extrapolate curves"))
@ -215,8 +221,6 @@ class Ui_Dialog(object):
self.numx_line.setPlaceholderText(_translate("Dialog", "# pts"))
self.curve_checkbox.setText(_translate("Dialog", "Plot fit curve"))
self.partial_checkBox.setText(_translate("Dialog", "Plot partial functions"))
self.reject_fit_checkBox.setText(_translate("Dialog", "Reject this fit"))
self.del_prev_checkBox.setText(_translate("Dialog", "Delete previous fits"))
self.logy_box.setText(_translate("Dialog", "logarithmic y axis"))
self.logx_box.setText(_translate("Dialog", "logarithmic x axis"))
self.stack.setTabText(self.stack.indexOf(self.stackPage1), _translate("Dialog", "Plot"))

View File

@ -1,10 +1,11 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'resources/_ui/graph.ui'
# Form implementation generated from reading ui file 'src/resources/_ui/graph.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
@ -196,12 +197,13 @@ class Ui_GraphWindow(object):
self.gridLayout.setHorizontalSpacing(3)
self.gridLayout.setVerticalSpacing(0)
self.gridLayout.setObjectName("gridLayout")
self.listWidget = QtWidgets.QListWidget(GraphWindow)
self.listWidget = QListWidgetSelect(GraphWindow)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.MinimumExpanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.listWidget.sizePolicy().hasHeightForWidth())
self.listWidget.setSizePolicy(sizePolicy)
self.listWidget.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
self.listWidget.setObjectName("listWidget")
self.gridLayout.addWidget(self.listWidget, 1, 1, 1, 1)
self.checkBox = QtWidgets.QCheckBox(GraphWindow)
@ -272,4 +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.listwidget import QListWidgetSelect
from pyqtgraph import PlotWidget

View File

@ -1,10 +1,11 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'resources/_ui/interpol_dialog.ui'
# Form implementation generated from reading ui file 'src/resources/_ui/interpol_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
@ -65,12 +66,13 @@ class Ui_Dialog(object):
self.label_2 = QtWidgets.QLabel(Dialog)
self.label_2.setObjectName("label_2")
self.gridLayout.addWidget(self.label_2, 6, 0, 1, 1)
self.listWidget = QtWidgets.QListWidget(Dialog)
self.listWidget = QListWidgetSelect(Dialog)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.listWidget.sizePolicy().hasHeightForWidth())
self.listWidget.setSizePolicy(sizePolicy)
self.listWidget.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
self.listWidget.setObjectName("listWidget")
self.gridLayout.addWidget(self.listWidget, 1, 0, 1, 2)
self.sampling_widget = QtWidgets.QWidget(Dialog)
@ -130,8 +132,8 @@ class Ui_Dialog(object):
self.label_8.setBuddy(self.dest_combobox)
self.retranslateUi(Dialog)
self.buttonBox.accepted.connect(Dialog.accept)
self.buttonBox.rejected.connect(Dialog.reject)
self.buttonBox.accepted.connect(Dialog.accept) # type: ignore
self.buttonBox.rejected.connect(Dialog.reject) # type: ignore
QtCore.QMetaObject.connectSlotsByName(Dialog)
Dialog.setTabOrder(self.listWidget, self.ylog_checkBox)
Dialog.setTabOrder(self.ylog_checkBox, self.interp_comboBox)
@ -164,3 +166,4 @@ class Ui_Dialog(object):
self.xaxis_comboBox.setItemText(1, _translate("Dialog", "from data"))
self.label_8.setText(_translate("Dialog", "Add interpolated data to"))
self.xlog_checkBox.setText(_translate("Dialog", "use log(x)"))
from ..lib.listwidget import QListWidgetSelect

View File

@ -1,8 +1,8 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'resources/_ui/valueeditor.ui'
# Form implementation generated from reading ui file 'src/resources/_ui/valueeditor.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.

View File

@ -10,6 +10,7 @@ from nmreval.data.points import Points
from nmreval.data.signals import Signal
from nmreval.utils.text import convert
from nmreval.data.bds import BDS
from nmreval.data.dsc import DSC
from nmreval.lib.colors import BaseColor, TUColors
from nmreval.lib.lines import LineStyle
from nmreval.lib.symbols import SymbolStyle, symbolcycle
@ -44,6 +45,7 @@ class ExperimentContainer(QtCore.QObject):
self.actions = {}
self._update_actions()
@plot_update
def _init_plot(self):
raise NotImplementedError
@ -312,10 +314,8 @@ class ExperimentContainer(QtCore.QObject):
err_pen.setColor(QtGui.QColor(*self.plot_real.symbolcolor.rgb()))
self.plot_error.setData(pen=err_pen)
elif mode == 'imag' and self.plot_imag is not None:
if mode in ['imag', 'all'] and self.plot_imag is not None:
self.plot_imag.set_color(color, symbol=symbol, line=line)
else:
print('Updating color failed for ' + str(self.id))
def setSymbol(self, symbol=None, color=None, size=None, mode='real'):
if mode in ['real', 'all']:
@ -460,7 +460,7 @@ class ExperimentContainer(QtCore.QObject):
return namespace
def eval_expression(self, cmds, namespace):
namespace.update({'x': self.x, 'y': self.y, 'y_err': self.y_err, 'value': self.value})
namespace.update({'x': self._data.x, 'y': self._data.y, 'y_err': self._data.y_err, 'value': self.value})
if len(self._fits) == 1:
namespace.update({"fit['%s']" % (convert(pname, old='tex', new='str')): pvalue.value
@ -475,7 +475,7 @@ class ExperimentContainer(QtCore.QObject):
if c:
exec(c, globals(), namespace)
new_data.set_data(x=namespace['x'], y=namespace['y'], y_err=namespace['y_err'])
new_data.set_data(x=namespace['x'], y=namespace['y'], y_err=namespace['y_err'], replace_mask=False)
new_data.value = namespace['value']
return new_data
@ -496,6 +496,9 @@ class PointContainer(ExperimentContainer):
self.mode = 'pts'
self._init_plot(**kwargs)
if isinstance(self._data, DSC):
self.mode = 'dsc'
def _init_plot(self, **kwargs):
self.plot_imag = None
@ -532,17 +535,17 @@ class PointContainer(ExperimentContainer):
line_kwargs['style'] = LineStyle.No
sym_kwargs['symbol'] = next(PointContainer.symbols)
self.plot_real = PlotItem(x=self._data.x, y=self._data.y, name=self.name,
self.plot_real = PlotItem(x=self.x, y=self.y, name=self.name,
symbol=None, pen=None, connect='finite')
self.setSymbol(mode='real', **sym_kwargs)
self.setLine(mode='real', **line_kwargs)
if sym_kwargs['symbol'] != SymbolStyle.No:
self.plot_error = ErrorBars(x=self._data.x, y=self._data.y, top=self._data.y_err, bottom=self._data.y_err,
self.plot_error = ErrorBars(x=self.x, y=self.y, top=self.y_err, bottom=self.y_err,
pen=mkPen({'color': self.plot_real.symbolcolor.rgb()}))
else:
self.plot_error = ErrorBars(x=self._data.x, y=self._data.y, top=self._data.y_err, bottom=self._data.y_err,
self.plot_error = ErrorBars(x=self.x, y=self.y, top=self.y_err, bottom=self.y_err,
pen=mkPen({'color': self.plot_real.linecolor.rgb()}))
@ -565,12 +568,12 @@ class FitContainer(ExperimentContainer):
if isinstance(color, BaseColor):
color = color.rgb()
self.plot_real = PlotItem(x=self._data.x, y=self._data.y.real, name=self.name,
self.plot_real = PlotItem(x=self.x, y=self.y.real, name=self.name,
pen=mkPen({'color': color}),
connect='finite', symbol=None)
if np.iscomplexobj(self._data.y):
self.plot_imag = PlotItem(x=self._data.x, y=self._data.y.imag, name=self.name,
self.plot_imag = PlotItem(x=self.x, y=self.y.imag, name=self.name,
pen=mkPen({'color': color}),
connect='finite', symbol=None)
@ -603,9 +606,9 @@ class SignalContainer(ExperimentContainer):
self._init_plot(symbol=symbol, **kwargs)
def _init_plot(self, **kwargs):
self.plot_real = PlotItem(x=self._data.x, y=self._data.y.real, name=self.name,
self.plot_real = PlotItem(x=self.x, y=self.y.real, name=self.name,
symbol=None, pen=None, connect='finite')
self.plot_imag = PlotItem(x=self._data.x, y=self._data.y.imag, name=self.name,
self.plot_imag = PlotItem(x=self.x, y=self.y.imag, name=self.name,
symbol=None, pen=None, connect='finite')
color = kwargs.get('color', None)

View File

@ -187,9 +187,15 @@ class PointSelectWidget(QtWidgets.QWidget, Ui_Form):
self.peaktable.blockSignals(False)
def set_graphs(self, graphs: list):
last_graph = self.graph_combobox.currentData()
self.graph_combobox.clear()
for g in graphs:
idx = 0
for i, g in enumerate(graphs):
self.graph_combobox.addItem(g[1], userData=g[0])
if g[0] == last_graph:
idx = i
self.graph_combobox.setCurrentIndex(idx)
@QtCore.pyqtSlot(int, name='on_graph_checkbox_stateChanged')
def changed_state(self, checked):

View File

@ -188,7 +188,15 @@ class ValueEditWidget(QtWidgets.QWidget, Ui_MaskDialog):
new_value = complex(val)
new_value = new_value.real if new_value.imag == 0 else new_value
# table view loses focus when itemChanged is emitted
# if edit of item is cause of change resume editing at next item
prev_state = self.tableView.state()
idx = self.tableView.currentIndex()
idx = idx.sibling((col+1)//3+row, (col+1) % 3)
self.itemChanged.emit(sid, (col, row), new_value)
if prev_state == self.tableView.State.EditingState:
self.tableView.setCurrentIndex(idx)
self.tableView.edit(idx)
@QtCore.pyqtSlot(QtCore.QItemSelection, QtCore.QItemSelection)
def show_position(self, *_):
@ -259,10 +267,7 @@ class ValueModel(QtCore.QAbstractTableModel):
row = idx.row()
if role in [QtCore.Qt.DisplayRole, QtCore.Qt.EditRole]:
val = self._data[row][idx.column()]
if isinstance(val, complex):
return f'{val.real:.8g}{val.imag:+.8g}j'
else:
return f'{val:.8g}'
return self.as_string(val)
elif role == QtCore.Qt.BackgroundRole:
pal = QtGui.QGuiApplication.palette()
@ -295,11 +300,16 @@ class ValueModel(QtCore.QAbstractTableModel):
if value:
if role == QtCore.Qt.EditRole:
if value == self.as_string(self._data[row][col]):
return True
try:
value = complex(value)
except ValueError:
# not a number
return False
value = value.real if value.imag == 0 else value
self._data[row][col] = value.real if value.imag == 0 else value
self.itemChanged.emit(col, row, str(value))
self.dataChanged.emit(self.index(0, 0), self.index(0, 1), [role])
@ -368,3 +378,10 @@ class ValueModel(QtCore.QAbstractTableModel):
def unmask(self):
self.mask = [True] * self.total_rows
self.dataChanged.emit(self.index(0, 0), self.index(0, 1), [ValueModel.maskRole])
@staticmethod
def as_string(value) -> str:
if isinstance(value, complex):
return f'{value.real:.8g}{value.imag:+.8g}j'
else:
return f'{value:.8g}'

View File

@ -181,6 +181,11 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
for i, value in enumerate(self.data_values[sid]):
w = self.data_parameter[i]
w.blockSignals(True)
try:
w.show_as_local_parameter(value is not None)
except AttributeError:
pass
if value is None:
w.value = self.glob_values[i]
else:
@ -263,17 +268,17 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
return data_parameter, lb, ub, is_fixed, global_p, is_linked
def set_parameter(self, set_id: str | None, parameter: list[float]) -> int:
param_len = len(list(filter(lambda g: not isinstance(g, SelectionWidget), self.global_parameter)))
num_parameter = list(filter(lambda g: not isinstance(g, SelectionWidget), self.global_parameter))
param_len = len(num_parameter)
if set_id is None:
for val, g in zip(parameter, self.global_parameter):
if isinstance(g, SelectionWidget):
continue
for i, g in enumerate(num_parameter):
val = parameter[i]
g.set_parameter(val)
self.glob_values[i] = val
else:
new_param = self.data_values[set_id]
min_len = min(param_len, len(new_param), len(new_param))
min_len = min(param_len, len(new_param))
for i in range(min_len):
new_param[i] = parameter[i]
@ -293,6 +298,7 @@ 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.value_line.setValidator(QtGui.QDoubleValidator())
self.value_line.textChanged.connect(lambda: self.valueChanged.emit(self.value) if self.value is not None else 0)
@ -309,10 +315,12 @@ class ParameterSingleWidget(QtWidgets.QWidget):
layout.addSpacerItem(QtWidgets.QSpacerItem(0, 0, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum))
self.value_line = QtWidgets.QLineEdit(self)
self.value_line.textEdited.connect(lambda x: self.show_as_local_parameter(True))
layout.addWidget(self.value_line)
self.reset_button = QtWidgets.QToolButton(self)
self.reset_button.setText('Use global')
self.reset_button.clicked.connect(lambda: self.show_as_local_parameter(False))
layout.addWidget(self.reset_button)
self.setLayout(layout)
@ -327,3 +335,9 @@ class ParameterSingleWidget(QtWidgets.QWidget):
@value.setter
def value(self, val):
self.value_line.setText(f'{float(val):.5g}')
def show_as_local_parameter(self, is_local):
if is_local:
self.label.setStyleSheet('font-weight: bold;')
else:
self.label.setStyleSheet('')

View File

@ -77,16 +77,11 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
w.deleteLater()
del self.param_widgets[idx]
if len(self.functionwidget) == 0:
self._current_function = None
if len(self.param_widgets) == 0:
# empty model
self.newmodel_button.setEnabled(False)
self.deletemodel_button.setEnabled(False)
self._current_function = None
else:
f_tree = self.functionwidget.functree
func_idx = f_tree.currentItem().data(0, f_tree.counterRole)
self._current_function = self.functionwidget.functions[func_idx]
@QtCore.pyqtSlot(int)
def show_function_parameter(self, function_id: int, function_idx: int = None):

View File

@ -27,70 +27,80 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
self.extrapolate_box.stateChanged.connect(lambda x: self.minx_line.setEnabled(x))
self.extrapolate_box.stateChanged.connect(lambda x: self.numx_line.setEnabled(x))
self._prevs = {}
self._models = {}
self._previous_fits = {}
self._opts = []
self._results = {}
self.graph_opts = {}
self.last_idx = None
for res in results:
idx = res.idx
data_k = management.data[idx]
self.resid_plot = self.graphicsView.addPlot(row=0, col=0, title='Residual')
self.fit_plot = self.graphicsView.addPlot(row=1, col=0, title='Fit')
if res.name not in self._models:
self._models[res.name] = []
self.graphicsView.ci.layout.setRowStretchFactor(0, 1)
self.graphicsView.ci.layout.setRowStretchFactor(1, 2)
self._models[res.name].append(idx)
self._prevs[idx] = []
for fit in data_k.get_fits():
self._prevs[idx].append((fit.name, fit.statistics, fit.nobs-fit.nvar))
self._results = {res.idx: res for res in results}
self._opts = [(False, False) for _ in range(len(self._results))]
self.residplot = self.graphicsView.addPlot(row=0, col=0)
self.resid_graph = PlotItem(x=[], y=[],
symbol='o', symbolPen=None, symbolBrush=mkBrush(color=(31, 119, 180)),
pen=None)
self.resid_graph_imag = PlotItem(x=[], y=[],
symbol='s', symbolPen=None, symbolBrush=mkBrush(color=(255, 127, 14)),
pen=None)
self.residplot.addItem(self.resid_graph)
self.residplot.addItem(self.resid_graph_imag)
self.residplot.setLabel('left', 'Residual')
self.resid_plot.addItem(self.resid_graph)
self.resid_plot.addItem(self.resid_graph_imag)
self.fitplot = self.graphicsView.addPlot(row=1, col=0)
self.data_graph = PlotItem(x=[], y=[],
symbol='o', symbolPen=None, symbolBrush=mkBrush(color=(31, 119, 180)),
pen=None)
self.data_graph_imag = PlotItem(x=[], y=[],
symbol='s', symbolPen=None, symbolBrush=mkBrush(color=(255, 127, 14)),
pen=None)
self.fitplot.addItem(self.data_graph)
self.fitplot.addItem(self.data_graph_imag)
self.fitplot.setLabel('left', 'Function')
self.fit_plot.addItem(self.data_graph)
self.fit_plot.addItem(self.data_graph_imag)
self.fit_graph = PlotItem(x=[], y=[])
self.fit_graph_imag = PlotItem(x=[], y=[])
self.fitplot.addItem(self.fit_graph)
self.fitplot.addItem(self.fit_graph_imag)
self.fit_plot.addItem(self.fit_graph)
self.fit_plot.addItem(self.fit_graph_imag)
self.cmap = RdBuCMap(vmin=-1, vmax=1)
self.sets_comboBox.blockSignals(True)
for n in self._models.keys():
self.sets_comboBox.addItem(n)
self.sets_comboBox.blockSignals(False)
self.set_parameter(0)
self.buttonBox.accepted.connect(self.accept)
self.param_tableWidget.itemClicked.connect(self.show_results)
self.param_tableWidget.horizontalHeader().sectionClicked.connect(lambda i: self.show_results(None, idx=i))
self.graph_checkBox.stateChanged.connect(lambda x: self.graph_comboBox.setEnabled(x == QtCore.Qt.Unchecked))
self.logy_box.stateChanged.connect(lambda x: self.fitplot.setLogMode(y=bool(x)))
self.logx_box.stateChanged.connect(lambda x: self.fitplot.setLogMode(x=bool(x)))
self.residplot.setXLink(self.fitplot)
self.logy_box.stateChanged.connect(lambda x: self.fit_plot.setLogMode(y=bool(x)))
self.logx_box.stateChanged.connect(lambda x: self.fit_plot.setLogMode(x=bool(x)))
self.resid_plot.setXLink(self.fit_plot)
self.set_results(results)
def __call__(self, results: list):
self._previous_fits = {}
self.sets_comboBox.blockSignals(True)
self.sets_comboBox.clear()
self.sets_comboBox.blockSignals(False)
self._results = {}
self._opts = {}
self.set_results(results)
def set_results(self, results: list):
self.sets_comboBox.blockSignals(True)
for res in results:
idx = res.idx
data_k = self._management.data[idx]
self._previous_fits[idx] = []
for fit in data_k.get_fits():
self._previous_fits[idx].append((fit.name, fit.statistics, fit.nobs - fit.nvar))
self.sets_comboBox.addItem(data_k.name, userData=idx)
self.sets_comboBox.blockSignals(False)
self._results = {res.idx: res for res in results}
self._opts = [(False, False) for _ in range(len(self._results))]
self.set_parameter(0)
def add_graphs(self, graphs: list):
self.graph_comboBox.clear()
@ -99,56 +109,40 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
@QtCore.pyqtSlot(int, name='on_sets_comboBox_currentIndexChanged')
def set_parameter(self, idx: int):
model_name = self.sets_comboBox.itemText(idx)
sets = self._models[model_name]
self.param_tableWidget.setColumnCount(len(sets))
set_id = self.sets_comboBox.itemData(idx, QtCore.Qt.UserRole)
r = self._results[sets[0]]
self.param_tableWidget.setRowCount(len(r.parameter))
res = self._results[set_id]
self.param_tableWidget.setRowCount(len(res.parameter))
for j, (pkey, pvalue) in enumerate(res.parameter.items()):
name = pkey
p_header = QtWidgets.QTableWidgetItem(convert(name, 'tex', 'str', brackets=True))
self.param_tableWidget.setVerticalHeaderItem(j, p_header)
for i, pval in enumerate(r.parameter.values()):
name = pval.full_name
p_header = QtWidgets.QTableWidgetItem(convert(name, 'tex', 'html', brackets=False))
self.param_tableWidget.setVerticalHeaderItem(i, p_header)
item_text = f'{pvalue.value:.4g}'
if pvalue.error is not None:
item_text += f' \u00b1 {pvalue.error:.4g}'
self.param_tableWidget.setItem(2*j+1, 0, QtWidgets.QTableWidgetItem('-'))
else:
self.param_tableWidget.setItem(2*j+1, 0, QtWidgets.QTableWidgetItem())
item = QtWidgets.QTableWidgetItem(item_text)
self.param_tableWidget.setItem(j, 0, item)
for i, set_id in enumerate(sets):
data_i = self._management[set_id]
header_item = QtWidgets.QTableWidgetItem(data_i.name)
header_item.setData(QtCore.Qt.UserRole, set_id)
self.param_tableWidget.setHorizontalHeaderItem(i, header_item)
res = self._results[set_id]
for j, pvalue in enumerate(res.parameter.values()):
item_text = f'{pvalue.value:.4g}'
if pvalue.error is not None:
item_text += f' \u00b1 {pvalue.error:.4g}'
self.param_tableWidget.setItem(2*j+1, i, QtWidgets.QTableWidgetItem('-'))
else:
self.param_tableWidget.setItem(2*j+1, i, QtWidgets.QTableWidgetItem())
item = QtWidgets.QTableWidgetItem(item_text)
self.param_tableWidget.setItem(j, i, item)
self.param_tableWidget.resizeColumnsToContents()
self.param_tableWidget.selectColumn(0)
self.show_results(None, idx=0)
self.param_tableWidget.resizeColumnToContents(0)
self.show_results(idx)
@QtCore.pyqtSlot(int, name='on_reject_fit_checkBox_stateChanged')
@QtCore.pyqtSlot(int, name='on_del_prev_checkBox_stateChanged')
def change_opts(self, _):
idx = self.param_tableWidget.currentIndex().column()
idx = self.sets_comboBox.currentIndex()
self._opts[idx] = (self.reject_fit_checkBox.checkState() == QtCore.Qt.Checked,
self.del_prev_checkBox.checkState() == QtCore.Qt.Checked)
def show_results(self, item, idx=None):
if item is not None:
idx = self.param_tableWidget.indexFromItem(item).column()
set_id = self.param_tableWidget.horizontalHeaderItem(idx).data(QtCore.Qt.UserRole)
def show_results(self, idx):
set_id = self.sets_comboBox.itemData(idx, QtCore.Qt.UserRole)
self.set_plot(set_id)
self.set_correlation(set_id)
self.set_statistics(set_id)
self.reject_fit_checkBox.blockSignals(True)
self.reject_fit_checkBox.setChecked(self._opts[idx][0])
self.reject_fit_checkBox.blockSignals(False)
@ -157,13 +151,21 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
self.del_prev_checkBox.blockSignals(False)
def set_plot(self, idx: str):
if self.last_idx is not None:
self.graph_opts[self.last_idx] = (
self.fit_plot.viewRange(),
self.logx_box.isChecked(),
self.logy_box.isChecked(),
)
self.last_idx = idx
res = self._results[idx]
iscomplex = res.iscomplex
sub_funcs = res.sub(res.x)
for item in self.fitplot.curves[::-1]:
for item in self.fit_plot.items[::-1]:
if item not in [self.data_graph, self.data_graph_imag, self.fit_graph, self.fit_graph_imag]:
self.fitplot.removeItem(item)
self.fit_plot.removeItem(item)
if iscomplex:
self.data_graph.setData(x=res.x_data, y=res.y_data.real)
@ -173,11 +175,11 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
self.resid_graph.setData(x=res.x_data, y=res.residual.real)
self.resid_graph_imag.setData(x=res.x_data, y=res.residual.imag)
for f in sub_funcs:
item = PlotItem(x=f.x, y=f.y.real)
self.fitplot.addItem(item)
item = PlotItem(x=f.x, y=f.y.imag)
self.fitplot.addItem(item)
for i, f in enumerate(sub_funcs):
item = PlotItem(x=f.x, y=f.y.real, pen=mkPen({'color': i, 'style': 2}))
self.fit_plot.addItem(item)
item = PlotItem(x=f.x, y=f.y.imag, pen=mkPen({'color': i, 'style': 2}))
self.fit_plot.addItem(item)
else:
self.resid_graph.setData(x=res.x_data, y=res.residual)
@ -187,12 +189,27 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
self.fit_graph.setData(x=res.x, y=res.y)
self.fit_graph_imag.setData(x=[], y=[])
for f in sub_funcs:
item = PlotItem(x=f.x, y=f.y, pen=mkPen({'style': 2}))
self.fitplot.addItem(item)
for i, f in enumerate(sub_funcs):
item = PlotItem(x=f.x, y=f.y, pen=mkPen({'color': i, 'style': 2}))
self.fit_plot.addItem(item)
self.fitplot.setLogMode(x=res.islog)
self.residplot.setLogMode(x=res.islog)
self.logx_box.blockSignals(True)
self.logx_box.setChecked(res.islog)
self.logx_box.blockSignals(False)
self.fit_plot.setLogMode(x=res.islog)
self.resid_plot.setLogMode(x=res.islog)
if idx in self.graph_opts:
view_range, logx, logy = self.graph_opts[idx]
self.fit_plot.setRange(xRange=view_range[0], yRange=view_range[1], padding=0)
self.fit_plot.setLogMode(x=logx, y=logy)
self.logx_box.blockSignals(True)
self.logx_box.setChecked(logx)
self.logx_box.blockSignals(False)
self.logy_box.blockSignals(True)
self.logy_box.setChecked(logy)
self.logy_box.blockSignals(False)
def set_correlation(self, idx: str):
while self.corr_tableWidget.rowCount():
@ -223,7 +240,7 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
res = self._results[idx]
self.stats_tableWidget.setColumnCount(1 + len(self._prevs[idx]))
self.stats_tableWidget.setColumnCount(1 + len(self._previous_fits[idx]))
self.stats_tableWidget.setRowCount(len(res.statistics)+3)
it = QtWidgets.QTableWidgetItem(f'{res.dof}')
@ -231,7 +248,7 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
self.stats_tableWidget.setVerticalHeaderItem(0, QtWidgets.QTableWidgetItem('DoF'))
self.stats_tableWidget.setItem(0, 0, it)
for col, (name, _, dof) in enumerate(self._prevs[idx], start=1):
for col, (name, _, dof) in enumerate(self._previous_fits[idx], start=1):
self.stats_tableWidget.setHorizontalHeaderItem(0, QtWidgets.QTableWidgetItem(name))
it = QtWidgets.QTableWidgetItem(f'{dof}')
it.setFlags(it.flags() ^ QtCore.Qt.ItemIsEditable)
@ -245,7 +262,7 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
best_idx = -1
best_val = v
for col, (_, stats, _) in enumerate(self._prevs[idx], start=1):
for col, (_, stats, _) in enumerate(self._previous_fits[idx], start=1):
if k in ['adj. R^2', 'R^2']:
best_idx = col if best_val < stats[k] else max(0, best_idx)
else:
@ -265,7 +282,7 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
self.stats_tableWidget.setVerticalHeaderItem(row+1, QtWidgets.QTableWidgetItem('Pr(>F)'))
self.stats_tableWidget.setItem(row+1, 0, QtWidgets.QTableWidgetItem('-'))
for col, (_, stats, dof) in enumerate(self._prevs[idx], start=1):
for col, (_, stats, dof) in enumerate(self._previous_fits[idx], start=1):
f_value, prob_f = res.f_test(stats['chi^2'], dof)
it = QtWidgets.QTableWidgetItem(f'{f_value:.4g}')
it.setFlags(it.flags() ^ QtCore.Qt.ItemIsEditable)
@ -312,7 +329,6 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
except TypeError:
pass
self.closed.emit(self._results, self._opts, graph, plot_fits, parts, extrapolate)
self.accept()
@ -348,7 +364,7 @@ class FitExtension(QtWidgets.QDialog):
self.buttonBox = QtWidgets.QDialogButtonBox()
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel | QtWidgets.QDialogButtonBox.Ok)
gridLayout.addWidget(self.buttonBox, 3, 0, 1, 2)
self.setLayout(gridLayout)
@ -365,4 +381,4 @@ class FitExtension(QtWidgets.QDialog):
except TypeError:
return None
return xmin, xmax, nums
return xmin, xmax, nums

View File

@ -98,15 +98,19 @@ class QAsciiReader(QtWidgets.QDialog, Ui_ascii_reader):
@QtCore.pyqtSlot(int, name='on_preview_spinBox_valueChanged')
def show_preview(self, line_no: int):
preview, width = self.reader.make_preview(line_no)
preview, width, comments = self.reader.make_preview(line_no)
self.ascii_table.setRowCount(min(line_no, len(preview)))
self.ascii_table.setColumnCount(width)
self.ascii_table.setColumnCount(width + 1)
for i, line in enumerate(preview):
comment_line = comments[i]
for j, field in enumerate(line):
it = QtWidgets.QTableWidgetItem(field)
self.ascii_table.setItem(i, j, it)
it = QtWidgets.QTableWidgetItem(comment_line)
self.ascii_table.setItem(i, len(line), it)
self.ascii_table.resizeColumnsToContents()
@QtCore.pyqtSlot(int, name='on_column_checkBox_stateChanged')

View File

@ -55,9 +55,9 @@ class GraceExporter:
break
if c_num == -1:
c_num = max(colors.keys())
colors[c_num + 1] = (f'color{c_num + 1}', sc)
new_colors.append((c_num + 1, f'color{c_num + 1}', sc))
c_num = max(colors.keys())+1
colors[c_num] = (f'color{c_num}', sc)
new_colors.append((c_num, f'color{c_num}', sc))
new_s.set_symbol(**{'symbol': item['symbol'].value, 'size': item['symbolsize'] / 10., 'color': c_num,
'fill color': c_num, 'fill pattern': 1})

View File

@ -89,8 +89,11 @@ class QGraceReader(QtWidgets.QDialog, Ui_Dialog):
item = iterator.value()
key = (item.data(0, QtCore.Qt.UserRole))
s = self._reader.dataset(*key)
label = self._reader.get_property(*key, 'legend').replace('"', '')
# label = self._reader.graphs[key[0]].sets[key[1]]['legend'].replace('"', '')
label = self._reader.get_property(*key, 'legend')
if label is None:
label = ''
else:
label = label.replace('"', '')
sd = s.data
sd = np.atleast_2d(sd)
if s.type == 'xydy':

View File

@ -42,7 +42,7 @@ class PropertyDelegate(QtWidgets.QStyledItemDelegate):
painter.setPen(pen)
pm = make_symbol_pixmap(r)
painter.drawPixmap(options.rect.topLeft()+QtCore.QPoint(3, (options.rect.height()-pm.height())/2), pm)
painter.drawPixmap(options.rect.topLeft()+QtCore.QPoint(3, int((options.rect.height()-pm.height())/2)), pm)
style = QtWidgets.QApplication.style()
text_rect = style.subElementRect(QtWidgets.QStyle.SE_ItemViewItemText, options, None)
@ -171,7 +171,7 @@ class LineStyleEditor(QtWidgets.QComboBox):
rect = painter.style().subControlRect(QtWidgets.QStyle.CC_ComboBox,
opt, QtWidgets.QStyle.SC_ComboBoxEditField, None)
rect.adjust(+10, 0, -10, 0)
mid = (rect.bottom() + rect.top()) / 2
mid = int((rect.bottom() + rect.top()) / 2)
painter.drawLine(rect.left(), mid, rect.right(), mid)
painter.end()
else:
@ -193,7 +193,7 @@ class LineStyleDelegate(QtWidgets.QStyledItemDelegate):
rect = option.rect
rect.adjust(+10, 0, -10, 0)
mid = (rect.bottom()+rect.top()) / 2
mid = int((rect.bottom()+rect.top()) / 2)
painter.drawLine(rect.left(), mid, rect.right(), mid)
else:
QtWidgets.QStyledItemDelegate.paint(self, painter, option, index)

View File

@ -58,7 +58,7 @@ class RdBuCMap:
elif val < self.min:
col = QtGui.QColor.fromRgb(*RdBuCMap._rdbu[-1])
else:
col = QtGui.QColor.fromRgbF(*(float(self.spline[i](val)) for i in range(3)))
col = QtGui.QColor.fromRgb(*(int(self.spline[i](val)) for i in range(3)))
return col

View File

@ -59,6 +59,7 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
self._fit_plot_id = None
self.savefitdialog = None
self._tg_dialog = None
self.fitresult_dialog = None
self.eval = None
self.editor = None
@ -78,9 +79,11 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
if Updater.get_update_information(os.getenv('APPIMAGE'))[0]:
self.look_for_update()
self.check_for_backup()
self.__timer = QtCore.QTimer()
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.start(3*60*1000) # every three minutes
self.__timer.timeout.connect(self._autosave)
self.fit_timer = QtCore.QTimer()
@ -242,6 +245,7 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
self.actionConcatenate_sets.triggered.connect(lambda: self.management.cat())
self.management.graphs.valueChanged.connect(self.update_graph_list)
@QtCore.pyqtSlot(name='on_action_open_triggered')
def open(self):
@ -376,10 +380,15 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
if wdgt == self.current_graph_widget:
if self.ptsselectwidget.connected_figure == gid:
self.ptsselectwidget.connected_figure = None
for line in self.ptsselectwidget.pts_lines:
self.current_graph_widget.remove_external(line)
self.tabWidget.removeTab(self.tabWidget.indexOf(self.ptsselectwidget))
if self.t1tauwidget.connected_figure == gid:
self.t1tauwidget.connected_figure = None
self.current_graph_widget.add_external(self.t1tauwidget.min_pos)
self.current_graph_widget.add_external(self.t1tauwidget.parabola)
self.tabWidget.removeTab(self.tabWidget.indexOf(self.t1tauwidget))
if self.fit_dialog.connected_figure == gid:
@ -388,6 +397,8 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
self.current_graph_widget.remove_external(item)
if val_figure == gid:
self.current_graph_widget.remove_external(self.valuewidget.selection_real)
self.current_graph_widget.remove_external(self.valuewidget.selection_imag)
self.tabWidget.setCurrentIndex(0)
self.current_graph_widget.enable_picking(False)
@ -416,6 +427,12 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
if self.area.subWindowList():
self.area.activateNextSubWindow()
@QtCore.pyqtSlot()
def update_graph_list(self):
graph_list = self.management.graphs.list()
self.t1tauwidget.set_graphs(graph_list)
self.ptsselectwidget.set_graphs(graph_list)
@QtCore.pyqtSlot(str)
def set_graph(self, key: str):
w = self.management.graphs[key]
@ -932,11 +949,15 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
self.fit_timer.stop()
self.status.setText('')
if results:
res_dialog = QFitResult(results, self.management, parent=self)
res_dialog.add_graphs(self.management.graphs.list())
res_dialog.closed.connect(self.accepts_fit)
res_dialog.redoFit.connect(self.management.redo_fits)
res_dialog.show()
if self.fitresult_dialog is None:
self.fitresult_dialog = QFitResult(results, self.management, parent=self)
self.fitresult_dialog.add_graphs(self.management.graphs.list())
self.fitresult_dialog.closed.connect(self.accepts_fit)
self.fitresult_dialog.redoFit.connect(self.management.redo_fits)
else:
self.fitresult_dialog(results)
self.fitresult_dialog.add_graphs(self.management.graphs.list())
self.fitresult_dialog.show()
@QtCore.pyqtSlot(dict, list, str, bool, bool, list)
def accepts_fit(self, res: dict, opts: list, param_graph: str,
@ -1082,6 +1103,32 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
NMRWriter(self.management.graphs, self.management.data).export(self.__backup_path)
self.status.setText('')
def check_for_backup(self):
backups = []
for filename in config_paths().glob('*.nmr'):
try:
backups.append((filename, datetime.datetime.strptime(filename.stem, "%Y-%m-%d_%H%M%S")))
except ValueError:
continue
if backups:
backup_by_date = sorted(backups, key=lambda x: x[1])
msg = QtWidgets.QMessageBox.information(
self, 'Backup found',
f'{len(backups)} backup files in directory {backup_by_date[-1][0].parent} found.\n\n'
f'Latest backup date: {backup_by_date[-1][1]}\n\n'
f'Press Ok to load, Cancel to delete backup, Close to do nothing.',
QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel | QtWidgets.QMessageBox.Close
)
if msg == QtWidgets.QMessageBox.Ok:
self.management.load_files([str(backup_by_date[-1][0])])
backup_by_date[-1][0].unlink()
elif msg == QtWidgets.QMessageBox.Cancel:
backup_by_date[-1][0].unlink()
else:
pass
@QtCore.pyqtSlot(name='on_actionCreate_starter_triggered')
def create_starter(self):
make_starter(os.getenv('APPIMAGE'))

View File

@ -343,7 +343,7 @@ class UpperManagement(QtCore.QObject):
if joined is None:
joined = data_i.copy()
else:
joined.append(data_i.x, data_i.y, data_i.y_err)
joined.append(data_i.data.x, data_i.data.y, y_err=data_i.data.y_err, mask=data_i.data.mask)
name_set.add(data_i.name)
group_set.add(data_i.group)
@ -653,12 +653,10 @@ class UpperManagement(QtCore.QObject):
else:
continue
for key, pvalue in data.parameter.items():
name = pvalue.full_name
fit_key = key + data.model_name
for fit_key, pvalue in data.parameter.items():
if fit_key not in fit_dict:
fit_dict[fit_key] = [[], name]
fit_dict[fit_key] = [[], fit_key]
err = 0 if pvalue.error is None else pvalue.error