work on ui

This commit is contained in:
Dominik Demuth 2023-09-11 18:09:08 +02:00
parent 5e55f06723
commit e4dbaf2b91
7 changed files with 62 additions and 164 deletions

View File

@ -1,10 +1,11 @@
# -*- coding: utf-8 -*- # -*- 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 from PyQt5 import QtCore, QtGui, QtWidgets
@ -13,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_FitParameter(object): class Ui_FitParameter(object):
def setupUi(self, FitParameter): def setupUi(self, FitParameter):
FitParameter.setObjectName("FitParameter") FitParameter.setObjectName("FitParameter")
FitParameter.resize(365, 78) FitParameter.resize(365, 66)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.MinimumExpanding) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.MinimumExpanding)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
@ -36,7 +37,7 @@ class Ui_FitParameter(object):
self.parametername.setObjectName("parametername") self.parametername.setObjectName("parametername")
self.horizontalLayout_2.addWidget(self.parametername) self.horizontalLayout_2.addWidget(self.parametername)
self.parameter_line = LineEdit(FitParameter) 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.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.parameter_line.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(self.parameter_line.sizePolicy().hasHeightForWidth())
@ -44,20 +45,12 @@ class Ui_FitParameter(object):
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)
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 = QtWidgets.QCheckBox(FitParameter)
self.fixed_check.setObjectName("fixed_check") self.fixed_check.setObjectName("fixed_check")
self.horizontalLayout_2.addWidget(self.fixed_check) self.horizontalLayout_2.addWidget(self.fixed_check)
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.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.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)

View File

@ -19,16 +19,16 @@ class FitModelWidget(QtWidgets.QWidget, Ui_FitParameter):
self.parametername.setText(label + ' ') self.parametername.setText(label + ' ')
# self.parameter_line.setValidator(validator)
self.parameter_line.setText('1') self.parameter_line.setText('1')
self.parameter_line.setMaximumWidth(60) self.parameter_line.setMaximumWidth(160)
self.lineEdit.setMaximumWidth(60) self.lineEdit.setMaximumWidth(100)
self.lineEdit_2.setMaximumWidth(60) self.lineEdit_2.setMaximumWidth(100)
self.label_3.setText(f'< {label} <') self.label_3.setText(f'< {label} <')
self.checkBox.stateChanged.connect(self.enableBounds) self.checkBox.stateChanged.connect(self.enableBounds)
self.global_checkbox.stateChanged.connect(lambda: self.state_changed.emit()) 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.values_requested.connect(lambda: self.value_requested.emit(self))
self.parameter_line.editingFinished.connect(lambda: self.value_changed.emit(self.parameter_line.text())) self.parameter_line.editingFinished.connect(lambda: self.value_changed.emit(self.parameter_line.text()))
self.fixed_check.toggled.connect(self.set_fixed) self.fixed_check.toggled.connect(self.set_fixed)
@ -36,20 +36,12 @@ class FitModelWidget(QtWidgets.QWidget, Ui_FitParameter):
if fixed: if fixed:
self.fixed_check.hide() self.fixed_check.hide()
self.is_linked = None
self.parameter_pos = None self.parameter_pos = None
self.func_idx = None self.func_idx = None
self._linetext = '1' 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.menu = QtWidgets.QMenu(self)
self.add_links()
@property @property
def name(self): 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, def set_parameter(self, p: float | None, bds: tuple[float, float, bool] = None,
fixed: bool = None, glob: bool = None): fixed: bool = None, glob: bool = None):
if p is None: ptext = f'{p:.4g}'
# 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}'
self.set_parameter_string(ptext) self.set_parameter_string(ptext)
if bds is not None: if bds is not None:
self.set_bounds(*bds) self.set_bounds(*bds)
if fixed is not None: if fixed is not None:
self.fixed_check.setCheckState(QtCore.Qt.Unchecked if fixed else QtCore.Qt.Checked) self.fixed_check.setCheckState(QtCore.Qt.Unchecked if fixed else QtCore.Qt.Checked)
if glob is not None: if glob is not None:
self.global_checkbox.setCheckState(QtCore.Qt.Checked if glob else QtCore.Qt.Unchecked) self.global_checkbox.setCheckState(QtCore.Qt.Checked if glob else QtCore.Qt.Unchecked)
def get_parameter(self): def get_parameter(self):
if self.is_linked: try:
try: p = float(self.parameter_line.text().replace(',', '.'))
p = float(self._linetext) except ValueError:
except ValueError: p = self.parameter_line.text().replace(',', '.')
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
if self.checkBox.isChecked(): if self.checkBox.isChecked():
try: try:
@ -122,84 +99,26 @@ class FitModelWidget(QtWidgets.QWidget, Ui_FitParameter):
bounds = (lb, rb) 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) @QtCore.pyqtSlot(bool)
def set_fixed(self, state: bool): def set_fixed(self, state: bool):
# self.global_checkbox.setVisible(not state) # self.global_checkbox.setVisible(not state)
self.frame.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() @QtCore.pyqtSlot()
def link_parameter(self, linkto=None): def update_parameter(self):
if linkto is None: new_value = self.parameter_line.text()
action = self.sender() if not new_value:
else: self.parameter_line.setText('1')
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
try: try:
new_text = f'Linked to {action.parentWidget().title()}.{action.text()}' float(new_value)
self._linetext = self.parameter_line.text() is_text = False
self.parameter_line.setText(new_text) except ValueError:
self.parameter_line.setEnabled(False) is_text = True
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()
except AttributeError: self.set_fixed(is_text)
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()
class QSaveModelDialog(QtWidgets.QDialog, Ui_SaveDialog): class QSaveModelDialog(QtWidgets.QDialog, Ui_SaveDialog):
@ -294,8 +213,17 @@ class FitModelTree(QtWidgets.QTreeWidget):
idx = item.data(0, self.counterRole) idx = item.data(0, self.counterRole)
self.itemRemoved.emit(idx) self.itemRemoved.emit(idx)
def add_function(self, idx: int, cnt: int, op: int, name: str, color: QtGui.QColor | str | tuple, def add_function(self,
parent: QtWidgets.QTreeWidgetItem = None, children: list = None, active: bool = True, **kwargs): 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. 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.counterRole, cnt)
it.setData(0, self.operatorRole, op) it.setData(0, self.operatorRole, op)
it.setText(0, name) 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.setForeground(0, QtGui.QBrush(color))
it.setIcon(0, get_icon(self.icons[op])) it.setIcon(0, get_icon(self.icons[op]))

