194-fitrange (#219)
All checks were successful
Build AppImage / Explore-Gitea-Actions (push) Successful in 1m35s

keyboard-setting of custom fit range; closes #194; helps for #32
This commit is contained in:
Dominik Demuth 2024-01-18 18:25:07 +00:00
parent 06491ff413
commit 465fb0c09a
12 changed files with 368 additions and 274 deletions

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'resources/_ui/basewindow.ui' # Form implementation generated from reading ui file 'src/resources/_ui/basewindow.ui'
# #
# Created by: PyQt5 UI code generator 5.15.10 # Created by: PyQt5 UI code generator 5.15.10
# #
@ -153,15 +153,6 @@ class Ui_BaseWindow(object):
self.toolBar_nmr.setIconSize(QtCore.QSize(24, 24)) self.toolBar_nmr.setIconSize(QtCore.QSize(24, 24))
self.toolBar_nmr.setObjectName("toolBar_nmr") self.toolBar_nmr.setObjectName("toolBar_nmr")
BaseWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar_nmr) BaseWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar_nmr)
self.toolBar_fit = QtWidgets.QToolBar(BaseWindow)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.toolBar_fit.sizePolicy().hasHeightForWidth())
self.toolBar_fit.setSizePolicy(sizePolicy)
self.toolBar_fit.setIconSize(QtCore.QSize(24, 24))
self.toolBar_fit.setObjectName("toolBar_fit")
BaseWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar_fit)
self.toolBar_spectrum = QtWidgets.QToolBar(BaseWindow) self.toolBar_spectrum = QtWidgets.QToolBar(BaseWindow)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
@ -496,7 +487,6 @@ class Ui_BaseWindow(object):
self.toolbar_edit.addAction(self.actionShift) self.toolbar_edit.addAction(self.actionShift)
self.toolBar_nmr.addAction(self.t1action) self.toolBar_nmr.addAction(self.t1action)
self.toolBar_nmr.addAction(self.actionCalculateT1) self.toolBar_nmr.addAction(self.actionCalculateT1)
self.toolBar_fit.addAction(self.action_FitWidget)
self.toolBar_spectrum.addAction(self.action_edit) self.toolBar_spectrum.addAction(self.action_edit)
self.toolBar_spectrum.addAction(self.actionPick_position) self.toolBar_spectrum.addAction(self.actionPick_position)
self.toolBar_data.addAction(self.actionConcatenate_sets) self.toolBar_data.addAction(self.actionConcatenate_sets)
@ -537,7 +527,6 @@ class Ui_BaseWindow(object):
self.toolBar.setWindowTitle(_translate("BaseWindow", "Main")) self.toolBar.setWindowTitle(_translate("BaseWindow", "Main"))
self.toolbar_edit.setWindowTitle(_translate("BaseWindow", "Math")) self.toolbar_edit.setWindowTitle(_translate("BaseWindow", "Math"))
self.toolBar_nmr.setWindowTitle(_translate("BaseWindow", "NMR")) self.toolBar_nmr.setWindowTitle(_translate("BaseWindow", "NMR"))
self.toolBar_fit.setWindowTitle(_translate("BaseWindow", "Fit"))
self.toolBar_spectrum.setWindowTitle(_translate("BaseWindow", "Spectrum")) self.toolBar_spectrum.setWindowTitle(_translate("BaseWindow", "Spectrum"))
self.toolBar_data.setWindowTitle(_translate("BaseWindow", "Data")) self.toolBar_data.setWindowTitle(_translate("BaseWindow", "Data"))
self.action_close.setText(_translate("BaseWindow", "&Quit")) self.action_close.setText(_translate("BaseWindow", "&Quit"))

View File

@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'src/resources/_ui/fitmodelwidget.ui' # Form implementation generated from reading ui file 'src/resources/_ui/fitmodelwidget.ui'
# #
# Created by: PyQt5 UI code generator 5.15.9 # Created by: PyQt5 UI code generator 5.15.10
# #
# WARNING: Any manual changes made to this file will be lost when pyuic5 is # 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. # run again. Do not edit this file unless you know what you are doing.
@ -42,6 +42,7 @@ class Ui_FitParameter(object):
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.parameter_line.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(self.parameter_line.sizePolicy().hasHeightForWidth())
self.parameter_line.setSizePolicy(sizePolicy) self.parameter_line.setSizePolicy(sizePolicy)
self.parameter_line.setMaximumSize(QtCore.QSize(160, 16777215))
self.parameter_line.setText("") self.parameter_line.setText("")
self.parameter_line.setObjectName("parameter_line") self.parameter_line.setObjectName("parameter_line")
self.horizontalLayout_2.addWidget(self.parameter_line) self.horizontalLayout_2.addWidget(self.parameter_line)
@ -51,6 +52,9 @@ class Ui_FitParameter(object):
self.global_checkbox = QtWidgets.QCheckBox(FitParameter) self.global_checkbox = QtWidgets.QCheckBox(FitParameter)
self.global_checkbox.setObjectName("global_checkbox") self.global_checkbox.setObjectName("global_checkbox")
self.horizontalLayout_2.addWidget(self.global_checkbox) self.horizontalLayout_2.addWidget(self.global_checkbox)
self.reset_button = QtWidgets.QPushButton(FitParameter)
self.reset_button.setObjectName("reset_button")
self.horizontalLayout_2.addWidget(self.reset_button)
self.verticalLayout.addLayout(self.horizontalLayout_2) self.verticalLayout.addLayout(self.horizontalLayout_2)
self.frame = QtWidgets.QFrame(FitParameter) self.frame = QtWidgets.QFrame(FitParameter)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
@ -82,6 +86,7 @@ class Ui_FitParameter(object):
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.lineEdit.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(self.lineEdit.sizePolicy().hasHeightForWidth())
self.lineEdit.setSizePolicy(sizePolicy) self.lineEdit.setSizePolicy(sizePolicy)
self.lineEdit.setMaximumSize(QtCore.QSize(100, 16777215))
self.lineEdit.setText("") self.lineEdit.setText("")
self.lineEdit.setFrame(True) self.lineEdit.setFrame(True)
self.lineEdit.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) self.lineEdit.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter)
@ -100,6 +105,7 @@ class Ui_FitParameter(object):
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.lineEdit_2.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(self.lineEdit_2.sizePolicy().hasHeightForWidth())
self.lineEdit_2.setSizePolicy(sizePolicy) self.lineEdit_2.setSizePolicy(sizePolicy)
self.lineEdit_2.setMaximumSize(QtCore.QSize(100, 16777215))
self.lineEdit_2.setText("") self.lineEdit_2.setText("")
self.lineEdit_2.setFrame(True) self.lineEdit_2.setFrame(True)
self.lineEdit_2.setObjectName("lineEdit_2") self.lineEdit_2.setObjectName("lineEdit_2")
@ -122,6 +128,7 @@ class Ui_FitParameter(object):
self.parameter_line.setPlaceholderText(_translate("FitParameter", "0")) self.parameter_line.setPlaceholderText(_translate("FitParameter", "0"))
self.fixed_check.setText(_translate("FitParameter", "Fix")) self.fixed_check.setText(_translate("FitParameter", "Fix"))
self.global_checkbox.setText(_translate("FitParameter", "Global")) self.global_checkbox.setText(_translate("FitParameter", "Global"))
self.reset_button.setText(_translate("FitParameter", "Use global"))
self.lineEdit.setToolTip(_translate("FitParameter", "<html><head/><body><p>Lower bound. Same bound is used for all data. Leave empty for no boundary condition.</p></body></html>")) self.lineEdit.setToolTip(_translate("FitParameter", "<html><head/><body><p>Lower bound. Same bound is used for all data. Leave empty for no boundary condition.</p></body></html>"))
self.label_3.setText(_translate("FitParameter", "Textlabel")) self.label_3.setText(_translate("FitParameter", "Textlabel"))
self.lineEdit_2.setToolTip(_translate("FitParameter", "<html><head/><body><p>Upper bound. Same bound is used for all data. Leave empty for no boundary condition.</p></body></html>")) self.lineEdit_2.setToolTip(_translate("FitParameter", "<html><head/><body><p>Upper bound. Same bound is used for all data. Leave empty for no boundary condition.</p></body></html>"))

