forked from IPKM/nmreval
Merge branch 'main' into dsc
# Conflicts: # src/gui_qt/main/mainwindow.py
This commit is contained in:
commit
032ffb72b1
@ -41,6 +41,7 @@ AppDir:
|
||||
# - zsync
|
||||
# - hicolor-icon-theme
|
||||
- libatlas3-base
|
||||
- gnuplot-nox
|
||||
- python3.9-minimal
|
||||
- python3-numpy
|
||||
- python3-scipy
|
||||
@ -70,7 +71,7 @@ AppDir:
|
||||
- usr/share/doc/*/README.*
|
||||
- usr/share/doc/*/changelog.*
|
||||
- usr/share/doc/*/NEWS.*
|
||||
- usr/share/doc/*/TODO.}*
|
||||
- usr/share/doc/*/TODO.*
|
||||
runtime:
|
||||
# if needed, apparently replaces hardcoded location with APPDIR location
|
||||
# path_mappings:
|
||||
|
@ -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
|
||||
|
@ -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"))
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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):
|
||||
|
@ -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}'
|
||||
|
@ -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('')
|
||||
|
@ -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):
|
||||
|
@ -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)
|
||||
|
@ -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')
|
||||
|
@ -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})
|
||||
|
@ -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':
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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'))
|
||||
|
@ -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
|
||||
|
||||
|
@ -10,23 +10,25 @@ __all__ = ['config_paths', 'check_for_config', 'read_configuration', 'write_conf
|
||||
|
||||
def check_for_config(make=True):
|
||||
try:
|
||||
config_paths()
|
||||
conf_path = config_paths()
|
||||
except FileNotFoundError as e:
|
||||
if make:
|
||||
conf_path = pathlib.Path('~/.auswerten').expanduser()
|
||||
conf_path.mkdir(parents=True)
|
||||
cwd = pathlib.Path(__file__).parent
|
||||
copyfile(cwd / 'models' / 'usermodels.py', conf_path / 'usermodels.py')
|
||||
|
||||
with resource_path('resources', 'Default.agr') as fp:
|
||||
copyfile(fp, conf_path / 'Default.agr')
|
||||
|
||||
with resource_path('resources', 'logo.png') as fp:
|
||||
copyfile(fp, conf_path / 'logo.png')
|
||||
|
||||
else:
|
||||
raise e
|
||||
|
||||
for filename in ('Default.agr', 'logo.png'):
|
||||
_file = conf_path / filename
|
||||
if not _file.exists():
|
||||
with resource_path('resources', filename) as fp:
|
||||
copyfile(fp, _file)
|
||||
|
||||
if not (conf_path / 'usermodels.py').exists():
|
||||
cwd = pathlib.Path(__file__).parent
|
||||
copyfile(cwd / 'models' / 'usermodels.py', conf_path / 'usermodels.py')
|
||||
|
||||
|
||||
def config_paths() -> pathlib.Path:
|
||||
searchpaths = ['~/.config/nmreval', '~/.auswerten', '/usr/share/nmreval']
|
||||
|
@ -484,7 +484,7 @@ class Points:
|
||||
|
||||
return self
|
||||
|
||||
def set_data(self, x: np.ndarray = None, y: np.ndarray = None, y_err: np.ndarray = None) -> PointLike:
|
||||
def set_data(self, x: np.ndarray = None, y: np.ndarray = None, y_err: np.ndarray = None, replace_mask=True) -> PointLike:
|
||||
if x is None:
|
||||
x = self._x
|
||||
if y is None:
|
||||
@ -492,12 +492,17 @@ class Points:
|
||||
if y_err is None:
|
||||
y_err = self._y_err
|
||||
|
||||
self._x, self._y, self._y_err, self.mask = self._prepare_xy(x, y, y_err)
|
||||
self._x, self._y, self._y_err, mask = self._prepare_xy(x, y, y_err)
|
||||
if replace_mask:
|
||||
self.mask = mask
|
||||
|
||||
return self
|
||||
|
||||
def append(self, x: ArrayLike, y: ArrayLike, y_err: ArrayLike = None):
|
||||
x, y, y_err, mask = self._prepare_xy(x, y, y_err)
|
||||
def append(self, x: ArrayLike, y: ArrayLike, y_err: ArrayLike = None, mask: ArrayLike = None):
|
||||
if mask is None:
|
||||
x, y, y_err, mask = self._prepare_xy(x, y, y_err)
|
||||
else:
|
||||
x, y, y_err, _ = self._prepare_xy(x, y, y_err)
|
||||
|
||||
self._x = np.r_[self._x, x]
|
||||
self._y = np.r_[self._y, y]
|
||||
|
@ -68,6 +68,7 @@ class MultiModel:
|
||||
self._kwargs_right = {}
|
||||
self._kwargs_left = {}
|
||||
self.fun_kwargs = {}
|
||||
self.idx = (left_idx, right_idx)
|
||||
|
||||
# mapping kwargs to kwargs of underlying functions
|
||||
self._ext_int_kw = {}
|
||||
@ -178,13 +179,13 @@ class MultiModel:
|
||||
if isinstance(self._left, MultiModel):
|
||||
yield from self._left.sub_name()
|
||||
elif hasattr(self._left, 'name'):
|
||||
yield self._left.name
|
||||
yield f'{self._left.name}({self.idx[0]})'
|
||||
else:
|
||||
yield self.name + '(lhs)'
|
||||
|
||||
if isinstance(self._right, MultiModel):
|
||||
yield from self._right.sub_name()
|
||||
elif hasattr(self._right, 'name'):
|
||||
yield self._right.name
|
||||
yield f'{self._right.name}({self.idx[1]})'
|
||||
else:
|
||||
yield self.name + '(rhs)'
|
||||
|
@ -63,9 +63,23 @@ class FitResultCreator:
|
||||
parameters = OrderedDict([(k, v) for k, v in zip(pnames, p)])
|
||||
p_final = [p.value for p in parameters.values()]
|
||||
|
||||
_y = model.func(p_final, _x, **fun_kwargs)
|
||||
resid = model.func(p_final, x_orig, **fun_kwargs) - y_orig
|
||||
|
||||
actual_mode = -1
|
||||
if 'complex_mode' in fun_kwargs:
|
||||
actual_mode = fun_kwargs['complex_mode']
|
||||
fun_kwargs['complex_mode'] = 0
|
||||
|
||||
_y = model.func(p_final, _x, **fun_kwargs)
|
||||
|
||||
if not actual_mode < 0:
|
||||
if actual_mode == 1:
|
||||
_y.imag = 0
|
||||
elif actual_mode == 2:
|
||||
_y.real = 0
|
||||
|
||||
fun_kwargs['complex_mode'] = actual_mode
|
||||
|
||||
stats = FitResultCreator.calc_statistics(_y, resid, nobs, nvar)
|
||||
varied = [p.var for p in parameters.values()]
|
||||
|
||||
@ -230,6 +244,7 @@ class FitResult(Points):
|
||||
ret_val = ''
|
||||
|
||||
for pval in self.parameter.values():
|
||||
print(pval)
|
||||
ret_val += convert(str(pval), old='tex', new='str') + '\n'
|
||||
|
||||
if self.fun_kwargs:
|
||||
@ -319,7 +334,13 @@ class FitResult(Points):
|
||||
f_value = 1e318
|
||||
else:
|
||||
f_value = (chi2-self.statistics['chi^2']) / (dof-self.dof) / self.statistics['red. chi^2']
|
||||
return f_value, 1-fdist.cdf(f_value, dof-self.dof, self.dof)
|
||||
|
||||
try:
|
||||
prob_f = 1-fdist.cdf(f_value, dof-self.dof, self.dof)
|
||||
except:
|
||||
prob_f = 0
|
||||
|
||||
return f_value, prob_f
|
||||
|
||||
def get_state(self):
|
||||
state = super().get_state()
|
||||
@ -349,20 +370,47 @@ class FitResult(Points):
|
||||
|
||||
def with_new_x(self, x_values):
|
||||
if self.func is None:
|
||||
raise ValueError('no fit function available to calcualate new y values')
|
||||
raise ValueError('no fit function available to calculate new y values')
|
||||
|
||||
actual_mode = -1
|
||||
if 'complex_mode' in self.fun_kwargs:
|
||||
actual_mode = self.fun_kwargs['complex_mode']
|
||||
self.fun_kwargs['complex_mode'] = 0
|
||||
|
||||
new_fit = self.copy()
|
||||
y_values = self.func.func(self.p_final, x_values, **self.fun_kwargs)
|
||||
if not actual_mode < 0:
|
||||
if actual_mode == 1:
|
||||
y_values.imag = 0
|
||||
elif actual_mode == 2:
|
||||
y_values.real = 0
|
||||
|
||||
self.fun_kwargs['complex_mode'] = actual_mode
|
||||
|
||||
new_fit.set_data(x_values, y_values)
|
||||
|
||||
return new_fit
|
||||
|
||||
def sub(self, x_values):
|
||||
part_functions = []
|
||||
actual_mode = -1
|
||||
if 'complex_mode' in self.fun_kwargs:
|
||||
actual_mode = self.fun_kwargs['complex_mode']
|
||||
self.fun_kwargs['complex_mode'] = 0
|
||||
|
||||
for sub_name, sub_y in zip(self.func.sub_name(), self.func.sub(self.p_final, x_values, **self.fun_kwargs)):
|
||||
if np.iscomplexobj(sub_y):
|
||||
if not actual_mode < 0:
|
||||
if actual_mode == 1:
|
||||
sub_y.imag = 0
|
||||
elif actual_mode == 2:
|
||||
sub_y.real = 0
|
||||
|
||||
part_functions.append(Signal(x_values, sub_y, name=sub_name))
|
||||
|
||||
else:
|
||||
part_functions.append(Points(x_values, sub_y, name=sub_name))
|
||||
|
||||
if actual_mode < 0:
|
||||
self.fun_kwargs['complex_mode'] = actual_mode
|
||||
|
||||
return part_functions
|
@ -21,10 +21,8 @@ class AsciiReader:
|
||||
self.fname = None
|
||||
self.header = []
|
||||
self.lines = []
|
||||
self.num_data = []
|
||||
self.delays = None
|
||||
self.width = []
|
||||
self.num_width = []
|
||||
self.line_comment = []
|
||||
self._last_read_pos = 0
|
||||
|
||||
@ -45,16 +43,14 @@ class AsciiReader:
|
||||
|
||||
def make_preview(self, num_lines: int):
|
||||
if num_lines <= len(self.lines):
|
||||
return self.lines[:num_lines], max(self.width[:num_lines])
|
||||
return self.lines[:num_lines], max(self.width[:num_lines]), self.line_comment
|
||||
|
||||
num_lines += len(self.header)
|
||||
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, ')
|
||||
|
||||
is_empty = len(line) == 0
|
||||
|
||||
line = re.split(r'[\s,;]', line)
|
||||
|
||||
try:
|
||||
comment_start = line.index('#')
|
||||
self.line_comment.append(' '.join(line[comment_start:]))
|
||||
@ -62,14 +58,15 @@ class AsciiReader:
|
||||
except ValueError:
|
||||
self.line_comment.append('')
|
||||
|
||||
if not is_empty:
|
||||
self.width.append(len(line))
|
||||
self.lines.append(line)
|
||||
if not line[0].startswith('#'):
|
||||
self.num_data.append(line)
|
||||
self.num_width.append(len(line))
|
||||
is_empty = len(line) == 0
|
||||
|
||||
return self.lines, max(self.width)
|
||||
if not is_empty:
|
||||
self.lines.append(line)
|
||||
self.width.append(len(line))
|
||||
else:
|
||||
self.lines.append('')
|
||||
|
||||
return self.lines, max(self.width), self.line_comment
|
||||
|
||||
def look_for_delay(self, fname=None):
|
||||
if fname is None:
|
||||
@ -112,7 +109,7 @@ class AsciiReader:
|
||||
raise ValueError(f'x is {type(x)} not int')
|
||||
|
||||
if y is None:
|
||||
y = list(range(1, max(self.num_width)))
|
||||
y = list(range(1, max(self.width)))
|
||||
|
||||
cols = x + y + yerr
|
||||
with self.fname.open('rb') as fh:
|
||||
@ -122,7 +119,7 @@ class AsciiReader:
|
||||
|
||||
if raw_data.ndim == 1:
|
||||
# only one row or column
|
||||
if len(self.num_data) == 1:
|
||||
if len(self.lines) == 1:
|
||||
# one row
|
||||
raw_data = raw_data.reshape(1, -1)
|
||||
else:
|
||||
@ -161,7 +158,7 @@ class AsciiReader:
|
||||
for j in range(1, num_y+1, stepsize):
|
||||
if col_names is not None:
|
||||
# predefined name
|
||||
kwargs['name'] = col_names[j]
|
||||
kwargs['name'] = col_names[j-1]
|
||||
elif num_y > single_len:
|
||||
# more than one axis, append column number
|
||||
kwargs['name'] = filename + '_' + str(y[j-1])
|
||||
|
@ -5,6 +5,7 @@ import re
|
||||
from collections import namedtuple
|
||||
|
||||
import numpy as np
|
||||
from scipy.stats import linregress
|
||||
|
||||
try:
|
||||
from scipy.integrate import simpson
|
||||
@ -200,35 +201,24 @@ class DSCCalibrator:
|
||||
high_border = np.argmin(np.abs(measurement[0] - t_high_lim))
|
||||
ref_zoom = measurement[:, low_border:high_border]
|
||||
|
||||
x_val = np.array([[ref_zoom[0, 0], 1], [ref_zoom[0, -1], 1]])
|
||||
y_val = np.array([ref_zoom[1, 0], ref_zoom[1, -1]])
|
||||
|
||||
sol = np.linalg.solve(x_val, y_val)
|
||||
ref_zoom[1] -= (ref_zoom[0] * sol[0] + sol[1])
|
||||
|
||||
ref_grad = np.gradient(ref_zoom[1])
|
||||
crossing = np.where(np.diff(np.sign(np.abs(ref_grad)-0.001)))[0]
|
||||
|
||||
almost_flat = np.sort(crossing-np.argmax(ref_zoom[1]))
|
||||
integ_limit = (almost_flat[np.where((almost_flat < -20))[0][-1]]+np.argmax(ref_zoom[1]),
|
||||
almost_flat[np.where((almost_flat > 20))[0][0]]+np.argmax(ref_zoom[1]))
|
||||
|
||||
# subtract baseline around reference peak
|
||||
sol = self.solve_linear_eq(integ_limit, ref_zoom)
|
||||
ref_zoom[1] -= (ref_zoom[0] * sol[0] + sol[1])
|
||||
|
||||
# calculate onset slope (use points at position of maximum gradient - 100/rate (+50/rate))
|
||||
ref_grad = np.gradient(ref_zoom[1])
|
||||
max_grad = np.argmax(ref_grad)
|
||||
|
||||
grad_pos = max_grad-max(1, int(160 / rate)), max_grad
|
||||
|
||||
sol = self.solve_linear_eq(grad_pos, ref_zoom)
|
||||
onset = sol[0] * ref_zoom[0] + sol[1]
|
||||
|
||||
melts.append(-sol[1] / sol[0])
|
||||
|
||||
if enthalpy is not None:
|
||||
x_val = np.array([[ref_zoom[0, 0], 1], [ref_zoom[0, -1], 1]])
|
||||
y_val = np.array([ref_zoom[1, 0], ref_zoom[1, -1]])
|
||||
|
||||
sol = np.linalg.solve(x_val, y_val)
|
||||
ref_zoom[1] -= (ref_zoom[0] * sol[0] + sol[1])
|
||||
|
||||
ref_grad = np.gradient(ref_zoom[1])
|
||||
crossing = np.where(np.diff(np.sign(np.abs(ref_grad)-0.001)))[0]
|
||||
|
||||
almost_flat = np.sort(crossing-np.argmax(ref_zoom[1]))
|
||||
integ_limit = (almost_flat[np.where((almost_flat < -40))[0][-1]]+np.argmax(ref_zoom[1]),
|
||||
almost_flat[np.where((almost_flat > 40))[0][0]]+np.argmax(ref_zoom[1]))
|
||||
|
||||
# subtract baseline around reference peak
|
||||
sol = self.solve_linear_eq(integ_limit, ref_zoom)
|
||||
ref_zoom[1] -= (ref_zoom[0] * sol[0] + sol[1])
|
||||
|
||||
# integrate over peak to calibrate y axis
|
||||
# delta H in J/g: Integrate Peak over time and divide by weight
|
||||
area = simpson(ref_zoom[1, integ_limit[0]:integ_limit[1]],
|
||||
@ -236,6 +226,23 @@ class DSCCalibrator:
|
||||
even='avg') * 1e-3
|
||||
calib_y.append(enthalpy / (area / data.weight))
|
||||
|
||||
else:
|
||||
ref_grad = np.gradient(ref_zoom[1])
|
||||
res = linregress(ref_zoom[0, :len(ref_grad)//5], ref_zoom[1, :len(ref_grad)//5])
|
||||
|
||||
ref_zoom[1] -= (res.slope*ref_zoom[0] + res.intercept)
|
||||
|
||||
# calculate onset slope (use points at position of maximum gradient - 100/rate (+50/rate))
|
||||
ref_grad = np.gradient(ref_zoom[1])
|
||||
max_grad = np.argmax(ref_grad)
|
||||
|
||||
grad_pos = max_grad - max(1, int(160 / rate)), max_grad
|
||||
|
||||
sol = self.solve_linear_eq(grad_pos, ref_zoom)
|
||||
onset = sol[0] * ref_zoom[0] + sol[1]
|
||||
|
||||
melts.append(-sol[1] / sol[0])
|
||||
|
||||
results.append([ref_zoom, onset, ref_zoom[:, grad_pos]])
|
||||
|
||||
if len(melts) > 1:
|
||||
|
@ -1,6 +1,8 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import pathlib
|
||||
import subprocess
|
||||
import tempfile
|
||||
|
||||
# import matplotlib.pyplot as plt
|
||||
from scipy.optimize import curve_fit
|
||||
@ -9,6 +11,7 @@ import numpy as np
|
||||
from nmreval.data.points import Points
|
||||
from nmreval.io.asciireader import AsciiReader
|
||||
from nmreval.io.hdfreader import HdfReader
|
||||
from nmreval.lib.logger import logger
|
||||
from nmreval.utils.utils import get_temperature, roundrobin
|
||||
|
||||
|
||||
@ -54,7 +57,7 @@ class FCReader:
|
||||
_temp = self._read_from_dir(filename)
|
||||
|
||||
else:
|
||||
raise TypeError
|
||||
raise TypeError(f'{filename} is of unknown type')
|
||||
|
||||
if not _temp:
|
||||
raise OSError(-666, f'No magnetization found for {filename.name}.', filename.name)
|
||||
@ -130,7 +133,7 @@ class FCReader:
|
||||
no_bevo = True
|
||||
break
|
||||
|
||||
if str(k.parent) != 'ACC_ABS_FID_sig (group)':
|
||||
if str(k.parent) != 'ABS_ACC_FID_sig (group)':
|
||||
continue
|
||||
|
||||
tevo = k.parameter['tevo']
|
||||
@ -141,14 +144,14 @@ class FCReader:
|
||||
if bevo not in _temp:
|
||||
_temp[bevo] = []
|
||||
|
||||
_temp[bevo].append((tevo, *[pp[1] for pp in pts]))
|
||||
_temp[bevo].append((tevo, *[np.real(pp[1]) for pp in pts]))
|
||||
|
||||
if no_bevo:
|
||||
break
|
||||
|
||||
if no_bevo:
|
||||
# hopefully only for old scripts
|
||||
sig = reader.get_selected('/data/B=*/ACC_ABS_FID*', dtype='signal')
|
||||
sig = reader.get_selected('/data/B=*/ABS_ACC_FID*', dtype='signal')
|
||||
_temp = {}
|
||||
for s in sig:
|
||||
pts = s.points([region])
|
||||
@ -156,7 +159,7 @@ class FCReader:
|
||||
if b not in _temp:
|
||||
_temp[b] = []
|
||||
|
||||
_temp[b].append([s.value, *[pp[1] for pp in pts]])
|
||||
_temp[b].append([s.value, *[np.real(pp[1]) for pp in pts]])
|
||||
|
||||
for b, m in sorted(_temp.items()):
|
||||
m = np.array(m)
|
||||
@ -178,6 +181,7 @@ class FCReader:
|
||||
fit_path.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
if save_fig:
|
||||
data_path = fname_no_ext.joinpath('data')
|
||||
image_path = fname_no_ext.joinpath('png')
|
||||
image_path.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
@ -188,15 +192,16 @@ class FCReader:
|
||||
freqs = []
|
||||
|
||||
for k, v in sorted(self.data[temperature].items()):
|
||||
freqs.append(k)
|
||||
|
||||
# fit
|
||||
p0 = [v.y[0], v.y[-1]-v.y[0], v.x[int(0.5*len(v.x) - 0.5)], 1]
|
||||
try:
|
||||
p0, pcov = curve_fit(FCReader.kww, v.x, v.y, p0=p0, bounds=bounds, max_nfev=500*len(v))
|
||||
except RuntimeError:
|
||||
except Exception as e:
|
||||
logger.error(f'Fit of field {k} failed with exception', exc_info=e)
|
||||
continue
|
||||
|
||||
freqs.append(k)
|
||||
|
||||
perr = np.sqrt(np.diag(pcov))
|
||||
params.append(p0)
|
||||
errors.append(perr)
|
||||
@ -218,16 +223,34 @@ class FCReader:
|
||||
np.savetxt(fit_path.joinpath(save_name), np.c_[xplot, yplot],
|
||||
header=header+'\t'.join([f'{p}+/-{err}' for p, err in zip(p0, perr)]))
|
||||
|
||||
# if save_fig:
|
||||
# fig, ax = plt.subplots()
|
||||
# ax.set_xlabel('t / s')
|
||||
# ax.set_ylabel('M')
|
||||
# axheader = f'T1: {p0[2]:.4g}(+/-{perr[2]:.4g}) beta: {p0[3]:.4g}(+/-{perr[3]:.4g})'
|
||||
# ax.set_title(f'f = {k:.4g} Hz\n{axheader}')
|
||||
# ax.semilogx(v.x, v.y, 'o')
|
||||
# ax.semilogx(xplot, yplot, '-')
|
||||
# fig.savefig(image_path.joinpath(save_name).with_suffix('.png'))
|
||||
# plt.close(fig)
|
||||
if save_fig:
|
||||
img_file = image_path.joinpath(save_name).with_suffix(".png")
|
||||
|
||||
gnuplot_args = [
|
||||
'set terminal png;',
|
||||
f'set output "{img_file}";',
|
||||
f'set title "f = {k:.4g} Hz\\n{p0[2]:.4g}(+/-{perr[2]:.4g}) beta: {p0[3]:.4g}(+/-{perr[3]:.4g})";',
|
||||
'set xlabel "t / s";',
|
||||
'set logscale x;',
|
||||
'set format x "10^{{%L}}";',
|
||||
'set ylabel "M";',
|
||||
'set key off;',
|
||||
f'plot "{data_path.joinpath(save_name)}" with points pointtype 5, "{fit_path.joinpath(save_name)}" with lines;',
|
||||
]
|
||||
|
||||
try:
|
||||
proc = subprocess.Popen(
|
||||
['gnuplot', '-p'],
|
||||
shell=True,
|
||||
stdin=subprocess.PIPE,
|
||||
encoding='utf8',
|
||||
)
|
||||
for args in gnuplot_args:
|
||||
proc.stdin.write(args)
|
||||
proc.stdin.write('quit\n')
|
||||
proc.stdin.flush()
|
||||
except Exception as e:
|
||||
logger.error(f'saving image {save_name} failed', e)
|
||||
|
||||
freqs = np.asanyarray(freqs)
|
||||
params = np.asanyarray(params)
|
||||
|
@ -1,9 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import codecs
|
||||
import pathlib
|
||||
import re
|
||||
import warnings
|
||||
from io import StringIO
|
||||
from typing import Optional, Tuple
|
||||
|
||||
@ -46,6 +44,22 @@ class GraceEditor:
|
||||
if filename is not None:
|
||||
self.parse(filename)
|
||||
|
||||
def _fix_tuda_colors(self):
|
||||
# 2023-05-11: Default.agr had wrong TUDa colors (4a, 7b, 9b, 9d), so set the values given in colors.py
|
||||
color_mapping = [
|
||||
('tuda4a', (175, 204, 80)),
|
||||
('tuda7b', (245, 163, 0)),
|
||||
('tuda9b', (230, 0, 26)),
|
||||
('tuda9d', (156, 28, 38)),
|
||||
]
|
||||
|
||||
for i, line in enumerate(self.header):
|
||||
m = self._RE_COLOR.match(line)
|
||||
if m:
|
||||
for name, right_color in color_mapping:
|
||||
if m['disp'].lower() == name:
|
||||
self.header[i] = f'@map color {m["id"]} to {right_color}, "{m["disp"]}"\n'
|
||||
|
||||
def __call__(self, filename: str):
|
||||
self.clear()
|
||||
self.parse(filename)
|
||||
@ -193,6 +207,8 @@ class GraceEditor:
|
||||
|
||||
self.graphs[-1].append(line)
|
||||
|
||||
self._fix_tuda_colors()
|
||||
|
||||
def _make_graph(self, line: str):
|
||||
m = self._RE_GRAPH_START.match(line)
|
||||
g_idx = int(m.group(1))
|
||||
@ -212,7 +228,6 @@ class GraceEditor:
|
||||
m = self._RE_COLOR.match(line)
|
||||
if m:
|
||||
_colors[int(m['id'])] = (m['disp'], (int(m['red']), int(m['green']), int(m['blue'])))
|
||||
|
||||
return _colors
|
||||
|
||||
def get_color(self, color_num):
|
||||
|
@ -5,6 +5,8 @@ from collections import OrderedDict
|
||||
|
||||
from .read_old_nmr import HAS_BSDDB3, _read_file_v1
|
||||
from ..data.nmr import FID, Spectrum
|
||||
from ..data.bds import BDS
|
||||
from ..data.dsc import DSC
|
||||
from ..data.points import Points
|
||||
from ..fit.result import FitResult, FitResultCreator
|
||||
from ..lib.colors import Colors
|
||||
@ -51,11 +53,17 @@ class NMRReader:
|
||||
states = pickle.load(fp)
|
||||
|
||||
datalist = OrderedDict()
|
||||
_dtypes = {'pts': Points, 'fit': FitResult, 'fid': FID}
|
||||
_dtypes = {'pts': Points,
|
||||
'fit': FitResult,
|
||||
'fid': FID,
|
||||
'bds': BDS,
|
||||
'dsc': DSC,
|
||||
'spectrum': Spectrum
|
||||
}
|
||||
|
||||
for s in states['sets']:
|
||||
set_id = s.pop('id')
|
||||
dtype = _dtypes[s.pop('mode')]
|
||||
dtype = _dtypes.get(s.pop('mode'), FID)
|
||||
data = dtype.set_state(s.pop('data'))
|
||||
datalist[set_id] = (data, s)
|
||||
|
||||
|
@ -247,6 +247,7 @@ class Tab10(BaseColor):
|
||||
TabChartreuse = TUColorsC.TUDa5c.value
|
||||
TabTurquoise = TUColorsA.TUDa2a.value
|
||||
|
||||
|
||||
class Tab20(BaseColor):
|
||||
TabBlue = (31, 119, 180)
|
||||
TabBlue2 = (174, 199, 232)
|
||||
|
@ -64,7 +64,7 @@
|
||||
@map color 2 to (93, 133, 195), "TUDa1a"
|
||||
@map color 3 to (0, 156, 218), "TUDa2a"
|
||||
@map color 4 to (80, 182, 149), "TUDa3a"
|
||||
@map color 5 to (176, 204, 80), "TUDa4a"
|
||||
@map color 5 to (175, 204, 80), "TUDa4a"
|
||||
@map color 6 to (221, 223, 72), "TUDa5a"
|
||||
@map color 7 to (255, 224, 92), "TUDa6a"
|
||||
@map color 8 to (248, 186, 60), "TUDa7a"
|
||||
@ -78,9 +78,9 @@
|
||||
@map color 16 to (153, 192, 0), "TUDa4b"
|
||||
@map color 17 to (201, 212, 0), "TUDa5b"
|
||||
@map color 18 to (253, 202, 0), "TUDa6b"
|
||||
@map color 19 to (248, 163, 0), "TUDa7b"
|
||||
@map color 19 to (245, 163, 0), "TUDa7b"
|
||||
@map color 20 to (236, 101, 0), "TUDa8b"
|
||||
@map color 21 to (239, 0, 26), "TUDa9b"
|
||||
@map color 21 to (230, 0, 26), "TUDa9b"
|
||||
@map color 22 to (166, 0, 132), "TUDa10b"
|
||||
@map color 23 to (114, 16, 133), "TUDa11b"
|
||||
@map color 24 to (0, 78, 138), "TUDa1c"
|
||||
@ -102,7 +102,7 @@
|
||||
@map color 40 to (174, 142, 0), "TUDa6d"
|
||||
@map color 41 to (190, 111, 0), "TUDa7d"
|
||||
@map color 42 to (169, 73, 19), "TUDa8d"
|
||||
@map color 43 to (188, 28, 38), "TUDa9d"
|
||||
@map color 43 to (156, 28, 38), "TUDa9d"
|
||||
@map color 44 to (115, 32, 84), "TUDa10d"
|
||||
@map color 45 to (76, 34, 106), "TUDa11d"
|
||||
@map color 46 to (220, 220, 220), "TUDa0a"
|
||||
|
@ -30,13 +30,16 @@
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item row="1" column="0" rowspan="2">
|
||||
<widget class="QListWidget" name="listWidget">
|
||||
<widget class="QListWidgetSelect" name="listWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
@ -207,6 +210,13 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>QListWidgetSelect</class>
|
||||
<extends>QListWidget</extends>
|
||||
<header>..lib.listwidget</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>freq_button</tabstop>
|
||||
<tabstop>temp_button</tabstop>
|
||||
|
@ -6,36 +6,39 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>864</width>
|
||||
<height>649</height>
|
||||
<width>969</width>
|
||||
<height>974</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Fit results</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="ElideComboBox" name="sets_comboBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="reject_fit_checkBox">
|
||||
<property name="text">
|
||||
<string>Reject this fit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="del_prev_checkBox">
|
||||
<property name="text">
|
||||
<string>Delete previous fits</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -46,37 +49,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QTableWidget" name="param_tableWidget">
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAsNeeded</enum>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QAbstractScrollArea::AdjustIgnored</enum>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectColumns</enum>
|
||||
</property>
|
||||
<property name="showGrid">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="columnCount">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
@ -223,35 +195,67 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>3</number>
|
||||
<item row="1" column="0">
|
||||
<widget class="QTableWidget" name="param_tableWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="reject_fit_checkBox">
|
||||
<property name="text">
|
||||
<string>Reject this fit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="del_prev_checkBox">
|
||||
<property name="text">
|
||||
<string>Delete previous fits</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAsNeeded</enum>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QAbstractScrollArea::AdjustIgnored</enum>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::NoSelection</enum>
|
||||
</property>
|
||||
<property name="columnCount">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<column/>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<item row="0" column="0">
|
||||
<widget class="ElideComboBox" name="sets_comboBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" rowspan="3">
|
||||
<item row="0" column="1" rowspan="2">
|
||||
<widget class="QTabWidget" name="stack">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||
@ -262,7 +266,7 @@
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="stackPage1" native="true">
|
||||
<widget class="QWidget" name="stackPage1">
|
||||
<attribute name="title">
|
||||
<string>Plot</string>
|
||||
</attribute>
|
||||
@ -307,7 +311,7 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="stackPage2" native="true">
|
||||
<widget class="QWidget" name="stackPage2">
|
||||
<attribute name="title">
|
||||
<string>Statistics</string>
|
||||
</attribute>
|
||||
@ -349,7 +353,7 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="stackPage3" native="true">
|
||||
<widget class="QWidget" name="stackPage3">
|
||||
<attribute name="title">
|
||||
<string>Correlations</string>
|
||||
</attribute>
|
||||
@ -415,16 +419,16 @@
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>GraphicsLayoutWidget</class>
|
||||
<extends>QGraphicsView</extends>
|
||||
<header>pyqtgraph</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ElideComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>..lib.forms</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>GraphicsLayoutWidget</class>
|
||||
<extends>QGraphicsView</extends>
|
||||
<header>pyqtgraph</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
@ -515,13 +515,16 @@
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="1" column="1">
|
||||
<widget class="QListWidget" name="listWidget">
|
||||
<widget class="QListWidgetSelect" name="listWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
@ -554,6 +557,11 @@
|
||||
<extends>QGraphicsView</extends>
|
||||
<header>pyqtgraph</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>QListWidgetSelect</class>
|
||||
<extends>QListWidget</extends>
|
||||
<header>..lib.listwidget</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>logx_button</tabstop>
|
||||
|
@ -141,7 +141,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QListWidget" name="listWidget">
|
||||
<widget class="QListWidgetSelect" name="listWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
@ -151,6 +151,9 @@
|
||||
<property name="toolTip">
|
||||
<string>Select sets that shall be interpolated. No selection will create interpolations of all visible sets.</string>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::MultiSelection</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="2">
|
||||
@ -276,6 +279,13 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>QListWidgetSelect</class>
|
||||
<extends>QListWidget</extends>
|
||||
<header>..lib.listwidget</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>listWidget</tabstop>
|
||||
<tabstop>ylog_checkBox</tabstop>
|
||||
|
Loading…
Reference in New Issue
Block a user