From 45d319834bfe9e2d2bcd09e8eef27127864d4b49 Mon Sep 17 00:00:00 2001 From: Dominik Demuth Date: Fri, 12 May 2023 20:13:56 +0200 Subject: [PATCH] fitresult window is reused and remembers fitplot range/log; closes #65 add color to sub-functions in fit result window Fitresult window shows one set at a time, more space for plot; closes #66 --- src/gui_qt/_py/fitresult.py | 109 ++++++++++-------- src/gui_qt/fit/result.py | 202 +++++++++++++++++---------------- src/gui_qt/lib/utils.py | 2 +- src/gui_qt/main/mainwindow.py | 18 +-- src/nmreval/fit/result.py | 1 + src/resources/_ui/fitresult.ui | 186 ++++++++++++++++-------------- 6 files changed, 281 insertions(+), 237 deletions(-) diff --git a/src/gui_qt/_py/fitresult.py b/src/gui_qt/_py/fitresult.py index ae2d077..ebb298e 100644 --- a/src/gui_qt/_py/fitresult.py +++ b/src/gui_qt/_py/fitresult.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'src/resources/_ui/fitresult.ui' # -# Created by: PyQt5 UI code generator 5.15.2 +# Created by: PyQt5 UI code generator 5.15.9 # # 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. @@ -14,37 +14,28 @@ from PyQt5 import QtCore, QtGui, QtWidgets class Ui_Dialog(object): def setupUi(self, Dialog): Dialog.setObjectName("Dialog") - Dialog.resize(864, 649) + Dialog.resize(864, 712) self.gridLayout = QtWidgets.QGridLayout(Dialog) self.gridLayout.setObjectName("gridLayout") - self.sets_comboBox = ElideComboBox(Dialog) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.sets_comboBox.sizePolicy().hasHeightForWidth()) - self.sets_comboBox.setSizePolicy(sizePolicy) - self.sets_comboBox.setMaximumSize(QtCore.QSize(400, 16777215)) - self.sets_comboBox.setBaseSize(QtCore.QSize(200, 0)) - self.sets_comboBox.setSizeAdjustPolicy(QtWidgets.QComboBox.AdjustToMinimumContentsLength) - self.sets_comboBox.setObjectName("sets_comboBox") - self.gridLayout.addWidget(self.sets_comboBox, 0, 0, 1, 1) + self.horizontalLayout_2 = QtWidgets.QHBoxLayout() + self.horizontalLayout_2.setSpacing(3) + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.reject_fit_checkBox = QtWidgets.QCheckBox(Dialog) + self.reject_fit_checkBox.setObjectName("reject_fit_checkBox") + self.horizontalLayout_2.addWidget(self.reject_fit_checkBox) + self.del_prev_checkBox = QtWidgets.QCheckBox(Dialog) + self.del_prev_checkBox.setObjectName("del_prev_checkBox") + self.horizontalLayout_2.addWidget(self.del_prev_checkBox) + self.gridLayout.addLayout(self.horizontalLayout_2, 2, 0, 1, 2) + self.line = QtWidgets.QFrame(Dialog) + self.line.setFrameShape(QtWidgets.QFrame.HLine) + self.line.setFrameShadow(QtWidgets.QFrame.Sunken) + self.line.setObjectName("line") + self.gridLayout.addWidget(self.line, 3, 0, 1, 2) self.buttonBox = QtWidgets.QDialogButtonBox(Dialog) self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok|QtWidgets.QDialogButtonBox.Retry) self.buttonBox.setObjectName("buttonBox") self.gridLayout.addWidget(self.buttonBox, 6, 0, 1, 2) - self.param_tableWidget = QtWidgets.QTableWidget(Dialog) - self.param_tableWidget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) - self.param_tableWidget.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustIgnored) - self.param_tableWidget.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers) - self.param_tableWidget.setAlternatingRowColors(True) - self.param_tableWidget.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection) - self.param_tableWidget.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectColumns) - self.param_tableWidget.setShowGrid(False) - self.param_tableWidget.setColumnCount(0) - self.param_tableWidget.setObjectName("param_tableWidget") - self.param_tableWidget.setRowCount(0) - self.param_tableWidget.horizontalHeader().setStretchLastSection(False) - self.gridLayout.addWidget(self.param_tableWidget, 1, 0, 1, 1) self.groupBox = QtWidgets.QGroupBox(Dialog) self.groupBox.setObjectName("groupBox") self.gridLayout_2 = QtWidgets.QGridLayout(self.groupBox) @@ -113,21 +104,34 @@ class Ui_Dialog(object): self.horizontalLayout.addWidget(self.partial_checkBox) self.gridLayout_2.addLayout(self.horizontalLayout, 0, 0, 1, 4) self.gridLayout.addWidget(self.groupBox, 5, 0, 1, 2) - self.horizontalLayout_2 = QtWidgets.QHBoxLayout() - self.horizontalLayout_2.setSpacing(3) - self.horizontalLayout_2.setObjectName("horizontalLayout_2") - self.reject_fit_checkBox = QtWidgets.QCheckBox(Dialog) - self.reject_fit_checkBox.setObjectName("reject_fit_checkBox") - self.horizontalLayout_2.addWidget(self.reject_fit_checkBox) - self.del_prev_checkBox = QtWidgets.QCheckBox(Dialog) - self.del_prev_checkBox.setObjectName("del_prev_checkBox") - self.horizontalLayout_2.addWidget(self.del_prev_checkBox) - self.gridLayout.addLayout(self.horizontalLayout_2, 2, 0, 1, 1) - self.line = QtWidgets.QFrame(Dialog) - self.line.setFrameShape(QtWidgets.QFrame.HLine) - self.line.setFrameShadow(QtWidgets.QFrame.Sunken) - self.line.setObjectName("line") - self.gridLayout.addWidget(self.line, 3, 0, 1, 2) + self.param_tableWidget = QtWidgets.QTableWidget(Dialog) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.param_tableWidget.sizePolicy().hasHeightForWidth()) + self.param_tableWidget.setSizePolicy(sizePolicy) + self.param_tableWidget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) + self.param_tableWidget.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustIgnored) + self.param_tableWidget.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers) + self.param_tableWidget.setAlternatingRowColors(True) + self.param_tableWidget.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection) + self.param_tableWidget.setColumnCount(1) + self.param_tableWidget.setObjectName("param_tableWidget") + self.param_tableWidget.setRowCount(0) + self.param_tableWidget.horizontalHeader().setVisible(False) + self.param_tableWidget.horizontalHeader().setStretchLastSection(True) + self.gridLayout.addWidget(self.param_tableWidget, 1, 0, 1, 1) + self.sets_comboBox = ElideComboBox(Dialog) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.sets_comboBox.sizePolicy().hasHeightForWidth()) + self.sets_comboBox.setSizePolicy(sizePolicy) + self.sets_comboBox.setMaximumSize(QtCore.QSize(400, 16777215)) + self.sets_comboBox.setBaseSize(QtCore.QSize(200, 0)) + self.sets_comboBox.setSizeAdjustPolicy(QtWidgets.QComboBox.AdjustToMinimumContentsLength) + self.sets_comboBox.setObjectName("sets_comboBox") + self.gridLayout.addWidget(self.sets_comboBox, 0, 0, 1, 1) self.stack = QtWidgets.QTabWidget(Dialog) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) @@ -149,10 +153,18 @@ class Ui_Dialog(object): self.logx_box.setLayoutDirection(QtCore.Qt.RightToLeft) self.logx_box.setObjectName("logx_box") self.gridLayout_3.addWidget(self.logx_box, 2, 0, 1, 1) - self.graphicsView = GraphicsLayoutWidget(self.stackPage1) - self.graphicsView.setObjectName("graphicsView") - self.gridLayout_3.addWidget(self.graphicsView, 0, 0, 1, 2) + self.fit_plot = PlotWidget(self.stackPage1) + self.fit_plot.setObjectName("fit_plot") + self.gridLayout_3.addWidget(self.fit_plot, 0, 0, 1, 2) self.stack.addTab(self.stackPage1, "") + self.tab = QtWidgets.QWidget() + self.tab.setObjectName("tab") + self.verticalLayout = QtWidgets.QVBoxLayout(self.tab) + self.verticalLayout.setObjectName("verticalLayout") + self.resid_plot = PlotWidget(self.tab) + self.resid_plot.setObjectName("resid_plot") + self.verticalLayout.addWidget(self.resid_plot) + self.stack.addTab(self.tab, "") self.stackPage2 = QtWidgets.QWidget() self.stackPage2.setObjectName("stackPage2") self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.stackPage2) @@ -194,7 +206,7 @@ class Ui_Dialog(object): self.corr_tableWidget.verticalHeader().setVisible(False) self.verticalLayout_3.addWidget(self.corr_tableWidget) self.stack.addTab(self.stackPage3, "") - self.gridLayout.addWidget(self.stack, 0, 1, 3, 1) + self.gridLayout.addWidget(self.stack, 0, 1, 2, 1) self.retranslateUi(Dialog) self.stack.setCurrentIndex(0) @@ -203,6 +215,8 @@ class Ui_Dialog(object): def retranslateUi(self, Dialog): _translate = QtCore.QCoreApplication.translate Dialog.setWindowTitle(_translate("Dialog", "Fit results")) + self.reject_fit_checkBox.setText(_translate("Dialog", "Reject this fit")) + self.del_prev_checkBox.setText(_translate("Dialog", "Delete previous fits")) self.groupBox.setTitle(_translate("Dialog", "Output")) self.extrapolate_box.setToolTip(_translate("Dialog", "Extrapolates only main function")) self.extrapolate_box.setText(_translate("Dialog", "Extrapolate curves")) @@ -215,11 +229,10 @@ class Ui_Dialog(object): self.numx_line.setPlaceholderText(_translate("Dialog", "# pts")) self.curve_checkbox.setText(_translate("Dialog", "Plot fit curve")) self.partial_checkBox.setText(_translate("Dialog", "Plot partial functions")) - self.reject_fit_checkBox.setText(_translate("Dialog", "Reject this fit")) - self.del_prev_checkBox.setText(_translate("Dialog", "Delete previous fits")) self.logy_box.setText(_translate("Dialog", "logarithmic y axis")) self.logx_box.setText(_translate("Dialog", "logarithmic x axis")) self.stack.setTabText(self.stack.indexOf(self.stackPage1), _translate("Dialog", "Plot")) + self.stack.setTabText(self.stack.indexOf(self.tab), _translate("Dialog", "Residuals")) self.stack.setTabText(self.stack.indexOf(self.stackPage2), _translate("Dialog", "Statistics")) item = self.corr_tableWidget.horizontalHeaderItem(0) item.setText(_translate("Dialog", "Parameter 1")) @@ -231,4 +244,4 @@ class Ui_Dialog(object): item.setText(_translate("Dialog", "Partial Corr.")) self.stack.setTabText(self.stack.indexOf(self.stackPage3), _translate("Dialog", "Correlations")) from ..lib.forms import ElideComboBox -from pyqtgraph import GraphicsLayoutWidget +from pyqtgraph import PlotWidget diff --git a/src/gui_qt/fit/result.py b/src/gui_qt/fit/result.py index 92a4f74..f8c79b9 100644 --- a/src/gui_qt/fit/result.py +++ b/src/gui_qt/fit/result.py @@ -27,70 +27,76 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog): self.extrapolate_box.stateChanged.connect(lambda x: self.minx_line.setEnabled(x)) self.extrapolate_box.stateChanged.connect(lambda x: self.numx_line.setEnabled(x)) - self._prevs = {} - self._models = {} + self._previous_fits = {} + self._opts = [] + self._results = {} + self.graph_opts = {} + self.last_idx = None - for res in results: - idx = res.idx - data_k = management.data[idx] - - if res.name not in self._models: - self._models[res.name] = [] - - self._models[res.name].append(idx) - - self._prevs[idx] = [] - for fit in data_k.get_fits(): - self._prevs[idx].append((fit.name, fit.statistics, fit.nobs-fit.nvar)) - - self._results = {res.idx: res for res in results} - self._opts = [(False, False) for _ in range(len(self._results))] - - self.residplot = self.graphicsView.addPlot(row=0, col=0) self.resid_graph = PlotItem(x=[], y=[], symbol='o', symbolPen=None, symbolBrush=mkBrush(color=(31, 119, 180)), pen=None) self.resid_graph_imag = PlotItem(x=[], y=[], symbol='s', symbolPen=None, symbolBrush=mkBrush(color=(255, 127, 14)), pen=None) - self.residplot.addItem(self.resid_graph) - self.residplot.addItem(self.resid_graph_imag) - self.residplot.setLabel('left', 'Residual') + self.resid_plot.addItem(self.resid_graph) + self.resid_plot.addItem(self.resid_graph_imag) + self.resid_plot.setLabel('left', 'Residual') - self.fitplot = self.graphicsView.addPlot(row=1, col=0) self.data_graph = PlotItem(x=[], y=[], symbol='o', symbolPen=None, symbolBrush=mkBrush(color=(31, 119, 180)), pen=None) self.data_graph_imag = PlotItem(x=[], y=[], symbol='s', symbolPen=None, symbolBrush=mkBrush(color=(255, 127, 14)), pen=None) - self.fitplot.addItem(self.data_graph) - self.fitplot.addItem(self.data_graph_imag) - self.fitplot.setLabel('left', 'Function') + self.fit_plot.addItem(self.data_graph) + self.fit_plot.addItem(self.data_graph_imag) + self.fit_plot.setLabel('left', 'Function') self.fit_graph = PlotItem(x=[], y=[]) self.fit_graph_imag = PlotItem(x=[], y=[]) - self.fitplot.addItem(self.fit_graph) - self.fitplot.addItem(self.fit_graph_imag) + self.fit_plot.addItem(self.fit_graph) + self.fit_plot.addItem(self.fit_graph_imag) self.cmap = RdBuCMap(vmin=-1, vmax=1) - self.sets_comboBox.blockSignals(True) - for n in self._models.keys(): - self.sets_comboBox.addItem(n) - self.sets_comboBox.blockSignals(False) - - self.set_parameter(0) self.buttonBox.accepted.connect(self.accept) - self.param_tableWidget.itemClicked.connect(self.show_results) - self.param_tableWidget.horizontalHeader().sectionClicked.connect(lambda i: self.show_results(None, idx=i)) - self.graph_checkBox.stateChanged.connect(lambda x: self.graph_comboBox.setEnabled(x == QtCore.Qt.Unchecked)) - self.logy_box.stateChanged.connect(lambda x: self.fitplot.setLogMode(y=bool(x))) - self.logx_box.stateChanged.connect(lambda x: self.fitplot.setLogMode(x=bool(x))) - self.residplot.setXLink(self.fitplot) + self.logy_box.stateChanged.connect(lambda x: self.fit_plot.setLogMode(y=bool(x))) + self.logx_box.stateChanged.connect(lambda x: self.fit_plot.setLogMode(x=bool(x))) + self.resid_plot.setXLink(self.fit_plot) + + self.set_results(results) + + def __call__(self, results: list): + self._previous_fits = {} + self.sets_comboBox.blockSignals(True) + self.sets_comboBox.clear() + self.sets_comboBox.blockSignals(False) + self._results = {} + self._opts = {} + + self.set_results(results) + + def set_results(self, results: list): + self.sets_comboBox.blockSignals(True) + for res in results: + idx = res.idx + data_k = self._management.data[idx] + + self._previous_fits[idx] = [] + for fit in data_k.get_fits(): + self._previous_fits[idx].append((fit.name, fit.statistics, fit.nobs - fit.nvar)) + + self.sets_comboBox.addItem(data_k.name, userData=idx) + self.sets_comboBox.blockSignals(False) + + self._results = {res.idx: res for res in results} + self._opts = [(False, False) for _ in range(len(self._results))] + + self.set_parameter(0) def add_graphs(self, graphs: list): self.graph_comboBox.clear() @@ -99,56 +105,40 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog): @QtCore.pyqtSlot(int, name='on_sets_comboBox_currentIndexChanged') def set_parameter(self, idx: int): - model_name = self.sets_comboBox.itemText(idx) - sets = self._models[model_name] - self.param_tableWidget.setColumnCount(len(sets)) + set_id = self.sets_comboBox.itemData(idx, QtCore.Qt.UserRole) - r = self._results[sets[0]] - self.param_tableWidget.setRowCount(len(r.parameter)) + res = self._results[set_id] + self.param_tableWidget.setRowCount(len(res.parameter)) + for j, pvalue in enumerate(res.parameter.values()): + name = pvalue.name + p_header = QtWidgets.QTableWidgetItem(convert(name, 'tex', 'str', brackets=True)) + self.param_tableWidget.setVerticalHeaderItem(j, p_header) - for i, pval in enumerate(r.parameter.values()): - name = pval.full_name - p_header = QtWidgets.QTableWidgetItem(convert(name, 'tex', 'html', brackets=False)) - self.param_tableWidget.setVerticalHeaderItem(i, p_header) + item_text = f'{pvalue.value:.4g}' + if pvalue.error is not None: + item_text += f' \u00b1 {pvalue.error:.4g}' + self.param_tableWidget.setItem(2*j+1, 0, QtWidgets.QTableWidgetItem('-')) + else: + self.param_tableWidget.setItem(2*j+1, 0, QtWidgets.QTableWidgetItem()) + item = QtWidgets.QTableWidgetItem(item_text) + self.param_tableWidget.setItem(j, 0, item) - for i, set_id in enumerate(sets): - data_i = self._management[set_id] - header_item = QtWidgets.QTableWidgetItem(data_i.name) - header_item.setData(QtCore.Qt.UserRole, set_id) - self.param_tableWidget.setHorizontalHeaderItem(i, header_item) - - res = self._results[set_id] - for j, pvalue in enumerate(res.parameter.values()): - item_text = f'{pvalue.value:.4g}' - if pvalue.error is not None: - item_text += f' \u00b1 {pvalue.error:.4g}' - self.param_tableWidget.setItem(2*j+1, i, QtWidgets.QTableWidgetItem('-')) - else: - self.param_tableWidget.setItem(2*j+1, i, QtWidgets.QTableWidgetItem()) - item = QtWidgets.QTableWidgetItem(item_text) - self.param_tableWidget.setItem(j, i, item) - - self.param_tableWidget.resizeColumnsToContents() - self.param_tableWidget.selectColumn(0) - self.show_results(None, idx=0) + self.param_tableWidget.resizeColumnToContents(0) + self.show_results(idx) @QtCore.pyqtSlot(int, name='on_reject_fit_checkBox_stateChanged') @QtCore.pyqtSlot(int, name='on_del_prev_checkBox_stateChanged') def change_opts(self, _): - idx = self.param_tableWidget.currentIndex().column() + idx = self.sets_comboBox.currentIndex() self._opts[idx] = (self.reject_fit_checkBox.checkState() == QtCore.Qt.Checked, self.del_prev_checkBox.checkState() == QtCore.Qt.Checked) - def show_results(self, item, idx=None): - if item is not None: - idx = self.param_tableWidget.indexFromItem(item).column() - - set_id = self.param_tableWidget.horizontalHeaderItem(idx).data(QtCore.Qt.UserRole) + def show_results(self, idx): + set_id = self.sets_comboBox.itemData(idx, QtCore.Qt.UserRole) self.set_plot(set_id) self.set_correlation(set_id) self.set_statistics(set_id) - self.reject_fit_checkBox.blockSignals(True) self.reject_fit_checkBox.setChecked(self._opts[idx][0]) self.reject_fit_checkBox.blockSignals(False) @@ -157,13 +147,21 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog): self.del_prev_checkBox.blockSignals(False) def set_plot(self, idx: str): + if self.last_idx is not None: + self.graph_opts[self.last_idx] = ( + self.fit_plot.getPlotItem().viewRange(), + self.logx_box.isChecked(), + self.logy_box.isChecked(), + ) + + self.last_idx = idx res = self._results[idx] iscomplex = res.iscomplex sub_funcs = res.sub(res.x) - for item in self.fitplot.curves[::-1]: + for item in self.fit_plot.plotItem.items[::-1]: if item not in [self.data_graph, self.data_graph_imag, self.fit_graph, self.fit_graph_imag]: - self.fitplot.removeItem(item) + self.fit_plot.removeItem(item) if iscomplex: self.data_graph.setData(x=res.x_data, y=res.y_data.real) @@ -173,11 +171,11 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog): self.resid_graph.setData(x=res.x_data, y=res.residual.real) self.resid_graph_imag.setData(x=res.x_data, y=res.residual.imag) - for f in sub_funcs: - item = PlotItem(x=f.x, y=f.y.real) - self.fitplot.addItem(item) - item = PlotItem(x=f.x, y=f.y.imag) - self.fitplot.addItem(item) + for i, f in enumerate(sub_funcs): + item = PlotItem(x=f.x, y=f.y.real, pen=mkPen({'color': i, 'style': 2})) + self.fit_plot.addItem(item) + item = PlotItem(x=f.x, y=f.y.imag, pen=mkPen({'color': i, 'style': 2})) + self.fit_plot.addItem(item) else: self.resid_graph.setData(x=res.x_data, y=res.residual) @@ -187,12 +185,27 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog): self.fit_graph.setData(x=res.x, y=res.y) self.fit_graph_imag.setData(x=[], y=[]) - for f in sub_funcs: - item = PlotItem(x=f.x, y=f.y, pen=mkPen({'style': 2})) - self.fitplot.addItem(item) + for i, f in enumerate(sub_funcs): + item = PlotItem(x=f.x, y=f.y, pen=mkPen({'color': i, 'style': 2})) + self.fit_plot.addItem(item) - self.fitplot.setLogMode(x=res.islog) - self.residplot.setLogMode(x=res.islog) + self.logx_box.blockSignals(True) + self.logx_box.setChecked(res.islog) + self.logx_box.blockSignals(False) + + self.fit_plot.setLogMode(x=res.islog) + self.resid_plot.setLogMode(x=res.islog) + + if idx in self.graph_opts: + view_range, logx, logy = self.graph_opts[idx] + 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.setChecked(logx) + self.logx_box.blockSignals(False) + self.logy_box.blockSignals(True) + self.logy_box.setChecked(logy) + self.logy_box.blockSignals(False) def set_correlation(self, idx: str): while self.corr_tableWidget.rowCount(): @@ -223,7 +236,7 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog): res = self._results[idx] - self.stats_tableWidget.setColumnCount(1 + len(self._prevs[idx])) + self.stats_tableWidget.setColumnCount(1 + len(self._previous_fits[idx])) self.stats_tableWidget.setRowCount(len(res.statistics)+3) it = QtWidgets.QTableWidgetItem(f'{res.dof}') @@ -231,7 +244,7 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog): self.stats_tableWidget.setVerticalHeaderItem(0, QtWidgets.QTableWidgetItem('DoF')) self.stats_tableWidget.setItem(0, 0, it) - for col, (name, _, dof) in enumerate(self._prevs[idx], start=1): + for col, (name, _, dof) in enumerate(self._previous_fits[idx], start=1): self.stats_tableWidget.setHorizontalHeaderItem(0, QtWidgets.QTableWidgetItem(name)) it = QtWidgets.QTableWidgetItem(f'{dof}') it.setFlags(it.flags() ^ QtCore.Qt.ItemIsEditable) @@ -245,7 +258,7 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog): best_idx = -1 best_val = v - for col, (_, stats, _) in enumerate(self._prevs[idx], start=1): + for col, (_, stats, _) in enumerate(self._previous_fits[idx], start=1): if k in ['adj. R^2', 'R^2']: best_idx = col if best_val < stats[k] else max(0, best_idx) else: @@ -265,7 +278,7 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog): self.stats_tableWidget.setVerticalHeaderItem(row+1, QtWidgets.QTableWidgetItem('Pr(>F)')) self.stats_tableWidget.setItem(row+1, 0, QtWidgets.QTableWidgetItem('-')) - for col, (_, stats, dof) in enumerate(self._prevs[idx], start=1): + for col, (_, stats, dof) in enumerate(self._previous_fits[idx], start=1): f_value, prob_f = res.f_test(stats['chi^2'], dof) it = QtWidgets.QTableWidgetItem(f'{f_value:.4g}') it.setFlags(it.flags() ^ QtCore.Qt.ItemIsEditable) @@ -312,7 +325,6 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog): except TypeError: pass - self.closed.emit(self._results, self._opts, graph, plot_fits, parts, extrapolate) self.accept() @@ -348,7 +360,7 @@ class FitExtension(QtWidgets.QDialog): self.buttonBox = QtWidgets.QDialogButtonBox() self.buttonBox.setOrientation(QtCore.Qt.Horizontal) - self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok) + self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel | QtWidgets.QDialogButtonBox.Ok) gridLayout.addWidget(self.buttonBox, 3, 0, 1, 2) self.setLayout(gridLayout) @@ -365,4 +377,4 @@ class FitExtension(QtWidgets.QDialog): except TypeError: return None - return xmin, xmax, nums \ No newline at end of file + return xmin, xmax, nums diff --git a/src/gui_qt/lib/utils.py b/src/gui_qt/lib/utils.py index db0de99..2849e3f 100644 --- a/src/gui_qt/lib/utils.py +++ b/src/gui_qt/lib/utils.py @@ -58,7 +58,7 @@ class RdBuCMap: elif val < self.min: col = QtGui.QColor.fromRgb(*RdBuCMap._rdbu[-1]) else: - col = QtGui.QColor.fromRgbF(*(float(self.spline[i](val)) for i in range(3))) + col = QtGui.QColor.fromRgb(*(int(self.spline[i](val)) for i in range(3))) return col diff --git a/src/gui_qt/main/mainwindow.py b/src/gui_qt/main/mainwindow.py index e228552..0bb4938 100644 --- a/src/gui_qt/main/mainwindow.py +++ b/src/gui_qt/main/mainwindow.py @@ -55,7 +55,7 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow): self.fitlimitvalues = [None, None] self.fitpreview = [] self._fit_plot_id = None - self.savefitdialog = None + self.fitresult_dialog = None self.eval = None self.editor = None @@ -77,7 +77,7 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow): self.__timer = QtCore.QTimer() self.__backup_path = config_paths() / f'{datetime.datetime.now().strftime("%Y-%m-%d_%H%M%S")}.nmr' - self.__timer.start(3*60*1000) # every three minutese + self.__timer.start(3*60*1000) # every three minutes self.__timer.timeout.connect(self._autosave) self.fit_timer = QtCore.QTimer() @@ -920,11 +920,15 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow): self.fit_timer.stop() self.status.setText('') if results: - res_dialog = QFitResult(results, self.management, parent=self) - res_dialog.add_graphs(self.management.graphs.list()) - res_dialog.closed.connect(self.accepts_fit) - res_dialog.redoFit.connect(self.management.redo_fits) - res_dialog.show() + if self.fitresult_dialog is None: + self.fitresult_dialog = QFitResult(results, self.management, parent=self) + self.fitresult_dialog.add_graphs(self.management.graphs.list()) + self.fitresult_dialog.closed.connect(self.accepts_fit) + self.fitresult_dialog.redoFit.connect(self.management.redo_fits) + else: + self.fitresult_dialog(results) + self.fitresult_dialog.add_graphs(self.management.graphs.list()) + self.fitresult_dialog.show() @QtCore.pyqtSlot(dict, list, str, bool, bool, list) def accepts_fit(self, res: dict, opts: list, param_graph: str, diff --git a/src/nmreval/fit/result.py b/src/nmreval/fit/result.py index 74c1c47..95037f0 100644 --- a/src/nmreval/fit/result.py +++ b/src/nmreval/fit/result.py @@ -230,6 +230,7 @@ class FitResult(Points): ret_val = '' for pval in self.parameter.values(): + print(pval) ret_val += convert(str(pval), old='tex', new='str') + '\n' if self.fun_kwargs: diff --git a/src/resources/_ui/fitresult.ui b/src/resources/_ui/fitresult.ui index c6dd2c0..cd2b130 100644 --- a/src/resources/_ui/fitresult.ui +++ b/src/resources/_ui/fitresult.ui @@ -7,35 +7,38 @@ 0 0 864 - 649 + 712 Fit results - - - - - 0 - 0 - + + + + 3 - - - 400 - 16777215 - - - - - 200 - 0 - - - - QComboBox::AdjustToMinimumContentsLength + + + + Reject this fit + + + + + + + Delete previous fits + + + + + + + + + Qt::Horizontal @@ -46,37 +49,6 @@ - - - - Qt::ScrollBarAsNeeded - - - QAbstractScrollArea::AdjustIgnored - - - QAbstractItemView::NoEditTriggers - - - true - - - QAbstractItemView::SingleSelection - - - QAbstractItemView::SelectColumns - - - false - - - 0 - - - false - - - @@ -223,35 +195,67 @@ - - - - 3 + + + + + 0 + 0 + - - - - Reject this fit - - - - - - - Delete previous fits - - - - + + Qt::ScrollBarAsNeeded + + + QAbstractScrollArea::AdjustIgnored + + + QAbstractItemView::NoEditTriggers + + + true + + + QAbstractItemView::NoSelection + + + 1 + + + false + + + true + + + - - - - Qt::Horizontal + + + + + 0 + 0 + + + + + 400 + 16777215 + + + + + 200 + 0 + + + + QComboBox::AdjustToMinimumContentsLength - + @@ -262,7 +266,7 @@ 0 - + Plot @@ -303,11 +307,21 @@ - + - + + + Residuals + + + + + + + + Statistics @@ -349,7 +363,7 @@ - + Correlations @@ -415,16 +429,16 @@ - - GraphicsLayoutWidget - QGraphicsView -
pyqtgraph
-
ElideComboBox QComboBox
..lib.forms
+ + PlotWidget + QGraphicsView +
pyqtgraph
+