View File

@ -1,138 +1,11 @@
from __future__ import annotations from __future__ import annotations
from nmreval.utils.text import convert
from ..Qt import QtCore, QtWidgets, QtGui from ..Qt import QtCore, QtWidgets, QtGui
from .._py.fitmodelwidget import Ui_FitParameter
from .._py.save_fitmodel_dialog import Ui_SaveDialog from .._py.save_fitmodel_dialog import Ui_SaveDialog
from ..lib.iconloading import get_icon from ..lib.iconloading import get_icon
from ..lib.tables import TableWidget from ..lib.tables import TableWidget
class FitModelWidget(QtWidgets.QWidget, Ui_FitParameter):
"""
Widget to show a global parameter
"""
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)
self.setupUi(self)
self.name = label
self.parametername.setText(convert(label) + ' ')
self.parameter_line.setText('1')
self.parameter_line.setMaximumWidth(160)
self.lineEdit.setMaximumWidth(100)
self.lineEdit_2.setMaximumWidth(100)
self.label_3.setText(f'&lt; {convert(label)} &lt;')
self.checkBox.stateChanged.connect(self.enableBounds)
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)
if fixed:
self.fixed_check.hide()
self.parameter_pos = None
self.func_idx = None
self._linetext = '1'
self.menu = QtWidgets.QMenu(self)
def set_parameter_string(self, p: str):
self.parameter_line.setText(p)
self.parameter_line.setToolTip(p)
def set_bounds(self, lb: float, ub: float, cbox: bool = True):
self.checkBox.setCheckState(QtCore.Qt.Checked if cbox else QtCore.Qt.Unchecked)
for val, bds_line in [(lb, self.lineEdit), (ub, self.lineEdit_2)]:
if val is not None:
bds_line.setText(str(val))
else:
bds_line.setText('')
def enableBounds(self, value: int):
self.lineEdit.setEnabled(value == 2)
self.lineEdit_2.setEnabled(value == 2)
def set_parameter(self, p: float | None, bds: tuple[float, float, bool] = None,
fixed: bool = None, glob: bool = None):
ptext = f'{p:.4g}'
self.set_parameter_string(ptext)
if bds is not None:
self.set_bounds(*bds)
if fixed is not None:
self.fixed_check.setCheckState(QtCore.Qt.CheckState.Unchecked if fixed else QtCore.Qt.CheckState.Checked)
if glob is not None:
self.global_checkbox.setCheckState(QtCore.Qt.CheckState.Checked if glob else QtCore.Qt.CheckState.Unchecked)
def get_parameter(self):
try:
p = float(self.parameter_line.text().replace(',', '.'))
except ValueError:
p = self.parameter_line.text().replace(',', '.')
if self.checkBox.isChecked():
lb_text = self.lineEdit.text()
lb = None
if lb_text:
try:
lb = float(lb_text.replace(',', '.'))
except ValueError:
lb = lb_text
ub_text = self.lineEdit_2.text()
rb = None
if ub_text:
try:
rb = float(ub_text.replace(',', '.'))
except ValueError:
rb = ub_text
else:
lb = rb = None
bounds = (lb, rb)
return p, bounds, not self.fixed_check.isChecked(), self.global_checkbox.isChecked()
@QtCore.pyqtSlot(bool)
def set_fixed(self, state: bool):
# self.global_checkbox.setVisible(not state)
self.frame.setVisible(not state)
@QtCore.pyqtSlot()
def update_parameter(self):
new_value = self.parameter_line.text()
if not new_value:
self.parameter_line.setText('1')
try:
float(new_value)
is_text = False
except ValueError:
is_text = True
self.global_checkbox.setCheckState(False)
self.set_fixed(is_text or self.fixed_check.isChecked())
class QSaveModelDialog(QtWidgets.QDialog, Ui_SaveDialog): class QSaveModelDialog(QtWidgets.QDialog, Ui_SaveDialog):
def __init__(self, types=None, parent=None): def __init__(self, types=None, parent=None):
super().__init__(parent=parent) super().__init__(parent=parent)
@ -172,30 +45,37 @@ class FitModelTree(QtWidgets.QTreeWidget):
treeChanged = QtCore.pyqtSignal() treeChanged = QtCore.pyqtSignal()
itemRemoved = QtCore.pyqtSignal(int) itemRemoved = QtCore.pyqtSignal(int)
counterRole = QtCore.Qt.UserRole + 1 counterRole = QtCore.Qt.ItemDataRole.UserRole + 1
operatorRole = QtCore.Qt.UserRole + 2 operatorRole = QtCore.Qt.ItemDataRole.UserRole + 2
def __init__(self, parent=None): def __init__(self, parent=None):
super().__init__(parent=parent) super().__init__(parent=parent)
self.setHeaderHidden(True) self.setHeaderHidden(True)
self.setDragEnabled(True) self.setDragEnabled(True)
self.setDragDropMode(QtWidgets.QTreeWidget.InternalMove) self.setDragDropMode(QtWidgets.QTreeWidget.InternalMove)
self.setDefaultDropAction(QtCore.Qt.MoveAction) self.setDefaultDropAction(QtCore.Qt.DropAction.MoveAction)
self.itemSelectionChanged.connect(lambda: self.treeChanged.emit()) self.itemSelectionChanged.connect(lambda: self.treeChanged.emit())
def keyPressEvent(self, evt): def keyPressEvent(self, evt):
operators = [QtCore.Qt.Key_Plus, QtCore.Qt.Key_Asterisk, operators = [
QtCore.Qt.Key_Minus, QtCore.Qt.Key_Slash] QtCore.Qt.Key.Key_Plus,
QtCore.Qt.Key.Key_Asterisk,
QtCore.Qt.Key.Key_Minus,
QtCore.Qt.Key.Key_Slash
]
if evt.key() == QtCore.Qt.Key_Delete: if evt.key() == QtCore.Qt.Key.Key_Delete:
for item in self.selectedItems(): for item in self.selectedItems():
self.remove_function(item) self.remove_function(item)
elif evt.key() == QtCore.Qt.Key_Space: elif evt.key() == QtCore.Qt.Key.Key_Space:
for item in self.treeWidget.selectedItems(): for item in self.treeWidget.selectedItems():
item.setCheckState(0, QtCore.Qt.Checked) if item.checkState( cs = item.checkState(0)
0) == QtCore.Qt.Unchecked else item.setCheckState(0, QtCore.Qt.Unchecked) if cs == QtCore.Qt.CheckState.Unchecked:
item.setCheckState(0, QtCore.Qt.CheckState.Checked)
else:
item.setCheckState(0, QtCore.Qt.CheckState.Unchecked)
elif evt.key() in operators: elif evt.key() in operators:
idx = operators.index(evt.key()) idx = operators.index(evt.key())
@ -246,7 +126,7 @@ class FitModelTree(QtWidgets.QTreeWidget):
color = QtGui.QColor(color) color = QtGui.QColor(color)
it = QtWidgets.QTreeWidgetItem() it = QtWidgets.QTreeWidgetItem()
it.setData(0, QtCore.Qt.UserRole, idx) it.setData(0, QtCore.Qt.ItemDataRole.UserRole, idx)
it.setData(0, self.counterRole, cnt) it.setData(0, self.counterRole, cnt)
it.setData(0, self.operatorRole, op) it.setData(0, self.operatorRole, op)
it.setText(0, name) it.setText(0, name)
@ -257,7 +137,7 @@ class FitModelTree(QtWidgets.QTreeWidget):
it.setForeground(0, QtGui.QBrush(color)) it.setForeground(0, QtGui.QBrush(color))
it.setIcon(0, get_icon(self.icons[op])) it.setIcon(0, get_icon(self.icons[op]))
it.setCheckState(0, QtCore.Qt.Checked if active else QtCore.Qt.Unchecked) it.setCheckState(0, QtCore.Qt.CheckState.Checked if active else QtCore.Qt.CheckState.Unchecked)
if parent is None: if parent is None:
self.addTopLevelItem(it) self.addTopLevelItem(it)
@ -277,7 +157,7 @@ class FitModelTree(QtWidgets.QTreeWidget):
def get_selected(self): def get_selected(self):
try: try:
it = self.selectedItems()[0] it = self.selectedItems()[0]
function_nr = it.data(0, QtCore.Qt.UserRole) function_nr = it.data(0, QtCore.Qt.ItemDataRole.UserRole)
idx = it.data(0, self.counterRole) idx = it.data(0, self.counterRole)
except IndexError: except IndexError:
@ -300,10 +180,10 @@ class FitModelTree(QtWidgets.QTreeWidget):
it = parent.child(i) it = parent.child(i)
child = { child = {
'idx': it.data(0, QtCore.Qt.UserRole), 'idx': it.data(0, QtCore.Qt.ItemDataRole.UserRole),
'op': it.data(0, self.operatorRole), 'op': it.data(0, self.operatorRole),
'pos': pos, 'pos': pos,
'active': (it.checkState(0) == QtCore.Qt.Checked), 'active': (it.checkState(0) == QtCore.Qt.CheckState.Checked),
'children': [] 'children': []
} }
@ -371,8 +251,8 @@ class FitTableWidget(TableWidget):
for (sid, name) in set_ids: for (sid, name) in set_ids:
item = QtWidgets.QTableWidgetItem(name) item = QtWidgets.QTableWidgetItem(name)
item.setCheckState(QtCore.Qt.Checked) item.setCheckState(QtCore.Qt.CheckState.Checked)
item.setData(QtCore.Qt.UserRole+1, sid) item.setData(QtCore.Qt.ItemDataRole.UserRole+1, sid)
row = self.rowCount() row = self.rowCount()
self.setRowCount(row+1) self.setRowCount(row+1)
self.setItem(row, 0, item) self.setItem(row, 0, item)
@ -390,15 +270,15 @@ class FitTableWidget(TableWidget):
for i in range(self.rowCount()): for i in range(self.rowCount()):
item = self.item(i, 0) item = self.item(i, 0)
if item.checkState() == QtCore.Qt.Checked: if item.checkState() == QtCore.Qt.CheckState.Checked:
mod = self.cellWidget(i, 1).currentData() mod = self.cellWidget(i, 1).currentData()
if mod is None: if mod is None:
mod = default mod = default
if include_name: if include_name:
arg = (item.data(QtCore.Qt.UserRole+1), item.text()) arg = (item.data(QtCore.Qt.ItemDataRole.UserRole+1), item.text())
else: else:
arg = item.data(QtCore.Qt.UserRole+1) arg = item.data(QtCore.Qt.ItemDataRole.UserRole+1)
if mod not in data: if mod not in data:
data[mod] = [] data[mod] = []
@ -411,8 +291,8 @@ class FitTableWidget(TableWidget):
for i in range(self.rowCount()): for i in range(self.rowCount()):
item = self.item(i, 0) item = self.item(i, 0)
if include_name: if include_name:
ret_val.append((item.data(QtCore.Qt.UserRole+1), item.text())) ret_val.append((item.data(QtCore.Qt.ItemDataRole.UserRole+1), item.text()))
else: else:
ret_val.append(item.data(QtCore.Qt.UserRole+1)) ret_val.append(item.data(QtCore.Qt.ItemDataRole.UserRole+1))
return ret_val return ret_val