View File

@ -114,10 +114,10 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
self.scrollwidget.layout().addStretch(1) self.scrollwidget.layout().addStretch(1)
self.scrollwidget2.layout().addStretch(1) self.scrollwidget2.layout().addStretch(1)
def set_links(self, parameter): # def set_links(self, parameter):
for w in self.global_parameter: # for w in self.global_parameter:
if isinstance(w, FitModelWidget): # if isinstance(w, FitModelWidget):
w.add_links(parameter) # w.add_links(parameter)
@QtCore.pyqtSlot(str) @QtCore.pyqtSlot(str)
def change_global_parameter(self, value: str, idx: int = None): def change_global_parameter(self, value: str, idx: int = None):
@ -203,17 +203,15 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
is_global = [] is_global = []
is_fixed = [] is_fixed = []
globs = [] globs = []
is_linked = []
for g in self.global_parameter: for g in self.global_parameter:
if isinstance(g, FitModelWidget): 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) globs.append(p_i)
bds.append(bds_i) bds.append(bds_i)
is_fixed.append(fixed_i) is_fixed.append(fixed_i)
is_global.append(global_i) is_global.append(global_i)
is_linked.append(link_i)
lb, ub = list(zip(*bds)) lb, ub = list(zip(*bds))
@ -267,7 +265,7 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
data_parameter[sid] = (p, kw_p) 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: 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)) num_parameter = list(filter(lambda g: not isinstance(g, SelectionWidget), self.global_parameter))

View File

@ -128,7 +128,7 @@ class QFunctionWidget(QtWidgets.QWidget, Ui_Form):
self.newFunction.emit(idx, cnt) 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, def add_function(self, idx: int, cnt: int, op: int,
name: str, color: str | tuple[float, float, float] | BaseColor, **kwargs): 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) qcolor = QtGui.QColor.fromRgbF(*color)
else: else:
qcolor = QtGui.QColor(color) qcolor = QtGui.QColor(color)
self.functree.add_function(idx, cnt, op, name, qcolor, **kwargs) self.functree.add_function(idx, cnt, op, name, qcolor, **kwargs)
f = self.functions[idx] f = self.functions[idx]

View File

@ -116,7 +116,7 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
# collect parameter names etc. to allow linkage # collect parameter names etc. to allow linkage
self._func_list[self._current_model] = self.functionwidget.get_parameter_list() 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) # show same tab (general parameter/Data parameter)
tab_idx = 0 tab_idx = 0
@ -229,7 +229,7 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
continue continue
try: 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: except ValueError as e:
_ = QtWidgets.QMessageBox().warning(self, 'Invalid value', str(e), _ = QtWidgets.QMessageBox().warning(self, 'Invalid value', str(e),
QtWidgets.QMessageBox.Ok) QtWidgets.QMessageBox.Ok)
@ -240,7 +240,6 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
parameter['lb'] += lb parameter['lb'] += lb
parameter['ub'] += ub parameter['ub'] += ub
parameter['var'] += var parameter['var'] += var
parameter['links'] += links
parameter['color'] += [f['color']] parameter['color'] += [f['color']]
cnt = f['cnt'] cnt = f['cnt']

View File

@ -223,8 +223,6 @@ class FitRoutine(object):
def run(self, mode: str = 'lsq'): def run(self, mode: str = 'lsq'):
self._abort = False self._abort = False
print('run')
fit_groups, linked_parameter = self.prepare_links() fit_groups, linked_parameter = self.prepare_links()
for data_groups in fit_groups: for data_groups in fit_groups:
if len(data_groups) == 1 and not self.linked: if len(data_groups) == 1 and not self.linked:
@ -256,6 +254,9 @@ class FitRoutine(object):
self.unprep_run() self.unprep_run()
for r in self.result:
r.pprint()
return self.result return self.result
def _prep_data(self, data): def _prep_data(self, data):

View File

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>365</width> <width>365</width>
<height>78</height> <height>66</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@ -62,7 +62,7 @@
<item> <item>
<widget class="LineEdit" name="parameter_line"> <widget class="LineEdit" name="parameter_line">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed"> <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
@ -78,19 +78,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item> <item>
<widget class="QCheckBox" name="fixed_check"> <widget class="QCheckBox" name="fixed_check">
<property name="text"> <property name="text">
@ -105,19 +92,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QToolButton" name="toolButton">
<property name="text">
<string/>
</property>
<property name="popupMode">
<enum>QToolButton::InstantPopup</enum>
</property>
<property name="arrowType">
<enum>Qt::RightArrow</enum>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item> <item>