forked from IPKM/nmreval
use Parameter when collecting fit values
This commit is contained in:
parent
3af5cb0301
commit
03d172bade
@ -19,14 +19,16 @@ class FitModelWidget(QtWidgets.QWidget, Ui_FitParameter):
|
|||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
|
|
||||||
self.parametername.setText(label + ' ')
|
self.name = label
|
||||||
|
|
||||||
|
self.parametername.setText(convert(label) + ' ')
|
||||||
|
|
||||||
self.parameter_line.setText('1')
|
self.parameter_line.setText('1')
|
||||||
self.parameter_line.setMaximumWidth(160)
|
self.parameter_line.setMaximumWidth(160)
|
||||||
self.lineEdit.setMaximumWidth(100)
|
self.lineEdit.setMaximumWidth(100)
|
||||||
self.lineEdit_2.setMaximumWidth(100)
|
self.lineEdit_2.setMaximumWidth(100)
|
||||||
|
|
||||||
self.label_3.setText(f'< {label} <')
|
self.label_3.setText(f'< {convert(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())
|
||||||
@ -46,10 +48,6 @@ class FitModelWidget(QtWidgets.QWidget, Ui_FitParameter):
|
|||||||
|
|
||||||
self.menu = QtWidgets.QMenu(self)
|
self.menu = QtWidgets.QMenu(self)
|
||||||
|
|
||||||
@property
|
|
||||||
def name(self):
|
|
||||||
return convert(self.parametername.text().strip(), old='html', new='str')
|
|
||||||
|
|
||||||
def set_parameter_string(self, p: str):
|
def set_parameter_string(self, p: str):
|
||||||
self.parameter_line.setText(p)
|
self.parameter_line.setText(p)
|
||||||
self.parameter_line.setToolTip(p)
|
self.parameter_line.setToolTip(p)
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
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
|
||||||
@ -62,8 +65,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):
|
||||||
name = convert(v)
|
widgt = FitModelWidget(label=v, parent=self.scrollwidget)
|
||||||
widgt = FitModelWidget(label=name, parent=self.scrollwidget)
|
|
||||||
widgt.parameter_pos = k
|
widgt.parameter_pos = k
|
||||||
widgt.func_idx = idx
|
widgt.func_idx = idx
|
||||||
try:
|
try:
|
||||||
@ -83,7 +85,7 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
|
|||||||
self.global_parameter.append(widgt)
|
self.global_parameter.append(widgt)
|
||||||
self.scrollwidget.layout().addWidget(widgt)
|
self.scrollwidget.layout().addWidget(widgt)
|
||||||
|
|
||||||
widgt2 = ParameterSingleWidget(name=name, parent=self.scrollwidget2)
|
widgt2 = ParameterSingleWidget(name=v, parent=self.scrollwidget2)
|
||||||
widgt2.valueChanged.connect(self.change_single_parameter)
|
widgt2.valueChanged.connect(self.change_single_parameter)
|
||||||
widgt2.removeSingleValue.connect(self.change_single_parameter)
|
widgt2.removeSingleValue.connect(self.change_single_parameter)
|
||||||
widgt2.installEventFilter(self)
|
widgt2.installEventFilter(self)
|
||||||
@ -206,62 +208,51 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
|
|||||||
if sid not in self.data_values:
|
if sid not in self.data_values:
|
||||||
self.data_values[sid] = [None] * len(self.data_parameter)
|
self.data_values[sid] = [None] * len(self.data_parameter)
|
||||||
|
|
||||||
def get_parameter(self, use_func=None):
|
def get_parameter(self, use_func=None) -> tuple[dict[str, list[Parameter]], list[Optional[Parameter]]]:
|
||||||
bds = []
|
bds = []
|
||||||
is_global = []
|
is_global = []
|
||||||
is_fixed = []
|
is_fixed = []
|
||||||
globs = []
|
|
||||||
|
param_general = []
|
||||||
|
|
||||||
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 = 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)
|
||||||
|
param_general.append(parameter_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)
|
||||||
|
|
||||||
lb, ub = list(zip(*bds))
|
|
||||||
|
|
||||||
data_parameter = {}
|
data_parameter = {}
|
||||||
if use_func is None:
|
if use_func is None:
|
||||||
use_func = list(self.data_values.keys())
|
use_func = list(self.data_values.keys())
|
||||||
|
|
||||||
global_p = None
|
|
||||||
for sid, parameter in self.data_values.items():
|
for sid, parameter in self.data_values.items():
|
||||||
if sid not in use_func:
|
if sid not in use_func:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
kw_p = {}
|
kw_p = {}
|
||||||
p = []
|
p = []
|
||||||
if global_p is None:
|
|
||||||
global_p = {'value': [], 'idx': [], 'var': [], 'ub': [], 'lb': []}
|
|
||||||
|
|
||||||
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, FitModelWidget):
|
||||||
if (p_i is None) or is_global[i]:
|
if p_i is None:
|
||||||
p.append(globs[i])
|
# set has no oen value
|
||||||
if is_global[i]:
|
p.append(param_general[i].copy())
|
||||||
if i not in global_p['idx']:
|
|
||||||
global_p['value'].append(globs[i])
|
|
||||||
global_p['idx'].append(i)
|
|
||||||
global_p['var'].append(is_fixed[i])
|
|
||||||
global_p['ub'].append(ub[i])
|
|
||||||
global_p['lb'].append(lb[i])
|
|
||||||
else:
|
else:
|
||||||
p.append(p_i)
|
lb, ub = bds[i]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if p[i] > ub[i]:
|
if not (lb < p[i] < ub):
|
||||||
raise ValueError(f'Parameter {g.name} is outside bounds ({lb[i]}, {ub[i]})')
|
raise ValueError(f'Parameter {g.name} is outside bounds ({lb}, {ub})')
|
||||||
except TypeError:
|
except TypeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
# create Parameter
|
||||||
if p[i] < lb[i]:
|
p.append(
|
||||||
raise ValueError(f'Parameter {g.name} is outside bounds ({lb[i]}, {ub[i]})')
|
Parameter(name=g.name, value=p_i, lb=lb, ub=ub, var=is_fixed[i])
|
||||||
except TypeError:
|
)
|
||||||
pass
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if p_i is None:
|
if p_i is None:
|
||||||
@ -271,9 +262,17 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
|
|||||||
else:
|
else:
|
||||||
kw_p[g.argname] = p_i
|
kw_p[g.argname] = p_i
|
||||||
|
|
||||||
|
global_parameter = []
|
||||||
|
for param, global_flag in zip(param_general, is_global):
|
||||||
|
if global_flag:
|
||||||
|
global_parameter.append(param)
|
||||||
|
else:
|
||||||
|
global_parameter.append(None)
|
||||||
|
|
||||||
|
|
||||||
data_parameter[sid] = (p, kw_p)
|
data_parameter[sid] = (p, kw_p)
|
||||||
|
|
||||||
return data_parameter, lb, ub, is_fixed, global_p
|
return data_parameter, global_parameter
|
||||||
|
|
||||||
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))
|
||||||
@ -304,7 +303,7 @@ class ParameterSingleWidget(QtWidgets.QWidget):
|
|||||||
|
|
||||||
self._init_ui()
|
self._init_ui()
|
||||||
|
|
||||||
self._name = name
|
self.name = name
|
||||||
self.label.setText(convert(name))
|
self.label.setText(convert(name))
|
||||||
self.label.setToolTip('If this is bold then this parameter is only for this data. '
|
self.label.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')
|
||||||
|
@ -220,27 +220,31 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
|
|||||||
def _prepare(self, model: list, function_use: list = None,
|
def _prepare(self, model: list, function_use: list = None,
|
||||||
parameter: dict = None, add_idx: bool = False, cnt: int = 0) -> tuple[dict, int]:
|
parameter: dict = None, add_idx: bool = False, cnt: int = 0) -> tuple[dict, int]:
|
||||||
if parameter is None:
|
if parameter is None:
|
||||||
parameter = {'parameter': {}, 'lb': (), 'ub': (), 'var': [],
|
parameter = {
|
||||||
'glob': {'idx': [], 'value': [], 'var': [], 'lb': [], 'ub': []},
|
'parameter': {},
|
||||||
'links': [], 'color': []}
|
'glob': [],
|
||||||
|
'links': [],
|
||||||
|
'color': [],
|
||||||
|
}
|
||||||
|
|
||||||
for i, f in enumerate(model):
|
for i, f in enumerate(model):
|
||||||
|
print(i, f)
|
||||||
if not f['active']:
|
if not f['active']:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
p, lb, ub, var, glob = self.param_widgets[f['cnt']].get_parameter(function_use)
|
p, 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)
|
||||||
return {}, -1
|
return {}, -1
|
||||||
|
|
||||||
p_len = len(parameter['lb'])
|
print(p)
|
||||||
|
print(glob)
|
||||||
|
p_len = len(p)
|
||||||
|
parameter['color'].append(f['color'])
|
||||||
|
|
||||||
parameter['lb'] += lb
|
print(parameter)
|
||||||
parameter['ub'] += ub
|
|
||||||
parameter['var'] += var
|
|
||||||
parameter['color'] += [f['color']]
|
|
||||||
|
|
||||||
cnt = f['cnt']
|
cnt = f['cnt']
|
||||||
|
|
||||||
|
@ -190,20 +190,23 @@ class Parameter:
|
|||||||
self._value = value * self.scale
|
self._value = value * self.scale
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def value(self) -> float:
|
def value(self) -> float | None:
|
||||||
# TODO first _value, then _expr
|
# TODO first _value, then _expr
|
||||||
|
if self._value is not None:
|
||||||
|
return self._value
|
||||||
|
|
||||||
if self._expr is not None and self.eval_allowed:
|
if self._expr is not None and self.eval_allowed:
|
||||||
return eval(self._expr, {}, self.namespace)
|
return eval(self._expr, {}, self.namespace)
|
||||||
elif self._value is not None:
|
|
||||||
return self._value
|
return
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def scaled_error(self) -> None | float:
|
def scaled_error(self) -> None | float:
|
||||||
if self.error is None:
|
if self.error is not None:
|
||||||
return self.error
|
|
||||||
else:
|
|
||||||
return self.error / self.scale
|
return self.error / self.scale
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
@scaled_error.setter
|
@scaled_error.setter
|
||||||
def scaled_error(self, value) -> None:
|
def scaled_error(self, value) -> None:
|
||||||
self.error = value * self.scale
|
self.error = value * self.scale
|
||||||
|
Loading…
Reference in New Issue
Block a user