View File

@ -1,14 +1,12 @@
from __future__ import annotations from __future__ import annotations
from typing import Optional
from nmreval.fit.parameter import Parameter from nmreval.fit.parameter import Parameter
from nmreval.utils.text import convert from nmreval.utils.text import convert
from ..Qt import QtWidgets, QtCore, QtGui from ..Qt import QtWidgets, QtCore, QtGui
from .._py.fitfuncwidget import Ui_FormFit from .._py.fitfuncwidget import Ui_FormFit
from .._py.fitmodelwidget import Ui_FitParameter
from ..lib.forms import SelectionWidget from ..lib.forms import SelectionWidget
from .fit_forms import FitModelWidget
class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit): class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
@ -30,16 +28,15 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
self.scrollwidget2.setLayout(QtWidgets.QVBoxLayout()) self.scrollwidget2.setLayout(QtWidgets.QVBoxLayout())
def eventFilter(self, src: QtCore.QObject, evt: QtCore.QEvent): def eventFilter(self, src: QtCore.QObject, evt: QtCore.QEvent):
modifiers = QtCore.Qt.KeyboardModifier.ControlModifier | QtCore.Qt.KeyboardModifier.ShiftModifier
if isinstance(evt, QtGui.QKeyEvent): if isinstance(evt, QtGui.QKeyEvent):
if (evt.key() == QtCore.Qt.Key_Right) and \ if (evt.key() == QtCore.Qt.Key.Key_Right) and (evt.modifiers() == modifiers):
(evt.modifiers() == QtCore.Qt.ControlModifier | QtCore.Qt.ShiftModifier):
self.change_single_parameter(src.value, sender=src) self.change_single_parameter(src.value, sender=src)
self.select_next_preview(1) self.select_next_preview(1)
return True return True
elif (evt.key() == QtCore.Qt.Key_Left) and \ elif (evt.key() == QtCore.Qt.Key.Key_Left) and (evt.modifiers() == modifiers):
(evt.modifiers() == QtCore.Qt.ControlModifier | QtCore.Qt.ShiftModifier):
self.change_single_parameter(src.value, sender=src) self.change_single_parameter(src.value, sender=src)
self.select_next_preview(-1) self.select_next_preview(-1)
@ -65,7 +62,7 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
self.glob_values = [1] * len(func.params) self.glob_values = [1] * len(func.params)
for k, v in enumerate(func.params): for k, v in enumerate(func.params):
widgt = FitModelWidget(label=v, parent=self.scrollwidget) widgt = ParameterGlobalWidget(name=v, parent=self.scrollwidget)
widgt.parameter_pos = k widgt.parameter_pos = k
widgt.func_idx = idx widgt.func_idx = idx
try: try:
@ -95,7 +92,7 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
for w1, w2 in zip(self.global_parameter, self.data_parameter): for w1, w2 in zip(self.global_parameter, self.data_parameter):
w1.parametername.setFixedSize(self.max_width) w1.parametername.setFixedSize(self.max_width)
w1.checkBox.setFixedSize(self.max_width) w1.checkBox.setFixedSize(self.max_width)
w2.label.setFixedSize(self.max_width) w2.parametername.setFixedSize(self.max_width)
if hasattr(func, 'choices') and func.choices is not None: if hasattr(func, 'choices') and func.choices is not None:
cbox = func.choices cbox = func.choices
@ -175,7 +172,7 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
# disable single parameter if it is set global, enable if global is unset # disable single parameter if it is set global, enable if global is unset
widget = self.sender() widget = self.sender()
idx = self.global_parameter.index(widget) idx = self.global_parameter.index(widget)
enable = (widget.global_checkbox.checkState() == QtCore.Qt.Unchecked) enable = (widget.global_checkbox.checkState() == QtCore.Qt.CheckState.Unchecked)
self.data_parameter[idx].setEnabled(enable) self.data_parameter[idx].setEnabled(enable)
def select_next_preview(self, direction): def select_next_preview(self, direction):
@ -215,7 +212,7 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
param_general = [] param_general = []
for g in self.global_parameter: for g in self.global_parameter:
if isinstance(g, FitModelWidget): if isinstance(g, ParameterGlobalWidget):
p_i, bds_i, fixed_i, global_i = g.get_parameter() p_i, bds_i, fixed_i, global_i = g.get_parameter()
parameter_i = Parameter(name=g.name, value=p_i, lb=bds_i[0], ub=bds_i[1], var=fixed_i) parameter_i = Parameter(name=g.name, value=p_i, lb=bds_i[0], ub=bds_i[1], var=fixed_i)
param_general.append(parameter_i) param_general.append(parameter_i)
@ -236,7 +233,7 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
p = [] p = []
for i, (p_i, g) in enumerate(zip(parameter, self.global_parameter)): for i, (p_i, g) in enumerate(zip(parameter, self.global_parameter)):
if isinstance(g, FitModelWidget): if isinstance(g, ParameterGlobalWidget):
if (p_i is None) or is_global[i]: if (p_i is None) or is_global[i]:
# set has no oen value # set has no oen value
p.append(param_general[i].copy()) p.append(param_general[i].copy())
@ -303,8 +300,8 @@ class ParameterSingleWidget(QtWidgets.QWidget):
self._init_ui() self._init_ui()
self.name = name self.name = name
self.label.setText(convert(name)) self.parametername.setText(convert(name))
self.label.setToolTip('If this is bold then this parameter is only for this data. ' self.parametername.setToolTip('If this is bold then this parameter is only for this data. '
'Otherwise, the general parameter is used and displayed') 'Otherwise, the general parameter is used and displayed')
# self.value_line.setValidator(QtGui.QDoubleValidator()) # self.value_line.setValidator(QtGui.QDoubleValidator())
@ -316,8 +313,8 @@ class ParameterSingleWidget(QtWidgets.QWidget):
layout.setContentsMargins(2, 2, 2, 2) layout.setContentsMargins(2, 2, 2, 2)
layout.setSpacing(2) layout.setSpacing(2)
self.label = QtWidgets.QLabel(self) self.parametername = QtWidgets.QLabel(self)
layout.addWidget(self.label) layout.addWidget(self.parametername)
layout.addSpacerItem(QtWidgets.QSpacerItem(0, 0, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)) layout.addSpacerItem(QtWidgets.QSpacerItem(0, 0, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum))
@ -347,6 +344,133 @@ class ParameterSingleWidget(QtWidgets.QWidget):
def show_as_local_parameter(self, is_local: bool): def show_as_local_parameter(self, is_local: bool):
if is_local: if is_local:
self.label.setStyleSheet('font-weight: bold;') self.parametername.setStyleSheet('font-weight: bold;')
else: else:
self.label.setStyleSheet('') self.parametername.setStyleSheet('')
class ParameterGlobalWidget(QtWidgets.QWidget, Ui_FitParameter):
"""
Widget to show a global parameter
"""
value_requested = QtCore.pyqtSignal(object)
value_changed = QtCore.pyqtSignal(str)
state_changed = QtCore.pyqtSignal()
replace_single_value = QtCore.pyqtSignal(object)
def __init__(self, name: str = 'Fitparameter', parent=None, fixed: bool = False):
super().__init__(parent)
self.setupUi(self)
self.name = name
self.reset_button.setVisible(False)
self.parametername.setText(convert(name) + ' ')
self.parameter_line.setText('1')
self.parameter_line.setMaximumWidth(160)
self.lineEdit.setMaximumWidth(100)
self.lineEdit_2.setMaximumWidth(100)
self.label_3.setText(f'&lt; {convert(name)} &lt;')
self.checkBox.stateChanged.connect(self.enableBounds)
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)
if fixed:
self.fixed_check.hide()
self.reset_button.setVisible(False)
self.parameter_pos = None
self.func_idx = None
self._linetext = '1'
self.menu = QtWidgets.QMenu(self)
def set_parameter_string(self, p: str):
self.parameter_line.setText(p)
self.parameter_line.setToolTip(p)
def set_bounds(self, lb: float, ub: float, cbox: bool = True):
self.checkBox.setCheckState(QtCore.Qt.CheckState.Checked if cbox else QtCore.Qt.CheckState.Unchecked)
for val, bds_line in [(lb, self.lineEdit), (ub, self.lineEdit_2)]:
if val is not None:
bds_line.setText(str(val))
else:
bds_line.setText('')
def enableBounds(self, value: int):
self.lineEdit.setEnabled(value == 2)
self.lineEdit_2.setEnabled(value == 2)
def set_parameter(self, p: float | None, bds: tuple[float, float, bool] = None,
fixed: bool = None, glob: bool = None):
ptext = f'{p:.4g}'
self.set_parameter_string(ptext)
if bds is not None:
self.set_bounds(*bds)
if fixed is not None:
self.fixed_check.setCheckState(QtCore.Qt.CheckState.Unchecked if fixed else QtCore.Qt.CheckState.Checked)
if glob is not None:
self.global_checkbox.setCheckState(QtCore.Qt.CheckState.Checked if glob else QtCore.Qt.CheckState.Unchecked)
def get_parameter(self):
try:
p = float(self.parameter_line.text().replace(',', '.'))
except ValueError:
p = self.parameter_line.text().replace(',', '.')
if self.checkBox.isChecked():
lb_text = self.lineEdit.text()
lb = None
if lb_text:
try:
lb = float(lb_text.replace(',', '.'))
except ValueError:
lb = lb_text
ub_text = self.lineEdit_2.text()
rb = None
if ub_text:
try:
rb = float(ub_text.replace(',', '.'))
except ValueError:
rb = ub_text
else:
lb = rb = None
bounds = (lb, rb)
return p, bounds, not self.fixed_check.isChecked(), self.global_checkbox.isChecked()
@QtCore.pyqtSlot(bool)
def set_fixed(self, state: bool):
# self.global_checkbox.setVisible(not state)
self.frame.setVisible(not state)
@QtCore.pyqtSlot()
def update_parameter(self):
new_value = self.parameter_line.text()
if not new_value:
self.parameter_line.setText('1')
try:
float(new_value)
is_text = False
except ValueError:
is_text = True
self.global_checkbox.setCheckState(False)
self.set_fixed(is_text or self.fixed_check.isChecked())

