From e4dbaf2b91db88e9c053f86fccea901f730fdcb4 Mon Sep 17 00:00:00 2001 From: Dominik Demuth Date: Mon, 11 Sep 2023 18:09:08 +0200 Subject: [PATCH] work on ui --- src/gui_qt/_py/fitmodelwidget.py | 19 ++-- src/gui_qt/fit/fit_forms.py | 150 ++++++++-------------------- src/gui_qt/fit/fit_parameter.py | 14 ++- src/gui_qt/fit/fitfunction.py | 3 +- src/gui_qt/fit/fitwindow.py | 5 +- src/nmreval/fit/minimizer.py | 5 +- src/resources/_ui/fitmodelwidget.ui | 30 +----- 7 files changed, 62 insertions(+), 164 deletions(-) diff --git a/src/gui_qt/_py/fitmodelwidget.py b/src/gui_qt/_py/fitmodelwidget.py index a41f14b..f183f36 100644 --- a/src/gui_qt/_py/fitmodelwidget.py +++ b/src/gui_qt/_py/fitmodelwidget.py @@ -1,10 +1,11 @@ # -*- coding: utf-8 -*- -# Form implementation generated from reading ui file 'resources/_ui/fitmodelwidget.ui' +# Form implementation generated from reading ui file 'src/resources/_ui/fitmodelwidget.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 @@ -13,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets class Ui_FitParameter(object): def setupUi(self, FitParameter): FitParameter.setObjectName("FitParameter") - FitParameter.resize(365, 78) + FitParameter.resize(365, 66) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.MinimumExpanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) @@ -36,7 +37,7 @@ class Ui_FitParameter(object): self.parametername.setObjectName("parametername") self.horizontalLayout_2.addWidget(self.parametername) self.parameter_line = LineEdit(FitParameter) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.parameter_line.sizePolicy().hasHeightForWidth()) @@ -44,20 +45,12 @@ class Ui_FitParameter(object): self.parameter_line.setText("") self.parameter_line.setObjectName("parameter_line") self.horizontalLayout_2.addWidget(self.parameter_line) - spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) - self.horizontalLayout_2.addItem(spacerItem) self.fixed_check = QtWidgets.QCheckBox(FitParameter) self.fixed_check.setObjectName("fixed_check") self.horizontalLayout_2.addWidget(self.fixed_check) self.global_checkbox = QtWidgets.QCheckBox(FitParameter) self.global_checkbox.setObjectName("global_checkbox") self.horizontalLayout_2.addWidget(self.global_checkbox) - self.toolButton = QtWidgets.QToolButton(FitParameter) - self.toolButton.setText("") - self.toolButton.setPopupMode(QtWidgets.QToolButton.InstantPopup) - self.toolButton.setArrowType(QtCore.Qt.RightArrow) - self.toolButton.setObjectName("toolButton") - self.horizontalLayout_2.addWidget(self.toolButton) self.verticalLayout.addLayout(self.horizontalLayout_2) self.frame = QtWidgets.QFrame(FitParameter) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum) diff --git a/src/gui_qt/fit/fit_forms.py b/src/gui_qt/fit/fit_forms.py index d49fac9..0a4179f 100644 --- a/src/gui_qt/fit/fit_forms.py +++ b/src/gui_qt/fit/fit_forms.py @@ -19,16 +19,16 @@ class FitModelWidget(QtWidgets.QWidget, Ui_FitParameter): self.parametername.setText(label + ' ') - # self.parameter_line.setValidator(validator) self.parameter_line.setText('1') - self.parameter_line.setMaximumWidth(60) - self.lineEdit.setMaximumWidth(60) - self.lineEdit_2.setMaximumWidth(60) + self.parameter_line.setMaximumWidth(160) + self.lineEdit.setMaximumWidth(100) + self.lineEdit_2.setMaximumWidth(100) self.label_3.setText(f'< {label} <') 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.editingFinished.connect(lambda: self.value_changed.emit(self.parameter_line.text())) self.fixed_check.toggled.connect(self.set_fixed) @@ -36,20 +36,12 @@ class FitModelWidget(QtWidgets.QWidget, Ui_FitParameter): if fixed: self.fixed_check.hide() - self.is_linked = None self.parameter_pos = None self.func_idx = None self._linetext = '1' - self.completer = QtWidgets.QCompleter() - self.completer.setCompletionMode(QtWidgets.QCompleter.UnfilteredPopupCompletion) - self.parameter_hint_model = QtGui.QStandardItemModel() - self.completer.setModel(self.parameter_hint_model) - self.parameter_line.setCompleter(self.completer) - self.menu = QtWidgets.QMenu(self) - self.add_links() @property def name(self): @@ -73,39 +65,24 @@ class FitModelWidget(QtWidgets.QWidget, Ui_FitParameter): def set_parameter(self, p: float | None, bds: tuple[float, float, bool] = None, fixed: bool = None, glob: bool = None): - if p is None: - # bad hack: linked parameter return (None, linked parameter) - # if p is None -> parameter is linked to argument given by bds - self.link_parameter(linkto=bds) - else: - ptext = f'{p:.4g}' + ptext = f'{p:.4g}' - self.set_parameter_string(ptext) + self.set_parameter_string(ptext) - if bds is not None: - self.set_bounds(*bds) + if bds is not None: + self.set_bounds(*bds) - if fixed is not None: - self.fixed_check.setCheckState(QtCore.Qt.Unchecked if fixed else QtCore.Qt.Checked) + if fixed is not None: + self.fixed_check.setCheckState(QtCore.Qt.Unchecked if fixed else QtCore.Qt.Checked) - if glob is not None: - self.global_checkbox.setCheckState(QtCore.Qt.Checked if glob else QtCore.Qt.Unchecked) + if glob is not None: + self.global_checkbox.setCheckState(QtCore.Qt.Checked if glob else QtCore.Qt.Unchecked) def get_parameter(self): - if self.is_linked: - try: - p = float(self._linetext) - except ValueError: - p = 1.0 - else: - try: - p = float(self.parameter_line.text().replace(',', '.')) - except ValueError: - p = self.parameter_line.text().replace(',', '.') - # _ = QtWidgets.QMessageBox().warning(self, 'Invalid value', - # f'{self.parametername.text()} contains invalid values', - # QtWidgets.QMessageBox.Cancel) - # return None + try: + p = float(self.parameter_line.text().replace(',', '.')) + except ValueError: + p = self.parameter_line.text().replace(',', '.') if self.checkBox.isChecked(): try: @@ -122,84 +99,26 @@ class FitModelWidget(QtWidgets.QWidget, Ui_FitParameter): bounds = (lb, rb) - return p, bounds, not self.fixed_check.isChecked(), self.global_checkbox.isChecked(), self.is_linked + 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) - def add_links(self, parameter: dict = None): - if parameter is None: - parameter = {} - self.menu.clear() - - self.parameter_hint_model.clear() - - ac = QtWidgets.QAction('Link to...', self) - ac.triggered.connect(self.link_parameter) - self.menu.addAction(ac) - - for model_key, model_funcs in parameter.items(): - m = QtWidgets.QMenu('Model ' + model_key, self) - hint_key = model_key - - for func_name, func_params in model_funcs.items(): - m2 = QtWidgets.QMenu(func_name, m) - hint_key += f'.{func_name}' - for p_name, idx in func_params: - ac = QtWidgets.QAction(p_name, m2) - hint_key += f'.{p_name}' - item = QtGui.QStandardItem(hint_key) - item.setData((model_key, *idx)) - self.parameter_hint_model.appendRow(item) - ac.setData((model_key, *idx)) - ac.triggered.connect(self.link_parameter) - m2.addAction(ac) - m.addMenu(m2) - self.menu.addMenu(m) - - self.toolButton.setMenu(self.menu) - @QtCore.pyqtSlot() - def link_parameter(self, linkto=None): - if linkto is None: - action = self.sender() - else: - action = False - for m in self.menu.actions(): - if m.menu(): - for a in m.menu().actions(): - if a.data() == linkto: - action = a - break - if action: - break - - if (self.func_idx, self.parameter_pos) == action.data(): - return + def update_parameter(self): + new_value = self.parameter_line.text() + if not new_value: + self.parameter_line.setText('1') try: - new_text = f'Linked to {action.parentWidget().title()}.{action.text()}' - self._linetext = self.parameter_line.text() - self.parameter_line.setText(new_text) - self.parameter_line.setEnabled(False) - self.global_checkbox.hide() - self.global_checkbox.blockSignals(True) - self.global_checkbox.setCheckState(QtCore.Qt.Checked) - self.global_checkbox.blockSignals(False) - self.frame.hide() - self.is_linked = action.data() + float(new_value) + is_text = False + except ValueError: + is_text = True - except AttributeError: - self.parameter_line.setText(self._linetext) - self.parameter_line.setEnabled(True) - if self.fixed_check.isEnabled(): - self.global_checkbox.show() - self.frame.show() - self.is_linked = None - - self.state_changed.emit() + self.set_fixed(is_text) class QSaveModelDialog(QtWidgets.QDialog, Ui_SaveDialog): @@ -294,8 +213,17 @@ class FitModelTree(QtWidgets.QTreeWidget): idx = item.data(0, self.counterRole) self.itemRemoved.emit(idx) - def add_function(self, idx: int, cnt: int, op: int, name: str, color: QtGui.QColor | str | tuple, - parent: QtWidgets.QTreeWidgetItem = None, children: list = None, active: bool = True, **kwargs): + def add_function(self, + idx: int, + cnt: int, + op: int, + name: str, + color: QtGui.QColor | str | tuple, + parent: QtWidgets.QTreeWidgetItem = None, + children: list = None, + active: bool = True, + param_names: list[str] = None, + **kwargs): """ Add function to tree and dictionary of functions. """ @@ -310,6 +238,10 @@ class FitModelTree(QtWidgets.QTreeWidget): it.setData(0, self.counterRole, cnt) it.setData(0, self.operatorRole, op) it.setText(0, name) + if param_names is not None: + it.setToolTip(0, + 'Parameter names:\n' + + '\n'.join(f'{pn}({cnt})' for pn in param_names)) it.setForeground(0, QtGui.QBrush(color)) it.setIcon(0, get_icon(self.icons[op])) diff --git a/src/gui_qt/fit/fit_parameter.py b/src/gui_qt/fit/fit_parameter.py index 7c75f73..ae41510 100644 --- a/src/gui_qt/fit/fit_parameter.py +++ b/src/gui_qt/fit/fit_parameter.py @@ -114,10 +114,10 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit): self.scrollwidget.layout().addStretch(1) self.scrollwidget2.layout().addStretch(1) - def set_links(self, parameter): - for w in self.global_parameter: - if isinstance(w, FitModelWidget): - w.add_links(parameter) + # def set_links(self, parameter): + # for w in self.global_parameter: + # if isinstance(w, FitModelWidget): + # w.add_links(parameter) @QtCore.pyqtSlot(str) def change_global_parameter(self, value: str, idx: int = None): @@ -203,17 +203,15 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit): is_global = [] is_fixed = [] globs = [] - is_linked = [] for g in self.global_parameter: if isinstance(g, FitModelWidget): - p_i, bds_i, fixed_i, global_i, link_i = g.get_parameter() + p_i, bds_i, fixed_i, global_i = g.get_parameter() globs.append(p_i) bds.append(bds_i) is_fixed.append(fixed_i) is_global.append(global_i) - is_linked.append(link_i) lb, ub = list(zip(*bds)) @@ -267,7 +265,7 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit): data_parameter[sid] = (p, kw_p) - return data_parameter, lb, ub, is_fixed, global_p, is_linked + return data_parameter, lb, ub, is_fixed, global_p def set_parameter(self, set_id: str | None, parameter: list[float]) -> int: num_parameter = list(filter(lambda g: not isinstance(g, SelectionWidget), self.global_parameter)) diff --git a/src/gui_qt/fit/fitfunction.py b/src/gui_qt/fit/fitfunction.py index 0d1c412..2b74641 100644 --- a/src/gui_qt/fit/fitfunction.py +++ b/src/gui_qt/fit/fitfunction.py @@ -128,7 +128,7 @@ class QFunctionWidget(QtWidgets.QWidget, Ui_Form): self.newFunction.emit(idx, cnt) - self.add_function(idx, cnt, op, name, col) + self.add_function(idx, cnt, op, name, col, param_names=self.functions[idx].params) def add_function(self, idx: int, cnt: int, op: int, name: str, color: str | tuple[float, float, float] | BaseColor, **kwargs): @@ -141,6 +141,7 @@ class QFunctionWidget(QtWidgets.QWidget, Ui_Form): qcolor = QtGui.QColor.fromRgbF(*color) else: qcolor = QtGui.QColor(color) + self.functree.add_function(idx, cnt, op, name, qcolor, **kwargs) f = self.functions[idx] diff --git a/src/gui_qt/fit/fitwindow.py b/src/gui_qt/fit/fitwindow.py index 55116b7..d0b88be 100644 --- a/src/gui_qt/fit/fitwindow.py +++ b/src/gui_qt/fit/fitwindow.py @@ -116,7 +116,7 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog): # collect parameter names etc. to allow linkage self._func_list[self._current_model] = self.functionwidget.get_parameter_list() - dialog.set_links(self._func_list) + # dialog.set_links(self._func_list) # show same tab (general parameter/Data parameter) tab_idx = 0 @@ -229,7 +229,7 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog): continue try: - p, lb, ub, var, glob, links = self.param_widgets[f['cnt']].get_parameter(function_use) + p, lb, ub, var, glob = self.param_widgets[f['cnt']].get_parameter(function_use) except ValueError as e: _ = QtWidgets.QMessageBox().warning(self, 'Invalid value', str(e), QtWidgets.QMessageBox.Ok) @@ -240,7 +240,6 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog): parameter['lb'] += lb parameter['ub'] += ub parameter['var'] += var - parameter['links'] += links parameter['color'] += [f['color']] cnt = f['cnt'] diff --git a/src/nmreval/fit/minimizer.py b/src/nmreval/fit/minimizer.py index 355769d..bc07df9 100644 --- a/src/nmreval/fit/minimizer.py +++ b/src/nmreval/fit/minimizer.py @@ -223,8 +223,6 @@ class FitRoutine(object): def run(self, mode: str = 'lsq'): self._abort = False - print('run') - fit_groups, linked_parameter = self.prepare_links() for data_groups in fit_groups: if len(data_groups) == 1 and not self.linked: @@ -256,6 +254,9 @@ class FitRoutine(object): self.unprep_run() + for r in self.result: + r.pprint() + return self.result def _prep_data(self, data): diff --git a/src/resources/_ui/fitmodelwidget.ui b/src/resources/_ui/fitmodelwidget.ui index 02069fb..ffc0b93 100755 --- a/src/resources/_ui/fitmodelwidget.ui +++ b/src/resources/_ui/fitmodelwidget.ui @@ -7,7 +7,7 @@ 0 0 365 - 78 + 66 @@ -62,7 +62,7 @@ - + 0 0 @@ -78,19 +78,6 @@ - - - - Qt::Horizontal - - - - 40 - 20 - - - - @@ -105,19 +92,6 @@ - - - - - - - QToolButton::InstantPopup - - - Qt::RightArrow - - -