From 1e9a390ae2a286f75997dd2f85416b1ec54e91b7 Mon Sep 17 00:00:00 2001 From: Dominik Demuth Date: Fri, 19 May 2023 16:17:49 +0200 Subject: [PATCH 1/4] attempt to distinguish general and set-specifi parameter --- src/gui_qt/fit/fit_parameter.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/gui_qt/fit/fit_parameter.py b/src/gui_qt/fit/fit_parameter.py index 69b7301..fb36072 100644 --- a/src/gui_qt/fit/fit_parameter.py +++ b/src/gui_qt/fit/fit_parameter.py @@ -181,6 +181,7 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit): for i, value in enumerate(self.data_values[sid]): w = self.data_parameter[i] w.blockSignals(True) + w.show_as_local_parameter(value is not None) if value is None: w.value = self.glob_values[i] else: @@ -293,6 +294,7 @@ class ParameterSingleWidget(QtWidgets.QWidget): self._name = name self.label.setText(convert(name)) + self.label.setToolTip('IIf this is bold then this parameter is only for this data. otherwise the general parameter is used and displayed') self.value_line.setValidator(QtGui.QDoubleValidator()) self.value_line.textChanged.connect(lambda: self.valueChanged.emit(self.value) if self.value is not None else 0) @@ -309,10 +311,12 @@ class ParameterSingleWidget(QtWidgets.QWidget): layout.addSpacerItem(QtWidgets.QSpacerItem(0, 0, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)) self.value_line = QtWidgets.QLineEdit(self) + self.value_line.textEdited.connect(lambda x: self.show_as_local_parameter(True)) layout.addWidget(self.value_line) self.reset_button = QtWidgets.QToolButton(self) self.reset_button.setText('Use global') + self.reset_button.clicked.connect(lambda: self.show_as_local_parameter(False)) layout.addWidget(self.reset_button) self.setLayout(layout) @@ -327,3 +331,9 @@ class ParameterSingleWidget(QtWidgets.QWidget): @value.setter def value(self, val): self.value_line.setText(f'{float(val):.5g}') + + def show_as_local_parameter(self, is_local): + if is_local: + self.label.setStyleSheet('font-weight: bold;') + else: + self.label.setStyleSheet('') From f60e125487be76d412c0f2e3c7c77cca709c6877 Mon Sep 17 00:00:00 2001 From: Dominik Demuth Date: Fri, 19 May 2023 16:41:24 +0200 Subject: [PATCH 2/4] display parameter name with number ind window --- src/gui_qt/fit/result.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui_qt/fit/result.py b/src/gui_qt/fit/result.py index 22ef2a1..d854ce4 100644 --- a/src/gui_qt/fit/result.py +++ b/src/gui_qt/fit/result.py @@ -113,8 +113,8 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog): res = self._results[set_id] self.param_tableWidget.setRowCount(len(res.parameter)) - for j, pvalue in enumerate(res.parameter.values()): - name = pvalue.name + for j, (pkey, pvalue) in enumerate(res.parameter.items()): + name = pkey p_header = QtWidgets.QTableWidgetItem(convert(name, 'tex', 'str', brackets=True)) self.param_tableWidget.setVerticalHeaderItem(j, p_header) From 2adf15104f052ad5e47e6d623ecd62015cf2a7dc Mon Sep 17 00:00:00 2001 From: Dominik Demuth Date: Fri, 19 May 2023 17:35:32 +0200 Subject: [PATCH 3/4] attempt to only show real/imag part of complex fit functions; closes #72 --- src/nmreval/fit/result.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/nmreval/fit/result.py b/src/nmreval/fit/result.py index c888b32..c7bd517 100644 --- a/src/nmreval/fit/result.py +++ b/src/nmreval/fit/result.py @@ -63,9 +63,19 @@ class FitResultCreator: parameters = OrderedDict([(k, v) for k, v in zip(pnames, p)]) p_final = [p.value for p in parameters.values()] - _y = model.func(p_final, _x, **fun_kwargs) resid = model.func(p_final, x_orig, **fun_kwargs) - y_orig + actual_complex_mode = 0 + if 'complex_mode' in fun_kwargs: + actual_complex_mode = fun_kwargs['complex_mode'] + fun_kwargs['complex_mode'] = 0 + + _y = model.func(p_final, _x, **fun_kwargs) + if actual_complex_mode == 1: + _y.imag = 0 + elif actual_complex_mode == 2: + _y.real = 0 + stats = FitResultCreator.calc_statistics(_y, resid, nobs, nvar) varied = [p.var for p in parameters.values()] @@ -356,7 +366,7 @@ class FitResult(Points): def with_new_x(self, x_values): if self.func is None: - raise ValueError('no fit function available to calcualate new y values') + raise ValueError('no fit function available to calculate new y values') new_fit = self.copy() y_values = self.func.func(self.p_final, x_values, **self.fun_kwargs) @@ -372,4 +382,4 @@ class FitResult(Points): else: part_functions.append(Points(x_values, sub_y, name=sub_name)) - return part_functions \ No newline at end of file + return part_functions From 65034d45189630e8531b5844edba3c145710aa29 Mon Sep 17 00:00:00 2001 From: Dominik Demuth Date: Fri, 19 May 2023 18:13:57 +0200 Subject: [PATCH 4/4] sub function show numbering; closes #70 --- src/gui_qt/main/management.py | 6 ++--- src/nmreval/fit/_meta.py | 5 ++-- src/nmreval/fit/result.py | 45 +++++++++++++++++++++++++++++------ 3 files changed, 43 insertions(+), 13 deletions(-) diff --git a/src/gui_qt/main/management.py b/src/gui_qt/main/management.py index 0a817c1..a85e4d1 100644 --- a/src/gui_qt/main/management.py +++ b/src/gui_qt/main/management.py @@ -653,12 +653,10 @@ class UpperManagement(QtCore.QObject): else: continue - for key, pvalue in data.parameter.items(): - name = pvalue.full_name - fit_key = key + data.model_name + for fit_key, pvalue in data.parameter.items(): if fit_key not in fit_dict: - fit_dict[fit_key] = [[], name] + fit_dict[fit_key] = [[], fit_key] err = 0 if pvalue.error is None else pvalue.error diff --git a/src/nmreval/fit/_meta.py b/src/nmreval/fit/_meta.py index 230cb68..9fe9c34 100644 --- a/src/nmreval/fit/_meta.py +++ b/src/nmreval/fit/_meta.py @@ -68,6 +68,7 @@ class MultiModel: self._kwargs_right = {} self._kwargs_left = {} self.fun_kwargs = {} + self.idx = (left_idx, right_idx) # mapping kwargs to kwargs of underlying functions self._ext_int_kw = {} @@ -178,13 +179,13 @@ class MultiModel: if isinstance(self._left, MultiModel): yield from self._left.sub_name() elif hasattr(self._left, 'name'): - yield self._left.name + yield f'{self._left.name}({self.idx[0]})' else: yield self.name + '(lhs)' if isinstance(self._right, MultiModel): yield from self._right.sub_name() elif hasattr(self._right, 'name'): - yield self._right.name + yield f'{self._right.name}({self.idx[1]})' else: yield self.name + '(rhs)' diff --git a/src/nmreval/fit/result.py b/src/nmreval/fit/result.py index c7bd517..65d340d 100644 --- a/src/nmreval/fit/result.py +++ b/src/nmreval/fit/result.py @@ -65,16 +65,20 @@ class FitResultCreator: resid = model.func(p_final, x_orig, **fun_kwargs) - y_orig - actual_complex_mode = 0 + actual_mode = -1 if 'complex_mode' in fun_kwargs: - actual_complex_mode = fun_kwargs['complex_mode'] + actual_mode = fun_kwargs['complex_mode'] fun_kwargs['complex_mode'] = 0 _y = model.func(p_final, _x, **fun_kwargs) - if actual_complex_mode == 1: - _y.imag = 0 - elif actual_complex_mode == 2: - _y.real = 0 + + if not actual_mode < 0: + if actual_mode == 1: + _y.imag = 0 + elif actual_mode == 2: + _y.real = 0 + + fun_kwargs['complex_mode'] = actual_mode stats = FitResultCreator.calc_statistics(_y, resid, nobs, nvar) varied = [p.var for p in parameters.values()] @@ -368,18 +372,45 @@ class FitResult(Points): if self.func is None: raise ValueError('no fit function available to calculate new y values') + actual_mode = -1 + if 'complex_mode' in self.fun_kwargs: + actual_mode = self.fun_kwargs['complex_mode'] + self.fun_kwargs['complex_mode'] = 0 + new_fit = self.copy() y_values = self.func.func(self.p_final, x_values, **self.fun_kwargs) + if not actual_mode < 0: + if actual_mode == 1: + y_values.imag = 0 + elif actual_mode == 2: + y_values.real = 0 + + self.fun_kwargs['complex_mode'] = actual_mode + new_fit.set_data(x_values, y_values) return new_fit def sub(self, x_values): part_functions = [] + actual_mode = -1 + if 'complex_mode' in self.fun_kwargs: + actual_mode = self.fun_kwargs['complex_mode'] + self.fun_kwargs['complex_mode'] = 0 + for sub_name, sub_y in zip(self.func.sub_name(), self.func.sub(self.p_final, x_values, **self.fun_kwargs)): - if np.iscomplexobj(sub_y): + if not actual_mode < 0: + if actual_mode == 1: + sub_y.imag = 0 + elif actual_mode == 2: + sub_y.real = 0 + part_functions.append(Signal(x_values, sub_y, name=sub_name)) + else: part_functions.append(Points(x_values, sub_y, name=sub_name)) + if actual_mode < 0: + self.fun_kwargs['complex_mode'] = actual_mode + return part_functions