View File

@ -0,0 +1,97 @@
from ..Qt import QtWidgets, QtGui, QtCore
from ..lib.iconloading import get_icon
from ..lib.pg_objects import RegionItem
class FitToolbar(QtWidgets.QToolBar):
def __init__(
self,
fitaction: QtWidgets.QAction,
limit_menu: QtWidgets.QMenu,
parent=None,
):
super().__init__(parent=parent)
self.fit_action = fitaction
self.region = RegionItem()
self.addAction(fitaction)
self.fitlim_button = QtWidgets.QToolButton(self)
self.fitlim_button.setMenu(limit_menu)
self.fitlim_button.setPopupMode(self.fitlim_button.InstantPopup)
self.fitlim_button.setIcon(get_icon('fit_region'))
self.addWidget(self.fitlim_button)
self.label = QtWidgets.QLabel(self)
self.label.setText('L: ')
self.addWidget(self.label)
self.label.setEnabled(False)
self.lineedit = QtWidgets.QLineEdit(self)
self.lineedit.setValidator(QtGui.QDoubleValidator())
self.lineedit.setMaximumWidth(92)
self.addWidget(self.lineedit)
self.lineedit.setEnabled(False)
self.label2 = QtWidgets.QLabel(self)
self.label2.setText(' R: ')
self.addWidget(self.label2)
self.label2.setEnabled(False)
self.lineedit2 = QtWidgets.QLineEdit(self)
self.lineedit2.setValidator(QtGui.QDoubleValidator())
self.addWidget(self.lineedit2)
self.lineedit2.setMaximumWidth(92)
self.lineedit2.setEnabled(False)
self.limit_group = QtWidgets.QActionGroup(self)
for ac in limit_menu.actions():
self.limit_group.addAction(ac)
self.limit_group.triggered.connect(self.change_limit_type)
self.region.sigRegionChanged.connect(self.change_labels)
self.change_labels()
self.lineedit.textChanged.connect(self.move_region)
self.lineedit2.textChanged.connect(self.move_region)
@QtCore.pyqtSlot(QtWidgets.QAction)
def change_limit_type(self, action: QtWidgets.QAction):
is_custom = (action.text() == 'Custom')
for w in [self.label, self.label2, self.lineedit, self.lineedit2]:
w.setEnabled(is_custom)
def change_labels(self):
r = self.region.getRegion()
self.lineedit.blockSignals(True)
self.lineedit.setText(f'{r[0]:.4g}')
self.lineedit.blockSignals(False)
self.lineedit2.blockSignals(True)
self.lineedit2.setText(f'{r[1]:.4g}')
self.lineedit2.blockSignals(False)
def move_region(self):
try:
r_min = float(self.lineedit.text())
except ValueError:
r_min = None
try:
r_max = float(self.lineedit2.text())
except ValueError:
r_max = None
if r_min is not None and r_max is not None:
self.region.setRegion((r_min, r_max), use_log=True)
def get_limit(self):
action_text = self.limit_group.checkedAction().text()
return {
'None': 'none',
'Visible x range': 'x',
'Custom': self.region.getRegion(),
}[action_text]

