use tree colors in fit result for sub-funcs #253
@ -17,7 +17,7 @@ body:
|
|||||||
description: For which version have you observed this behavior?
|
description: For which version have you observed this behavior?
|
||||||
placeholder: You find the program version in "Help/About"
|
placeholder: You find the program version in "Help/About"
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: false
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: Expected behavior
|
label: Expected behavior
|
||||||
|
@ -365,6 +365,9 @@ class Ui_BaseWindow(object):
|
|||||||
self.actionBinning.setObjectName("actionBinning")
|
self.actionBinning.setObjectName("actionBinning")
|
||||||
self.actionTNMH = QtWidgets.QAction(BaseWindow)
|
self.actionTNMH = QtWidgets.QAction(BaseWindow)
|
||||||
self.actionTNMH.setObjectName("actionTNMH")
|
self.actionTNMH.setObjectName("actionTNMH")
|
||||||
|
self.actionExclude_region = QtWidgets.QAction(BaseWindow)
|
||||||
|
self.actionExclude_region.setCheckable(True)
|
||||||
|
self.actionExclude_region.setObjectName("actionExclude_region")
|
||||||
self.menuSave.addAction(self.actionSave)
|
self.menuSave.addAction(self.actionSave)
|
||||||
self.menuSave.addAction(self.actionExportGraphic)
|
self.menuSave.addAction(self.actionExportGraphic)
|
||||||
self.menuSave.addAction(self.action_save_fit_parameter)
|
self.menuSave.addAction(self.action_save_fit_parameter)
|
||||||
@ -419,6 +422,7 @@ class Ui_BaseWindow(object):
|
|||||||
self.menuLimits.addAction(self.action_no_range)
|
self.menuLimits.addAction(self.action_no_range)
|
||||||
self.menuLimits.addAction(self.action_x_range)
|
self.menuLimits.addAction(self.action_x_range)
|
||||||
self.menuLimits.addAction(self.action_custom_range)
|
self.menuLimits.addAction(self.action_custom_range)
|
||||||
|
self.menuLimits.addAction(self.actionExclude_region)
|
||||||
self.menuFit.addAction(self.action_FitWidget)
|
self.menuFit.addAction(self.action_FitWidget)
|
||||||
self.menuFit.addSeparator()
|
self.menuFit.addSeparator()
|
||||||
self.menuFit.addAction(self.action_create_fit_function)
|
self.menuFit.addAction(self.action_create_fit_function)
|
||||||
@ -631,6 +635,7 @@ class Ui_BaseWindow(object):
|
|||||||
self.actionTNMH_model.setText(_translate("BaseWindow", "Tg , Hodge, TNMH,,,"))
|
self.actionTNMH_model.setText(_translate("BaseWindow", "Tg , Hodge, TNMH,,,"))
|
||||||
self.actionBinning.setText(_translate("BaseWindow", "Binning..."))
|
self.actionBinning.setText(_translate("BaseWindow", "Binning..."))
|
||||||
self.actionTNMH.setText(_translate("BaseWindow", "TNMH..."))
|
self.actionTNMH.setText(_translate("BaseWindow", "TNMH..."))
|
||||||
|
self.actionExclude_region.setText(_translate("BaseWindow", "Exclude region"))
|
||||||
from ..data.datawidget.datawidget import DataWidget
|
from ..data.datawidget.datawidget import DataWidget
|
||||||
from ..data.integral_widget import IntegralWidget
|
from ..data.integral_widget import IntegralWidget
|
||||||
from ..data.point_select import PointSelectWidget
|
from ..data.point_select import PointSelectWidget
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Form implementation generated from reading ui file 'resources/_ui/fitresult.ui'
|
# Form implementation generated from reading ui file 'src/resources/_ui/fitresult.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt5 UI code generator 5.15.10
|
# Created by: PyQt5 UI code generator 5.15.10
|
||||||
#
|
#
|
||||||
@ -157,67 +157,91 @@ class Ui_Dialog(object):
|
|||||||
self.gridLayout_2.setContentsMargins(3, 3, 3, 3)
|
self.gridLayout_2.setContentsMargins(3, 3, 3, 3)
|
||||||
self.gridLayout_2.setSpacing(3)
|
self.gridLayout_2.setSpacing(3)
|
||||||
self.gridLayout_2.setObjectName("gridLayout_2")
|
self.gridLayout_2.setObjectName("gridLayout_2")
|
||||||
self.extrapolate_box = QtWidgets.QCheckBox(self.groupBox)
|
|
||||||
self.extrapolate_box.setObjectName("extrapolate_box")
|
|
||||||
self.gridLayout_2.addWidget(self.extrapolate_box, 1, 0, 1, 1)
|
|
||||||
self.parameter_checkbox = QtWidgets.QCheckBox(self.groupBox)
|
|
||||||
self.parameter_checkbox.setObjectName("parameter_checkbox")
|
|
||||||
self.gridLayout_2.addWidget(self.parameter_checkbox, 0, 5, 1, 1)
|
|
||||||
self.graph_comboBox = QtWidgets.QComboBox(self.groupBox)
|
self.graph_comboBox = QtWidgets.QComboBox(self.groupBox)
|
||||||
self.graph_comboBox.setEnabled(False)
|
self.graph_comboBox.setEnabled(False)
|
||||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, 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.graph_comboBox.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.graph_comboBox.sizePolicy().hasHeightForWidth())
|
||||||
self.graph_comboBox.setSizePolicy(sizePolicy)
|
self.graph_comboBox.setSizePolicy(sizePolicy)
|
||||||
self.graph_comboBox.setObjectName("graph_comboBox")
|
self.graph_comboBox.setObjectName("graph_comboBox")
|
||||||
self.gridLayout_2.addWidget(self.graph_comboBox, 1, 6, 1, 1)
|
self.gridLayout_2.addWidget(self.graph_comboBox, 1, 7, 1, 1)
|
||||||
self.graph_checkBox = QtWidgets.QCheckBox(self.groupBox)
|
|
||||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
|
|
||||||
sizePolicy.setHorizontalStretch(0)
|
|
||||||
sizePolicy.setVerticalStretch(0)
|
|
||||||
sizePolicy.setHeightForWidth(self.graph_checkBox.sizePolicy().hasHeightForWidth())
|
|
||||||
self.graph_checkBox.setSizePolicy(sizePolicy)
|
|
||||||
self.graph_checkBox.setChecked(True)
|
|
||||||
self.graph_checkBox.setObjectName("graph_checkBox")
|
|
||||||
self.gridLayout_2.addWidget(self.graph_checkBox, 1, 5, 1, 1)
|
|
||||||
self.minx_line = QtWidgets.QLineEdit(self.groupBox)
|
self.minx_line = QtWidgets.QLineEdit(self.groupBox)
|
||||||
self.minx_line.setEnabled(False)
|
self.minx_line.setEnabled(False)
|
||||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
|
||||||
sizePolicy.setHorizontalStretch(0)
|
sizePolicy.setHorizontalStretch(0)
|
||||||
sizePolicy.setVerticalStretch(0)
|
sizePolicy.setVerticalStretch(0)
|
||||||
sizePolicy.setHeightForWidth(self.minx_line.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.minx_line.sizePolicy().hasHeightForWidth())
|
||||||
self.minx_line.setSizePolicy(sizePolicy)
|
self.minx_line.setSizePolicy(sizePolicy)
|
||||||
self.minx_line.setObjectName("minx_line")
|
self.minx_line.setObjectName("minx_line")
|
||||||
self.gridLayout_2.addWidget(self.minx_line, 1, 1, 1, 1)
|
self.gridLayout_2.addWidget(self.minx_line, 1, 1, 1, 1)
|
||||||
self.line_2 = QtWidgets.QFrame(self.groupBox)
|
self.extrapolate_box = QtWidgets.QCheckBox(self.groupBox)
|
||||||
self.line_2.setFrameShape(QtWidgets.QFrame.VLine)
|
self.extrapolate_box.setObjectName("extrapolate_box")
|
||||||
self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken)
|
self.gridLayout_2.addWidget(self.extrapolate_box, 1, 0, 1, 1)
|
||||||
self.line_2.setObjectName("line_2")
|
self.numx_line = QtWidgets.QLineEdit(self.groupBox)
|
||||||
self.gridLayout_2.addWidget(self.line_2, 0, 4, 2, 1)
|
self.numx_line.setEnabled(False)
|
||||||
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.numx_line.sizePolicy().hasHeightForWidth())
|
||||||
|
self.numx_line.setSizePolicy(sizePolicy)
|
||||||
|
self.numx_line.setObjectName("numx_line")
|
||||||
|
self.gridLayout_2.addWidget(self.numx_line, 1, 3, 1, 1)
|
||||||
|
self.graph_checkBox = QtWidgets.QCheckBox(self.groupBox)
|
||||||
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Fixed)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.graph_checkBox.sizePolicy().hasHeightForWidth())
|
||||||
|
self.graph_checkBox.setSizePolicy(sizePolicy)
|
||||||
|
self.graph_checkBox.setChecked(True)
|
||||||
|
self.graph_checkBox.setObjectName("graph_checkBox")
|
||||||
|
self.gridLayout_2.addWidget(self.graph_checkBox, 1, 6, 1, 1)
|
||||||
self.maxx_line = QtWidgets.QLineEdit(self.groupBox)
|
self.maxx_line = QtWidgets.QLineEdit(self.groupBox)
|
||||||
self.maxx_line.setEnabled(False)
|
self.maxx_line.setEnabled(False)
|
||||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
|
||||||
sizePolicy.setHorizontalStretch(0)
|
sizePolicy.setHorizontalStretch(0)
|
||||||
sizePolicy.setVerticalStretch(0)
|
sizePolicy.setVerticalStretch(0)
|
||||||
sizePolicy.setHeightForWidth(self.maxx_line.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.maxx_line.sizePolicy().hasHeightForWidth())
|
||||||
self.maxx_line.setSizePolicy(sizePolicy)
|
self.maxx_line.setSizePolicy(sizePolicy)
|
||||||
self.maxx_line.setObjectName("maxx_line")
|
self.maxx_line.setObjectName("maxx_line")
|
||||||
self.gridLayout_2.addWidget(self.maxx_line, 1, 2, 1, 1)
|
self.gridLayout_2.addWidget(self.maxx_line, 1, 2, 1, 1)
|
||||||
self.numx_line = QtWidgets.QLineEdit(self.groupBox)
|
self.line_2 = QtWidgets.QFrame(self.groupBox)
|
||||||
self.numx_line.setEnabled(False)
|
self.line_2.setFrameShape(QtWidgets.QFrame.VLine)
|
||||||
self.numx_line.setObjectName("numx_line")
|
self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken)
|
||||||
self.gridLayout_2.addWidget(self.numx_line, 1, 3, 1, 1)
|
self.line_2.setObjectName("line_2")
|
||||||
|
self.gridLayout_2.addWidget(self.line_2, 0, 5, 2, 1)
|
||||||
|
self.newx_log_checkbox = QtWidgets.QCheckBox(self.groupBox)
|
||||||
|
self.newx_log_checkbox.setEnabled(False)
|
||||||
|
self.newx_log_checkbox.setObjectName("newx_log_checkbox")
|
||||||
|
self.gridLayout_2.addWidget(self.newx_log_checkbox, 1, 4, 1, 1)
|
||||||
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
||||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||||
self.curve_checkbox = QtWidgets.QCheckBox(self.groupBox)
|
self.curve_checkbox = QtWidgets.QCheckBox(self.groupBox)
|
||||||
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.curve_checkbox.sizePolicy().hasHeightForWidth())
|
||||||
|
self.curve_checkbox.setSizePolicy(sizePolicy)
|
||||||
self.curve_checkbox.setChecked(True)
|
self.curve_checkbox.setChecked(True)
|
||||||
self.curve_checkbox.setObjectName("curve_checkbox")
|
self.curve_checkbox.setObjectName("curve_checkbox")
|
||||||
self.horizontalLayout.addWidget(self.curve_checkbox)
|
self.horizontalLayout.addWidget(self.curve_checkbox)
|
||||||
self.partial_checkBox = QtWidgets.QCheckBox(self.groupBox)
|
self.partial_checkBox = QtWidgets.QCheckBox(self.groupBox)
|
||||||
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.partial_checkBox.sizePolicy().hasHeightForWidth())
|
||||||
|
self.partial_checkBox.setSizePolicy(sizePolicy)
|
||||||
self.partial_checkBox.setObjectName("partial_checkBox")
|
self.partial_checkBox.setObjectName("partial_checkBox")
|
||||||
self.horizontalLayout.addWidget(self.partial_checkBox)
|
self.horizontalLayout.addWidget(self.partial_checkBox)
|
||||||
self.gridLayout_2.addLayout(self.horizontalLayout, 0, 0, 1, 4)
|
self.gridLayout_2.addLayout(self.horizontalLayout, 0, 0, 1, 5)
|
||||||
|
self.parameter_checkbox = QtWidgets.QCheckBox(self.groupBox)
|
||||||
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Fixed)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.parameter_checkbox.sizePolicy().hasHeightForWidth())
|
||||||
|
self.parameter_checkbox.setSizePolicy(sizePolicy)
|
||||||
|
self.parameter_checkbox.setObjectName("parameter_checkbox")
|
||||||
|
self.gridLayout_2.addWidget(self.parameter_checkbox, 0, 6, 1, 2)
|
||||||
self.gridLayout.addWidget(self.groupBox, 7, 0, 1, 2)
|
self.gridLayout.addWidget(self.groupBox, 7, 0, 1, 2)
|
||||||
self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
|
self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
|
||||||
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok|QtWidgets.QDialogButtonBox.Retry)
|
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok|QtWidgets.QDialogButtonBox.Retry)
|
||||||
@ -253,16 +277,17 @@ class Ui_Dialog(object):
|
|||||||
self.del_prev_checkBox.setText(_translate("Dialog", "Delete previous fits of this set"))
|
self.del_prev_checkBox.setText(_translate("Dialog", "Delete previous fits of this set"))
|
||||||
self.reject_fit_checkBox.setText(_translate("Dialog", "Reject this fit"))
|
self.reject_fit_checkBox.setText(_translate("Dialog", "Reject this fit"))
|
||||||
self.groupBox.setTitle(_translate("Dialog", "Output"))
|
self.groupBox.setTitle(_translate("Dialog", "Output"))
|
||||||
self.extrapolate_box.setToolTip(_translate("Dialog", "Extrapolates only main function"))
|
|
||||||
self.extrapolate_box.setText(_translate("Dialog", "Extrapolate curves"))
|
|
||||||
self.parameter_checkbox.setText(_translate("Dialog", "Plot parameter"))
|
|
||||||
self.graph_checkBox.setText(_translate("Dialog", "New graph for parameter"))
|
|
||||||
self.minx_line.setToolTip(_translate("Dialog", "Leave empty to start at lowest point"))
|
self.minx_line.setToolTip(_translate("Dialog", "Leave empty to start at lowest point"))
|
||||||
self.minx_line.setPlaceholderText(_translate("Dialog", "min x"))
|
self.minx_line.setPlaceholderText(_translate("Dialog", "min x"))
|
||||||
|
self.extrapolate_box.setToolTip(_translate("Dialog", "Extrapolates only main function"))
|
||||||
|
self.extrapolate_box.setText(_translate("Dialog", "Extrapolate curves"))
|
||||||
|
self.numx_line.setPlaceholderText(_translate("Dialog", "# pts"))
|
||||||
|
self.graph_checkBox.setText(_translate("Dialog", "New graph for parameter"))
|
||||||
self.maxx_line.setToolTip(_translate("Dialog", "Leave empty to start at highest point"))
|
self.maxx_line.setToolTip(_translate("Dialog", "Leave empty to start at highest point"))
|
||||||
self.maxx_line.setPlaceholderText(_translate("Dialog", "max x"))
|
self.maxx_line.setPlaceholderText(_translate("Dialog", "max x"))
|
||||||
self.numx_line.setPlaceholderText(_translate("Dialog", "# pts"))
|
self.newx_log_checkbox.setText(_translate("Dialog", "log-spaced?"))
|
||||||
self.curve_checkbox.setText(_translate("Dialog", "Plot fit curve"))
|
self.curve_checkbox.setText(_translate("Dialog", "Plot fit curve"))
|
||||||
self.partial_checkBox.setText(_translate("Dialog", "Plot partial functions"))
|
self.partial_checkBox.setText(_translate("Dialog", "Plot partial functions"))
|
||||||
|
self.parameter_checkbox.setText(_translate("Dialog", "Plot parameter"))
|
||||||
from ..lib.forms import ElideComboBox
|
from ..lib.forms import ElideComboBox
|
||||||
from pyqtgraph import GraphicsLayoutWidget
|
from pyqtgraph import GraphicsLayoutWidget
|
||||||
|
@ -49,11 +49,16 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
|
|
||||||
def add_graph(self, idd: str, name: str):
|
def add_graph(self, idd: str, name: str):
|
||||||
item = QtWidgets.QTreeWidgetItem()
|
item = QtWidgets.QTreeWidgetItem()
|
||||||
item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsDropEnabled | QtCore.Qt.ItemIsEditable |
|
item.setFlags(
|
||||||
QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsUserCheckable)
|
QtCore.Qt.ItemFlag.ItemIsSelectable |
|
||||||
|
QtCore.Qt.ItemFlag.ItemIsDropEnabled |
|
||||||
|
QtCore.Qt.ItemFlag.ItemIsEditable |
|
||||||
|
QtCore.Qt.ItemFlag.ItemIsEnabled |
|
||||||
|
QtCore.Qt.ItemFlag.ItemIsUserCheckable
|
||||||
|
)
|
||||||
item.setText(0, name)
|
item.setText(0, name)
|
||||||
item.setData(0, QtCore.Qt.UserRole, idd)
|
item.setData(0, QtCore.Qt.ItemDataRole.UserRole, idd)
|
||||||
item.setCheckState(0, QtCore.Qt.Checked)
|
item.setCheckState(0, QtCore.Qt.CheckState.Checked)
|
||||||
|
|
||||||
self.addTopLevelItem(item)
|
self.addTopLevelItem(item)
|
||||||
self._checked_graphs.add(idd)
|
self._checked_graphs.add(idd)
|
||||||
@ -67,14 +72,19 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
|
|
||||||
for row in range(self.invisibleRootItem().childCount()):
|
for row in range(self.invisibleRootItem().childCount()):
|
||||||
graph = self.invisibleRootItem().child(row)
|
graph = self.invisibleRootItem().child(row)
|
||||||
if graph.data(0, QtCore.Qt.UserRole) == gid:
|
if graph.data(0, QtCore.Qt.ItemDataRole.UserRole) == gid:
|
||||||
for (idd, name, value) in items:
|
for (idd, name, value) in items:
|
||||||
item = QtWidgets.QTreeWidgetItem([name])
|
item = QtWidgets.QTreeWidgetItem([name])
|
||||||
item.setToolTip(0, f'Value: {value}')
|
item.setToolTip(0, f'Value: {value}')
|
||||||
item.setData(0, QtCore.Qt.UserRole, idd)
|
item.setData(0, QtCore.Qt.ItemDataRole.UserRole, idd)
|
||||||
item.setCheckState(0, QtCore.Qt.Checked)
|
item.setCheckState(0, QtCore.Qt.CheckState.Checked)
|
||||||
item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsDragEnabled | QtCore.Qt.ItemIsEditable |
|
item.setFlags(
|
||||||
QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsUserCheckable)
|
QtCore.Qt.ItemFlag.ItemIsSelectable |
|
||||||
|
QtCore.Qt.ItemFlag.ItemIsDragEnabled |
|
||||||
|
QtCore.Qt.ItemFlag.ItemIsEditable |
|
||||||
|
QtCore.Qt.ItemFlag.ItemIsEnabled |
|
||||||
|
QtCore.Qt.ItemFlag.ItemIsUserCheckable
|
||||||
|
)
|
||||||
graph.addChild(item)
|
graph.addChild(item)
|
||||||
self._checked_sets.add(idd)
|
self._checked_sets.add(idd)
|
||||||
|
|
||||||
@ -85,8 +95,8 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
|
|
||||||
@QtCore.pyqtSlot(QtWidgets.QTreeWidgetItem)
|
@QtCore.pyqtSlot(QtWidgets.QTreeWidgetItem)
|
||||||
def data_change(self, item: QtWidgets.QTreeWidgetItem, emit: bool = True) -> tuple[set, set]:
|
def data_change(self, item: QtWidgets.QTreeWidgetItem, emit: bool = True) -> tuple[set, set]:
|
||||||
idd = item.data(0, QtCore.Qt.UserRole)
|
idd = item.data(0, QtCore.Qt.ItemDataRole.UserRole)
|
||||||
is_selected = item.checkState(0) == QtCore.Qt.Checked
|
is_selected = item.checkState(0) == QtCore.Qt.CheckState.Checked
|
||||||
to_be_hidden = set()
|
to_be_hidden = set()
|
||||||
to_be_shown = set()
|
to_be_shown = set()
|
||||||
|
|
||||||
@ -104,9 +114,9 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
self.blockSignals(True)
|
self.blockSignals(True)
|
||||||
for i in range(item.childCount()):
|
for i in range(item.childCount()):
|
||||||
child = item.child(i)
|
child = item.child(i)
|
||||||
child.setCheckState(0, QtCore.Qt.Checked)
|
child.setCheckState(0, QtCore.Qt.CheckState.Checked)
|
||||||
to_be_shown.add(child.data(0, QtCore.Qt.UserRole))
|
to_be_shown.add(child.data(0, QtCore.Qt.ItemDataRole.UserRole))
|
||||||
self._checked_sets.add(child.data(0, QtCore.Qt.UserRole))
|
self._checked_sets.add(child.data(0, QtCore.Qt.ItemDataRole.UserRole))
|
||||||
self.blockSignals(False)
|
self.blockSignals(False)
|
||||||
|
|
||||||
# check state change to unchecked
|
# check state change to unchecked
|
||||||
@ -115,10 +125,10 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
self.blockSignals(True)
|
self.blockSignals(True)
|
||||||
for i in range(item.childCount()):
|
for i in range(item.childCount()):
|
||||||
child = item.child(i)
|
child = item.child(i)
|
||||||
child.setCheckState(0, QtCore.Qt.Unchecked)
|
child.setCheckState(0, QtCore.Qt.CheckState.Unchecked)
|
||||||
to_be_hidden.add(child.data(0, QtCore.Qt.UserRole))
|
to_be_hidden.add(child.data(0, QtCore.Qt.ItemDataRole.UserRole))
|
||||||
try:
|
try:
|
||||||
self._checked_sets.remove(child.data(0, QtCore.Qt.UserRole))
|
self._checked_sets.remove(child.data(0, QtCore.Qt.ItemDataRole.UserRole))
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
self.blockSignals(False)
|
self.blockSignals(False)
|
||||||
@ -153,7 +163,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
@QtCore.pyqtSlot(QtWidgets.QTreeWidgetItem)
|
@QtCore.pyqtSlot(QtWidgets.QTreeWidgetItem)
|
||||||
def new_selection(self, item: QtWidgets.QTreeWidgetItem):
|
def new_selection(self, item: QtWidgets.QTreeWidgetItem):
|
||||||
if item.parent() is None:
|
if item.parent() is None:
|
||||||
self.management.select_window(item.data(0, QtCore.Qt.UserRole))
|
self.management.select_window(item.data(0, QtCore.Qt.ItemDataRole.UserRole))
|
||||||
|
|
||||||
def dropEvent(self, evt: QtGui.QDropEvent):
|
def dropEvent(self, evt: QtGui.QDropEvent):
|
||||||
dropped_index = self.indexAt(evt.pos())
|
dropped_index = self.indexAt(evt.pos())
|
||||||
@ -179,7 +189,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
|
|
||||||
from_parent.removeChild(it)
|
from_parent.removeChild(it)
|
||||||
tobemoved.append(it)
|
tobemoved.append(it)
|
||||||
take_from.append(from_parent.data(0, QtCore.Qt.UserRole))
|
take_from.append(from_parent.data(0, QtCore.Qt.ItemDataRole.UserRole))
|
||||||
|
|
||||||
pos = QtCore.QModelIndex(persistent_drop)
|
pos = QtCore.QModelIndex(persistent_drop)
|
||||||
if self.dropIndicatorPosition() == QtWidgets.QAbstractItemView.BelowItem:
|
if self.dropIndicatorPosition() == QtWidgets.QAbstractItemView.BelowItem:
|
||||||
@ -191,8 +201,8 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
else:
|
else:
|
||||||
to_parent.insertChildren(row, tobemoved)
|
to_parent.insertChildren(row, tobemoved)
|
||||||
|
|
||||||
self.management.move_sets([it.data(0, QtCore.Qt.UserRole) for it in tobemoved],
|
self.management.move_sets([it.data(0, QtCore.Qt.ItemDataRole.UserRole) for it in tobemoved],
|
||||||
to_parent.data(0, QtCore.Qt.UserRole), take_from,
|
to_parent.data(0, QtCore.Qt.ItemDataRole.UserRole), take_from,
|
||||||
pos=-1 if append else row)
|
pos=-1 if append else row)
|
||||||
|
|
||||||
self.update_indexes()
|
self.update_indexes()
|
||||||
@ -207,7 +217,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
while iterator.value():
|
while iterator.value():
|
||||||
item = iterator.value()
|
item = iterator.value()
|
||||||
if item is not None:
|
if item is not None:
|
||||||
data = item.data(0, QtCore.Qt.UserRole)
|
data = item.data(0, QtCore.Qt.ItemDataRole.UserRole)
|
||||||
if data == gid_out:
|
if data == gid_out:
|
||||||
from_parent = item
|
from_parent = item
|
||||||
|
|
||||||
@ -231,7 +241,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
self.blockSignals(False)
|
self.blockSignals(False)
|
||||||
|
|
||||||
def sort(self, graph_item: QtWidgets.QTreeWidgetItem, mode: str = 'value'):
|
def sort(self, graph_item: QtWidgets.QTreeWidgetItem, mode: str = 'value'):
|
||||||
graph_id = graph_item.data(0, QtCore.Qt.UserRole)
|
graph_id = graph_item.data(0, QtCore.Qt.ItemDataRole.UserRole)
|
||||||
sets = self.management.get_attributes(graph_id, mode)
|
sets = self.management.get_attributes(graph_id, mode)
|
||||||
sets = [el[0] for el in sorted(sets.items(), key=lambda x: x[1])]
|
sets = [el[0] for el in sorted(sets.items(), key=lambda x: x[1])]
|
||||||
|
|
||||||
@ -243,7 +253,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
|
|
||||||
for s in sets:
|
for s in sets:
|
||||||
for c in children:
|
for c in children:
|
||||||
if c.data(0, QtCore.Qt.UserRole) == s:
|
if c.data(0, QtCore.Qt.ItemDataRole.UserRole) == s:
|
||||||
graph_item.addChild(c)
|
graph_item.addChild(c)
|
||||||
|
|
||||||
self.update_indexes()
|
self.update_indexes()
|
||||||
@ -276,7 +286,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
while iterator.value():
|
while iterator.value():
|
||||||
item = iterator.value()
|
item = iterator.value()
|
||||||
if item is not None:
|
if item is not None:
|
||||||
data = item.data(0, QtCore.Qt.UserRole)
|
data = item.data(0, QtCore.Qt.ItemDataRole.UserRole)
|
||||||
if data == sid:
|
if data == sid:
|
||||||
if name != item.text(0):
|
if name != item.text(0):
|
||||||
item.setText(0, name)
|
item.setText(0, name)
|
||||||
@ -285,7 +295,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
iterator += 1
|
iterator += 1
|
||||||
|
|
||||||
def keyPressEvent(self, evt: QtGui.QKeyEvent):
|
def keyPressEvent(self, evt: QtGui.QKeyEvent):
|
||||||
if evt.key() == QtCore.Qt.Key_Delete:
|
if evt.key() == QtCore.Qt.Key.Key_Delete:
|
||||||
rm_sets = []
|
rm_sets = []
|
||||||
rm_graphs = []
|
rm_graphs = []
|
||||||
for idx in self.selectedIndexes():
|
for idx in self.selectedIndexes():
|
||||||
@ -296,20 +306,20 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
if item.parent() is None:
|
if item.parent() is None:
|
||||||
for c_i in range(item.childCount()):
|
for c_i in range(item.childCount()):
|
||||||
# add sets inside graph to removal
|
# add sets inside graph to removal
|
||||||
child_data = item.child(c_i).data(0, QtCore.Qt.UserRole)
|
child_data = item.child(c_i).data(0, QtCore.Qt.ItemDataRole.UserRole)
|
||||||
if child_data not in rm_sets:
|
if child_data not in rm_sets:
|
||||||
rm_sets.append(child_data)
|
rm_sets.append(child_data)
|
||||||
rm_graphs.append(item.data(0, QtCore.Qt.UserRole))
|
rm_graphs.append(item.data(0, QtCore.Qt.ItemDataRole.UserRole))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
item_data = item.data(0, QtCore.Qt.UserRole)
|
item_data = item.data(0, QtCore.Qt.ItemDataRole.UserRole)
|
||||||
if item_data not in rm_sets:
|
if item_data not in rm_sets:
|
||||||
rm_sets.append(item_data)
|
rm_sets.append(item_data)
|
||||||
|
|
||||||
# self.deleteItem.emit(rm_sets+rm_graphs)
|
# self.deleteItem.emit(rm_sets+rm_graphs)
|
||||||
self.management.delete_sets(rm_sets+rm_graphs)
|
self.management.delete_sets(rm_sets+rm_graphs)
|
||||||
|
|
||||||
elif evt.key() == QtCore.Qt.Key_Space:
|
elif evt.key() == QtCore.Qt.Key.Key_Space:
|
||||||
sets = []
|
sets = []
|
||||||
from_parent = []
|
from_parent = []
|
||||||
|
|
||||||
@ -329,7 +339,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
for it in sets:
|
for it in sets:
|
||||||
if it in from_parent:
|
if it in from_parent:
|
||||||
continue
|
continue
|
||||||
it.setCheckState(0, QtCore.Qt.Unchecked if it.checkState(0) == QtCore.Qt.Checked else QtCore.Qt.Checked)
|
it.setCheckState(0, QtCore.Qt.CheckState.Unchecked if it.checkState(0) == QtCore.Qt.CheckState.Checked else QtCore.Qt.CheckState.Checked)
|
||||||
s1, s2 = self.data_change(it, emit=False)
|
s1, s2 = self.data_change(it, emit=False)
|
||||||
to_be_hidden |= s2
|
to_be_hidden |= s2
|
||||||
to_be_shown |= s1
|
to_be_shown |= s1
|
||||||
@ -353,7 +363,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
# find all items that have to be removed
|
# find all items that have to be removed
|
||||||
while iterator.value():
|
while iterator.value():
|
||||||
item = iterator.value()
|
item = iterator.value()
|
||||||
_id = item.data(0, QtCore.Qt.UserRole)
|
_id = item.data(0, QtCore.Qt.ItemDataRole.UserRole)
|
||||||
if _id in ids:
|
if _id in ids:
|
||||||
try:
|
try:
|
||||||
item_parent = item.parent()
|
item_parent = item.parent()
|
||||||
@ -431,7 +441,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
if i.column() == 0:
|
if i.column() == 0:
|
||||||
continue
|
continue
|
||||||
items.append(self.itemFromIndex(i))
|
items.append(self.itemFromIndex(i))
|
||||||
graphs.append(self.itemFromIndex(i).data(0, QtCore.Qt.UserRole))
|
graphs.append(self.itemFromIndex(i).data(0, QtCore.Qt.ItemDataRole.UserRole))
|
||||||
|
|
||||||
if action == del_action:
|
if action == del_action:
|
||||||
for gid in graphs:
|
for gid in graphs:
|
||||||
@ -473,12 +483,12 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
else:
|
else:
|
||||||
graph_id = parent.data(0, QtCore.Qt.UserRole)
|
graph_id = parent.data(0, QtCore.Qt.ItemDataRole.UserRole)
|
||||||
if graph_id not in idx:
|
if graph_id not in idx:
|
||||||
idx[graph_id] = []
|
idx[graph_id] = []
|
||||||
# collect sets in their graph
|
# collect sets in their graph
|
||||||
idx[graph_id].append(item.data(0, QtCore.Qt.UserRole))
|
idx[graph_id].append(item.data(0, QtCore.Qt.ItemDataRole.UserRole))
|
||||||
data = self.management[item.data(0, QtCore.Qt.UserRole)]
|
data = self.management[item.data(0, QtCore.Qt.ItemDataRole.UserRole)]
|
||||||
if data.mode == 'fit':
|
if data.mode == 'fit':
|
||||||
has_fits = True
|
has_fits = True
|
||||||
|
|
||||||
@ -523,7 +533,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
while iterator.value():
|
while iterator.value():
|
||||||
item = iterator.value()
|
item = iterator.value()
|
||||||
if item is not None:
|
if item is not None:
|
||||||
if item.data(0, QtCore.Qt.UserRole) == gid:
|
if item.data(0, QtCore.Qt.ItemDataRole.UserRole) == gid:
|
||||||
item.setBackground(0, QtGui.QBrush(QtGui.QColor('gray')))
|
item.setBackground(0, QtGui.QBrush(QtGui.QColor('gray')))
|
||||||
else:
|
else:
|
||||||
item.setBackground(0, QtGui.QBrush())
|
item.setBackground(0, QtGui.QBrush())
|
||||||
@ -536,10 +546,10 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
while iterator.value():
|
while iterator.value():
|
||||||
item = iterator.value()
|
item = iterator.value()
|
||||||
if item is not None:
|
if item is not None:
|
||||||
if item.data(0, QtCore.Qt.UserRole) in sets:
|
if item.data(0, QtCore.Qt.ItemDataRole.UserRole) in sets:
|
||||||
item.setCheckState(0, QtCore.Qt.Unchecked)
|
item.setCheckState(0, QtCore.Qt.CheckState.Unchecked)
|
||||||
else:
|
else:
|
||||||
self._checked_sets.add(item.data(0, QtCore.Qt.UserRole))
|
self._checked_sets.add(item.data(0, QtCore.Qt.ItemDataRole.UserRole))
|
||||||
iterator += 1
|
iterator += 1
|
||||||
self.blockSignals(False)
|
self.blockSignals(False)
|
||||||
|
|
||||||
@ -594,7 +604,7 @@ class DataWidget(QtWidgets.QWidget, Ui_DataWidget):
|
|||||||
sid = []
|
sid = []
|
||||||
for i in self.tree.selectedIndexes():
|
for i in self.tree.selectedIndexes():
|
||||||
if i.column() == 0:
|
if i.column() == 0:
|
||||||
sid.append(i.data(role=QtCore.Qt.UserRole))
|
sid.append(i.data(role=QtCore.Qt.ItemDataRole.UserRole))
|
||||||
|
|
||||||
self.startShowProperty.emit(sid)
|
self.startShowProperty.emit(sid)
|
||||||
|
|
||||||
@ -603,15 +613,23 @@ class DataWidget(QtWidgets.QWidget, Ui_DataWidget):
|
|||||||
self.proptable.populate(props)
|
self.proptable.populate(props)
|
||||||
|
|
||||||
def change_property(self, key1, key2, value):
|
def change_property(self, key1, key2, value):
|
||||||
ids = [item.data(0, QtCore.Qt.UserRole) for item in self.tree.selectedItems()]
|
|
||||||
if key2 == 'Value':
|
if key2 == 'Value':
|
||||||
try:
|
try:
|
||||||
value = float(value)
|
value = float(value)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
QtWidgets.QMessageBox.warning(self, 'Invalid entry',
|
QtWidgets.QMessageBox.warning(
|
||||||
'Value %r is not a valid number for `value`.' % value)
|
self,
|
||||||
|
'Invalid entry',
|
||||||
|
f'Value {value!r} is not a valid number for `value`.')
|
||||||
return
|
return
|
||||||
|
|
||||||
|
ids = []
|
||||||
|
for item in self.tree.selectedItems():
|
||||||
|
ids.append(item.data(0, QtCore.Qt.ItemDataRole.UserRole))
|
||||||
|
item.setToolTip(0, str(value))
|
||||||
|
else:
|
||||||
|
ids = [item.data(0, QtCore.Qt.ItemDataRole.UserRole) for item in self.tree.selectedItems()]
|
||||||
|
|
||||||
self.propertyChanged.emit(ids, key1, key2, value)
|
self.propertyChanged.emit(ids, key1, key2, value)
|
||||||
|
|
||||||
def uncheck_sets(self, sets: list[str]):
|
def uncheck_sets(self, sets: list[str]):
|
||||||
|
@ -41,7 +41,7 @@ class PropWidget(QtWidgets.QWidget):
|
|||||||
idx = table.indexFromItem(item)
|
idx = table.indexFromItem(item)
|
||||||
self.propertyChanged.emit(self.tab.tabText(tab_idx),
|
self.propertyChanged.emit(self.tab.tabText(tab_idx),
|
||||||
table.item(idx.row(), idx.column()-1).text(),
|
table.item(idx.row(), idx.column()-1).text(),
|
||||||
item.data(QtCore.Qt.DisplayRole))
|
item.data(QtCore.Qt.ItemDataRole.DisplayRole))
|
||||||
|
|
||||||
@QtCore.pyqtSlot(int)
|
@QtCore.pyqtSlot(int)
|
||||||
def tab_change(self, idx: int):
|
def tab_change(self, idx: int):
|
||||||
@ -66,10 +66,10 @@ class PropTable(QtWidgets.QTableWidget):
|
|||||||
self.blockSignals(True)
|
self.blockSignals(True)
|
||||||
for k, v in prop.items():
|
for k, v in prop.items():
|
||||||
value_item = QtWidgets.QTableWidgetItem('')
|
value_item = QtWidgets.QTableWidgetItem('')
|
||||||
value_item.setData(QtCore.Qt.DisplayRole, v)
|
value_item.setData(QtCore.Qt.ItemDataRole.DisplayRole, v)
|
||||||
|
|
||||||
key_item = QtWidgets.QTableWidgetItem(k)
|
key_item = QtWidgets.QTableWidgetItem(k)
|
||||||
key_item.setFlags(QtCore.Qt.NoItemFlags)
|
key_item.setFlags(QtCore.Qt.ItemFlag.NoItemFlags)
|
||||||
key_item.setForeground(QtGui.QBrush(QtGui.QColor(0, 0, 0)))
|
key_item.setForeground(QtGui.QBrush(QtGui.QColor(0, 0, 0)))
|
||||||
|
|
||||||
self.setRowCount(self.rowCount()+1)
|
self.setRowCount(self.rowCount()+1)
|
||||||
|
@ -3,10 +3,10 @@ from __future__ import annotations
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from numpy import ndarray, iscomplexobj, asarray
|
from numpy import ndarray, iscomplexobj, asarray
|
||||||
from pyqtgraph import PlotDataItem
|
|
||||||
|
|
||||||
from ..Qt import QtGui, QtCore, QtWidgets
|
from ..Qt import QtGui, QtCore, QtWidgets
|
||||||
from .._py.valueeditor import Ui_MaskDialog
|
from .._py.valueeditor import Ui_MaskDialog
|
||||||
|
from ..lib.pg_objects import PlotItem
|
||||||
|
|
||||||
|
|
||||||
class ValueEditWidget(QtWidgets.QWidget, Ui_MaskDialog):
|
class ValueEditWidget(QtWidgets.QWidget, Ui_MaskDialog):
|
||||||
@ -35,12 +35,12 @@ class ValueEditWidget(QtWidgets.QWidget, Ui_MaskDialog):
|
|||||||
|
|
||||||
self.tableView.setModel(self.model)
|
self.tableView.setModel(self.model)
|
||||||
self.tableView.setSelectionModel(self.selection_model)
|
self.tableView.setSelectionModel(self.selection_model)
|
||||||
self.tableView.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
self.tableView.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.CustomContextMenu)
|
||||||
self.tableView.customContextMenuRequested.connect(self.ctx)
|
self.tableView.customContextMenuRequested.connect(self.ctx)
|
||||||
|
|
||||||
self.selection_real = PlotDataItem(x=[], y=[], symbolSize=25, symbol='x',
|
self.selection_real = PlotItem(x=[], y=[], symbolSize=25, symbol='x',
|
||||||
pen=None, symbolPen='#c9308e', symbolBrush='#c9308e')
|
pen=None, symbolPen='#c9308e', symbolBrush='#c9308e')
|
||||||
self.selection_imag = PlotDataItem(x=[], y=[], symbolSize=25, symbol='+',
|
self.selection_imag = PlotItem(x=[], y=[], symbolSize=25, symbol='+',
|
||||||
pen=None, symbolPen='#dcdcdc', symbolBrush='#dcdcdc')
|
pen=None, symbolPen='#dcdcdc', symbolBrush='#dcdcdc')
|
||||||
|
|
||||||
def __call__(self, items: dict):
|
def __call__(self, items: dict):
|
||||||
@ -133,7 +133,7 @@ class ValueEditWidget(QtWidgets.QWidget, Ui_MaskDialog):
|
|||||||
def keyPressEvent(self, evt):
|
def keyPressEvent(self, evt):
|
||||||
if evt.matches(QtGui.QKeySequence.Copy):
|
if evt.matches(QtGui.QKeySequence.Copy):
|
||||||
self.copy_selection()
|
self.copy_selection()
|
||||||
elif evt.key() == QtCore.Qt.Key_Delete:
|
elif evt.key() == QtCore.Qt.Key.Key_Delete:
|
||||||
self.delete_item()
|
self.delete_item()
|
||||||
else:
|
else:
|
||||||
super().keyPressEvent(evt)
|
super().keyPressEvent(evt)
|
||||||
@ -229,7 +229,7 @@ class ValueModel(QtCore.QAbstractTableModel):
|
|||||||
"""
|
"""
|
||||||
itemChanged = QtCore.pyqtSignal(int, int, str)
|
itemChanged = QtCore.pyqtSignal(int, int, str)
|
||||||
load_number = 20
|
load_number = 20
|
||||||
maskRole = QtCore.Qt.UserRole+321
|
maskRole = QtCore.Qt.ItemDataRole.UserRole+321
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent=parent)
|
super().__init__(parent=parent)
|
||||||
@ -240,7 +240,7 @@ class ValueModel(QtCore.QAbstractTableModel):
|
|||||||
self.mask = None
|
self.mask = None
|
||||||
self.headers = ['x', 'y', '\u0394y']
|
self.headers = ['x', 'y', '\u0394y']
|
||||||
for i, hd in enumerate(self.headers):
|
for i, hd in enumerate(self.headers):
|
||||||
self.setHeaderData(i, QtCore.Qt.Horizontal, hd)
|
self.setHeaderData(i, QtCore.Qt.Orientation.Horizontal, hd)
|
||||||
|
|
||||||
def rowCount(self, *args, **kwargs) -> int:
|
def rowCount(self, *args, **kwargs) -> int:
|
||||||
return self.total_rows
|
return self.total_rows
|
||||||
@ -258,25 +258,28 @@ class ValueModel(QtCore.QAbstractTableModel):
|
|||||||
self.mask = mask.tolist()
|
self.mask = mask.tolist()
|
||||||
|
|
||||||
self.endResetModel()
|
self.endResetModel()
|
||||||
self.dataChanged.emit(self.index(0, 0), self.index(0, 1), [QtCore.Qt.DisplayRole])
|
self.dataChanged.emit(
|
||||||
|
self.index(0, 0),
|
||||||
|
self.index(0, 1), [QtCore.Qt.ItemDataRole.DisplayRole]
|
||||||
|
)
|
||||||
|
|
||||||
def data(self, idx: QtCore.QModelIndex, role=QtCore.Qt.DisplayRole) -> Any:
|
def data(self, idx: QtCore.QModelIndex, role=QtCore.Qt.ItemDataRole.DisplayRole) -> Any:
|
||||||
if not idx.isValid():
|
if not idx.isValid():
|
||||||
return
|
return
|
||||||
|
|
||||||
row = idx.row()
|
row = idx.row()
|
||||||
if role in [QtCore.Qt.DisplayRole, QtCore.Qt.EditRole]:
|
if role in [QtCore.Qt.ItemDataRole.DisplayRole, QtCore.Qt.ItemDataRole.EditRole]:
|
||||||
val = self._data[row][idx.column()]
|
val = self._data[row][idx.column()]
|
||||||
return self.as_string(val)
|
return self.as_string(val)
|
||||||
|
|
||||||
elif role == QtCore.Qt.BackgroundRole:
|
elif role == QtCore.Qt.ItemDataRole.BackgroundRole:
|
||||||
pal = QtGui.QGuiApplication.palette()
|
pal = QtGui.QGuiApplication.palette()
|
||||||
if not self.mask[row]:
|
if not self.mask[row]:
|
||||||
return pal.color(QtGui.QPalette.Disabled, QtGui.QPalette.Base)
|
return pal.color(QtGui.QPalette.Disabled, QtGui.QPalette.Base)
|
||||||
else:
|
else:
|
||||||
return pal.color(QtGui.QPalette.Base)
|
return pal.color(QtGui.QPalette.Base)
|
||||||
|
|
||||||
elif role == QtCore.Qt.ForegroundRole:
|
elif role == QtCore.Qt.ItemDataRole.ForegroundRole:
|
||||||
pal = QtGui.QGuiApplication.palette()
|
pal = QtGui.QGuiApplication.palette()
|
||||||
if not self.mask[row]:
|
if not self.mask[row]:
|
||||||
return pal.color(QtGui.QPalette.Disabled, QtGui.QPalette.Text)
|
return pal.color(QtGui.QPalette.Disabled, QtGui.QPalette.Text)
|
||||||
@ -289,7 +292,7 @@ class ValueModel(QtCore.QAbstractTableModel):
|
|||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
|
|
||||||
def setData(self, idx: QtCore.QModelIndex, value: str | bool, role=QtCore.Qt.DisplayRole) -> Any:
|
def setData(self, idx: QtCore.QModelIndex, value: str | bool, role=QtCore.Qt.ItemDataRole.DisplayRole) -> Any:
|
||||||
col, row = idx.column(), idx.row()
|
col, row = idx.column(), idx.row()
|
||||||
|
|
||||||
if role == ValueModel.maskRole:
|
if role == ValueModel.maskRole:
|
||||||
@ -299,7 +302,7 @@ class ValueModel(QtCore.QAbstractTableModel):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
if value:
|
if value:
|
||||||
if role == QtCore.Qt.EditRole:
|
if role == QtCore.Qt.ItemDataRole.EditRole:
|
||||||
if value == self.as_string(self._data[row][col]):
|
if value == self.as_string(self._data[row][col]):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -322,9 +325,9 @@ class ValueModel(QtCore.QAbstractTableModel):
|
|||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def headerData(self, section: int, orientation, role=QtCore.Qt.DisplayRole) -> Any:
|
def headerData(self, section: int, orientation, role=QtCore.Qt.ItemDataRole.DisplayRole) -> Any:
|
||||||
if role == QtCore.Qt.DisplayRole:
|
if role == QtCore.Qt.ItemDataRole.DisplayRole:
|
||||||
if orientation == QtCore.Qt.Horizontal:
|
if orientation == QtCore.Qt.Orientation.Horizontal:
|
||||||
return self.headers[section]
|
return self.headers[section]
|
||||||
else:
|
else:
|
||||||
return str(section+1)
|
return str(section+1)
|
||||||
@ -346,7 +349,7 @@ class ValueModel(QtCore.QAbstractTableModel):
|
|||||||
self.endInsertRows()
|
self.endInsertRows()
|
||||||
|
|
||||||
def flags(self, idx: QtCore.QModelIndex) -> QtCore.Qt.ItemFlag:
|
def flags(self, idx: QtCore.QModelIndex) -> QtCore.Qt.ItemFlag:
|
||||||
return QtCore.QAbstractTableModel.flags(self, idx) | QtCore.Qt.ItemIsEditable
|
return QtCore.QAbstractTableModel.flags(self, idx) | QtCore.Qt.ItemFlag.ItemIsEditable
|
||||||
|
|
||||||
def removeRows(self, pos: int, rows: int, parent=None, *args, **kwargs) -> bool:
|
def removeRows(self, pos: int, rows: int, parent=None, *args, **kwargs) -> bool:
|
||||||
self.beginRemoveRows(parent, pos, pos+rows-1)
|
self.beginRemoveRows(parent, pos, pos+rows-1)
|
||||||
|
@ -136,8 +136,8 @@ class TgCalculator(QtWidgets.QWizard, Ui_DSCEvalDialog):
|
|||||||
max_x = max(max_x, data.x.max())
|
max_x = max(max_x, data.x.max())
|
||||||
|
|
||||||
item = QtWidgets.QListWidgetItem(name)
|
item = QtWidgets.QListWidgetItem(name)
|
||||||
item.setCheckState(QtCore.Qt.Checked)
|
item.setCheckState(QtCore.Qt.CheckState.Checked)
|
||||||
item.setData(QtCore.Qt.UserRole, key)
|
item.setData(QtCore.Qt.ItemDataRole.UserRole, key)
|
||||||
item.setForeground(mkBrush(c.rgb()))
|
item.setForeground(mkBrush(c.rgb()))
|
||||||
self.listWidget.addItem(item)
|
self.listWidget.addItem(item)
|
||||||
|
|
||||||
@ -191,10 +191,10 @@ class TgCalculator(QtWidgets.QWizard, Ui_DSCEvalDialog):
|
|||||||
|
|
||||||
for idx in range(self.listWidget.count()):
|
for idx in range(self.listWidget.count()):
|
||||||
item = self.listWidget.item(idx)
|
item = self.listWidget.item(idx)
|
||||||
if item.checkState() == QtCore.Qt.Unchecked:
|
if item.checkState() == QtCore.Qt.CheckState.Unchecked:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
key = item.data(QtCore.Qt.UserRole)
|
key = item.data(QtCore.Qt.ItemDataRole.UserRole)
|
||||||
plot = self._plots[key]
|
plot = self._plots[key]
|
||||||
data, _ = self._dsc[key]
|
data, _ = self._dsc[key]
|
||||||
|
|
||||||
@ -214,7 +214,7 @@ class TgCalculator(QtWidgets.QWizard, Ui_DSCEvalDialog):
|
|||||||
item = self.listWidget.item(idx)
|
item = self.listWidget.item(idx)
|
||||||
|
|
||||||
tree_item = QtWidgets.QTreeWidgetItem([item.text()])
|
tree_item = QtWidgets.QTreeWidgetItem([item.text()])
|
||||||
values = self._tg_value.get(item.data(QtCore.Qt.UserRole))
|
values = self._tg_value.get(item.data(QtCore.Qt.ItemDataRole.UserRole))
|
||||||
|
|
||||||
if values is not None:
|
if values is not None:
|
||||||
for name, pos in values.items():
|
for name, pos in values.items():
|
||||||
@ -223,7 +223,7 @@ class TgCalculator(QtWidgets.QWizard, Ui_DSCEvalDialog):
|
|||||||
|
|
||||||
self.tg_tree.addTopLevelItem(tree_item)
|
self.tg_tree.addTopLevelItem(tree_item)
|
||||||
|
|
||||||
key = item.data(QtCore.Qt.UserRole)
|
key = item.data(QtCore.Qt.ItemDataRole.UserRole)
|
||||||
plot = self._plots[key]
|
plot = self._plots[key]
|
||||||
data, _ = self._dsc[key]
|
data, _ = self._dsc[key]
|
||||||
|
|
||||||
@ -251,7 +251,7 @@ class TgCalculator(QtWidgets.QWizard, Ui_DSCEvalDialog):
|
|||||||
@QtCore.pyqtSlot(QtWidgets.QListWidgetItem)
|
@QtCore.pyqtSlot(QtWidgets.QListWidgetItem)
|
||||||
def change_visibility(self, item: QtWidgets.QListWidgetItem):
|
def change_visibility(self, item: QtWidgets.QListWidgetItem):
|
||||||
is_checked = bool(item.checkState())
|
is_checked = bool(item.checkState())
|
||||||
plot = self._plots[item.data(QtCore.Qt.UserRole)]
|
plot = self._plots[item.data(QtCore.Qt.ItemDataRole.UserRole)]
|
||||||
for val in plot:
|
for val in plot:
|
||||||
val.setVisible(is_checked)
|
val.setVisible(is_checked)
|
||||||
|
|
||||||
@ -275,10 +275,10 @@ class TgCalculator(QtWidgets.QWizard, Ui_DSCEvalDialog):
|
|||||||
self.tnmh_tree.clear()
|
self.tnmh_tree.clear()
|
||||||
for idx in range(self.listWidget.count()):
|
for idx in range(self.listWidget.count()):
|
||||||
item = self.listWidget.item(idx)
|
item = self.listWidget.item(idx)
|
||||||
if item.checkState() == QtCore.Qt.Unchecked:
|
if item.checkState() == QtCore.Qt.CheckState.Unchecked:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
key = item.data(QtCore.Qt.UserRole)
|
key = item.data(QtCore.Qt.ItemDataRole.UserRole)
|
||||||
|
|
||||||
data = self.get_fictive(key, baselines)
|
data = self.get_fictive(key, baselines)
|
||||||
|
|
||||||
@ -292,7 +292,7 @@ class TgCalculator(QtWidgets.QWizard, Ui_DSCEvalDialog):
|
|||||||
item = self.listWidget.item(idx)
|
item = self.listWidget.item(idx)
|
||||||
|
|
||||||
tree_item = QtWidgets.QTreeWidgetItem([item.text()])
|
tree_item = QtWidgets.QTreeWidgetItem([item.text()])
|
||||||
values = self._fit.get(item.data(QtCore.Qt.UserRole))
|
values = self._fit.get(item.data(QtCore.Qt.ItemDataRole.UserRole))
|
||||||
|
|
||||||
if values is not None:
|
if values is not None:
|
||||||
child_item = QtWidgets.QTreeWidgetItem([values.parameter_string()])
|
child_item = QtWidgets.QTreeWidgetItem([values.parameter_string()])
|
||||||
@ -305,10 +305,10 @@ class TgCalculator(QtWidgets.QWizard, Ui_DSCEvalDialog):
|
|||||||
ret_dic = {}
|
ret_dic = {}
|
||||||
for idx in range(self.listWidget.count()):
|
for idx in range(self.listWidget.count()):
|
||||||
item = self.listWidget.item(idx)
|
item = self.listWidget.item(idx)
|
||||||
if item.checkState() == QtCore.Qt.Unchecked:
|
if item.checkState() == QtCore.Qt.CheckState.Unchecked:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
key = item.data(QtCore.Qt.UserRole)
|
key = item.data(QtCore.Qt.ItemDataRole.UserRole)
|
||||||
|
|
||||||
cp = None
|
cp = None
|
||||||
if self.fictive_export_check.isChecked():
|
if self.fictive_export_check.isChecked():
|
||||||
@ -332,10 +332,10 @@ class TgCalculator(QtWidgets.QWizard, Ui_DSCEvalDialog):
|
|||||||
m = []
|
m = []
|
||||||
for idx in range(self.listWidget.count()):
|
for idx in range(self.listWidget.count()):
|
||||||
item = self.listWidget.item(idx)
|
item = self.listWidget.item(idx)
|
||||||
if item.checkState() == QtCore.Qt.Unchecked:
|
if item.checkState() == QtCore.Qt.CheckState.Unchecked:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
key = item.data(QtCore.Qt.UserRole)
|
key = item.data(QtCore.Qt.ItemDataRole.UserRole)
|
||||||
data, _ = self._dsc[key]
|
data, _ = self._dsc[key]
|
||||||
try:
|
try:
|
||||||
tg_value = self._tg_value[key][tg_type][0]
|
tg_value = self._tg_value[key][tg_type][0]
|
||||||
|
@ -58,7 +58,8 @@ class FitToolbar(QtWidgets.QToolBar):
|
|||||||
|
|
||||||
@QtCore.pyqtSlot(QtWidgets.QAction)
|
@QtCore.pyqtSlot(QtWidgets.QAction)
|
||||||
def change_limit_type(self, action: QtWidgets.QAction):
|
def change_limit_type(self, action: QtWidgets.QAction):
|
||||||
is_custom = (action.text() == 'Custom')
|
is_custom = (action.text() in ['Custom', 'Exclude region'])
|
||||||
|
print(is_custom)
|
||||||
|
|
||||||
for w in [self.label, self.label2, self.lineedit, self.lineedit2]:
|
for w in [self.label, self.label2, self.lineedit, self.lineedit2]:
|
||||||
w.setEnabled(is_custom)
|
w.setEnabled(is_custom)
|
||||||
@ -93,5 +94,6 @@ class FitToolbar(QtWidgets.QToolBar):
|
|||||||
return {
|
return {
|
||||||
'None': 'none',
|
'None': 'none',
|
||||||
'Visible x range': 'x',
|
'Visible x range': 'x',
|
||||||
'Custom': self.region.getRegion(),
|
'Custom': ('in', self.region.getRegion()),
|
||||||
|
'Exclude region': ('out', self.region.getRegion()),
|
||||||
}[action_text]
|
}[action_text]
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
from math import isnan
|
from math import isnan
|
||||||
|
|
||||||
from pyqtgraph import mkBrush, mkPen, mkColor
|
from pyqtgraph import mkBrush, mkPen, mkColor
|
||||||
@ -28,6 +30,7 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
self.extrapolate_box.stateChanged.connect(lambda x: self.maxx_line.setEnabled(x))
|
self.extrapolate_box.stateChanged.connect(lambda x: self.maxx_line.setEnabled(x))
|
||||||
self.extrapolate_box.stateChanged.connect(lambda x: self.minx_line.setEnabled(x))
|
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.extrapolate_box.stateChanged.connect(lambda x: self.numx_line.setEnabled(x))
|
||||||
|
self.extrapolate_box.stateChanged.connect(lambda x: self.newx_log_checkbox.setEnabled(x))
|
||||||
|
|
||||||
self._previous_fits = {}
|
self._previous_fits = {}
|
||||||
self._opts = []
|
self._opts = []
|
||||||
@ -363,7 +366,7 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
|
|
||||||
parts = self.partial_checkBox.checkState() == QtCore.Qt.CheckState.Checked
|
parts = self.partial_checkBox.checkState() == QtCore.Qt.CheckState.Checked
|
||||||
|
|
||||||
extrapolate = [None, None, None]
|
extrapolate = [None, None, None, None]
|
||||||
error = []
|
error = []
|
||||||
if self.extrapolate_box.isChecked():
|
if self.extrapolate_box.isChecked():
|
||||||
try:
|
try:
|
||||||
@ -379,6 +382,8 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
except (TypeError, ValueError):
|
except (TypeError, ValueError):
|
||||||
error.append('Number of points is missing')
|
error.append('Number of points is missing')
|
||||||
|
|
||||||
|
extrapolate[3] = self.newx_log_checkbox.isChecked()
|
||||||
|
|
||||||
if error:
|
if error:
|
||||||
msg = QtWidgets.QMessageBox.warning(self, 'Error', 'Extrapolation failed because:\n' + '\n'.join(error))
|
msg = QtWidgets.QMessageBox.warning(self, 'Error', 'Extrapolation failed because:\n' + '\n'.join(error))
|
||||||
return
|
return
|
||||||
@ -416,10 +421,13 @@ class FitExtension(QtWidgets.QDialog):
|
|||||||
self.num_pts.setValidator(QtGui.QIntValidator())
|
self.num_pts.setValidator(QtGui.QIntValidator())
|
||||||
gridLayout.addWidget(self.num_pts, 2, 1, 1, 1)
|
gridLayout.addWidget(self.num_pts, 2, 1, 1, 1)
|
||||||
|
|
||||||
|
self.logx_checkbox = QtWidgets.QCheckBox('Log-spaced?')
|
||||||
|
gridLayout.addWidget(self.logx_checkbox, 3, 0, 1, 2)
|
||||||
|
|
||||||
self.buttonBox = QtWidgets.QDialogButtonBox()
|
self.buttonBox = QtWidgets.QDialogButtonBox()
|
||||||
self.buttonBox.setOrientation(QtCore.Qt.Orientation.Horizontal)
|
self.buttonBox.setOrientation(QtCore.Qt.Orientation.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)
|
gridLayout.addWidget(self.buttonBox, 4, 0, 1, 2)
|
||||||
|
|
||||||
self.setLayout(gridLayout)
|
self.setLayout(gridLayout)
|
||||||
|
|
||||||
@ -427,12 +435,13 @@ class FitExtension(QtWidgets.QDialog):
|
|||||||
self.buttonBox.rejected.connect(self.reject)
|
self.buttonBox.rejected.connect(self.reject)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def values(self):
|
def values(self) -> tuple[float, float, int, bool] | None:
|
||||||
try:
|
try:
|
||||||
xmin = float(self.min_line.text())
|
xmin = float(self.min_line.text())
|
||||||
xmax = float(self.max_line.text())
|
xmax = float(self.max_line.text())
|
||||||
nums = int(self.num_pts.text())
|
nums = int(self.num_pts.text())
|
||||||
|
logx = self.logx_checkbox.isChecked()
|
||||||
except TypeError:
|
except TypeError:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return xmin, xmax, nums
|
return xmin, xmax, nums, logx
|
||||||
|
@ -670,11 +670,14 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
if os.path.exists(outfile):
|
if os.path.exists(outfile):
|
||||||
if QtWidgets.QMessageBox.warning(self, 'Export graphic',
|
if QtWidgets.QMessageBox.warning(
|
||||||
|
self,
|
||||||
|
'Export graphic',
|
||||||
f'{os.path.split(outfile)[1]} already exists.\n'
|
f'{os.path.split(outfile)[1]} already exists.\n'
|
||||||
f'Do you REALLY want to replace it?',
|
f'Do you REALLY want to replace it?',
|
||||||
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
|
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
|
||||||
QtWidgets.QMessageBox.No) == QtWidgets.QMessageBox.No:
|
QtWidgets.QMessageBox.No
|
||||||
|
) == QtWidgets.QMessageBox.No:
|
||||||
return
|
return
|
||||||
|
|
||||||
bg_color = self._bgcolor
|
bg_color = self._bgcolor
|
||||||
@ -716,16 +719,20 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
|||||||
logger.exception(f'{item} could not exported because {e.args}')
|
logger.exception(f'{item} could not exported because {e.args}')
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if item_dic:
|
||||||
if len(item) == 2:
|
if len(item) == 2:
|
||||||
# plot can show errorbars
|
# plot can show errorbars
|
||||||
|
if len(item_dic['x']):
|
||||||
item_dic['yerr'] = item[1].opts['topData']
|
item_dic['yerr'] = item[1].opts['topData']
|
||||||
|
else:
|
||||||
if item_dic:
|
item_dic['yerr'] = []
|
||||||
dic['items'].append(item_dic)
|
dic['items'].append(item_dic)
|
||||||
|
|
||||||
for item in self._external_items:
|
for item in self._external_items:
|
||||||
try:
|
try:
|
||||||
dic['items'].append(item.get_data_opts())
|
item_dic = item.get_data_opts()
|
||||||
|
if item_dic:
|
||||||
|
dic['items'].append(item_dic)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(f'{item} could not be exported because {e.args}')
|
logger.exception(f'{item} could not be exported because {e.args}')
|
||||||
continue
|
continue
|
||||||
|
@ -38,7 +38,7 @@ class QAsciiReader(QtWidgets.QDialog, Ui_ascii_reader):
|
|||||||
self.changestaggeredrange(0)
|
self.changestaggeredrange(0)
|
||||||
|
|
||||||
self.ascii_table.contextMenuEvent = self.ctx_table
|
self.ascii_table.contextMenuEvent = self.ctx_table
|
||||||
self.ascii_table.horizontalHeader().setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
self.ascii_table.horizontalHeader().setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.CustomContextMenu)
|
||||||
self.ascii_table.horizontalHeader().customContextMenuRequested.connect(self.ctx_table)
|
self.ascii_table.horizontalHeader().customContextMenuRequested.connect(self.ctx_table)
|
||||||
|
|
||||||
self.skip = False
|
self.skip = False
|
||||||
@ -65,7 +65,7 @@ class QAsciiReader(QtWidgets.QDialog, Ui_ascii_reader):
|
|||||||
self.set_column_names(1)
|
self.set_column_names(1)
|
||||||
|
|
||||||
self.skippy_checkbox.blockSignals(True)
|
self.skippy_checkbox.blockSignals(True)
|
||||||
self.skippy_checkbox.setCheckState(QtCore.Qt.Unchecked)
|
self.skippy_checkbox.setCheckState(QtCore.Qt.CheckState.Unchecked)
|
||||||
self.skippy_checkbox.blockSignals(False)
|
self.skippy_checkbox.blockSignals(False)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
@ -232,7 +232,7 @@ class QAsciiReader(QtWidgets.QDialog, Ui_ascii_reader):
|
|||||||
|
|
||||||
@QtCore.pyqtSlot(int, name='on_buttonGroup_buttonClicked')
|
@QtCore.pyqtSlot(int, name='on_buttonGroup_buttonClicked')
|
||||||
def show_error(self, val: int):
|
def show_error(self, val: int):
|
||||||
self.deltay_lineEdit.setEnabled(val == -3)
|
self.deltay_lineEdit.setEnabled(val == -2)
|
||||||
|
|
||||||
@QtCore.pyqtSlot(int, name='on_skippy_checkbox_stateChanged')
|
@QtCore.pyqtSlot(int, name='on_skippy_checkbox_stateChanged')
|
||||||
def skip_next_dial(self, _: int):
|
def skip_next_dial(self, _: int):
|
||||||
|
@ -78,14 +78,22 @@ class QDSCReader(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
|
|
||||||
for opts in self.sample.steps:
|
for opts in self.sample.steps:
|
||||||
item = QtWidgets.QListWidgetItem()
|
item = QtWidgets.QListWidgetItem()
|
||||||
item.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsUserCheckable)
|
item.setFlags(
|
||||||
item.setCheckState(QtCore.Qt.Unchecked)
|
QtCore.Qt.ItemFlag.ItemIsEnabled |
|
||||||
|
QtCore.Qt.ItemFlag.ItemIsSelectable |
|
||||||
|
QtCore.Qt.ItemFlag.ItemIsUserCheckable
|
||||||
|
)
|
||||||
|
item.setCheckState(QtCore.Qt.CheckState.Unchecked)
|
||||||
|
|
||||||
if opts[0] == 'i':
|
if opts[0] == 'i':
|
||||||
item.setFlags(QtCore.Qt.NoItemFlags)
|
item.setFlags(QtCore.Qt.ItemFlag.NoItemFlags)
|
||||||
item.setText(f'{opts[1]:.2f} K for {opts[2] / 60:.0f} min')
|
item.setText(f'{opts[1]:.2f} K for {opts[2] / 60:.0f} min')
|
||||||
else:
|
else:
|
||||||
item.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsUserCheckable)
|
item.setFlags(
|
||||||
|
QtCore.Qt.ItemFlag.ItemIsEnabled |
|
||||||
|
QtCore.Qt.ItemFlag.ItemIsSelectable |
|
||||||
|
QtCore.Qt.ItemFlag.ItemIsUserCheckable
|
||||||
|
)
|
||||||
item.setText(f'{opts[2]:.2f} K to {opts[3]:.2f} K with {opts[1]} K/min')
|
item.setText(f'{opts[2]:.2f} K to {opts[3]:.2f} K with {opts[1]} K/min')
|
||||||
|
|
||||||
self.step_listWidget.addItem(item)
|
self.step_listWidget.addItem(item)
|
||||||
@ -97,7 +105,12 @@ class QDSCReader(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
|
|
||||||
if empty:
|
if empty:
|
||||||
self.empty = self.calibrator.set_measurement(empty, mode='empty')
|
self.empty = self.calibrator.set_measurement(empty, mode='empty')
|
||||||
|
|
||||||
|
# avoid ValueError breaking data update
|
||||||
|
if self.empty.fname.is_relative_to(Path.home()):
|
||||||
self.empty_label.setText('~/' + str(self.empty.fname.relative_to(Path.home())))
|
self.empty_label.setText('~/' + str(self.empty.fname.relative_to(Path.home())))
|
||||||
|
else:
|
||||||
|
self.empty_label.setText(str(self.empty.fname))
|
||||||
|
|
||||||
self.update_plots()
|
self.update_plots()
|
||||||
|
|
||||||
@ -118,8 +131,8 @@ class QDSCReader(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
|
|
||||||
self.references.append(ref)
|
self.references.append(ref)
|
||||||
item = QtWidgets.QTableWidgetItem(str(ref.fname.name))
|
item = QtWidgets.QTableWidgetItem(str(ref.fname.name))
|
||||||
item.setData(QtCore.Qt.UserRole, ref.fname)
|
item.setData(QtCore.Qt.ItemDataRole.UserRole, ref.fname)
|
||||||
item.setFlags(QtCore.Qt.ItemIsEnabled)
|
item.setFlags(QtCore.Qt.ItemFlag.ItemIsEnabled)
|
||||||
|
|
||||||
rowcnt = self.reference_tableWidget.rowCount()
|
rowcnt = self.reference_tableWidget.rowCount()
|
||||||
self.reference_tableWidget.setRowCount(rowcnt+1)
|
self.reference_tableWidget.setRowCount(rowcnt+1)
|
||||||
@ -132,7 +145,7 @@ class QDSCReader(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
@QtCore.pyqtSlot(name='on_ref_remove_pushButton_clicked')
|
@QtCore.pyqtSlot(name='on_ref_remove_pushButton_clicked')
|
||||||
def remove_reference(self):
|
def remove_reference(self):
|
||||||
idx = self.reference_tableWidget.currentRow()
|
idx = self.reference_tableWidget.currentRow()
|
||||||
self.calibrator.remove_reference(self.reference_tableWidget.item(idx, 0).data(QtCore.Qt.UserRole))
|
self.calibrator.remove_reference(self.reference_tableWidget.item(idx, 0).data(QtCore.Qt.ItemDataRole.UserRole))
|
||||||
|
|
||||||
self.reference_tableWidget.removeRow(idx)
|
self.reference_tableWidget.removeRow(idx)
|
||||||
self.update_plots()
|
self.update_plots()
|
||||||
@ -145,10 +158,10 @@ class QDSCReader(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
for row in range(self.step_listWidget.count()):
|
for row in range(self.step_listWidget.count()):
|
||||||
if idx == row:
|
if idx == row:
|
||||||
continue
|
continue
|
||||||
self.step_listWidget.item(row).setCheckState(QtCore.Qt.Unchecked)
|
self.step_listWidget.item(row).setCheckState(QtCore.Qt.CheckState.Unchecked)
|
||||||
self.step_listWidget.blockSignals(False)
|
self.step_listWidget.blockSignals(False)
|
||||||
|
|
||||||
if item.checkState() == QtCore.Qt.Checked:
|
if item.checkState() == QtCore.Qt.CheckState.Checked:
|
||||||
mode, rate, _, _ = self.sample.steps[idx]
|
mode, rate, _, _ = self.sample.steps[idx]
|
||||||
self.current_run = (rate, mode)
|
self.current_run = (rate, mode)
|
||||||
self.sample_idx = idx
|
self.sample_idx = idx
|
||||||
@ -217,6 +230,8 @@ class QDSCReader(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
|
|
||||||
if empty_data is not None:
|
if empty_data is not None:
|
||||||
self.empty_sample.setData(x=empty_data[0], y=empty_data[1])
|
self.empty_sample.setData(x=empty_data[0], y=empty_data[1])
|
||||||
|
else:
|
||||||
|
self.empty_sample.setData(x=[], y=[])
|
||||||
|
|
||||||
self.calib_graph.clear()
|
self.calib_graph.clear()
|
||||||
|
|
||||||
@ -249,11 +264,16 @@ class QDSCReader(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
except TypeError:
|
except TypeError:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if self.cp_checkBox.isChecked() and self.references:
|
||||||
|
y_label = 'cp'
|
||||||
|
else:
|
||||||
|
y_label = 'q'
|
||||||
|
|
||||||
rate, mode = self.current_run
|
rate, mode = self.current_run
|
||||||
new_val = DSC(sample_data[0], sample_data[1], value=rate, name=f'{self.fname.stem} {rate} ({mode})')
|
new_val = DSC(sample_data[0], sample_data[1], value=rate, name=f'{self.fname.stem} {rate}K-min ({mode}, {y_label})')
|
||||||
|
|
||||||
if filesave:
|
if filesave:
|
||||||
new_val.savetxt(self.fname.with_name(f'{self.fname.stem} {rate}K-min {mode}.dat'.replace(' ', '_')))
|
new_val.savetxt(self.fname.with_name(f'{self.fname.stem}_{rate}K-min_{y_label}{mode}.dat'.replace(' ', '_')))
|
||||||
close_after = False
|
close_after = False
|
||||||
else:
|
else:
|
||||||
self.data_read.emit([new_val])
|
self.data_read.emit([new_val])
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
from PyQt5 import QtWidgets
|
||||||
|
|
||||||
from .codeeditor import _make_textformats
|
from .codeeditor import _make_textformats
|
||||||
from ..Qt import QtWidgets, QtCore, QtGui
|
from ..Qt import QtWidgets, QtCore, QtGui
|
||||||
from nmreval.configs import config_paths
|
from nmreval.configs import config_paths
|
||||||
@ -113,3 +116,27 @@ class QLog(QtWidgets.QDialog):
|
|||||||
|
|
||||||
for lines in text[-100:]:
|
for lines in text[-100:]:
|
||||||
self.plainTextEdit.appendPlainText(lines[:-1])
|
self.plainTextEdit.appendPlainText(lines[:-1])
|
||||||
|
|
||||||
|
|
||||||
|
class ConsoleDock(QtWidgets.QDockWidget):
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
super().__init__(parent=parent)
|
||||||
|
|
||||||
|
self.code = QtWidgets.QPlainTextEdit(parent)
|
||||||
|
self.code.highlight = LogHighlighter(self.code.document())
|
||||||
|
self.code.setReadOnly(True)
|
||||||
|
self.code.setMaximumBlockCount(50)
|
||||||
|
self.setWidget(self.code)
|
||||||
|
|
||||||
|
|
||||||
|
class QTextHandler(logging.Handler):
|
||||||
|
def __init__(self, parent):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
self.console = ConsoleDock(parent)
|
||||||
|
self.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))
|
||||||
|
|
||||||
|
def emit(self, record):
|
||||||
|
msg = self.format(record)
|
||||||
|
self.console.code.appendPlainText(msg)
|
||||||
|
self.console.show()
|
||||||
|
@ -183,6 +183,8 @@ class PlotItem(PlotDataItem):
|
|||||||
brush = self.opts['symbolBrush']
|
brush = self.opts['symbolBrush']
|
||||||
if isinstance(brush, tuple):
|
if isinstance(brush, tuple):
|
||||||
self.opts['symbolcolor'] = brush
|
self.opts['symbolcolor'] = brush
|
||||||
|
elif isinstance(brush, str):
|
||||||
|
self.opts['symbolcolor'] = int(f'0x{brush[1:3]}', 16), int(f'0x{brush[3:5]}', 16), int(f'0x{brush[5:7]}', 16)
|
||||||
else:
|
else:
|
||||||
c = brush.color()
|
c = brush.color()
|
||||||
self.opts['symbolcolor'] = c.red(), c.green(), c.blue()
|
self.opts['symbolcolor'] = c.red(), c.green(), c.blue()
|
||||||
@ -340,7 +342,8 @@ class PlotItem(PlotDataItem):
|
|||||||
|
|
||||||
opts = self.opts
|
opts = self.opts
|
||||||
item_dic = {
|
item_dic = {
|
||||||
'x': x, 'y': y,
|
'x': x,
|
||||||
|
'y': y,
|
||||||
'name': opts.get('name', ''),
|
'name': opts.get('name', ''),
|
||||||
'symbolsize': opts['symbolSize'],
|
'symbolsize': opts['symbolSize'],
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ from ..Qt import QtGui, QtWidgets, QtCore
|
|||||||
@contextmanager
|
@contextmanager
|
||||||
def busy_cursor():
|
def busy_cursor():
|
||||||
try:
|
try:
|
||||||
cursor = QtGui.QCursor(QtCore.Qt.ForbiddenCursor)
|
cursor = QtGui.QCursor(QtCore.Qt.CursorShape.ForbiddenCursor)
|
||||||
QtWidgets.QApplication.setOverrideCursor(cursor)
|
QtWidgets.QApplication.setOverrideCursor(cursor)
|
||||||
yield
|
yield
|
||||||
|
|
||||||
|
3
src/gui_qt/main/console.py
Normal file
3
src/gui_qt/main/console.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
@ -12,6 +12,7 @@ from nmreval.lib.logger import logger
|
|||||||
from nmreval.io.sessionwriter import NMRWriter
|
from nmreval.io.sessionwriter import NMRWriter
|
||||||
|
|
||||||
from .management import UpperManagement
|
from .management import UpperManagement
|
||||||
|
from ..lib.logger import ConsoleDock, QTextHandler
|
||||||
from ..Qt import QtGui, QtPrintSupport
|
from ..Qt import QtGui, QtPrintSupport
|
||||||
from ..data.shift_graphs import QShift
|
from ..data.shift_graphs import QShift
|
||||||
from ..data.signaledit import QPreviewDialog, QBaselineDialog
|
from ..data.signaledit import QPreviewDialog, QBaselineDialog
|
||||||
@ -62,6 +63,11 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
self.eval = None
|
self.eval = None
|
||||||
self.editor = None
|
self.editor = None
|
||||||
|
|
||||||
|
self.logtext = QTextHandler(self)
|
||||||
|
logger.addHandler(self.logtext)
|
||||||
|
self.addDockWidget(QtCore.Qt.DockWidgetArea.BottomDockWidgetArea, self.logtext.console)
|
||||||
|
self.logtext.console.hide()
|
||||||
|
|
||||||
self.movedialog = QMover(self)
|
self.movedialog = QMover(self)
|
||||||
|
|
||||||
self.current_graph_widget = None
|
self.current_graph_widget = None
|
||||||
@ -888,7 +894,7 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
self.fit_dialog.load(self.management.active_sets)
|
self.fit_dialog.load(self.management.active_sets)
|
||||||
for item in self.fit_dialog.preview_lines:
|
for item in self.fit_dialog.preview_lines:
|
||||||
self.current_graph_widget.add_external(item)
|
self.current_graph_widget.add_external(item)
|
||||||
if self.action_custom_range.isChecked():
|
if self.action_custom_range.isChecked() or self.actionExclude_region.isChecked():
|
||||||
self.current_graph_widget.add_external(self.fit_toolbar.region)
|
self.current_graph_widget.add_external(self.fit_toolbar.region)
|
||||||
|
|
||||||
block_window = True
|
block_window = True
|
||||||
@ -904,7 +910,7 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
if self.current_graph_widget is None:
|
if self.current_graph_widget is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
if action == self.action_custom_range and self.fit_dialog.isVisible():
|
if action in [self.action_custom_range, self.actionExclude_region] and self.fit_dialog.isVisible():
|
||||||
self.current_graph_widget.add_external(self.fit_toolbar.region)
|
self.current_graph_widget.add_external(self.fit_toolbar.region)
|
||||||
else:
|
else:
|
||||||
self.current_graph_widget.remove_external(self.fit_toolbar.region)
|
self.current_graph_widget.remove_external(self.fit_toolbar.region)
|
||||||
@ -984,7 +990,8 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
res = w.exec()
|
res = w.exec()
|
||||||
if res:
|
if res:
|
||||||
p = w.values
|
p = w.values
|
||||||
x = linspace(p[0], p[1], num=p[2])
|
spacefunc = geomspace if p[3] else linspace
|
||||||
|
x = spacefunc(p[0], p[1], num=p[2])
|
||||||
self.management.extend_fits(sets, x)
|
self.management.extend_fits(sets, x)
|
||||||
|
|
||||||
@QtCore.pyqtSlot(name='on_action_create_fit_function_triggered')
|
@QtCore.pyqtSlot(name='on_action_create_fit_function_triggered')
|
||||||
|
@ -503,27 +503,44 @@ class UpperManagement(QtCore.QObject):
|
|||||||
we = we_option
|
we = we_option
|
||||||
|
|
||||||
if m_complex is None or m_complex == 1:
|
if m_complex is None or m_complex == 1:
|
||||||
|
# model is not complex: m_complex = None
|
||||||
|
# model is complex, fit real part: m_complex = 1
|
||||||
_y = data_i.y.real
|
_y = data_i.y.real
|
||||||
elif m_complex == 2 and np.iscomplexobj(data_i.y):
|
data_complex = 1
|
||||||
|
elif m_complex == 2:
|
||||||
|
# model is complex, fit imag part: m_complex = 2
|
||||||
|
if np.iscomplexobj(data_i.y):
|
||||||
|
# data is complex, use imag part
|
||||||
_y = data_i.y.imag
|
_y = data_i.y.imag
|
||||||
|
data_complex = 2
|
||||||
else:
|
else:
|
||||||
|
# data is real
|
||||||
_y = data_i.y
|
_y = data_i.y
|
||||||
|
data_complex = 1
|
||||||
|
else:
|
||||||
|
# model is complex, fit complex: m_complex = 0
|
||||||
|
# use data as given (complex or not)
|
||||||
|
_y = data_i.y
|
||||||
|
data_complex = 0
|
||||||
|
|
||||||
_x = data_i.x
|
_x = data_i.x
|
||||||
|
|
||||||
|
# options for fit limits 'none', 'x', ('in', custom region), ('out', excluded region)
|
||||||
if fit_limits == 'none':
|
if fit_limits == 'none':
|
||||||
inside = slice(None)
|
inside = slice(None)
|
||||||
elif fit_limits == 'x':
|
elif fit_limits == 'x':
|
||||||
x_lim, _ = self.graphs[self.current_graph].ranges
|
x_lim, _ = self.graphs[self.current_graph].ranges
|
||||||
inside = np.where((_x >= x_lim[0]) & (_x <= x_lim[1]))
|
inside = np.where((_x >= x_lim[0]) & (_x <= x_lim[1]))
|
||||||
|
elif fit_limits[0] == 'in':
|
||||||
|
inside = np.where((_x >= fit_limits[1][0]) & (_x <= fit_limits[1][1]))
|
||||||
else:
|
else:
|
||||||
inside = np.where((_x >= fit_limits[0]) & (_x <= fit_limits[1]))
|
inside = np.where((_x < fit_limits[1][0]) | (_x > fit_limits[1][1]))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if isinstance(we, str):
|
if isinstance(we, str):
|
||||||
d = fit_d.Data(_x[inside], _y[inside], we=we, idx=set_id)
|
d = fit_d.Data(_x[inside], _y[inside], we=we, idx=set_id, complex_type=data_complex)
|
||||||
else:
|
else:
|
||||||
d = fit_d.Data(_x[inside], _y[inside], we=we[inside], idx=set_id)
|
d = fit_d.Data(_x[inside], _y[inside], we=we[inside], idx=set_id, complex_type=data_complex)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise Exception(f'Setting data failed for {set_id}')
|
raise Exception(f'Setting data failed for {set_id}')
|
||||||
|
|
||||||
@ -623,7 +640,7 @@ class UpperManagement(QtCore.QObject):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
if not all(e is None for e in extrapolate):
|
if not all(e is None for e in extrapolate):
|
||||||
spacefunc = np.geomspace if fit.islog else np.linspace
|
spacefunc = np.geomspace if extrapolate[3] else np.linspace
|
||||||
|
|
||||||
xmin = fit.x.min()
|
xmin = fit.x.min()
|
||||||
xmax = fit.x.max()
|
xmax = fit.x.max()
|
||||||
|
@ -12,10 +12,10 @@ class QSmooth(QtWidgets.QDialog, Ui_SmoothDialog):
|
|||||||
|
|
||||||
@QtCore.pyqtSlot(int, name='on_comboBox_currentIndexChanged')
|
@QtCore.pyqtSlot(int, name='on_comboBox_currentIndexChanged')
|
||||||
def change_mode(self, idx: int):
|
def change_mode(self, idx: int):
|
||||||
if idx == 2:
|
if idx == 1:
|
||||||
self.widget.show()
|
self.widget.show()
|
||||||
self.widget_2.hide()
|
self.widget_2.hide()
|
||||||
elif idx == 3:
|
elif idx == 2:
|
||||||
self.widget.show()
|
self.widget.show()
|
||||||
self.widget_2.show()
|
self.widget_2.show()
|
||||||
else:
|
else:
|
||||||
@ -29,12 +29,24 @@ class QSmooth(QtWidgets.QDialog, Ui_SmoothDialog):
|
|||||||
idx = self.comboBox.currentIndex()
|
idx = self.comboBox.currentIndex()
|
||||||
|
|
||||||
# this order must match the combobox
|
# this order must match the combobox
|
||||||
para['mode'] = ['mean', 'savgol', 'loess', 'median', 'std', 'var', 'max', 'min', 'sum'][idx]
|
para['mode'] = [
|
||||||
|
'mean',
|
||||||
|
'savgol',
|
||||||
|
'loess',
|
||||||
|
'median',
|
||||||
|
'std',
|
||||||
|
'var',
|
||||||
|
'max',
|
||||||
|
'min',
|
||||||
|
'sum',
|
||||||
|
][idx]
|
||||||
|
|
||||||
if idx == 2:
|
# Savitzky-Golay needs also polynomial degree
|
||||||
|
if idx == 1:
|
||||||
para['deg'] = self.polynom_spinBox.value()
|
para['deg'] = self.polynom_spinBox.value()
|
||||||
|
|
||||||
if idx == 3:
|
# LOESS needs also polynomial degree and number of iterations
|
||||||
|
if idx == 2:
|
||||||
para['deg'] = self.polynom_spinBox.value()
|
para['deg'] = self.polynom_spinBox.value()
|
||||||
para['it'] = self.iter_spinBox.value()
|
para['it'] = self.iter_spinBox.value()
|
||||||
|
|
||||||
|
@ -320,7 +320,11 @@ class Points:
|
|||||||
pts = []
|
pts = []
|
||||||
|
|
||||||
_tmp_x = self._x[self.mask]
|
_tmp_x = self._x[self.mask]
|
||||||
_tmp_y = self._y[self.mask]
|
x_order = np.argsort(_tmp_x)
|
||||||
|
_tmp_x = _tmp_x[x_order]
|
||||||
|
_tmp_y = self._y[self.mask][x_order]
|
||||||
|
_tmp_yerr = self._y_err[self.mask][x_order]
|
||||||
|
|
||||||
if idx is not None:
|
if idx is not None:
|
||||||
for idx_i in idx:
|
for idx_i in idx:
|
||||||
if isinstance(idx_i, tuple):
|
if isinstance(idx_i, tuple):
|
||||||
@ -338,7 +342,7 @@ class Points:
|
|||||||
right_b = int(min(len(self), x_idx + avg_range[1] + 1))
|
right_b = int(min(len(self), x_idx + avg_range[1] + 1))
|
||||||
|
|
||||||
if left_b < right_b:
|
if left_b < right_b:
|
||||||
pts.append([_tmp_x[x_idx], *self._average(avg_mode, x_idx, left_b, right_b)])
|
pts.append([_tmp_x[x_idx], *self._average(_tmp_x, _tmp_y, _tmp_yerr, avg_mode, x_idx, left_b, right_b)])
|
||||||
else:
|
else:
|
||||||
pts.append([_tmp_x[x_idx], _tmp_y[x_idx], self._y_err[x_idx]])
|
pts.append([_tmp_x[x_idx], _tmp_y[x_idx], self._y_err[x_idx]])
|
||||||
|
|
||||||
@ -358,28 +362,37 @@ class Points:
|
|||||||
left_b = int(max(0, x_idx - avg_range[0]))
|
left_b = int(max(0, x_idx - avg_range[0]))
|
||||||
right_b = int(min(len(self), x_idx + avg_range[1] + 1))
|
right_b = int(min(len(self), x_idx + avg_range[1] + 1))
|
||||||
|
|
||||||
pts.append([_tmp_x[x_idx], *self._average(avg_mode, x_idx, left_b, right_b)])
|
pts.append([_tmp_x[x_idx], *self._average(_tmp_x, _tmp_y, _tmp_yerr, avg_mode, x_idx, left_b, right_b)])
|
||||||
|
|
||||||
return pts
|
return pts
|
||||||
|
|
||||||
def _average(self, mode: str, idx, left: int, right: int) -> tuple[float, float]:
|
@staticmethod
|
||||||
|
def _average(
|
||||||
|
x: np.ndarray,
|
||||||
|
y: np.ndarray,
|
||||||
|
y_err: np.ndarray,
|
||||||
|
mode: str,
|
||||||
|
idx: int,
|
||||||
|
left: int,
|
||||||
|
right: int,
|
||||||
|
) -> tuple[float, float]:
|
||||||
if mode == 'mean':
|
if mode == 'mean':
|
||||||
y_mean = np.mean(self._y[self.mask][left:right].real)
|
y_mean = np.mean(y[left:right].real)
|
||||||
y_err = np.linalg.norm(self._y_err[self.mask][left:right]) / (right - left)
|
y_err_mean = np.linalg.norm(y_err[left:right]) / (right - left)
|
||||||
|
|
||||||
elif mode == 'sum':
|
elif mode == 'sum':
|
||||||
y_mean = np.sum(self._y[self.mask][left:right].real)
|
y_mean = np.sum(y[left:right].real)
|
||||||
y_err = np.linalg.norm(self._y_err[self.mask][left:right])
|
y_err_mean = np.linalg.norm(y_err[left:right])
|
||||||
|
|
||||||
elif mode == 'integral':
|
elif mode == 'integral':
|
||||||
y_mean = simpson(self._y[self.mask][left:right].real, x=self._x[left:right])
|
y_mean = simpson(y[left:right].real, x=x[left:right])
|
||||||
y_err = np.linalg.norm(cumulative_trapezoid(self._y_err[self.mask][left:right].real, x=self._x[left:right]))
|
y_err_mean = np.linalg.norm(cumulative_trapezoid(y_err[left:right].real, x=x[left:right]))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
y_mean = self._y[self.mask][idx].real
|
y_mean = y[idx].real
|
||||||
y_err = self._y_err[self.mask][idx]
|
y_err_mean = y_err[idx]
|
||||||
|
|
||||||
return y_mean, y_err
|
return y_mean, y_err_mean
|
||||||
|
|
||||||
def concatenate(self, other):
|
def concatenate(self, other):
|
||||||
"""
|
"""
|
||||||
|
@ -6,8 +6,8 @@ from .model import Model
|
|||||||
from .parameter import Parameters, Parameter
|
from .parameter import Parameters, Parameter
|
||||||
|
|
||||||
|
|
||||||
class Data(object):
|
class Data:
|
||||||
def __init__(self, x, y, we=None, idx=None):
|
def __init__(self, x, y, we=None, idx=None, complex_type: int = 0):
|
||||||
self.x = np.asarray(x)
|
self.x = np.asarray(x)
|
||||||
self.y = np.asarray(y)
|
self.y = np.asarray(y)
|
||||||
if self.y.shape[0] != self.x.shape[0]:
|
if self.y.shape[0] != self.x.shape[0]:
|
||||||
@ -20,6 +20,7 @@ class Data(object):
|
|||||||
self.parameter = Parameters()
|
self.parameter = Parameters()
|
||||||
self.para_keys: list = []
|
self.para_keys: list = []
|
||||||
self.fun_kwargs = {}
|
self.fun_kwargs = {}
|
||||||
|
self.complex_type = complex_type
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
return self.y.shape[0]
|
return self.y.shape[0]
|
||||||
|
@ -361,7 +361,7 @@ class FitRoutine(object):
|
|||||||
with np.errstate(all='ignore'):
|
with np.errstate(all='ignore'):
|
||||||
res = optimize.least_squares(cost, p0, bounds=(lb, ub), max_nfev=500 * len(p0))
|
res = optimize.least_squares(cost, p0, bounds=(lb, ub), max_nfev=500 * len(p0))
|
||||||
|
|
||||||
err, corr, partial_corr = self._calc_error(res.jac, np.sum(res.fun**2), *res.jac.shape)
|
err, corr, partial_corr = _calc_error(res.jac, np.sum(res.fun**2), *res.jac.shape)
|
||||||
self.make_results(data, res.x, var, data.para_keys, res.jac.shape,
|
self.make_results(data, res.x, var, data.para_keys, res.jac.shape,
|
||||||
err=err, corr=corr, partial_corr=partial_corr)
|
err=err, corr=corr, partial_corr=partial_corr)
|
||||||
|
|
||||||
@ -375,7 +375,7 @@ class FitRoutine(object):
|
|||||||
with np.errstate(all='ignore'):
|
with np.errstate(all='ignore'):
|
||||||
res = optimize.least_squares(cost, p0, bounds=(lb, ub), max_nfev=500 * len(p0))
|
res = optimize.least_squares(cost, p0, bounds=(lb, ub), max_nfev=500 * len(p0))
|
||||||
|
|
||||||
err, corr, partial_corr = self._calc_error(res.jac, np.sum(res.fun**2), *res.jac.shape)
|
err, corr, partial_corr = _calc_error(res.jac, np.sum(res.fun**2), *res.jac.shape)
|
||||||
for v, var_pars_k in zip(data, data_pars):
|
for v, var_pars_k in zip(data, data_pars):
|
||||||
self.make_results(v, res.x, var, var_pars_k, res.jac.shape,
|
self.make_results(v, res.x, var, var_pars_k, res.jac.shape,
|
||||||
err=err, corr=corr, partial_corr=partial_corr)
|
err=err, corr=corr, partial_corr=partial_corr)
|
||||||
@ -458,9 +458,17 @@ class FitRoutine(object):
|
|||||||
self.make_results(v, res.beta, var, var_pars_k, (sum(len(d) for d in data), len(p0)),
|
self.make_results(v, res.beta, var, var_pars_k, (sum(len(d) for d in data), len(p0)),
|
||||||
err=res.sd_beta, corr=corr, partial_corr=partial_corr)
|
err=res.sd_beta, corr=corr, partial_corr=partial_corr)
|
||||||
|
|
||||||
def make_results(self, data, p, var_pars, used_pars, shape,
|
def make_results(
|
||||||
err=None, corr=None, partial_corr=None):
|
self,
|
||||||
|
data: Data,
|
||||||
|
p: list[float],
|
||||||
|
var_pars: list[str],
|
||||||
|
used_pars: list[str],
|
||||||
|
shape: tuple[int, int],
|
||||||
|
err: list[float] = None,
|
||||||
|
corr: np.ndarray = None,
|
||||||
|
partial_corr: np.ndarray = None,
|
||||||
|
):
|
||||||
if err is None:
|
if err is None:
|
||||||
err = [0] * len(p)
|
err = [0] * len(p)
|
||||||
|
|
||||||
@ -498,22 +506,24 @@ class FitRoutine(object):
|
|||||||
model = data.get_model()
|
model = data.get_model()
|
||||||
|
|
||||||
self.result[idx] = FitResultCreator.make_with_model(
|
self.result[idx] = FitResultCreator.make_with_model(
|
||||||
model,
|
model=model,
|
||||||
data.x,
|
x_orig=data.x,
|
||||||
data.y,
|
y_orig=data.y,
|
||||||
actual_parameters,
|
p=actual_parameters,
|
||||||
data.fun_kwargs,
|
fun_kwargs=data.fun_kwargs,
|
||||||
data.we_string,
|
we=data.we_string,
|
||||||
data.idx,
|
idx=data.idx,
|
||||||
*shape,
|
nobs=shape[0],
|
||||||
|
nvar=shape[1],
|
||||||
corr=actual_corr,
|
corr=actual_corr,
|
||||||
pcorr=actual_pcorr,
|
pcorr=actual_pcorr,
|
||||||
|
data_mode=data.complex_type,
|
||||||
)
|
)
|
||||||
|
|
||||||
return self.result
|
return self.result
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _calc_error(jac, chi, nobs, nvars):
|
def _calc_error(jac, chi, nobs, nvars):
|
||||||
# copy of scipy.curve_fit to calculate covariance
|
# copy of scipy.curve_fit to calculate covariance
|
||||||
# noinspection PyTupleAssignmentBalance
|
# noinspection PyTupleAssignmentBalance
|
||||||
try:
|
try:
|
||||||
|
@ -9,7 +9,7 @@ from ._meta import MultiModel
|
|||||||
from .parameter import Parameters, Parameter
|
from .parameter import Parameters, Parameter
|
||||||
|
|
||||||
|
|
||||||
class Model(object):
|
class Model:
|
||||||
def __init__(self, model, *args, **kwargs):
|
def __init__(self, model, *args, **kwargs):
|
||||||
self.idx = kwargs.pop('idx', None)
|
self.idx = kwargs.pop('idx', None)
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ from scipy.stats import f as fdist
|
|||||||
from scipy.interpolate import interp1d
|
from scipy.interpolate import interp1d
|
||||||
|
|
||||||
from ._meta import MultiModel
|
from ._meta import MultiModel
|
||||||
|
from .model import Model
|
||||||
from .parameter import Parameter
|
from .parameter import Parameter
|
||||||
from ..data.points import Points
|
from ..data.points import Points
|
||||||
from ..data.signals import Signal
|
from ..data.signals import Signal
|
||||||
@ -36,17 +37,30 @@ class FitResultCreator:
|
|||||||
else:
|
else:
|
||||||
resid = kwargs['y'] - y_orig
|
resid = kwargs['y'] - y_orig
|
||||||
|
|
||||||
stats = FitResultCreator.calc_statistics(resid, _y)
|
stats = calc_statistics(resid, _y)
|
||||||
|
|
||||||
return FitResult(kwargs['x'], kwargs['y'], x_orig, y_orig, params, dict(kwargs['choice']), resid, 0, 0,
|
return FitResult(
|
||||||
kwargs['name'], stats, idx)
|
x=kwargs['x'],
|
||||||
|
y=kwargs['y'],
|
||||||
|
x_data=x_orig,
|
||||||
|
y_data=y_orig,
|
||||||
|
params=params,
|
||||||
|
fun_kwargs=dict(kwargs['choice']),
|
||||||
|
resid=resid,
|
||||||
|
nobs=0,
|
||||||
|
nvar=0,
|
||||||
|
we='',
|
||||||
|
name=kwargs['name'],
|
||||||
|
stats=stats,
|
||||||
|
idx=idx,
|
||||||
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def make_with_model(
|
def make_with_model(
|
||||||
model: 'Model',
|
model: 'Model',
|
||||||
x_orig: np.ndarray,
|
x_orig: np.ndarray,
|
||||||
y_orig: np.ndarray,
|
y_orig: np.ndarray,
|
||||||
p: 'Parameters',
|
p: list,
|
||||||
fun_kwargs: dict,
|
fun_kwargs: dict,
|
||||||
we: str,
|
we: str,
|
||||||
idx: str | None,
|
idx: str | None,
|
||||||
@ -54,6 +68,7 @@ class FitResultCreator:
|
|||||||
nvar: int,
|
nvar: int,
|
||||||
corr: np.ndarray,
|
corr: np.ndarray,
|
||||||
pcorr: np.ndarray,
|
pcorr: np.ndarray,
|
||||||
|
data_mode: int,
|
||||||
) -> FitResult:
|
) -> FitResult:
|
||||||
if np.all(x_orig > 0) and (np.max(x_orig) > 100 * np.min(x_orig)):
|
if np.all(x_orig > 0) and (np.max(x_orig) > 100 * np.min(x_orig)):
|
||||||
islog = True
|
islog = True
|
||||||
@ -83,17 +98,11 @@ class FitResultCreator:
|
|||||||
actual_mode = fun_kwargs['complex_mode']
|
actual_mode = fun_kwargs['complex_mode']
|
||||||
fun_kwargs['complex_mode'] = 0
|
fun_kwargs['complex_mode'] = 0
|
||||||
|
|
||||||
_y = model.func(p_final, _x, **fun_kwargs)
|
_y = check_complex(model.func(p_final, _x, **fun_kwargs), actual_mode, data_mode)
|
||||||
|
|
||||||
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
|
fun_kwargs['complex_mode'] = actual_mode
|
||||||
|
|
||||||
stats = FitResultCreator.calc_statistics(_y, resid, nobs, nvar)
|
stats = calc_statistics(_y, resid, nobs, nvar)
|
||||||
varied = [p.var for p in parameters.values()]
|
varied = [p.var for p in parameters.values()]
|
||||||
|
|
||||||
if corr is None:
|
if corr is None:
|
||||||
@ -134,38 +143,9 @@ class FitResultCreator:
|
|||||||
pcorr=partial_correlation,
|
pcorr=partial_correlation,
|
||||||
islog=islog,
|
islog=islog,
|
||||||
func=model,
|
func=model,
|
||||||
|
data_complex=data_mode,
|
||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def calc_statistics(y, residual, nobs=None, nvar=None):
|
|
||||||
chi = (residual**2).sum()
|
|
||||||
try:
|
|
||||||
r = 1 - chi/((y-np.mean(y))**2).sum()
|
|
||||||
except RuntimeWarning:
|
|
||||||
r = -9999
|
|
||||||
|
|
||||||
if nobs is None:
|
|
||||||
nobs = 1
|
|
||||||
|
|
||||||
if nvar is None:
|
|
||||||
nvar = 0
|
|
||||||
|
|
||||||
dof = nobs - nvar
|
|
||||||
loglikehood = nobs * np.log(chi / nobs)
|
|
||||||
|
|
||||||
stats = {
|
|
||||||
'chi^2': chi,
|
|
||||||
'R^2': r,
|
|
||||||
'AIC': loglikehood + 2 * nvar,
|
|
||||||
'BIC': loglikehood + np.log(nobs) * nvar,
|
|
||||||
'adj. R^2': 1 - (nobs-1) / (dof+1e-13) * (1-r),
|
|
||||||
'red. chi^2': chi / (dof + 1e-13),
|
|
||||||
}
|
|
||||||
|
|
||||||
stats['AICc'] = stats['AIC'] + 2*(nvar+1)*nvar / (dof - 1 + 1e-13)
|
|
||||||
|
|
||||||
return stats
|
|
||||||
|
|
||||||
|
|
||||||
class FitResult(Points):
|
class FitResult(Points):
|
||||||
|
|
||||||
@ -188,7 +168,8 @@ class FitResult(Points):
|
|||||||
pcorr: np.ndarray = None,
|
pcorr: np.ndarray = None,
|
||||||
islog: bool = False,
|
islog: bool = False,
|
||||||
func=None,
|
func=None,
|
||||||
**kwargs
|
data_complex: int = 1,
|
||||||
|
**kwargs,
|
||||||
):
|
):
|
||||||
|
|
||||||
self.parameter, name = self._prepare_names(params, name)
|
self.parameter, name = self._prepare_names(params, name)
|
||||||
@ -210,6 +191,7 @@ class FitResult(Points):
|
|||||||
self.y_data = y_data
|
self.y_data = y_data
|
||||||
self._model_name = name
|
self._model_name = name
|
||||||
self._func = func
|
self._func = func
|
||||||
|
self._data_complex = data_complex
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _prepare_names(parameter: dict, modelname: str):
|
def _prepare_names(parameter: dict, modelname: str):
|
||||||
@ -418,20 +400,12 @@ class FitResult(Points):
|
|||||||
if self.func is None:
|
if self.func is None:
|
||||||
raise ValueError('no fit function available to calculate new y values')
|
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()
|
new_fit = self.copy()
|
||||||
y_values = self.func.func(self.p_final, x_values, **self.fun_kwargs)
|
fun_kwargs = {k: v for k, v in self.fun_kwargs.items()}
|
||||||
if not actual_mode < 0:
|
if self.fun_kwargs.get('complex_mode', -1) == -1:
|
||||||
if actual_mode == 1:
|
fun_kwargs.pop('complex_mode', None)
|
||||||
y_values.imag = 0
|
y_values = self.func.func(self.p_final, x_values, **fun_kwargs)
|
||||||
elif actual_mode == 2:
|
y_values = check_complex(y_values, self.fun_kwargs.get('complex_mode', -1), self._data_complex)
|
||||||
y_values.real = 0
|
|
||||||
|
|
||||||
self.fun_kwargs['complex_mode'] = actual_mode
|
|
||||||
|
|
||||||
new_fit.set_data(x_values, y_values, y_err=0.0)
|
new_fit.set_data(x_values, y_values, y_err=0.0)
|
||||||
|
|
||||||
@ -442,20 +416,16 @@ class FitResult(Points):
|
|||||||
raise ValueError('no fit function available to calculate new y values')
|
raise ValueError('no fit function available to calculate new y values')
|
||||||
|
|
||||||
part_functions = []
|
part_functions = []
|
||||||
actual_mode = -1
|
actual_mode = self.fun_kwargs.get('complex_mode', -1)
|
||||||
if 'complex_mode' in self.fun_kwargs:
|
fun_kwargs = {k: v for k, v in self.fun_kwargs.items()}
|
||||||
actual_mode = self.fun_kwargs['complex_mode']
|
if self.fun_kwargs.get('complex_mode', -1) == -1:
|
||||||
self.fun_kwargs['complex_mode'] = 0
|
fun_kwargs.pop('complex_mode', None)
|
||||||
|
|
||||||
for sub_name, sub_y in zip(self.func.sub_name(), self.func.sub(self.p_final, x_values, **self.fun_kwargs)):
|
for sub_name, sub_y in zip(self.func.sub_name(), self.func.sub(self.p_final, x_values, **self.fun_kwargs)):
|
||||||
if not actual_mode < 0:
|
sub_y = check_complex(sub_y, actual_mode, self._data_complex)
|
||||||
if actual_mode == 1:
|
|
||||||
sub_y.imag = 0
|
|
||||||
elif actual_mode == 2:
|
|
||||||
sub_y.real = 0
|
|
||||||
|
|
||||||
|
if np.iscomplexobj(sub_y):
|
||||||
part_functions.append(Signal(x_values, sub_y, name=sub_name))
|
part_functions.append(Signal(x_values, sub_y, name=sub_name))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
part_functions.append(Points(x_values, sub_y, name=sub_name))
|
part_functions.append(Points(x_values, sub_y, name=sub_name))
|
||||||
|
|
||||||
@ -463,3 +433,49 @@ class FitResult(Points):
|
|||||||
self.fun_kwargs['complex_mode'] = actual_mode
|
self.fun_kwargs['complex_mode'] = actual_mode
|
||||||
|
|
||||||
return part_functions
|
return part_functions
|
||||||
|
|
||||||
|
|
||||||
|
def check_complex(y, model_complex, data_complex):
|
||||||
|
if not np.iscomplexobj(y):
|
||||||
|
return y
|
||||||
|
|
||||||
|
if model_complex == 1:
|
||||||
|
y.imag = 0
|
||||||
|
if data_complex == 1:
|
||||||
|
y = y.real
|
||||||
|
elif model_complex == 2:
|
||||||
|
y.real = 0
|
||||||
|
if data_complex == 1:
|
||||||
|
y = y.imag
|
||||||
|
|
||||||
|
return y
|
||||||
|
|
||||||
|
|
||||||
|
def calc_statistics(y, residual, nobs=None, nvar=None):
|
||||||
|
chi = (residual**2).sum()
|
||||||
|
try:
|
||||||
|
r = 1 - chi/((y-np.mean(y))**2).sum()
|
||||||
|
except RuntimeWarning:
|
||||||
|
r = -9999
|
||||||
|
|
||||||
|
if nobs is None:
|
||||||
|
nobs = 1
|
||||||
|
|
||||||
|
if nvar is None:
|
||||||
|
nvar = 0
|
||||||
|
|
||||||
|
dof = nobs - nvar
|
||||||
|
loglikehood = nobs * np.log(chi / nobs)
|
||||||
|
|
||||||
|
stats = {
|
||||||
|
'chi^2': chi,
|
||||||
|
'R^2': r,
|
||||||
|
'AIC': loglikehood + 2 * nvar,
|
||||||
|
'BIC': loglikehood + np.log(nobs) * nvar,
|
||||||
|
'adj. R^2': 1 - (nobs-1) / (dof+1e-13) * (1-r),
|
||||||
|
'red. chi^2': chi / (dof + 1e-13),
|
||||||
|
}
|
||||||
|
|
||||||
|
stats['AICc'] = stats['AIC'] + 2*(nvar+1)*nvar / (dof - 1 + 1e-13)
|
||||||
|
|
||||||
|
return stats
|
||||||
|
@ -49,7 +49,7 @@ class AsciiReader:
|
|||||||
with self.fname.open('r') as f:
|
with self.fname.open('r') as f:
|
||||||
for i, line in enumerate(islice(f, len(self.header)+len(self.lines), num_lines)):
|
for i, line in enumerate(islice(f, len(self.header)+len(self.lines), num_lines)):
|
||||||
line = line.strip('\n\t\r, ')
|
line = line.strip('\n\t\r, ')
|
||||||
line = re.sub(r'[\t ;,] *', ';', line)
|
line = re.sub(r'[\t ;,]+', ';', line)
|
||||||
line = line.split(';')
|
line = line.split(';')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -183,7 +183,13 @@ class AsciiReader:
|
|||||||
single_len = 2
|
single_len = 2
|
||||||
stepsize = 2
|
stepsize = 2
|
||||||
|
|
||||||
cls = {'points': Points, 'fid': FID, 'spectrum': Spectrum, 'bds': BDS, 'dsc': DSC}[mode]
|
cls = {
|
||||||
|
'points': Points,
|
||||||
|
'fid': FID,
|
||||||
|
'spectrum': Spectrum,
|
||||||
|
'bds': BDS,
|
||||||
|
'dsc': DSC,
|
||||||
|
}[mode]
|
||||||
|
|
||||||
for j in range(1, num_y+1, stepsize):
|
for j in range(1, num_y+1, stepsize):
|
||||||
if col_names is not None:
|
if col_names is not None:
|
||||||
@ -191,7 +197,7 @@ class AsciiReader:
|
|||||||
kwargs['name'] = col_names[j-1]
|
kwargs['name'] = col_names[j-1]
|
||||||
elif num_y > single_len:
|
elif num_y > single_len:
|
||||||
# more than one axis, append column number
|
# more than one axis, append column number
|
||||||
kwargs['name'] = filename + '_' + str(y[j-1])
|
kwargs['name'] = f'{filename}_{y[j-1]+1}'
|
||||||
|
|
||||||
if j+num_y < raw_data.shape[2]:
|
if j+num_y < raw_data.shape[2]:
|
||||||
kwargs['y_err'] = raw_data[i, :, j+num_y]
|
kwargs['y_err'] = raw_data[i, :, j+num_y]
|
||||||
|
@ -11,7 +11,8 @@ try:
|
|||||||
from scipy.integrate import simpson
|
from scipy.integrate import simpson
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from scipy.integrate import simps as simpson
|
from scipy.integrate import simps as simpson
|
||||||
from scipy.interpolate import interp1d
|
from scipy.interpolate import CubicSpline
|
||||||
|
|
||||||
|
|
||||||
ReferenceValue = namedtuple('Reference', ['name', 'transitions'])
|
ReferenceValue = namedtuple('Reference', ['name', 'transitions'])
|
||||||
Cyclohexane = ReferenceValue('Cyclohexane', [(-87.06+273.15, 79.58), (6.54+273.15, None)])
|
Cyclohexane = ReferenceValue('Cyclohexane', [(-87.06+273.15, 79.58), (6.54+273.15, None)])
|
||||||
@ -38,7 +39,7 @@ class DSCSample:
|
|||||||
def read_file(self, fname: str | Path) -> None:
|
def read_file(self, fname: str | Path) -> None:
|
||||||
fname = Path(fname)
|
fname = Path(fname)
|
||||||
|
|
||||||
# file contains weird deg C character in stupiod ISO encoding
|
# file contains weird deg C character in stupid ISO encoding
|
||||||
with fname.open('r', encoding='iso-8859-15') as f:
|
with fname.open('r', encoding='iso-8859-15') as f:
|
||||||
ii = 1
|
ii = 1
|
||||||
for line in f:
|
for line in f:
|
||||||
@ -144,9 +145,12 @@ class DSCCalibrator:
|
|||||||
self.reference = []
|
self.reference = []
|
||||||
self.ref_list = []
|
self.ref_list = []
|
||||||
|
|
||||||
def set_measurement(self,
|
def set_measurement(
|
||||||
fname: str | Path | DSCSample, mode: str = 'sample',
|
self: DSCCalibrator,
|
||||||
reference: ReferenceValue = Cyclohexane):
|
fname: str | Path | DSCSample,
|
||||||
|
mode: str = 'sample',
|
||||||
|
reference: ReferenceValue = Cyclohexane
|
||||||
|
):
|
||||||
if mode not in ['sample', 'empty', 'reference']:
|
if mode not in ['sample', 'empty', 'reference']:
|
||||||
raise ValueError(f'Unknown mode {mode}, not "sample", "empty", "reference"')
|
raise ValueError(f'Unknown mode {mode}, not "sample", "empty", "reference"')
|
||||||
if mode == 'reference' and not isinstance(reference, ReferenceValue):
|
if mode == 'reference' and not isinstance(reference, ReferenceValue):
|
||||||
@ -266,7 +270,12 @@ class DSCCalibrator:
|
|||||||
|
|
||||||
return sol
|
return sol
|
||||||
|
|
||||||
def get_data(self, idx: int, slope: str = 'iso', limits: tuple[float, float] = None):
|
def get_data(
|
||||||
|
self: DSCCalibrator,
|
||||||
|
idx: int,
|
||||||
|
slope: str = 'iso',
|
||||||
|
limits: tuple[float, float] = None
|
||||||
|
) -> tuple[np.ndarray, np.ndarray, np.ndarray,np.ndarray | None, np.ndarray]:
|
||||||
if self.sample.steps[idx][0] == 'i':
|
if self.sample.steps[idx][0] == 'i':
|
||||||
raise ValueError('baseline correction is not implemented for isotherms')
|
raise ValueError('baseline correction is not implemented for isotherms')
|
||||||
|
|
||||||
@ -292,7 +301,7 @@ class DSCCalibrator:
|
|||||||
empty_y = empty_data[1]
|
empty_y = empty_data[1]
|
||||||
if self.sample.length(idx) != self.empty.length(idx_empty):
|
if self.sample.length(idx) != self.empty.length(idx_empty):
|
||||||
with np.errstate(all='ignore'):
|
with np.errstate(all='ignore'):
|
||||||
empty_y = interp1d(empty_data[2]-empty_data[2, 0], empty_data[1], fill_value='extrapolate')(sample_data[2, 0])
|
empty_y = CubicSpline(empty_data[2]-empty_data[2, 0], empty_data[1], extrapolate=True)(sample_data[2] - sample_data[2, 0])
|
||||||
|
|
||||||
sample_data[1] -= empty_y
|
sample_data[1] -= empty_y
|
||||||
drift_value = sample_data.copy()[(2, 1), :]
|
drift_value = sample_data.copy()[(2, 1), :]
|
||||||
@ -346,9 +355,10 @@ class DSCCalibrator:
|
|||||||
|
|
||||||
offset = region[0, 0]
|
offset = region[0, 0]
|
||||||
sample_data[1] -= m * (sample_data[2] - region[1, 0]) + offset
|
sample_data[1] -= m * (sample_data[2] - region[1, 0]) + offset
|
||||||
line = np.array([[sample_data[2, 0], sample_data[2, -1]],
|
line = np.array([
|
||||||
[m * (sample_data[2, 0] - region[1, 0]) + offset,
|
[sample_data[2, 0], sample_data[2, -1]],
|
||||||
m * (sample_data[2, -1] - region[1, 0]) + offset]])
|
[m * (sample_data[2, 0] - region[1, 0]) + offset, m * (sample_data[2, -1] - region[1, 0]) + offset]
|
||||||
|
])
|
||||||
|
|
||||||
else:
|
else:
|
||||||
line = np.array([[sample_data[2, 0], sample_data[2, -1]], [0, 0]])
|
line = np.array([[sample_data[2, 0], sample_data[2, -1]], [0, 0]])
|
||||||
|
@ -247,6 +247,7 @@
|
|||||||
<addaction name="action_no_range"/>
|
<addaction name="action_no_range"/>
|
||||||
<addaction name="action_x_range"/>
|
<addaction name="action_x_range"/>
|
||||||
<addaction name="action_custom_range"/>
|
<addaction name="action_custom_range"/>
|
||||||
|
<addaction name="actionExclude_region"/>
|
||||||
</widget>
|
</widget>
|
||||||
<addaction name="action_FitWidget"/>
|
<addaction name="action_FitWidget"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
@ -1021,6 +1022,14 @@
|
|||||||
<string>TNMH...</string>
|
<string>TNMH...</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionExclude_region">
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Exclude region</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
|
@ -354,59 +354,26 @@
|
|||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>3</number>
|
<number>3</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="1" column="0">
|
<item row="1" column="7">
|
||||||
<widget class="QCheckBox" name="extrapolate_box">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Extrapolates only main function</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Extrapolate curves</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="5">
|
|
||||||
<widget class="QCheckBox" name="parameter_checkbox">
|
|
||||||
<property name="text">
|
|
||||||
<string>Plot parameter</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="6">
|
|
||||||
<widget class="QComboBox" name="graph_comboBox">
|
<widget class="QComboBox" name="graph_comboBox">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="5">
|
|
||||||
<widget class="QCheckBox" name="graph_checkBox">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>New graph for parameter</string>
|
|
||||||
</property>
|
|
||||||
<property name="checked">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QLineEdit" name="minx_line">
|
<widget class="QLineEdit" name="minx_line">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
@ -419,10 +386,45 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="4" rowspan="2">
|
<item row="1" column="0">
|
||||||
<widget class="Line" name="line_2">
|
<widget class="QCheckBox" name="extrapolate_box">
|
||||||
<property name="orientation">
|
<property name="toolTip">
|
||||||
<enum>Qt::Vertical</enum>
|
<string>Extrapolates only main function</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Extrapolate curves</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="3">
|
||||||
|
<widget class="QLineEdit" name="numx_line">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="placeholderText">
|
||||||
|
<string># pts</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="6">
|
||||||
|
<widget class="QCheckBox" name="graph_checkBox">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>New graph for parameter</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -432,7 +434,7 @@
|
|||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
@ -445,20 +447,33 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="3">
|
<item row="0" column="5" rowspan="2">
|
||||||
<widget class="QLineEdit" name="numx_line">
|
<widget class="Line" name="line_2">
|
||||||
<property name="enabled">
|
<property name="orientation">
|
||||||
<bool>false</bool>
|
<enum>Qt::Vertical</enum>
|
||||||
</property>
|
|
||||||
<property name="placeholderText">
|
|
||||||
<string># pts</string>
|
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0" colspan="4">
|
<item row="1" column="4">
|
||||||
|
<widget class="QCheckBox" name="newx_log_checkbox">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>log-spaced?</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0" colspan="5">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="curve_checkbox">
|
<widget class="QCheckBox" name="curve_checkbox">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Plot fit curve</string>
|
<string>Plot fit curve</string>
|
||||||
</property>
|
</property>
|
||||||
@ -469,6 +484,12 @@
|
|||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="partial_checkBox">
|
<widget class="QCheckBox" name="partial_checkBox">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Plot partial functions</string>
|
<string>Plot partial functions</string>
|
||||||
</property>
|
</property>
|
||||||
@ -476,6 +497,19 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="0" column="6" colspan="2">
|
||||||
|
<widget class="QCheckBox" name="parameter_checkbox">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Plot parameter</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
Loading…
Reference in New Issue
Block a user