forked from IPKM/nmreval
Merge branch 'main' into fit_constraints
# Conflicts: # src/gui_qt/fit/fit_forms.py # src/gui_qt/main/management.py # src/nmreval/fit/minimizer.py
This commit is contained in:
@ -1,10 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file '_ui/apod_dialog.ui'
|
||||
# Form implementation generated from reading ui file 'src/resources/_ui/apod_dialog.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.12.3
|
||||
# Created by: PyQt5 UI code generator 5.15.9
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||
# run again. Do not edit this file unless you know what you are doing.
|
||||
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
@ -23,7 +24,7 @@ class Ui_ApodEdit(object):
|
||||
self.gridLayout.setContentsMargins(3, 3, 3, 3)
|
||||
self.gridLayout.setSpacing(3)
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
self.graphicsView = PlotWidget(ApodEdit)
|
||||
self.graphicsView = NMRPlotWidget(ApodEdit)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Expanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -31,7 +32,7 @@ class Ui_ApodEdit(object):
|
||||
self.graphicsView.setSizePolicy(sizePolicy)
|
||||
self.graphicsView.setObjectName("graphicsView")
|
||||
self.gridLayout.addWidget(self.graphicsView, 2, 0, 1, 1)
|
||||
self.graphicsView_2 = PlotWidget(ApodEdit)
|
||||
self.graphicsView_2 = NMRPlotWidget(ApodEdit)
|
||||
self.graphicsView_2.setObjectName("graphicsView_2")
|
||||
self.gridLayout.addWidget(self.graphicsView_2, 2, 1, 1, 1)
|
||||
self.apodcombobox = QtWidgets.QComboBox(ApodEdit)
|
||||
@ -63,12 +64,12 @@ class Ui_ApodEdit(object):
|
||||
self.gridLayout.addWidget(self.eqn_label, 0, 1, 1, 1)
|
||||
|
||||
self.retranslateUi(ApodEdit)
|
||||
self.buttonBox.accepted.connect(ApodEdit.accept)
|
||||
self.buttonBox.rejected.connect(ApodEdit.close)
|
||||
self.buttonBox.accepted.connect(ApodEdit.accept) # type: ignore
|
||||
self.buttonBox.rejected.connect(ApodEdit.close) # type: ignore
|
||||
QtCore.QMetaObject.connectSlotsByName(ApodEdit)
|
||||
|
||||
def retranslateUi(self, ApodEdit):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
ApodEdit.setWindowTitle(_translate("ApodEdit", "Apodization"))
|
||||
self.eqn_label.setText(_translate("ApodEdit", "TextLabel"))
|
||||
from pyqtgraph import PlotWidget
|
||||
from ..lib.graph_items import NMRPlotWidget
|
||||
|
@ -1,10 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file '_ui/baseline_dialog.ui'
|
||||
# Form implementation generated from reading ui file 'src/resources/_ui/baseline_dialog.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.12.3
|
||||
# Created by: PyQt5 UI code generator 5.15.9
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||
# run again. Do not edit this file unless you know what you are doing.
|
||||
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
@ -44,7 +45,7 @@ class Ui_SignalEdit(object):
|
||||
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
|
||||
self.buttonBox.setObjectName("buttonBox")
|
||||
self.gridLayout.addWidget(self.buttonBox, 1, 0, 1, 3)
|
||||
self.graphicsView = PlotWidget(SignalEdit)
|
||||
self.graphicsView = NMRPlotWidget(SignalEdit)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Expanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -54,11 +55,11 @@ class Ui_SignalEdit(object):
|
||||
self.gridLayout.addWidget(self.graphicsView, 0, 2, 1, 1)
|
||||
|
||||
self.retranslateUi(SignalEdit)
|
||||
self.buttonBox.accepted.connect(SignalEdit.accept)
|
||||
self.buttonBox.rejected.connect(SignalEdit.close)
|
||||
self.buttonBox.accepted.connect(SignalEdit.accept) # type: ignore
|
||||
self.buttonBox.rejected.connect(SignalEdit.close) # type: ignore
|
||||
QtCore.QMetaObject.connectSlotsByName(SignalEdit)
|
||||
|
||||
def retranslateUi(self, SignalEdit):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
SignalEdit.setWindowTitle(_translate("SignalEdit", "Dialog"))
|
||||
from pyqtgraph import PlotWidget
|
||||
from ..lib.graph_items import NMRPlotWidget
|
||||
|
@ -166,7 +166,7 @@ class Ui_Dialog(object):
|
||||
self.gridLayout = QtWidgets.QGridLayout(self.layoutWidget)
|
||||
self.gridLayout.setContentsMargins(0, 0, 0, 0)
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
self.raw_graph = PlotWidget(self.layoutWidget)
|
||||
self.raw_graph = NMRPlotWidget(self.layoutWidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -175,7 +175,7 @@ class Ui_Dialog(object):
|
||||
self.raw_graph.setMinimumSize(QtCore.QSize(300, 200))
|
||||
self.raw_graph.setObjectName("raw_graph")
|
||||
self.gridLayout.addWidget(self.raw_graph, 0, 0, 1, 1)
|
||||
self.calib_graph = PlotWidget(self.layoutWidget)
|
||||
self.calib_graph = NMRPlotWidget(self.layoutWidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -184,7 +184,7 @@ class Ui_Dialog(object):
|
||||
self.calib_graph.setMinimumSize(QtCore.QSize(300, 200))
|
||||
self.calib_graph.setObjectName("calib_graph")
|
||||
self.gridLayout.addWidget(self.calib_graph, 1, 0, 1, 1)
|
||||
self.baseline_graph = PlotWidget(self.layoutWidget)
|
||||
self.baseline_graph = NMRPlotWidget(self.layoutWidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -193,7 +193,7 @@ class Ui_Dialog(object):
|
||||
self.baseline_graph.setMinimumSize(QtCore.QSize(300, 200))
|
||||
self.baseline_graph.setObjectName("baseline_graph")
|
||||
self.gridLayout.addWidget(self.baseline_graph, 0, 1, 1, 1)
|
||||
self.end_graph = PlotWidget(self.layoutWidget)
|
||||
self.end_graph = NMRPlotWidget(self.layoutWidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -228,4 +228,4 @@ class Ui_Dialog(object):
|
||||
self.cp_checkBox.setText(_translate("Dialog", "Use reference to convert to heat capacity"))
|
||||
self.ref_add_pushButton.setText(_translate("Dialog", "Add reference"))
|
||||
self.ref_remove_pushButton.setText(_translate("Dialog", "Remove reference"))
|
||||
from pyqtgraph import PlotWidget
|
||||
from ..lib.graph_items import NMRPlotWidget
|
||||
|
@ -38,7 +38,6 @@ class Ui_FitDialog(object):
|
||||
self.weight_combobox.addItem("")
|
||||
self.weight_combobox.addItem("")
|
||||
self.weight_combobox.addItem("")
|
||||
self.weight_combobox.addItem("")
|
||||
self.gridLayout_2.addWidget(self.weight_combobox, 6, 1, 1, 1)
|
||||
self.newmodel_button = QtWidgets.QPushButton(self.scrollAreaWidgetContents_2)
|
||||
self.newmodel_button.setEnabled(False)
|
||||
@ -144,7 +143,6 @@ class Ui_FitDialog(object):
|
||||
self.weight_combobox.setItemText(1, _translate("FitDialog", "y"))
|
||||
self.weight_combobox.setItemText(2, _translate("FitDialog", "y²"))
|
||||
self.weight_combobox.setItemText(3, _translate("FitDialog", "Δy"))
|
||||
self.weight_combobox.setItemText(4, _translate("FitDialog", "log(y)"))
|
||||
self.newmodel_button.setText(_translate("FitDialog", "New model"))
|
||||
self.deletemodel_button.setText(_translate("FitDialog", "Delete model"))
|
||||
self.label_3.setText(_translate("FitDialog", "Weight"))
|
||||
|
@ -210,7 +210,7 @@ class Ui_GraphWindow(object):
|
||||
self.checkBox.setChecked(True)
|
||||
self.checkBox.setObjectName("checkBox")
|
||||
self.gridLayout.addWidget(self.checkBox, 0, 1, 1, 1)
|
||||
self.graphic = PlotWidget(GraphWindow)
|
||||
self.graphic = NMRPlotWidget(GraphWindow)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -274,5 +274,5 @@ class Ui_GraphWindow(object):
|
||||
self.label_6.setText(_translate("GraphWindow", "X Axis"))
|
||||
self.label_7.setText(_translate("GraphWindow", "Y Axis"))
|
||||
self.checkBox.setText(_translate("GraphWindow", "Show legend"))
|
||||
from ..lib.graph_items import NMRPlotWidget
|
||||
from ..lib.listwidget import QListWidgetSelect
|
||||
from pyqtgraph import PlotWidget
|
||||
|
@ -1,8 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'resources/_ui/phase_corr_dialog.ui'
|
||||
# Form implementation generated from reading ui file 'src/resources/_ui/phase_corr_dialog.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.15.4
|
||||
# Created by: PyQt5 UI code generator 5.15.9
|
||||
#
|
||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||
# run again. Do not edit this file unless you know what you are doing.
|
||||
@ -24,7 +24,7 @@ class Ui_SignalEdit(object):
|
||||
self.gridLayout.setContentsMargins(6, 6, 6, 6)
|
||||
self.gridLayout.setSpacing(3)
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
self.graphicsView = PlotWidget(SignalEdit)
|
||||
self.graphicsView = NMRPlotWidget(SignalEdit)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Expanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -83,8 +83,8 @@ class Ui_SignalEdit(object):
|
||||
self.gridLayout.addItem(spacerItem1, 1, 5, 1, 1)
|
||||
|
||||
self.retranslateUi(SignalEdit)
|
||||
self.buttonBox.accepted.connect(SignalEdit.accept)
|
||||
self.buttonBox.rejected.connect(SignalEdit.close)
|
||||
self.buttonBox.accepted.connect(SignalEdit.accept) # type: ignore
|
||||
self.buttonBox.rejected.connect(SignalEdit.close) # type: ignore
|
||||
QtCore.QMetaObject.connectSlotsByName(SignalEdit)
|
||||
|
||||
def retranslateUi(self, SignalEdit):
|
||||
@ -94,4 +94,4 @@ class Ui_SignalEdit(object):
|
||||
self.label_8.setText(_translate("SignalEdit", "Pivot"))
|
||||
self.label_6.setText(_translate("SignalEdit", "Phase 1"))
|
||||
self.label.setText(_translate("SignalEdit", "Phase 0"))
|
||||
from pyqtgraph import PlotWidget
|
||||
from ..lib.graph_items import NMRPlotWidget
|
||||
|
@ -1,10 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'resources/_ui/shift_scale_dialog.ui'
|
||||
# Form implementation generated from reading ui file 'src/resources/_ui/shift_scale_dialog.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.12.3
|
||||
# Created by: PyQt5 UI code generator 5.15.9
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||
# run again. Do not edit this file unless you know what you are doing.
|
||||
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
@ -162,7 +163,7 @@ class Ui_shift_dialog(object):
|
||||
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.verticalFrame_2)
|
||||
self.verticalLayout_2.setSpacing(3)
|
||||
self.verticalLayout_2.setObjectName("verticalLayout_2")
|
||||
self.graphicsView = PlotWidget(self.verticalFrame_2)
|
||||
self.graphicsView = NMRPlotWidget(self.verticalFrame_2)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.MinimumExpanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -267,8 +268,8 @@ class Ui_shift_dialog(object):
|
||||
|
||||
self.retranslateUi(shift_dialog)
|
||||
self.tabWidget.setCurrentIndex(0)
|
||||
self.buttonBox.accepted.connect(shift_dialog.accept)
|
||||
self.buttonBox.rejected.connect(shift_dialog.reject)
|
||||
self.buttonBox.accepted.connect(shift_dialog.accept) # type: ignore
|
||||
self.buttonBox.rejected.connect(shift_dialog.reject) # type: ignore
|
||||
QtCore.QMetaObject.connectSlotsByName(shift_dialog)
|
||||
shift_dialog.setTabOrder(self.tabWidget, self.shift_table)
|
||||
shift_dialog.setTabOrder(self.shift_table, self.x_shift_spinbox)
|
||||
@ -310,5 +311,5 @@ class Ui_shift_dialog(object):
|
||||
self.overwrite_checkbox.setText(_translate("shift_dialog", "Overwrite data"))
|
||||
self.data_newgraph.setText(_translate("shift_dialog", "New graph"))
|
||||
self.values_newgraph.setText(_translate("shift_dialog", "New graph"))
|
||||
from ..lib.graph_items import NMRPlotWidget
|
||||
from ..lib.spinboxes import SciSpinBox
|
||||
from pyqtgraph import PlotWidget
|
||||
|
@ -1,10 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'resources/_ui/t1dialog.ui'
|
||||
# Form implementation generated from reading ui file 'src/resources/_ui/t1dialog.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.12.3
|
||||
# Created by: PyQt5 UI code generator 5.15.9
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||
# run again. Do not edit this file unless you know what you are doing.
|
||||
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
@ -160,6 +161,7 @@ class Ui_t1dialog(object):
|
||||
self.tau_combox.addItem("")
|
||||
self.gridLayout_4.addWidget(self.tau_combox, 1, 0, 1, 2)
|
||||
self.checkBox_interpol = QtWidgets.QCheckBox(self.groupBox_3)
|
||||
self.checkBox_interpol.setEnabled(False)
|
||||
self.checkBox_interpol.setObjectName("checkBox_interpol")
|
||||
self.gridLayout_4.addWidget(self.checkBox_interpol, 2, 0, 1, 2)
|
||||
self.graph_checkbox = QtWidgets.QCheckBox(self.groupBox_3)
|
||||
|
@ -59,7 +59,7 @@ class Ui_DSCEvalDialog(object):
|
||||
self.tg_tree.headerItem().setText(0, "1")
|
||||
self.tg_tree.header().setVisible(False)
|
||||
self.gridLayout_2.addWidget(self.tg_tree, 2, 0, 1, 1)
|
||||
self.dsc_plot = PlotWidget(self.page)
|
||||
self.dsc_plot = NMRPlotWidget(self.page)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -89,10 +89,10 @@ class Ui_DSCEvalDialog(object):
|
||||
self.label_4 = QtWidgets.QLabel(self.page_2)
|
||||
self.label_4.setObjectName("label_4")
|
||||
self.gridLayout_3.addWidget(self.label_4, 2, 0, 1, 1)
|
||||
self.tghodge_graph = PlotWidget(self.page_2)
|
||||
self.tghodge_graph = NMRPlotWidget(self.page_2)
|
||||
self.tghodge_graph.setObjectName("tghodge_graph")
|
||||
self.gridLayout_3.addWidget(self.tghodge_graph, 1, 0, 1, 1)
|
||||
self.tau_plot = PlotWidget(self.page_2)
|
||||
self.tau_plot = NMRPlotWidget(self.page_2)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.MinimumExpanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -155,7 +155,7 @@ class Ui_DSCEvalDialog(object):
|
||||
self.page_3.setObjectName("page_3")
|
||||
self.gridLayout_6 = QtWidgets.QGridLayout(self.page_3)
|
||||
self.gridLayout_6.setObjectName("gridLayout_6")
|
||||
self.tnmh_graphics = PlotWidget(self.page_3)
|
||||
self.tnmh_graphics = NMRPlotWidget(self.page_3)
|
||||
self.tnmh_graphics.setObjectName("tnmh_graphics")
|
||||
self.gridLayout_6.addWidget(self.tnmh_graphics, 1, 0, 1, 2)
|
||||
self.tnmh_tree = QtWidgets.QTreeWidget(self.page_3)
|
||||
@ -249,5 +249,5 @@ class Ui_DSCEvalDialog(object):
|
||||
self.back_button.setText(_translate("DSCEvalDialog", "Back"))
|
||||
self.next_button.setText(_translate("DSCEvalDialog", "Next"))
|
||||
self.close_button.setText(_translate("DSCEvalDialog", "Close"))
|
||||
from ..lib.graph_items import NMRPlotWidget
|
||||
from ..lib.listwidget import QListWidgetSelect
|
||||
from pyqtgraph import PlotWidget
|
||||
|
@ -463,6 +463,16 @@ class ExperimentContainer(QtCore.QObject):
|
||||
|
||||
return offset
|
||||
|
||||
@plot_update
|
||||
def shift_scale(self, shift_factor: tuple[float, float], scaling_factor: tuple[float, float]):
|
||||
scale_x, scale_y = scaling_factor
|
||||
shift_x, shift_y = shift_factor
|
||||
self.data.x = self.data.x * scale_x + shift_x
|
||||
self.data.y = self.data.y * scale_y + shift_y
|
||||
self.data.y_err = self.data.y_err * scale_y
|
||||
|
||||
self.update({'shift': scaling_factor, 'scale': shift_factor})
|
||||
|
||||
def get_namespace(self, i: int = None, j: int = None) -> dict:
|
||||
if (i is None) and (j is None):
|
||||
prefix = ''
|
||||
|
@ -1,7 +1,7 @@
|
||||
import numpy as np
|
||||
from itertools import cycle
|
||||
|
||||
from pyqtgraph import mkColor, mkPen
|
||||
from pyqtgraph import mkColor, mkPen, mkBrush
|
||||
|
||||
from nmreval.lib.colors import Tab10
|
||||
|
||||
@ -42,11 +42,17 @@ class QShift(QtWidgets.QDialog, Ui_shift_dialog):
|
||||
|
||||
def add_item(self, idx, name, x, y):
|
||||
color = mkColor(next(self._colors).rgb())
|
||||
if np.iscomplexobj(y):
|
||||
pl = [PlotItem(x=x, y=y.real, name=name, pen=mkPen(color=color)),
|
||||
PlotItem(x=x, y=y.imag, name=name, pen=mkPen(color=color))]
|
||||
|
||||
if len(y) == 1:
|
||||
sym_kwds = {'symbol': 'o', 'symbolBrush': mkBrush(color=color), 'symbolPen': mkPen(color=color)}
|
||||
else:
|
||||
pl = [PlotItem(x=x, y=y, name=name, pen=mkPen(color=color))]
|
||||
sym_kwds = {'symbol': None, 'symbolBrush': mkBrush(color=color), 'symbolPen': mkPen(color=color)}
|
||||
|
||||
if np.iscomplexobj(y):
|
||||
pl = [PlotItem(x=x, y=y.real, name=name, pen=mkPen(color=color), **sym_kwds),
|
||||
PlotItem(x=x, y=y.imag, name=name, pen=mkPen(color=color), **sym_kwds)]
|
||||
else:
|
||||
pl = [PlotItem(x=x, y=y, name=name, pen=mkPen(color=color), **sym_kwds)]
|
||||
|
||||
self.data[idx] = (pl, x, y)
|
||||
|
||||
|
@ -6,12 +6,14 @@ from ..Qt import QtCore, QtWidgets, QtGui
|
||||
from .._py.fitmodelwidget import Ui_FitParameter
|
||||
from .._py.save_fitmodel_dialog import Ui_SaveDialog
|
||||
from ..lib.iconloading import get_icon
|
||||
from ..lib.tables import TableWidget
|
||||
|
||||
|
||||
class FitModelWidget(QtWidgets.QWidget, Ui_FitParameter):
|
||||
value_requested = QtCore.pyqtSignal(object)
|
||||
value_changed = QtCore.pyqtSignal(str)
|
||||
state_changed = QtCore.pyqtSignal()
|
||||
replace_single_value = QtCore.pyqtSignal(object)
|
||||
|
||||
def __init__(self, label: str = 'Fitparameter', parent=None, fixed: bool = False):
|
||||
super().__init__(parent)
|
||||
@ -30,6 +32,7 @@ class FitModelWidget(QtWidgets.QWidget, Ui_FitParameter):
|
||||
self.global_checkbox.stateChanged.connect(lambda: self.state_changed.emit())
|
||||
self.parameter_line.editingFinished.connect(self.update_parameter)
|
||||
self.parameter_line.values_requested.connect(lambda: self.value_requested.emit(self))
|
||||
self.parameter_line.replace_single_values.connect(lambda: self.replace_single_value.emit(None))
|
||||
self.parameter_line.editingFinished.connect(lambda: self.value_changed.emit(self.parameter_line.text()))
|
||||
self.fixed_check.toggled.connect(self.set_fixed)
|
||||
|
||||
@ -311,7 +314,7 @@ class FitModelTree(QtWidgets.QTreeWidget):
|
||||
return funcs
|
||||
|
||||
|
||||
class FitTableWidget(QtWidgets.QTableWidget):
|
||||
class FitTableWidget(TableWidget):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent=parent)
|
||||
|
||||
|
@ -78,6 +78,7 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
|
||||
widgt.state_changed.connect(self.make_global)
|
||||
widgt.value_requested.connect(self.look_for_value)
|
||||
widgt.value_changed.connect(self.change_global_parameter)
|
||||
widgt.replace_single_value.connect(self.delete_single_parameter)
|
||||
|
||||
self.global_parameter.append(widgt)
|
||||
self.scrollwidget.layout().addWidget(widgt)
|
||||
@ -150,6 +151,13 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
|
||||
if value is None:
|
||||
self.change_data(self.comboBox.currentIndex())
|
||||
|
||||
def delete_single_parameter(self):
|
||||
idx = self.global_parameter.index(self.sender())
|
||||
for i in range(self.comboBox.count()):
|
||||
set_id = self.comboBox.itemData(i)
|
||||
self.data_values[set_id][idx] = None
|
||||
self.change_data(self.comboBox.currentIndex())
|
||||
|
||||
def change_single_choice(self, _, value, sender=None):
|
||||
if sender is None:
|
||||
sender = self.sender()
|
||||
@ -298,7 +306,8 @@ class ParameterSingleWidget(QtWidgets.QWidget):
|
||||
|
||||
self._name = name
|
||||
self.label.setText(convert(name))
|
||||
self.label.setToolTip('IIf this is bold then this parameter is only for this data. otherwise the general parameter is used and displayed')
|
||||
self.label.setToolTip('If this is bold then this parameter is only for this data. '
|
||||
'Otherwise, the general parameter is used and displayed')
|
||||
|
||||
# self.value_line.setValidator(QtGui.QDoubleValidator())
|
||||
self.value_line.textChanged.connect(lambda: self.valueChanged.emit(self.value) if self.value is not None else 0)
|
||||
|
@ -14,7 +14,7 @@ from gui_qt.lib.namespace import QNamespaceWidget
|
||||
|
||||
__all__ = ['QUserFitCreator']
|
||||
|
||||
validator = QtGui.QRegExpValidator(QtCore.QRegExp('[A-Za-z]\S*'))
|
||||
validator = QtGui.QRegExpValidator(QtCore.QRegExp('[_A-Za-z][_A-Za-z0-9]*'))
|
||||
pattern = re.compile(r'def func\(.*\):', flags=re.MULTILINE)
|
||||
|
||||
|
||||
@ -145,6 +145,7 @@ class QUserFitCreator(QtWidgets.QDialog, Ui_Dialog):
|
||||
self.classCreated.emit()
|
||||
super().accept()
|
||||
|
||||
|
||||
class KwargsWidget(QtWidgets.QWidget):
|
||||
Changed = QtCore.pyqtSignal()
|
||||
|
||||
@ -209,7 +210,7 @@ class KwargsWidget(QtWidgets.QWidget):
|
||||
def get_strings(self) -> str:
|
||||
kwargs = []
|
||||
if self.use_nuclei.isChecked():
|
||||
kwargs.append("(r'\gamma', 'nucleus', gamma)")
|
||||
kwargs.append(r"(r'\gamma', 'nucleus', gamma)")
|
||||
|
||||
for i in range(self.choices.count()):
|
||||
kwargs.append(self.choices.widget(i).get_strings())
|
||||
@ -300,7 +301,7 @@ class ChoiceWidget(QtWidgets.QWidget):
|
||||
def get_strings(self) -> str:
|
||||
opts = []
|
||||
for i in range(self.table.rowCount()):
|
||||
name = self.table.item(i, 0).text()
|
||||
name = self.table.cellWidget(i, 0).text()
|
||||
val = self._make_value(i)
|
||||
opts.append(f'{name!r}: {val!r}')
|
||||
|
||||
|
@ -3,6 +3,7 @@ from math import isnan
|
||||
from pyqtgraph import mkBrush, mkPen
|
||||
|
||||
from nmreval.utils.text import convert
|
||||
from ..lib.graph_items import logTickValues
|
||||
|
||||
from ..lib.utils import RdBuCMap
|
||||
from ..Qt import QtWidgets, QtGui, QtCore
|
||||
@ -33,8 +34,12 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
|
||||
self.graph_opts = {}
|
||||
self.last_idx = None
|
||||
|
||||
self.resid_plot = self.graphicsView.addPlot(row=0, col=0, title='Residual')
|
||||
self.fit_plot = self.graphicsView.addPlot(row=1, col=0, title='Fit')
|
||||
self.resid_plot = self.graphicsView.addPlot(row=0, col=0, title='Residual')
|
||||
|
||||
for orient in ['top', 'bottom', 'left', 'right']:
|
||||
self.fit_plot.getAxis(orient).logTickValues = logTickValues
|
||||
self.resid_plot.getAxis(orient).logTickValues = logTickValues
|
||||
|
||||
self.graphicsView.ci.layout.setRowStretchFactor(0, 1)
|
||||
self.graphicsView.ci.layout.setRowStretchFactor(1, 2)
|
||||
|
@ -4,7 +4,7 @@ import itertools
|
||||
import os
|
||||
import uuid
|
||||
|
||||
from math import isnan
|
||||
from math import isfinite
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
@ -45,7 +45,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
self.id = str(uuid.uuid4())
|
||||
|
||||
self.sets = []
|
||||
self.active = []
|
||||
self._active = []
|
||||
|
||||
self.real_plots = {}
|
||||
self.imag_plots = {}
|
||||
@ -75,6 +75,8 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
self.scene.contextMenu[0].disconnect()
|
||||
self.scene.contextMenu[0].triggered.connect(self.export_dialog)
|
||||
|
||||
self.bwbutton.toggled.connect(self.change_background)
|
||||
|
||||
def _init_gui(self):
|
||||
self.setWindowTitle('Graph ' + str(next(QGraphWindow.counter)))
|
||||
|
||||
@ -114,11 +116,11 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
return iter(self.active)
|
||||
|
||||
def __len__(self):
|
||||
return len(self.active)
|
||||
return len(self._active)
|
||||
|
||||
def curves(self) -> tuple:
|
||||
for set_id in self.sets:
|
||||
if set_id in self.active:
|
||||
if set_id in self._active:
|
||||
if self.real_button.isChecked():
|
||||
if self.error_plots[set_id] is not None:
|
||||
yield self.real_plots[set_id], self.error_plots[set_id]
|
||||
@ -144,7 +146,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
tmp = [np.nan, np.nan]
|
||||
for j, x in enumerate(r[i]):
|
||||
try:
|
||||
tmp[j] = 10**x
|
||||
tmp[j] = 10**min(x, 199)
|
||||
except OverflowError:
|
||||
pass
|
||||
r[i] = tuple(tmp)
|
||||
@ -153,6 +155,14 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
|
||||
return tuple(r)
|
||||
|
||||
@property
|
||||
def active(self) -> list:
|
||||
return [set_id for set_id in self.sets if set_id in self._active]
|
||||
|
||||
@active.setter
|
||||
def active(self, value: list):
|
||||
self._active = value
|
||||
|
||||
def block(self, state: bool):
|
||||
self._block = state
|
||||
|
||||
@ -201,8 +211,8 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
for plot in [self.real_plots, self.imag_plots, self.error_plots]:
|
||||
self.graphic.removeItem(plot[n])
|
||||
|
||||
if n in self.active:
|
||||
self.active.remove(n)
|
||||
if n in self._active:
|
||||
self._active.remove(n)
|
||||
|
||||
# remove from label list
|
||||
self.listWidget.blockSignals(True)
|
||||
@ -246,8 +256,8 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
return
|
||||
|
||||
for a in idlist:
|
||||
if a not in self.active:
|
||||
self.active.append(a)
|
||||
if a not in self._active:
|
||||
self._active.append(a)
|
||||
|
||||
for (bttn, plot_dic) in [
|
||||
(self.real_button, self.real_plots),
|
||||
@ -266,8 +276,8 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
return
|
||||
|
||||
for r in idlist:
|
||||
if r in self.active:
|
||||
self.active.remove(r)
|
||||
if r in self._active:
|
||||
self._active.remove(r)
|
||||
|
||||
for plt in [self.real_plots, self.imag_plots, self.error_plots]:
|
||||
item = plt[r]
|
||||
@ -289,7 +299,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
else:
|
||||
func = self.graphic.removeItem
|
||||
|
||||
for a in self.active:
|
||||
for a in self._active:
|
||||
item = plots[a]
|
||||
if item is not None:
|
||||
func(item)
|
||||
@ -306,12 +316,12 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
return
|
||||
|
||||
if visible:
|
||||
for a in self.active:
|
||||
for a in self._active:
|
||||
item = self.error_plots[a]
|
||||
if (item is not None) and (item not in self.graphic.items()):
|
||||
self.graphic.addItem(item)
|
||||
else:
|
||||
for a in self.active:
|
||||
for a in self._active:
|
||||
item = self.error_plots[a]
|
||||
if (item is not None) and (item in self.graphic.items()):
|
||||
self.graphic.removeItem(item)
|
||||
@ -423,6 +433,9 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
def set_logmode(self, xmode: bool = None, ymode: bool = None):
|
||||
r = self.ranges
|
||||
|
||||
self.plotItem.setXRange(*r[0])
|
||||
self.plotItem.setYRange(*r[1])
|
||||
|
||||
if xmode is None:
|
||||
xmode = self.plotItem.ctrl.logXCheck.isChecked()
|
||||
else:
|
||||
@ -439,6 +452,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
item.logmode[0] = self.log[:]
|
||||
|
||||
self.plotItem.updateLogMode()
|
||||
self.set_range(x=r[0], y=r[1])
|
||||
|
||||
self.plotItem.enableAutoRange()
|
||||
|
||||
@ -481,9 +495,9 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
with errstate(all='ignore'):
|
||||
xy = [log10(val) for val in xy]
|
||||
|
||||
if isnan(xy[1]):
|
||||
if not isfinite(xy[1]):
|
||||
xy = [-1, 1]
|
||||
elif isnan(xy[0]):
|
||||
elif not isfinite(xy[0]):
|
||||
xy[0] = xy[1]-4
|
||||
|
||||
func(xy[0], xy[1], padding=0)
|
||||
@ -669,7 +683,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
'legend': self.legend.isVisible(),
|
||||
'plots': (self.real_button.isChecked(), self.imag_button.isChecked(), self.error_button.isChecked()),
|
||||
'children': self.sets,
|
||||
'active': self.active,
|
||||
'active': self._active,
|
||||
}
|
||||
|
||||
in_legend = []
|
||||
@ -760,8 +774,8 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
if y is not None:
|
||||
self.plotItem.setLabel('left', y, **{'font-size': '10pt', 'color': self._fgcolor.name()})
|
||||
|
||||
@QtCore.pyqtSlot(bool, name='on_bwbutton_toggled')
|
||||
def change_background(self, _):
|
||||
temp = self._fgcolor, self._bgcolor
|
||||
self.set_color(foreground=self._prev_colors[0], background=self._prev_colors[1])
|
||||
self._prev_colors = temp
|
||||
|
||||
|
@ -4,6 +4,7 @@ from nmreval.lib.lines import LineStyle
|
||||
from nmreval.lib.symbols import SymbolStyle
|
||||
from nmreval.data.points import Points
|
||||
from nmreval.io.graceeditor import GraceEditor
|
||||
from nmreval.utils.text import convert
|
||||
|
||||
from ..Qt import QtCore, QtWidgets, QtGui
|
||||
from .._py.gracereader import Ui_Dialog
|
||||
@ -55,7 +56,7 @@ class QGraceReader(QtWidgets.QDialog, Ui_Dialog):
|
||||
if ds is None:
|
||||
continue
|
||||
|
||||
item_2 = QtWidgets.QTreeWidgetItem([f'Set {gset.idx} (Label: {gset.get_property("legend")}, '
|
||||
item_2 = QtWidgets.QTreeWidgetItem([f'Set {gset.idx} (Label: {convert(gset.get_property("legend"), old="agr", new="str")}, '
|
||||
f'shape: {ds.shape})'])
|
||||
item_2.setCheckState(0, QtCore.Qt.Checked)
|
||||
item_2.setData(0, QtCore.Qt.UserRole, (graphs.idx, gset.idx))
|
||||
@ -94,6 +95,7 @@ class QGraceReader(QtWidgets.QDialog, Ui_Dialog):
|
||||
label = ''
|
||||
else:
|
||||
label = label.replace('"', '')
|
||||
label = convert(label, old='agr', new='str')
|
||||
sd = s.data
|
||||
sd = np.atleast_2d(sd)
|
||||
if s.type == 'xydy':
|
||||
|
@ -237,7 +237,7 @@ class CodeEditor(QtWidgets.QPlainTextEdit):
|
||||
if block.isVisible() and (bottom >= evt.rect().top()):
|
||||
number = str(block_number + 1)
|
||||
painter.setPen(QtCore.Qt.black)
|
||||
painter.drawText(0, top, self.current_linenumber.width() - 3, height,
|
||||
painter.drawText(0, int(top), self.current_linenumber.width() - 3, height,
|
||||
QtCore.Qt.AlignRight, number)
|
||||
|
||||
block = block.next()
|
||||
|
@ -52,19 +52,24 @@ class QDelayWidget(QtWidgets.QWidget):
|
||||
|
||||
class LineEdit(QtWidgets.QLineEdit):
|
||||
values_requested = QtCore.pyqtSignal()
|
||||
replace_single_values = QtCore.pyqtSignal()
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent=parent)
|
||||
|
||||
def contextMenuEvent(self, evt):
|
||||
menu = self.createStandardContextMenu()
|
||||
request_action = menu.addAction('Use value of sets')
|
||||
request_action = menu.addAction('Use numeric value of sets')
|
||||
set_value_action = menu.addAction('Replace single set values')
|
||||
|
||||
action = menu.exec(evt.globalPos())
|
||||
|
||||
if action == request_action:
|
||||
self.values_requested.emit()
|
||||
|
||||
elif action == set_value_action:
|
||||
self.replace_single_values.emit()
|
||||
|
||||
|
||||
class LineEditPost(QtWidgets.QLineEdit):
|
||||
values_requested = QtCore.pyqtSignal()
|
||||
|
53
src/gui_qt/lib/graph_items.py
Normal file
53
src/gui_qt/lib/graph_items.py
Normal file
@ -0,0 +1,53 @@
|
||||
from numpy import log10, arange, floor, ceil
|
||||
from pyqtgraph import PlotWidget, PlotItem
|
||||
|
||||
|
||||
__all__ = ['NMRPlotWidget', 'logTickValues']
|
||||
|
||||
|
||||
class NMRPlotWidget(PlotWidget):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
for orient in ['top', 'bottom', 'left', 'right']:
|
||||
# BAD HACK!!! but seems to work, see function for explanation
|
||||
self.plotItem.getAxis(orient).logTickValues = logTickValues
|
||||
|
||||
|
||||
class NMRPlotItem(PlotItem):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
for orient in ['top', 'bottom', 'left', 'right']:
|
||||
self.plotItem.getAxis(orient).logTickValues = logTickValues
|
||||
|
||||
|
||||
def logTickValues(minVal, maxVal, size, stdTicks):
|
||||
# TODO FIND A BETTER SOLUTION!!!
|
||||
# Sometimes minVal and maxVal are not log-scaled values and the loop from v1 to v2 is humongous,
|
||||
# The minor list then fills the RAM completely and freezes everything
|
||||
# Until there is a better solution, we overwrite this function for every AxesItem
|
||||
# and do not draw minor ticks at all if there are too many
|
||||
|
||||
# start with the tick spacing given by tickValues().
|
||||
# Any level whose spacing is < 1 needs to be converted to log scale
|
||||
ticks = []
|
||||
for (spacing, t) in stdTicks:
|
||||
if spacing >= 1.0:
|
||||
ticks.append((spacing, t))
|
||||
|
||||
if len(ticks) < 3:
|
||||
v1 = int(floor(minVal))
|
||||
v2 = int(ceil(maxVal))
|
||||
# major = list(range(v1+1, v2))
|
||||
minor = []
|
||||
|
||||
if v2 - v1 < 400:
|
||||
for v in range(v1, v2):
|
||||
minor.extend(v + log10(arange(1, 10)))
|
||||
minor = [x for x in minor if minVal < x < maxVal]
|
||||
ticks.append((None, minor))
|
||||
return ticks
|
||||
|
@ -375,9 +375,6 @@ class PlotItem(PlotDataItem):
|
||||
class RegionItem(LinearRegionItem):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.mode = kwargs.pop('mode', 'half')
|
||||
|
||||
print(args, kwargs)
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.logmode = False
|
||||
@ -475,11 +472,18 @@ class LegendItemBlock(LegendItem):
|
||||
def mouseDragEvent(self, ev):
|
||||
if ev.button() == QtCore.Qt.LeftButton:
|
||||
ev.accept()
|
||||
|
||||
dpos = ev.pos() - ev.lastPos()
|
||||
|
||||
upper_left = self.pos()
|
||||
lower_right = self.pos()
|
||||
lower_right.setX(lower_right.x() + self.width())
|
||||
lower_right.setY(lower_right.y() + self.height())
|
||||
|
||||
vb_rect = self.parentItem().rect()
|
||||
pos = self.pos()
|
||||
# upper left corner and a point a little more to the bottom right must be inside
|
||||
if vb_rect.contains(pos+dpos) and vb_rect.contains(pos+dpos+QtCore.QPointF(20., 20.)):
|
||||
self.autoAnchor(pos + dpos)
|
||||
|
||||
# upper left and lower right corner must be inside viewbox
|
||||
if vb_rect.contains(upper_left + dpos) and vb_rect.contains(lower_right + dpos):
|
||||
self.autoAnchor(upper_left + dpos)
|
||||
else:
|
||||
self.autoAnchor(pos)
|
||||
self.autoAnchor(upper_left)
|
||||
|
@ -28,4 +28,17 @@ class TreeWidget(QtWidgets.QTreeWidget):
|
||||
continue
|
||||
it.setCheckState(0, QtCore.Qt.Unchecked if it.checkState(0) == QtCore.Qt.Checked else QtCore.Qt.Checked)
|
||||
else:
|
||||
super().keyPressEvent(evt)
|
||||
super().keyPressEvent(evt)
|
||||
|
||||
|
||||
class TableWidget(QtWidgets.QTableWidget):
|
||||
def keyPressEvent(self, evt: QtGui.QKeyEvent):
|
||||
if evt.key() == QtCore.Qt.Key.Key_Space:
|
||||
for idx in self.selectedIndexes():
|
||||
item = self.itemFromIndex(idx)
|
||||
cs = item.checkState()
|
||||
item.setCheckState(QtCore.Qt.CheckState.Unchecked if cs == QtCore.Qt.CheckState.Checked
|
||||
else QtCore.Qt.CheckState.Checked)
|
||||
else:
|
||||
super().keyPressEvent(evt)
|
||||
|
||||
|
@ -211,7 +211,6 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
|
||||
self.ptsselectwidget.points_selected.connect(self.management.extract_points)
|
||||
|
||||
self.t1tauwidget.newData.connect(self.management.add_new_data)
|
||||
self.t1tauwidget.newData.connect(self.management.add_new_data)
|
||||
|
||||
self.editsignalwidget.do_something.connect(self.management.apply)
|
||||
@ -917,10 +916,12 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
self.action_odr_fit: 'odr'
|
||||
}[self.ac_group.checkedAction()]
|
||||
|
||||
self.fit_dialog.fit_button.setEnabled(False)
|
||||
self.management.start_fit(parameter, links, fit_options)
|
||||
self.status.setText('Fit running...'.format(self.management.fitter.step))
|
||||
self.fit_timer.start(500)
|
||||
fit_is_ready = self.management.prepare_fit(parameter, links, fit_options)
|
||||
if fit_is_ready:
|
||||
self.management.start_fit()
|
||||
self.fit_dialog.fit_button.setEnabled(False)
|
||||
self.status.setText('Fit running...'.format(self.management.fitter.step))
|
||||
self.fit_timer.start(500)
|
||||
|
||||
@QtCore.pyqtSlot(dict, int, bool)
|
||||
def show_fit_preview(self, funcs: dict, num: int, show: bool):
|
||||
|
@ -58,11 +58,18 @@ class GraphDict(OrderedDict):
|
||||
def list(self):
|
||||
return [(k, v.title) for k, v in self.items()]
|
||||
|
||||
def active(self, key: str):
|
||||
if key:
|
||||
return [(self._data[i].id, self._data[i].name) for i in self[key]]
|
||||
else:
|
||||
def active(self, key: str, return_val: str = 'both'):
|
||||
if not key:
|
||||
return []
|
||||
else:
|
||||
if return_val == 'both':
|
||||
return [(self._data[i].id, self._data[i].name) for i in self[key]]
|
||||
elif return_val == 'id':
|
||||
return [self._data[i].id for i in self[key]]
|
||||
elif return_val == 'name':
|
||||
return [self._data[i].name for i in self[key]]
|
||||
else:
|
||||
raise ValueError(f'return_val got wrong value {return_val!r}')
|
||||
|
||||
def current_sets(self, key: str):
|
||||
if key:
|
||||
@ -148,6 +155,10 @@ class UpperManagement(QtCore.QObject):
|
||||
def active_sets(self):
|
||||
return self.graphs.active(self.current_graph)
|
||||
|
||||
@property
|
||||
def active_id(self):
|
||||
return self.graphs.active(self.current_graph, return_val='id')
|
||||
|
||||
def get_attributes(self, graph_id: str, attr: str) -> dict[str, Any]:
|
||||
return {self.data[i].id: getattr(self.data[i], attr) for i in self.graphs[graph_id].sets}
|
||||
|
||||
@ -413,9 +424,9 @@ class UpperManagement(QtCore.QObject):
|
||||
for d in self.data.values():
|
||||
d.mask = np.ones_like(d.mask, dtype=bool)
|
||||
|
||||
def start_fit(self, parameter: dict, links: list, fit_options: dict):
|
||||
def prepare_fit(self, parameter: dict, links: list, fit_options: dict) -> bool:
|
||||
if self._fit_active:
|
||||
return
|
||||
return False
|
||||
|
||||
self.__fit_options = (parameter, links, fit_options)
|
||||
|
||||
@ -423,60 +434,84 @@ class UpperManagement(QtCore.QObject):
|
||||
models = {}
|
||||
fit_limits = fit_options['limits']
|
||||
fit_mode = fit_options['fit_mode']
|
||||
we = fit_options['we']
|
||||
we_option = fit_options['we']
|
||||
|
||||
for model_id, model_p in parameter.items():
|
||||
m = Model(model_p['func'])
|
||||
models[model_id] = m
|
||||
self.fitter.fitmethod = fit_mode
|
||||
|
||||
m_complex = model_p['complex']
|
||||
# all-encompassing error catch
|
||||
try:
|
||||
for model_id, model_p in parameter.items():
|
||||
m = Model(model_p['func'])
|
||||
models[model_id] = m
|
||||
|
||||
for set_id, set_params in model_p['parameter'].items():
|
||||
data_i = self.data[set_id]
|
||||
if we.lower() == 'deltay':
|
||||
we = data_i.y_err**2
|
||||
m_complex = model_p['complex']
|
||||
|
||||
if m_complex is None or m_complex == 1:
|
||||
_y = data_i.y.real
|
||||
elif m_complex == 2 and np.iscomplexobj(data_i.y):
|
||||
_y = data_i.y.imag
|
||||
else:
|
||||
_y = data_i.y
|
||||
# sets are not in active order but in order they first appeared in fit dialog
|
||||
# iterate over order of set id in active order and access parameter inside loop
|
||||
# instead of directly looping
|
||||
list_ids = list(model_p['parameter'].keys())
|
||||
set_order = [self.active_id.index(i) for i in list_ids]
|
||||
for pos in set_order:
|
||||
set_id = list_ids[pos]
|
||||
|
||||
_x = data_i.x
|
||||
data_i = self.data[set_id]
|
||||
set_params = model_p['parameter'][set_id]
|
||||
|
||||
if fit_limits == 'none':
|
||||
inside = slice(None)
|
||||
elif fit_limits == 'x':
|
||||
x_lim, _ = self.graphs[self.current_graph].ranges
|
||||
inside = np.where((_x >= x_lim[0]) & (_x <= x_lim[1]))
|
||||
else:
|
||||
inside = np.where((_x >= fit_limits[0]) & (_x <= fit_limits[1]))
|
||||
if we_option.lower() == 'deltay':
|
||||
we = data_i.y_err**2
|
||||
else:
|
||||
we = we_option
|
||||
|
||||
if isinstance(we, str):
|
||||
d = fit_d.Data(_x[inside], _y[inside], we=we, idx=set_id)
|
||||
else:
|
||||
d = fit_d.Data(_x[inside], _y[inside], we=we[inside], idx=set_id)
|
||||
if m_complex is None or m_complex == 1:
|
||||
_y = data_i.y.real
|
||||
elif m_complex == 2 and np.iscomplexobj(data_i.y):
|
||||
_y = data_i.y.imag
|
||||
else:
|
||||
_y = data_i.y
|
||||
|
||||
d.set_model(m)
|
||||
d.set_parameter(set_params[0], var=model_p['var'],
|
||||
lb=model_p['lb'], ub=model_p['ub'],
|
||||
fun_kwargs=set_params[1])
|
||||
_x = data_i.x
|
||||
|
||||
self.fitter.add_data(d)
|
||||
if fit_limits == 'none':
|
||||
inside = slice(None)
|
||||
elif fit_limits == 'x':
|
||||
x_lim, _ = self.graphs[self.current_graph].ranges
|
||||
inside = np.where((_x >= x_lim[0]) & (_x <= x_lim[1]))
|
||||
else:
|
||||
inside = np.where((_x >= fit_limits[0]) & (_x <= fit_limits[1]))
|
||||
|
||||
model_globs = model_p['glob']
|
||||
if model_globs:
|
||||
for parameter_args in zip(*model_globs.values()):
|
||||
m.set_global_parameter(**{k: v for k, v in zip(model_globs.keys(), parameter_args)})
|
||||
# m.set_global_parameter(**model_p['glob'])
|
||||
if isinstance(we, str):
|
||||
d = fit_d.Data(_x[inside], _y[inside], we=we, idx=set_id)
|
||||
else:
|
||||
d = fit_d.Data(_x[inside], _y[inside], we=we[inside], idx=set_id)
|
||||
|
||||
for links_i in links:
|
||||
self.fitter.set_link_parameter((models[links_i[0]], links_i[1]),
|
||||
(models[links_i[2]], links_i[3]))
|
||||
d.set_model(m)
|
||||
d.set_parameter(set_params[0], var=model_p['var'],
|
||||
lb=model_p['lb'], ub=model_p['ub'],
|
||||
fun_kwargs=set_params[1])
|
||||
|
||||
self.fitter.add_data(d)
|
||||
|
||||
model_globs = model_p['glob']
|
||||
if model_globs:
|
||||
for parameter_args in zip(*model_globs.values()):
|
||||
m.set_global_parameter(**{k: v for k, v in zip(model_globs.keys(), parameter_args)})
|
||||
# m.set_global_parameter(**model_p['glob'])
|
||||
|
||||
for links_i in links:
|
||||
self.fitter.set_link_parameter((models[links_i[0]], links_i[1]),
|
||||
(models[links_i[2]], links_i[3]))
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logger.error('Fit preparation failed', *e.args)
|
||||
QtWidgets.QMessageBox.warning(QtWidgets.QWidget(),
|
||||
'Fit prep failed',
|
||||
f'Fit preparation failed with message\n{e.args}')
|
||||
return False
|
||||
|
||||
def start_fit(self):
|
||||
with busy_cursor():
|
||||
self.fit_worker = FitWorker(self.fitter, fit_mode)
|
||||
self.fit_worker = FitWorker(self.fitter)
|
||||
self.fit_thread = QtCore.QThread()
|
||||
self.fit_worker.moveToThread(self.fit_thread)
|
||||
|
||||
@ -512,7 +547,8 @@ class UpperManagement(QtCore.QObject):
|
||||
for set_id, set_parameter in parameter.items():
|
||||
new_values = [v.value for v in res[set_id].parameter.values()]
|
||||
parameter[set_id] = (new_values, set_parameter[1])
|
||||
self.start_fit(*self.__fit_options)
|
||||
if self.prepare_fit(*self.__fit_options):
|
||||
self.start_fit()
|
||||
|
||||
def make_fits(self, res: dict, opts: list, param_graph: str, show_fit: bool, parts: bool, extrapolate: list) -> None:
|
||||
"""
|
||||
@ -637,7 +673,7 @@ class UpperManagement(QtCore.QObject):
|
||||
|
||||
def save_fit_parameter(self, fname: str | pathlib.Path, fit_sets: list[str] = None):
|
||||
if fit_sets is None:
|
||||
fit_sets = [s for (s, _) in self.active_sets]
|
||||
fit_sets = [s for s in self.active_id]
|
||||
|
||||
for set_id in fit_sets:
|
||||
data = self.data[set_id]
|
||||
@ -843,13 +879,10 @@ class UpperManagement(QtCore.QObject):
|
||||
d_k = self.data[k]
|
||||
|
||||
if copy_data is None:
|
||||
d_k.x = d_k.x*v[1][0] + v[0][0]
|
||||
d_k.y = d_k.y*v[1][1] + v[0][1]
|
||||
d_k.shift_scale(v[0], v[1])
|
||||
else:
|
||||
new_data = d_k.copy(full=True)
|
||||
new_data.update({'shift': v[0], 'scale': v[1]})
|
||||
new_data.data.x = new_data.x*v[1][0] + v[0][0]
|
||||
new_data.y = new_data.y*v[1][1] + v[0][1]
|
||||
new_data.shift_scale(v[0], v[1])
|
||||
|
||||
sid = self.add(new_data)
|
||||
sid_list.append(sid)
|
||||
@ -1009,7 +1042,7 @@ class UpperManagement(QtCore.QObject):
|
||||
def show_statistics(self, mode):
|
||||
x, y, = [], []
|
||||
|
||||
for i, _ in self.active_sets:
|
||||
for i in self.active_id:
|
||||
_temp = self.data[i]
|
||||
try:
|
||||
x.append(float(_temp.name))
|
||||
@ -1020,7 +1053,7 @@ class UpperManagement(QtCore.QObject):
|
||||
@QtCore.pyqtSlot()
|
||||
def calc_magn(self):
|
||||
new_id = []
|
||||
for k, _ in self.active_sets:
|
||||
for k in self.active_id:
|
||||
dataset = self.data[k]
|
||||
if isinstance(dataset, SignalContainer):
|
||||
new_value = dataset.copy(full=True)
|
||||
@ -1032,7 +1065,7 @@ class UpperManagement(QtCore.QObject):
|
||||
@QtCore.pyqtSlot()
|
||||
def center(self):
|
||||
new_id = []
|
||||
for k, _ in self.active_sets:
|
||||
for k in self.active_id:
|
||||
new_value = self.data[k].copy(full=True)
|
||||
new_value.x -= new_value.x[np.argmax(new_value.y.real)]
|
||||
new_id.append(self.add(new_value))
|
||||
@ -1071,7 +1104,7 @@ class UpperManagement(QtCore.QObject):
|
||||
def bds_deriv(self):
|
||||
new_sets = []
|
||||
|
||||
for (set_id, _) in self.active_sets:
|
||||
for set_id in self.active_id:
|
||||
data_i = self.data[set_id]
|
||||
diff = data_i.data.diff(log=True)
|
||||
new_data = Points(x=diff.x, y=-np.pi/2*diff.y.real)
|
||||
@ -1098,7 +1131,7 @@ class UpperManagement(QtCore.QObject):
|
||||
self.newData.emit(new_sets, kwargs['graph'])
|
||||
|
||||
def skip_points(self, offset: int, step: int, invert: bool = False, copy: bool = False):
|
||||
for k, _ in self.active_sets:
|
||||
for k in self.active_id:
|
||||
src = self.data[k]
|
||||
if invert:
|
||||
mask = np.mod(np.arange(offset, src.x.size+offset), step) != 0
|
||||
@ -1253,16 +1286,15 @@ class UpperManagement(QtCore.QObject):
|
||||
class FitWorker(QtCore.QObject):
|
||||
finished = QtCore.pyqtSignal(list, bool)
|
||||
|
||||
def __init__(self, fitter, mode):
|
||||
def __init__(self, fitter):
|
||||
super().__init__()
|
||||
|
||||
self.fitter = fitter
|
||||
self.mode = mode
|
||||
|
||||
@QtCore.pyqtSlot()
|
||||
def run(self):
|
||||
try:
|
||||
res = self.fitter.run(mode=self.mode)
|
||||
res = self.fitter.run()
|
||||
success = True
|
||||
except Exception as e:
|
||||
res = [e]
|
||||
|
@ -19,7 +19,7 @@ class QRelaxCalc(QtWidgets.QDialog, Ui_Dialog):
|
||||
|
||||
self.graphs = {}
|
||||
|
||||
self.specdens = [ColeCole, ColeDavidson, HavriliakNegami, KWW]
|
||||
self.specdens = [ColeCole, ColeDavidson, HavriliakNegami, KWW, LogGaussian]
|
||||
self.coupling = [Quadrupolar, HomoDipolar, Czjzek]
|
||||
self.tau_parameter = []
|
||||
|
||||
@ -199,3 +199,9 @@ class QRelaxCalc(QtWidgets.QDialog, Ui_Dialog):
|
||||
def accept(self):
|
||||
self.calc_relaxation()
|
||||
super().accept()
|
||||
|
||||
@QtCore.pyqtSlot(QtWidgets.QAbstractButton)
|
||||
def on_buttonBox_clicked(self, button: QtWidgets.QAbstractButton):
|
||||
role = self.buttonBox.buttonRole(button)
|
||||
if role == self.buttonBox.ApplyRole:
|
||||
self.calc_relaxation()
|
||||
|
@ -61,6 +61,8 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
|
||||
self.freq_combox.currentIndexChanged.connect(lambda x: self.update_model())
|
||||
self.freq_spinbox.valueChanged.connect(lambda x: self.update_model())
|
||||
|
||||
self.checkBox_interpol.setVisible(False)
|
||||
|
||||
self.update_specdens(0)
|
||||
self.update_coupling(0)
|
||||
|
||||
|
Reference in New Issue
Block a user