View File

@ -165,7 +165,7 @@ class QFunctionWidget(QtWidgets.QWidget, Ui_Form):
self.iscomplex = False self.iscomplex = False
while iterator.value(): while iterator.value():
item = iterator.value() item = iterator.value()
f = self.functions[item.data(0, QtCore.Qt.UserRole)] f = self.functions[item.data(0, QtCore.Qt.ItemDataRole.UserRole)]
if hasattr(f, 'iscomplex') and f.iscomplex: if hasattr(f, 'iscomplex') and f.iscomplex:
self.iscomplex = True self.iscomplex = True
break break
@ -226,7 +226,7 @@ class QFunctionWidget(QtWidgets.QWidget, Ui_Form):
iterator = QtWidgets.QTreeWidgetItemIterator(self.functree) iterator = QtWidgets.QTreeWidgetItemIterator(self.functree)
while iterator.value(): while iterator.value():
item = iterator.value() item = iterator.value()
f = self.functions[item.data(0, QtCore.Qt.UserRole)] f = self.functions[item.data(0, QtCore.Qt.ItemDataRole.UserRole)]
cnt = item.data(0, self.functree.counterRole) cnt = item.data(0, self.functree.counterRole)
all_parameters[f'{f.name}_{cnt}'] = [(convert(pp, new='str'), (cnt, i)) for i, pp in enumerate(f.params)] all_parameters[f'{f.name}_{cnt}'] = [(convert(pp, new='str'), (cnt, i)) for i, pp in enumerate(f.params)]
@ -240,7 +240,7 @@ class QFunctionWidget(QtWidgets.QWidget, Ui_Form):
while iterator.value(): while iterator.value():
item = iterator.value() item = iterator.value()
if item.checkState(0) != QtCore.Qt.CheckState.Unchecked: if item.checkState(0) != QtCore.Qt.CheckState.Unchecked:
f = self.functions[item.data(0, QtCore.Qt.UserRole)] f = self.functions[item.data(0, QtCore.Qt.ItemDataRole.UserRole)]
if hasattr(f, 'iscomplex') and f.iscomplex: if hasattr(f, 'iscomplex') and f.iscomplex:
iscomplex = True iscomplex = True
break break

View File

@ -9,7 +9,6 @@ import numpy as np
from pyqtgraph import mkPen from pyqtgraph import mkPen
from nmreval.fit._meta import MultiModel, ModelFactory from nmreval.fit._meta import MultiModel, ModelFactory
from nmreval.fit.data import Data
from nmreval.fit.model import Model from nmreval.fit.model import Model
from nmreval.fit.parameter import Parameters from nmreval.fit.parameter import Parameters
from nmreval.fit.result import FitResult from nmreval.fit.result import FitResult
@ -42,8 +41,8 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
self._management = mgmt self._management = mgmt
self._current_model = next(QFitDialog.model_cnt) self._current_model = next(QFitDialog.model_cnt)
self.show_combobox.setItemData(0, self._current_model, QtCore.Qt.UserRole) self.show_combobox.setItemData(0, self._current_model, QtCore.Qt.ItemDataRole.UserRole)
self.default_combobox.setItemData(0, self._current_model, QtCore.Qt.UserRole) self.default_combobox.setItemData(0, self._current_model, QtCore.Qt.ItemDataRole.UserRole)
self.data_table = FitTableWidget(self.data_widget) self.data_table = FitTableWidget(self.data_widget)
self.data_widget.addWidget(self.data_table) self.data_widget.addWidget(self.data_table)
@ -150,9 +149,9 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
# deselect all fit sets # deselect all fit sets
for i in range(self.data_table.rowCount()): for i in range(self.data_table.rowCount()):
data_id = self.data_table.item(i, 0).data(QtCore.Qt.UserRole+1) data_id = self.data_table.item(i, 0).data(QtCore.Qt.ItemDataRole.UserRole+1)
if self._management[data_id].mode == 'fit' or self._management[data_id].has_relation(Relations.isFitPartOf): if self._management[data_id].mode == 'fit' or self._management[data_id].has_relation(Relations.isFitPartOf):
self.data_table.item(i, 0).setCheckState(QtCore.Qt.Unchecked) self.data_table.item(i, 0).setCheckState(QtCore.Qt.CheckState.Unchecked)
if self.models: if self.models:
for m in self.models.keys(): for m in self.models.keys():
@ -176,7 +175,7 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
self.default_combobox.addItem('Model '+idx, userData=idx) self.default_combobox.addItem('Model '+idx, userData=idx)
self.show_combobox.addItem('Model '+idx, userData=idx) self.show_combobox.addItem('Model '+idx, userData=idx)
self.show_combobox.setItemData(self.show_combobox.count()-1, idx, QtCore.Qt.UserRole) self.show_combobox.setItemData(self.show_combobox.count()-1, idx, QtCore.Qt.ItemDataRole.UserRole)
self.show_combobox.setCurrentIndex(self.show_combobox.count()-1) self.show_combobox.setCurrentIndex(self.show_combobox.count()-1)
self._current_model = idx self._current_model = idx
@ -190,7 +189,7 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
self.get_functions() self.get_functions()
self.functionwidget.clear() self.functionwidget.clear()
self._current_model = self.show_combobox.itemData(idx, QtCore.Qt.UserRole) self._current_model = self.show_combobox.itemData(idx, QtCore.Qt.ItemDataRole.UserRole)
if self._current_model in self.models and len(self.models[self._current_model]): if self._current_model in self.models and len(self.models[self._current_model]):
for el in self.models[self._current_model]: for el in self.models[self._current_model]:
self.functionwidget.add_function(**el) self.functionwidget.add_function(**el)

View File

@ -217,8 +217,8 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
if idx in self.graph_opts: if idx in self.graph_opts:
view_range, logx, logy = self.graph_opts[idx] view_range, logx, logy = self.graph_opts[idx]
self.fit_plot.setLogMode(x=logx, y=logy)
self.fit_plot.setRange(xRange=view_range[0], yRange=view_range[1], padding=0) 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.blockSignals(True)
self.logx_box.setChecked(logx) self.logx_box.setChecked(logx)
self.logx_box.blockSignals(False) self.logx_box.blockSignals(False)

View File

@ -22,51 +22,59 @@ class Namespace:
if basic: if basic:
self.add_namespace( self.add_namespace(
{'x': (None, 'x values'), {
'y': (None, 'x values'), 'x': (None, 'x values'),
'y_err': (None, 'y error values'), 'y': (None, 'x values'),
'fit': (None, 'dictionary of fit parameter', 'fit["PIKA"]'), 'y_err': (None, 'y error values'),
'np': (np, 'numpy module'), 'fit': (None, 'dictionary of fit parameter', 'fit["PIKA"]'),
'np': (np, 'numpy module'),
}, },
parents=('Basic', 'General'), parents=('Basic', 'General'),
) )
self.add_namespace( self.add_namespace(
{'sin': (np.sin, 'Sine', 'sin(PIKA)'), {
'cos': (np.cos, 'Cosine', 'cos(PIKA)'), 'sin': (np.sin, 'Sine', 'sin(PIKA)'),
'tan': (np.tan, 'Tangens', 'tan(PIKA)'), 'cos': (np.cos, 'Cosine', 'cos(PIKA)'),
'ln': (np.log, 'Natural Logarithm', 'ln(PIKA)'), 'tan': (np.tan, 'Tangens', 'tan(PIKA)'),
'log': (np.log10, 'Logarithm (base 10)', 'log(PIKA)'), 'ln': (np.log, 'Natural Logarithm', 'ln(PIKA)'),
'exp': (np.exp, 'Exponential', 'exp(PIKA)'), 'log': (np.log10, 'Logarithm (base 10)', 'log(PIKA)'),
'sqrt': (np.sqrt, 'Root', 'sqrt(PIKA)'), 'exp': (np.exp, 'Exponential', 'exp(PIKA)'),
'lin_range': (np.linspace, 'N evenly spaced over interval [start, stop]', 'lin_range(start, stop, N)'), 'sqrt': (np.sqrt, 'Root', 'sqrt(PIKA)'),
'log_range': (np.geomspace, 'N evenly spaced (log-scale) over interval [start, stop]', 'lin_range(start, stop, N)'), 'lin_range': (np.linspace, 'N evenly spaced over interval [start, stop]', 'lin_range(start, stop, N)'),
}, 'log_range': (np.geomspace, 'N evenly spaced (log-scale) over interval [start, stop]', 'lin_range(start, stop, N)'),
},
parents=('Basic', 'Functions')) parents=('Basic', 'Functions'))
self.add_namespace( self.add_namespace(
{'max': (np.max, 'Maximum value', 'max(PIKA)'), {
'min': (np.min, 'Minimum value', 'min(PIKA)'), 'max': (np.max, 'Maximum value', 'max(PIKA)'),
'argmax': (np.argmax, 'Index of maximum value', 'argmax(PIKA)'), 'min': (np.min, 'Minimum value', 'min(PIKA)'),
'argmin': (np.argmax, 'Index of minimum value', 'argmin(PIKA)'), 'argmax': (np.argmax, 'Index of maximum value', 'argmax(PIKA)'),
}, 'argmin': (np.argmax, 'Index of minimum value', 'argmin(PIKA)'),
},
parents=('Basic', 'Values')), parents=('Basic', 'Values')),
if const: if const:
self.add_namespace( self.add_namespace(
{'e': (constants.e, 'e / As'), {
'eps0': (constants.epsilon0, 'epsilon0 / As/Vm'), 'e': (constants.e, 'e / As'),
'Eu': (constants.Eu,), 'h': (constants.h, 'h / eVs'), 'eps0': (constants.epsilon0, 'epsilon0 / As/Vm'),
'hbar': (constants.hbar, 'hbar / eVs'), 'kB': (constants.kB, 'kB / eV/K'), 'Eu': (constants.Eu,),
'mu0': (constants.mu0, 'mu0 / Vs/Am'), 'NA': (constants.NA, 'NA / 1/mol'), 'h': (constants.h, 'h / eVs'),
'pi': (constants.pi,), 'R': (constants.R, 'R / eV'), 'hbar': (constants.hbar, 'hbar / eVs'),
}, 'kB': (constants.kB, 'kB / eV/K'),
'mu0': (constants.mu0, 'mu0 / Vs/Am'),
'NA': (constants.NA, 'NA / 1/mol'),
'pi': (constants.pi,),
'R': (constants.R, 'R / eV'),
},
parents=('Constants', 'Maybe useful'), parents=('Constants', 'Maybe useful'),
) )
self.add_namespace( self.add_namespace(
{f'gamma["{k}"]': (v, k, f'gamma["{k}"]') for k, v in constants.gamma.items()}, {f'gamma["{k}"]': (v, k, f'gamma["{k}"]') for k, v in constants.gamma.items()},
parents=('Constants', 'Magnetogyric ratios (in 1/(sT))') parents=('Constants', 'Gyromagnetic ratios (in 1/(sT))')
) )
if fitfuncs: if fitfuncs:
@ -199,7 +207,7 @@ class QNamespaceWidget(QtWidgets.QWidget, Ui_Form):
for entry in subspace: for entry in subspace:
key_item = QtWidgets.QTableWidgetItem(entry) key_item = QtWidgets.QTableWidgetItem(entry)
key_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) key_item.setFlags(QtCore.Qt.ItemFlag.ItemIsSelectable | QtCore.Qt.ItemFlag.ItemIsEnabled)
vals = self.namespace.namespace[entry] vals = self.namespace.namespace[entry]
@ -214,12 +222,12 @@ class QNamespaceWidget(QtWidgets.QWidget, Ui_Form):
display = vals[1] display = vals[1]
value_item = QtWidgets.QTableWidgetItem(display) value_item = QtWidgets.QTableWidgetItem(display)
value_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) value_item.setFlags(QtCore.Qt.ItemFlag.ItemIsSelectable | QtCore.Qt.ItemFlag.ItemIsEnabled)
key_item.setData(QtCore.Qt.UserRole, alias) key_item.setData(QtCore.Qt.ItemDataRole.UserRole, alias)
key_item.setData(QtCore.Qt.UserRole+1, entry) key_item.setData(QtCore.Qt.ItemDataRole.UserRole+1, entry)
value_item.setData(QtCore.Qt.UserRole, alias) value_item.setData(QtCore.Qt.ItemDataRole.UserRole, alias)
value_item.setData(QtCore.Qt.UserRole+1, entry) value_item.setData(QtCore.Qt.ItemDataRole.UserRole+1, entry)
row = self.namespace_table.rowCount() row = self.namespace_table.rowCount()
self.namespace_table.setRowCount(row+1) self.namespace_table.setRowCount(row+1)
@ -241,5 +249,5 @@ class QNamespaceWidget(QtWidgets.QWidget, Ui_Form):
@QtCore.pyqtSlot(QtWidgets.QTableWidgetItem, name='on_namespace_table_itemDoubleClicked') @QtCore.pyqtSlot(QtWidgets.QTableWidgetItem, name='on_namespace_table_itemDoubleClicked')
def item_selected(self, item: QtWidgets.QTableWidgetItem): def item_selected(self, item: QtWidgets.QTableWidgetItem):
self.selected.emit(item.data(QtCore.Qt.UserRole)) self.selected.emit(item.data(QtCore.Qt.ItemDataRole.UserRole))
self.sendKey.emit(item.data(QtCore.Qt.UserRole+1)) self.sendKey.emit(item.data(QtCore.Qt.ItemDataRole.UserRole+1))

View File

@ -2,7 +2,6 @@ from __future__ import annotations
import os import os
import re import re
import time
from pathlib import Path from pathlib import Path
from numpy import geomspace, linspace from numpy import geomspace, linspace
@ -17,13 +16,13 @@ from ..Qt import QtGui, QtPrintSupport
from ..data.shift_graphs import QShift from ..data.shift_graphs import QShift
from ..data.signaledit import QPreviewDialog, QBaselineDialog from ..data.signaledit import QPreviewDialog, QBaselineDialog
from ..dsc.glass_dialog import TgCalculator from ..dsc.glass_dialog import TgCalculator
from ..fit.fit_toolbar import FitToolbar
from ..fit.result import FitExtension, QFitResult from ..fit.result import FitExtension, QFitResult
from ..graphs.graphwindow import QGraphWindow from ..graphs.graphwindow import QGraphWindow
from ..graphs.movedialog import QMover from ..graphs.movedialog import QMover
from ..io.fcbatchreader import QFCReader from ..io.fcbatchreader import QFCReader
from ..io.filedialog import * from ..io.filedialog import *
from ..lib.iconloading import make_action_icons, get_icon from ..lib.iconloading import make_action_icons, get_icon
from ..lib.pg_objects import RegionItem
from ..lib.starter import make_starter from ..lib.starter import make_starter
from ..math.binning import BinningWindow from ..math.binning import BinningWindow
from ..math.evaluation import QEvalDialog from ..math.evaluation import QEvalDialog
@ -97,12 +96,6 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
self.norm_toolbutton.setIcon(get_icon('normal')) self.norm_toolbutton.setIcon(get_icon('normal'))
self.toolbar_edit.addWidget(self.norm_toolbutton) self.toolbar_edit.addWidget(self.norm_toolbutton)
self.fitlim_button = QtWidgets.QToolButton(self)
self.fitlim_button.setMenu(self.menuLimits)
self.fitlim_button.setPopupMode(self.fitlim_button.InstantPopup)
self.fitlim_button.setIcon(get_icon('fit_region'))
self.toolBar_fit.addWidget(self.fitlim_button)
while self.tabWidget.count() > 2: while self.tabWidget.count() > 2:
self.tabWidget.removeTab(self.tabWidget.count()-1) self.tabWidget.removeTab(self.tabWidget.count()-1)
@ -120,9 +113,11 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
self.statusBar.addWidget(self.mousepos) self.statusBar.addWidget(self.mousepos)
self.fitregion = RegionItem()
self._fit_plot_id = None self._fit_plot_id = None
self.fit_toolbar = FitToolbar(self.action_FitWidget, self.menuLimits, self)
self.addToolBar(self.fit_toolbar)
self.setGeometry(QtWidgets.QStyle.alignedRect( self.setGeometry(QtWidgets.QStyle.alignedRect(
QtCore.Qt.LayoutDirection.LeftToRight, QtCore.Qt.LayoutDirection.LeftToRight,
QtCore.Qt.AlignmentFlag.AlignCenter, QtCore.Qt.AlignmentFlag.AlignCenter,
@ -138,11 +133,6 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
self.ac_group.addAction(self.action_nm_fit) self.ac_group.addAction(self.action_nm_fit)
self.ac_group.addAction(self.action_odr_fit) self.ac_group.addAction(self.action_odr_fit)
self.ac_group2 = QtWidgets.QActionGroup(self)
self.ac_group2.addAction(self.action_no_range)
self.ac_group2.addAction(self.action_x_range)
self.ac_group2.addAction(self.action_custom_range)
def _init_signals(self): def _init_signals(self):
self.actionRedo = self.management.undostack.createRedoAction(self) self.actionRedo = self.management.undostack.createRedoAction(self)
icon = QtGui.QIcon.fromTheme("edit-redo") icon = QtGui.QIcon.fromTheme("edit-redo")
@ -158,7 +148,7 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
self.action_save_fit_parameter.triggered.connect(self.save_fit_parameter) self.action_save_fit_parameter.triggered.connect(self.save_fit_parameter)
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
self.ac_group2.triggered.connect(self.change_fit_limits) self.fit_toolbar.limit_group.triggered.connect(self.change_fit_limits)
self.t1action.triggered.connect(lambda: self._show_tab('t1_temp')) self.t1action.triggered.connect(lambda: self._show_tab('t1_temp'))
self.action_edit.triggered.connect(self.do_preview) self.action_edit.triggered.connect(self.do_preview)
@ -899,29 +889,28 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
for item in self.fit_dialog.preview_lines: for item in self.fit_dialog.preview_lines:
self.current_graph_widget.add_external(item) self.current_graph_widget.add_external(item)
if self.action_custom_range.isChecked(): if self.action_custom_range.isChecked():
self.current_graph_widget.add_external(self.fitregion) self.current_graph_widget.add_external(self.fit_toolbar.region)
block_window = True block_window = True
else: else:
for item in self.fit_dialog.preview_lines: for item in self.fit_dialog.preview_lines:
self.current_graph_widget.remove_external(item) self.current_graph_widget.remove_external(item)
self.current_graph_widget.remove_external(self.fitregion) self.current_graph_widget.remove_external(self.fit_toolbar.region)
return block_window return block_window
@QtCore.pyqtSlot(QtWidgets.QAction) @QtCore.pyqtSlot(QtWidgets.QAction)
def change_fit_limits(self, action: QtWidgets.QAction): def change_fit_limits(self, action: QtWidgets.QAction):
if self.current_graph_widget is None:
return
if action == self.action_custom_range and self.fit_dialog.isVisible(): if action == self.action_custom_range and self.fit_dialog.isVisible():
self.current_graph_widget.add_external(self.fitregion) self.current_graph_widget.add_external(self.fit_toolbar.region)
else: else:
self.current_graph_widget.remove_external(self.fitregion) self.current_graph_widget.remove_external(self.fit_toolbar.region)
def start_fit(self, parameter, links, fit_options): def start_fit(self, parameter, links, fit_options):
fit_options['limits'] = { fit_options['limits'] = self.fit_toolbar.get_limit()
self.action_no_range: 'none',
self.action_x_range: 'x',
self.action_custom_range: self.fitregion.getRegion()
}[self.ac_group2.checkedAction()]
fit_options['fit_mode'] = { fit_options['fit_mode'] = {
self.action_lm_fit: 'lsq', self.action_lm_fit: 'lsq',

View File

@ -437,30 +437,6 @@
<addaction name="t1action"/> <addaction name="t1action"/>
<addaction name="actionCalculateT1"/> <addaction name="actionCalculateT1"/>
</widget> </widget>
<widget class="QToolBar" name="toolBar_fit">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Fit</string>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="action_FitWidget"/>
</widget>
<widget class="QToolBar" name="toolBar_spectrum"> <widget class="QToolBar" name="toolBar_spectrum">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed"> <sizepolicy hsizetype="Preferred" vsizetype="Fixed">

View File

@ -67,6 +67,12 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="maximumSize">
<size>
<width>160</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip"> <property name="toolTip">
<string>Initial values</string> <string>Initial values</string>
</property> </property>
@ -92,6 +98,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QPushButton" name="reset_button">
<property name="text">
<string>Use global</string>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item> <item>
@ -151,6 +164,12 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip"> <property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Lower bound. Same bound is used for all data. Leave empty for no boundary condition.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Lower bound. Same bound is used for all data. Leave empty for no boundary condition.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
@ -195,6 +214,12 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip"> <property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Upper bound. Same bound is used for all data. Leave empty for no boundary condition.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Upper bound. Same bound is used for all data. Leave empty for no boundary condition.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>