Merge branch 'main' into fit_constraints
# Conflicts: # src/gui_qt/fit/fit_forms.py # src/gui_qt/main/management.py # src/nmreval/fit/minimizer.py
This commit is contained in:
commit
869901596b
@ -32,7 +32,7 @@ AppDir:
|
||||
arch: amd64
|
||||
allow_unauthenticated: true
|
||||
sources:
|
||||
- sourceline: 'deb [arch=amd64] http://mirror.infra.pkm/ bullseye main contrib non-free'
|
||||
- sourceline: 'deb [arch=amd64] http://ftp.uni-mainz.de/debian bullseye main contrib non-free'
|
||||
|
||||
include:
|
||||
# for /usr/bin/env
|
||||
@ -42,7 +42,7 @@ AppDir:
|
||||
# - hicolor-icon-theme
|
||||
- libatlas3-base
|
||||
- gnuplot-nox
|
||||
- python3.9-minimal
|
||||
- python3-minimal
|
||||
- python3-numpy
|
||||
- python3-scipy
|
||||
- python3-bsddb3
|
||||
|
@ -1,10 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file '_ui/apod_dialog.ui'
|
||||
# Form implementation generated from reading ui file 'src/resources/_ui/apod_dialog.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.12.3
|
||||
# Created by: PyQt5 UI code generator 5.15.9
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||
# run again. Do not edit this file unless you know what you are doing.
|
||||
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
@ -23,7 +24,7 @@ class Ui_ApodEdit(object):
|
||||
self.gridLayout.setContentsMargins(3, 3, 3, 3)
|
||||
self.gridLayout.setSpacing(3)
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
self.graphicsView = PlotWidget(ApodEdit)
|
||||
self.graphicsView = NMRPlotWidget(ApodEdit)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Expanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -31,7 +32,7 @@ class Ui_ApodEdit(object):
|
||||
self.graphicsView.setSizePolicy(sizePolicy)
|
||||
self.graphicsView.setObjectName("graphicsView")
|
||||
self.gridLayout.addWidget(self.graphicsView, 2, 0, 1, 1)
|
||||
self.graphicsView_2 = PlotWidget(ApodEdit)
|
||||
self.graphicsView_2 = NMRPlotWidget(ApodEdit)
|
||||
self.graphicsView_2.setObjectName("graphicsView_2")
|
||||
self.gridLayout.addWidget(self.graphicsView_2, 2, 1, 1, 1)
|
||||
self.apodcombobox = QtWidgets.QComboBox(ApodEdit)
|
||||
@ -63,12 +64,12 @@ class Ui_ApodEdit(object):
|
||||
self.gridLayout.addWidget(self.eqn_label, 0, 1, 1, 1)
|
||||
|
||||
self.retranslateUi(ApodEdit)
|
||||
self.buttonBox.accepted.connect(ApodEdit.accept)
|
||||
self.buttonBox.rejected.connect(ApodEdit.close)
|
||||
self.buttonBox.accepted.connect(ApodEdit.accept) # type: ignore
|
||||
self.buttonBox.rejected.connect(ApodEdit.close) # type: ignore
|
||||
QtCore.QMetaObject.connectSlotsByName(ApodEdit)
|
||||
|
||||
def retranslateUi(self, ApodEdit):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
ApodEdit.setWindowTitle(_translate("ApodEdit", "Apodization"))
|
||||
self.eqn_label.setText(_translate("ApodEdit", "TextLabel"))
|
||||
from pyqtgraph import PlotWidget
|
||||
from ..lib.graph_items import NMRPlotWidget
|
||||
|
@ -1,10 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file '_ui/baseline_dialog.ui'
|
||||
# Form implementation generated from reading ui file 'src/resources/_ui/baseline_dialog.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.12.3
|
||||
# Created by: PyQt5 UI code generator 5.15.9
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||
# run again. Do not edit this file unless you know what you are doing.
|
||||
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
@ -44,7 +45,7 @@ class Ui_SignalEdit(object):
|
||||
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
|
||||
self.buttonBox.setObjectName("buttonBox")
|
||||
self.gridLayout.addWidget(self.buttonBox, 1, 0, 1, 3)
|
||||
self.graphicsView = PlotWidget(SignalEdit)
|
||||
self.graphicsView = NMRPlotWidget(SignalEdit)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Expanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -54,11 +55,11 @@ class Ui_SignalEdit(object):
|
||||
self.gridLayout.addWidget(self.graphicsView, 0, 2, 1, 1)
|
||||
|
||||
self.retranslateUi(SignalEdit)
|
||||
self.buttonBox.accepted.connect(SignalEdit.accept)
|
||||
self.buttonBox.rejected.connect(SignalEdit.close)
|
||||
self.buttonBox.accepted.connect(SignalEdit.accept) # type: ignore
|
||||
self.buttonBox.rejected.connect(SignalEdit.close) # type: ignore
|
||||
QtCore.QMetaObject.connectSlotsByName(SignalEdit)
|
||||
|
||||
def retranslateUi(self, SignalEdit):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
SignalEdit.setWindowTitle(_translate("SignalEdit", "Dialog"))
|
||||
from pyqtgraph import PlotWidget
|
||||
from ..lib.graph_items import NMRPlotWidget
|
||||
|
@ -166,7 +166,7 @@ class Ui_Dialog(object):
|
||||
self.gridLayout = QtWidgets.QGridLayout(self.layoutWidget)
|
||||
self.gridLayout.setContentsMargins(0, 0, 0, 0)
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
self.raw_graph = PlotWidget(self.layoutWidget)
|
||||
self.raw_graph = NMRPlotWidget(self.layoutWidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -175,7 +175,7 @@ class Ui_Dialog(object):
|
||||
self.raw_graph.setMinimumSize(QtCore.QSize(300, 200))
|
||||
self.raw_graph.setObjectName("raw_graph")
|
||||
self.gridLayout.addWidget(self.raw_graph, 0, 0, 1, 1)
|
||||
self.calib_graph = PlotWidget(self.layoutWidget)
|
||||
self.calib_graph = NMRPlotWidget(self.layoutWidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -184,7 +184,7 @@ class Ui_Dialog(object):
|
||||
self.calib_graph.setMinimumSize(QtCore.QSize(300, 200))
|
||||
self.calib_graph.setObjectName("calib_graph")
|
||||
self.gridLayout.addWidget(self.calib_graph, 1, 0, 1, 1)
|
||||
self.baseline_graph = PlotWidget(self.layoutWidget)
|
||||
self.baseline_graph = NMRPlotWidget(self.layoutWidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -193,7 +193,7 @@ class Ui_Dialog(object):
|
||||
self.baseline_graph.setMinimumSize(QtCore.QSize(300, 200))
|
||||
self.baseline_graph.setObjectName("baseline_graph")
|
||||
self.gridLayout.addWidget(self.baseline_graph, 0, 1, 1, 1)
|
||||
self.end_graph = PlotWidget(self.layoutWidget)
|
||||
self.end_graph = NMRPlotWidget(self.layoutWidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -228,4 +228,4 @@ class Ui_Dialog(object):
|
||||
self.cp_checkBox.setText(_translate("Dialog", "Use reference to convert to heat capacity"))
|
||||
self.ref_add_pushButton.setText(_translate("Dialog", "Add reference"))
|
||||
self.ref_remove_pushButton.setText(_translate("Dialog", "Remove reference"))
|
||||
from pyqtgraph import PlotWidget
|
||||
from ..lib.graph_items import NMRPlotWidget
|
||||
|
@ -38,7 +38,6 @@ class Ui_FitDialog(object):
|
||||
self.weight_combobox.addItem("")
|
||||
self.weight_combobox.addItem("")
|
||||
self.weight_combobox.addItem("")
|
||||
self.weight_combobox.addItem("")
|
||||
self.gridLayout_2.addWidget(self.weight_combobox, 6, 1, 1, 1)
|
||||
self.newmodel_button = QtWidgets.QPushButton(self.scrollAreaWidgetContents_2)
|
||||
self.newmodel_button.setEnabled(False)
|
||||
@ -144,7 +143,6 @@ class Ui_FitDialog(object):
|
||||
self.weight_combobox.setItemText(1, _translate("FitDialog", "y"))
|
||||
self.weight_combobox.setItemText(2, _translate("FitDialog", "y²"))
|
||||
self.weight_combobox.setItemText(3, _translate("FitDialog", "Δy"))
|
||||
self.weight_combobox.setItemText(4, _translate("FitDialog", "log(y)"))
|
||||
self.newmodel_button.setText(_translate("FitDialog", "New model"))
|
||||
self.deletemodel_button.setText(_translate("FitDialog", "Delete model"))
|
||||
self.label_3.setText(_translate("FitDialog", "Weight"))
|
||||
|
@ -210,7 +210,7 @@ class Ui_GraphWindow(object):
|
||||
self.checkBox.setChecked(True)
|
||||
self.checkBox.setObjectName("checkBox")
|
||||
self.gridLayout.addWidget(self.checkBox, 0, 1, 1, 1)
|
||||
self.graphic = PlotWidget(GraphWindow)
|
||||
self.graphic = NMRPlotWidget(GraphWindow)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -274,5 +274,5 @@ class Ui_GraphWindow(object):
|
||||
self.label_6.setText(_translate("GraphWindow", "X Axis"))
|
||||
self.label_7.setText(_translate("GraphWindow", "Y Axis"))
|
||||
self.checkBox.setText(_translate("GraphWindow", "Show legend"))
|
||||
from ..lib.graph_items import NMRPlotWidget
|
||||
from ..lib.listwidget import QListWidgetSelect
|
||||
from pyqtgraph import PlotWidget
|
||||
|
@ -1,8 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'resources/_ui/phase_corr_dialog.ui'
|
||||
# Form implementation generated from reading ui file 'src/resources/_ui/phase_corr_dialog.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.15.4
|
||||
# Created by: PyQt5 UI code generator 5.15.9
|
||||
#
|
||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||
# run again. Do not edit this file unless you know what you are doing.
|
||||
@ -24,7 +24,7 @@ class Ui_SignalEdit(object):
|
||||
self.gridLayout.setContentsMargins(6, 6, 6, 6)
|
||||
self.gridLayout.setSpacing(3)
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
self.graphicsView = PlotWidget(SignalEdit)
|
||||
self.graphicsView = NMRPlotWidget(SignalEdit)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Expanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -83,8 +83,8 @@ class Ui_SignalEdit(object):
|
||||
self.gridLayout.addItem(spacerItem1, 1, 5, 1, 1)
|
||||
|
||||
self.retranslateUi(SignalEdit)
|
||||
self.buttonBox.accepted.connect(SignalEdit.accept)
|
||||
self.buttonBox.rejected.connect(SignalEdit.close)
|
||||
self.buttonBox.accepted.connect(SignalEdit.accept) # type: ignore
|
||||
self.buttonBox.rejected.connect(SignalEdit.close) # type: ignore
|
||||
QtCore.QMetaObject.connectSlotsByName(SignalEdit)
|
||||
|
||||
def retranslateUi(self, SignalEdit):
|
||||
@ -94,4 +94,4 @@ class Ui_SignalEdit(object):
|
||||
self.label_8.setText(_translate("SignalEdit", "Pivot"))
|
||||
self.label_6.setText(_translate("SignalEdit", "Phase 1"))
|
||||
self.label.setText(_translate("SignalEdit", "Phase 0"))
|
||||
from pyqtgraph import PlotWidget
|
||||
from ..lib.graph_items import NMRPlotWidget
|
||||
|
@ -1,10 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'resources/_ui/shift_scale_dialog.ui'
|
||||
# Form implementation generated from reading ui file 'src/resources/_ui/shift_scale_dialog.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.12.3
|
||||
# Created by: PyQt5 UI code generator 5.15.9
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||
# run again. Do not edit this file unless you know what you are doing.
|
||||
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
@ -162,7 +163,7 @@ class Ui_shift_dialog(object):
|
||||
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.verticalFrame_2)
|
||||
self.verticalLayout_2.setSpacing(3)
|
||||
self.verticalLayout_2.setObjectName("verticalLayout_2")
|
||||
self.graphicsView = PlotWidget(self.verticalFrame_2)
|
||||
self.graphicsView = NMRPlotWidget(self.verticalFrame_2)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.MinimumExpanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -267,8 +268,8 @@ class Ui_shift_dialog(object):
|
||||
|
||||
self.retranslateUi(shift_dialog)
|
||||
self.tabWidget.setCurrentIndex(0)
|
||||
self.buttonBox.accepted.connect(shift_dialog.accept)
|
||||
self.buttonBox.rejected.connect(shift_dialog.reject)
|
||||
self.buttonBox.accepted.connect(shift_dialog.accept) # type: ignore
|
||||
self.buttonBox.rejected.connect(shift_dialog.reject) # type: ignore
|
||||
QtCore.QMetaObject.connectSlotsByName(shift_dialog)
|
||||
shift_dialog.setTabOrder(self.tabWidget, self.shift_table)
|
||||
shift_dialog.setTabOrder(self.shift_table, self.x_shift_spinbox)
|
||||
@ -310,5 +311,5 @@ class Ui_shift_dialog(object):
|
||||
self.overwrite_checkbox.setText(_translate("shift_dialog", "Overwrite data"))
|
||||
self.data_newgraph.setText(_translate("shift_dialog", "New graph"))
|
||||
self.values_newgraph.setText(_translate("shift_dialog", "New graph"))
|
||||
from ..lib.graph_items import NMRPlotWidget
|
||||
from ..lib.spinboxes import SciSpinBox
|
||||
from pyqtgraph import PlotWidget
|
||||
|
@ -1,10 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'resources/_ui/t1dialog.ui'
|
||||
# Form implementation generated from reading ui file 'src/resources/_ui/t1dialog.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.12.3
|
||||
# Created by: PyQt5 UI code generator 5.15.9
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||
# run again. Do not edit this file unless you know what you are doing.
|
||||
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
@ -160,6 +161,7 @@ class Ui_t1dialog(object):
|
||||
self.tau_combox.addItem("")
|
||||
self.gridLayout_4.addWidget(self.tau_combox, 1, 0, 1, 2)
|
||||
self.checkBox_interpol = QtWidgets.QCheckBox(self.groupBox_3)
|
||||
self.checkBox_interpol.setEnabled(False)
|
||||
self.checkBox_interpol.setObjectName("checkBox_interpol")
|
||||
self.gridLayout_4.addWidget(self.checkBox_interpol, 2, 0, 1, 2)
|
||||
self.graph_checkbox = QtWidgets.QCheckBox(self.groupBox_3)
|
||||
|
@ -59,7 +59,7 @@ class Ui_DSCEvalDialog(object):
|
||||
self.tg_tree.headerItem().setText(0, "1")
|
||||
self.tg_tree.header().setVisible(False)
|
||||
self.gridLayout_2.addWidget(self.tg_tree, 2, 0, 1, 1)
|
||||
self.dsc_plot = PlotWidget(self.page)
|
||||
self.dsc_plot = NMRPlotWidget(self.page)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -89,10 +89,10 @@ class Ui_DSCEvalDialog(object):
|
||||
self.label_4 = QtWidgets.QLabel(self.page_2)
|
||||
self.label_4.setObjectName("label_4")
|
||||
self.gridLayout_3.addWidget(self.label_4, 2, 0, 1, 1)
|
||||
self.tghodge_graph = PlotWidget(self.page_2)
|
||||
self.tghodge_graph = NMRPlotWidget(self.page_2)
|
||||
self.tghodge_graph.setObjectName("tghodge_graph")
|
||||
self.gridLayout_3.addWidget(self.tghodge_graph, 1, 0, 1, 1)
|
||||
self.tau_plot = PlotWidget(self.page_2)
|
||||
self.tau_plot = NMRPlotWidget(self.page_2)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.MinimumExpanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -155,7 +155,7 @@ class Ui_DSCEvalDialog(object):
|
||||
self.page_3.setObjectName("page_3")
|
||||
self.gridLayout_6 = QtWidgets.QGridLayout(self.page_3)
|
||||
self.gridLayout_6.setObjectName("gridLayout_6")
|
||||
self.tnmh_graphics = PlotWidget(self.page_3)
|
||||
self.tnmh_graphics = NMRPlotWidget(self.page_3)
|
||||
self.tnmh_graphics.setObjectName("tnmh_graphics")
|
||||
self.gridLayout_6.addWidget(self.tnmh_graphics, 1, 0, 1, 2)
|
||||
self.tnmh_tree = QtWidgets.QTreeWidget(self.page_3)
|
||||
@ -249,5 +249,5 @@ class Ui_DSCEvalDialog(object):
|
||||
self.back_button.setText(_translate("DSCEvalDialog", "Back"))
|
||||
self.next_button.setText(_translate("DSCEvalDialog", "Next"))
|
||||
self.close_button.setText(_translate("DSCEvalDialog", "Close"))
|
||||
from ..lib.graph_items import NMRPlotWidget
|
||||
from ..lib.listwidget import QListWidgetSelect
|
||||
from pyqtgraph import PlotWidget
|
||||
|
@ -463,6 +463,16 @@ class ExperimentContainer(QtCore.QObject):
|
||||
|
||||
return offset
|
||||
|
||||
@plot_update
|
||||
def shift_scale(self, shift_factor: tuple[float, float], scaling_factor: tuple[float, float]):
|
||||
scale_x, scale_y = scaling_factor
|
||||
shift_x, shift_y = shift_factor
|
||||
self.data.x = self.data.x * scale_x + shift_x
|
||||
self.data.y = self.data.y * scale_y + shift_y
|
||||
self.data.y_err = self.data.y_err * scale_y
|
||||
|
||||
self.update({'shift': scaling_factor, 'scale': shift_factor})
|
||||
|
||||
def get_namespace(self, i: int = None, j: int = None) -> dict:
|
||||
if (i is None) and (j is None):
|
||||
prefix = ''
|
||||
|
@ -1,7 +1,7 @@
|
||||
import numpy as np
|
||||
from itertools import cycle
|
||||
|
||||
from pyqtgraph import mkColor, mkPen
|
||||
from pyqtgraph import mkColor, mkPen, mkBrush
|
||||
|
||||
from nmreval.lib.colors import Tab10
|
||||
|
||||
@ -42,11 +42,17 @@ class QShift(QtWidgets.QDialog, Ui_shift_dialog):
|
||||
|
||||
def add_item(self, idx, name, x, y):
|
||||
color = mkColor(next(self._colors).rgb())
|
||||
if np.iscomplexobj(y):
|
||||
pl = [PlotItem(x=x, y=y.real, name=name, pen=mkPen(color=color)),
|
||||
PlotItem(x=x, y=y.imag, name=name, pen=mkPen(color=color))]
|
||||
|
||||
if len(y) == 1:
|
||||
sym_kwds = {'symbol': 'o', 'symbolBrush': mkBrush(color=color), 'symbolPen': mkPen(color=color)}
|
||||
else:
|
||||
pl = [PlotItem(x=x, y=y, name=name, pen=mkPen(color=color))]
|
||||
sym_kwds = {'symbol': None, 'symbolBrush': mkBrush(color=color), 'symbolPen': mkPen(color=color)}
|
||||
|
||||
if np.iscomplexobj(y):
|
||||
pl = [PlotItem(x=x, y=y.real, name=name, pen=mkPen(color=color), **sym_kwds),
|
||||
PlotItem(x=x, y=y.imag, name=name, pen=mkPen(color=color), **sym_kwds)]
|
||||
else:
|
||||
pl = [PlotItem(x=x, y=y, name=name, pen=mkPen(color=color), **sym_kwds)]
|
||||
|
||||
self.data[idx] = (pl, x, y)
|
||||
|
||||
|
@ -6,12 +6,14 @@ from ..Qt import QtCore, QtWidgets, QtGui
|
||||
from .._py.fitmodelwidget import Ui_FitParameter
|
||||
from .._py.save_fitmodel_dialog import Ui_SaveDialog
|
||||
from ..lib.iconloading import get_icon
|
||||
from ..lib.tables import TableWidget
|
||||
|
||||
|
||||
class FitModelWidget(QtWidgets.QWidget, Ui_FitParameter):
|
||||
value_requested = QtCore.pyqtSignal(object)
|
||||
value_changed = QtCore.pyqtSignal(str)
|
||||
state_changed = QtCore.pyqtSignal()
|
||||
replace_single_value = QtCore.pyqtSignal(object)
|
||||
|
||||
def __init__(self, label: str = 'Fitparameter', parent=None, fixed: bool = False):
|
||||
super().__init__(parent)
|
||||
@ -30,6 +32,7 @@ class FitModelWidget(QtWidgets.QWidget, Ui_FitParameter):
|
||||
self.global_checkbox.stateChanged.connect(lambda: self.state_changed.emit())
|
||||
self.parameter_line.editingFinished.connect(self.update_parameter)
|
||||
self.parameter_line.values_requested.connect(lambda: self.value_requested.emit(self))
|
||||
self.parameter_line.replace_single_values.connect(lambda: self.replace_single_value.emit(None))
|
||||
self.parameter_line.editingFinished.connect(lambda: self.value_changed.emit(self.parameter_line.text()))
|
||||
self.fixed_check.toggled.connect(self.set_fixed)
|
||||
|
||||
@ -311,7 +314,7 @@ class FitModelTree(QtWidgets.QTreeWidget):
|
||||
return funcs
|
||||
|
||||
|
||||
class FitTableWidget(QtWidgets.QTableWidget):
|
||||
class FitTableWidget(TableWidget):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent=parent)
|
||||
|
||||
|
@ -78,6 +78,7 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
|
||||
widgt.state_changed.connect(self.make_global)
|
||||
widgt.value_requested.connect(self.look_for_value)
|
||||
widgt.value_changed.connect(self.change_global_parameter)
|
||||
widgt.replace_single_value.connect(self.delete_single_parameter)
|
||||
|
||||
self.global_parameter.append(widgt)
|
||||
self.scrollwidget.layout().addWidget(widgt)
|
||||
@ -150,6 +151,13 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
|
||||
if value is None:
|
||||
self.change_data(self.comboBox.currentIndex())
|
||||
|
||||
def delete_single_parameter(self):
|
||||
idx = self.global_parameter.index(self.sender())
|
||||
for i in range(self.comboBox.count()):
|
||||
set_id = self.comboBox.itemData(i)
|
||||
self.data_values[set_id][idx] = None
|
||||
self.change_data(self.comboBox.currentIndex())
|
||||
|
||||
def change_single_choice(self, _, value, sender=None):
|
||||
if sender is None:
|
||||
sender = self.sender()
|
||||
@ -298,7 +306,8 @@ class ParameterSingleWidget(QtWidgets.QWidget):
|
||||
|
||||
self._name = name
|
||||
self.label.setText(convert(name))
|
||||
self.label.setToolTip('IIf this is bold then this parameter is only for this data. otherwise the general parameter is used and displayed')
|
||||
self.label.setToolTip('If this is bold then this parameter is only for this data. '
|
||||
'Otherwise, the general parameter is used and displayed')
|
||||
|
||||
# self.value_line.setValidator(QtGui.QDoubleValidator())
|
||||
self.value_line.textChanged.connect(lambda: self.valueChanged.emit(self.value) if self.value is not None else 0)
|
||||
|
@ -14,7 +14,7 @@ from gui_qt.lib.namespace import QNamespaceWidget
|
||||
|
||||
__all__ = ['QUserFitCreator']
|
||||
|
||||
validator = QtGui.QRegExpValidator(QtCore.QRegExp('[A-Za-z]\S*'))
|
||||
validator = QtGui.QRegExpValidator(QtCore.QRegExp('[_A-Za-z][_A-Za-z0-9]*'))
|
||||
pattern = re.compile(r'def func\(.*\):', flags=re.MULTILINE)
|
||||
|
||||
|
||||
@ -145,6 +145,7 @@ class QUserFitCreator(QtWidgets.QDialog, Ui_Dialog):
|
||||
self.classCreated.emit()
|
||||
super().accept()
|
||||
|
||||
|
||||
class KwargsWidget(QtWidgets.QWidget):
|
||||
Changed = QtCore.pyqtSignal()
|
||||
|
||||
@ -209,7 +210,7 @@ class KwargsWidget(QtWidgets.QWidget):
|
||||
def get_strings(self) -> str:
|
||||
kwargs = []
|
||||
if self.use_nuclei.isChecked():
|
||||
kwargs.append("(r'\gamma', 'nucleus', gamma)")
|
||||
kwargs.append(r"(r'\gamma', 'nucleus', gamma)")
|
||||
|
||||
for i in range(self.choices.count()):
|
||||
kwargs.append(self.choices.widget(i).get_strings())
|
||||
@ -300,7 +301,7 @@ class ChoiceWidget(QtWidgets.QWidget):
|
||||
def get_strings(self) -> str:
|
||||
opts = []
|
||||
for i in range(self.table.rowCount()):
|
||||
name = self.table.item(i, 0).text()
|
||||
name = self.table.cellWidget(i, 0).text()
|
||||
val = self._make_value(i)
|
||||
opts.append(f'{name!r}: {val!r}')
|
||||
|
||||
|
@ -3,6 +3,7 @@ from math import isnan
|
||||
from pyqtgraph import mkBrush, mkPen
|
||||
|
||||
from nmreval.utils.text import convert
|
||||
from ..lib.graph_items import logTickValues
|
||||
|
||||
from ..lib.utils import RdBuCMap
|
||||
from ..Qt import QtWidgets, QtGui, QtCore
|
||||
@ -33,8 +34,12 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
|
||||
self.graph_opts = {}
|
||||
self.last_idx = None
|
||||
|
||||
self.resid_plot = self.graphicsView.addPlot(row=0, col=0, title='Residual')
|
||||
self.fit_plot = self.graphicsView.addPlot(row=1, col=0, title='Fit')
|
||||
self.resid_plot = self.graphicsView.addPlot(row=0, col=0, title='Residual')
|
||||
|
||||
for orient in ['top', 'bottom', 'left', 'right']:
|
||||
self.fit_plot.getAxis(orient).logTickValues = logTickValues
|
||||
self.resid_plot.getAxis(orient).logTickValues = logTickValues
|
||||
|
||||
self.graphicsView.ci.layout.setRowStretchFactor(0, 1)
|
||||
self.graphicsView.ci.layout.setRowStretchFactor(1, 2)
|
||||
|
@ -4,7 +4,7 @@ import itertools
|
||||
import os
|
||||
import uuid
|
||||
|
||||
from math import isnan
|
||||
from math import isfinite
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
@ -45,7 +45,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
self.id = str(uuid.uuid4())
|
||||
|
||||
self.sets = []
|
||||
self.active = []
|
||||
self._active = []
|
||||
|
||||
self.real_plots = {}
|
||||
self.imag_plots = {}
|
||||
@ -75,6 +75,8 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
self.scene.contextMenu[0].disconnect()
|
||||
self.scene.contextMenu[0].triggered.connect(self.export_dialog)
|
||||
|
||||
self.bwbutton.toggled.connect(self.change_background)
|
||||
|
||||
def _init_gui(self):
|
||||
self.setWindowTitle('Graph ' + str(next(QGraphWindow.counter)))
|
||||
|
||||
@ -114,11 +116,11 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
return iter(self.active)
|
||||
|
||||
def __len__(self):
|
||||
return len(self.active)
|
||||
return len(self._active)
|
||||
|
||||
def curves(self) -> tuple:
|
||||
for set_id in self.sets:
|
||||
if set_id in self.active:
|
||||
if set_id in self._active:
|
||||
if self.real_button.isChecked():
|
||||
if self.error_plots[set_id] is not None:
|
||||
yield self.real_plots[set_id], self.error_plots[set_id]
|
||||
@ -144,7 +146,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
tmp = [np.nan, np.nan]
|
||||
for j, x in enumerate(r[i]):
|
||||
try:
|
||||
tmp[j] = 10**x
|
||||
tmp[j] = 10**min(x, 199)
|
||||
except OverflowError:
|
||||
pass
|
||||
r[i] = tuple(tmp)
|
||||
@ -153,6 +155,14 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
|
||||
return tuple(r)
|
||||
|
||||
@property
|
||||
def active(self) -> list:
|
||||
return [set_id for set_id in self.sets if set_id in self._active]
|
||||
|
||||
@active.setter
|
||||
def active(self, value: list):
|
||||
self._active = value
|
||||
|
||||
def block(self, state: bool):
|
||||
self._block = state
|
||||
|
||||
@ -201,8 +211,8 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
for plot in [self.real_plots, self.imag_plots, self.error_plots]:
|
||||
self.graphic.removeItem(plot[n])
|
||||
|
||||
if n in self.active:
|
||||
self.active.remove(n)
|
||||
if n in self._active:
|
||||
self._active.remove(n)
|
||||
|
||||
# remove from label list
|
||||
self.listWidget.blockSignals(True)
|
||||
@ -246,8 +256,8 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
return
|
||||
|
||||
for a in idlist:
|
||||
if a not in self.active:
|
||||
self.active.append(a)
|
||||
if a not in self._active:
|
||||
self._active.append(a)
|
||||
|
||||
for (bttn, plot_dic) in [
|
||||
(self.real_button, self.real_plots),
|
||||
@ -266,8 +276,8 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
return
|
||||
|
||||
for r in idlist:
|
||||
if r in self.active:
|
||||
self.active.remove(r)
|
||||
if r in self._active:
|
||||
self._active.remove(r)
|
||||
|
||||
for plt in [self.real_plots, self.imag_plots, self.error_plots]:
|
||||
item = plt[r]
|
||||
@ -289,7 +299,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
else:
|
||||
func = self.graphic.removeItem
|
||||
|
||||
for a in self.active:
|
||||
for a in self._active:
|
||||
item = plots[a]
|
||||
if item is not None:
|
||||
func(item)
|
||||
@ -306,12 +316,12 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
return
|
||||
|
||||
if visible:
|
||||
for a in self.active:
|
||||
for a in self._active:
|
||||
item = self.error_plots[a]
|
||||
if (item is not None) and (item not in self.graphic.items()):
|
||||
self.graphic.addItem(item)
|
||||
else:
|
||||
for a in self.active:
|
||||
for a in self._active:
|
||||
item = self.error_plots[a]
|
||||
if (item is not None) and (item in self.graphic.items()):
|
||||
self.graphic.removeItem(item)
|
||||
@ -423,6 +433,9 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
def set_logmode(self, xmode: bool = None, ymode: bool = None):
|
||||
r = self.ranges
|
||||
|
||||
self.plotItem.setXRange(*r[0])
|
||||
self.plotItem.setYRange(*r[1])
|
||||
|
||||
if xmode is None:
|
||||
xmode = self.plotItem.ctrl.logXCheck.isChecked()
|
||||
else:
|
||||
@ -439,6 +452,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
item.logmode[0] = self.log[:]
|
||||
|
||||
self.plotItem.updateLogMode()
|
||||
self.set_range(x=r[0], y=r[1])
|
||||
|
||||
self.plotItem.enableAutoRange()
|
||||
|
||||
@ -481,9 +495,9 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
with errstate(all='ignore'):
|
||||
xy = [log10(val) for val in xy]
|
||||
|
||||
if isnan(xy[1]):
|
||||
if not isfinite(xy[1]):
|
||||
xy = [-1, 1]
|
||||
elif isnan(xy[0]):
|
||||
elif not isfinite(xy[0]):
|
||||
xy[0] = xy[1]-4
|
||||
|
||||
func(xy[0], xy[1], padding=0)
|
||||
@ -669,7 +683,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
'legend': self.legend.isVisible(),
|
||||
'plots': (self.real_button.isChecked(), self.imag_button.isChecked(), self.error_button.isChecked()),
|
||||
'children': self.sets,
|
||||
'active': self.active,
|
||||
'active': self._active,
|
||||
}
|
||||
|
||||
in_legend = []
|
||||
@ -760,8 +774,8 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
if y is not None:
|
||||
self.plotItem.setLabel('left', y, **{'font-size': '10pt', 'color': self._fgcolor.name()})
|
||||
|
||||
@QtCore.pyqtSlot(bool, name='on_bwbutton_toggled')
|
||||
def change_background(self, _):
|
||||
temp = self._fgcolor, self._bgcolor
|
||||
self.set_color(foreground=self._prev_colors[0], background=self._prev_colors[1])
|
||||
self._prev_colors = temp
|
||||
|
||||
|
@ -4,6 +4,7 @@ from nmreval.lib.lines import LineStyle
|
||||
from nmreval.lib.symbols import SymbolStyle
|
||||
from nmreval.data.points import Points
|
||||
from nmreval.io.graceeditor import GraceEditor
|
||||
from nmreval.utils.text import convert
|
||||
|
||||
from ..Qt import QtCore, QtWidgets, QtGui
|
||||
from .._py.gracereader import Ui_Dialog
|
||||
@ -55,7 +56,7 @@ class QGraceReader(QtWidgets.QDialog, Ui_Dialog):
|
||||
if ds is None:
|
||||
continue
|
||||
|
||||
item_2 = QtWidgets.QTreeWidgetItem([f'Set {gset.idx} (Label: {gset.get_property("legend")}, '
|
||||
item_2 = QtWidgets.QTreeWidgetItem([f'Set {gset.idx} (Label: {convert(gset.get_property("legend"), old="agr", new="str")}, '
|
||||
f'shape: {ds.shape})'])
|
||||
item_2.setCheckState(0, QtCore.Qt.Checked)
|
||||
item_2.setData(0, QtCore.Qt.UserRole, (graphs.idx, gset.idx))
|
||||
@ -94,6 +95,7 @@ class QGraceReader(QtWidgets.QDialog, Ui_Dialog):
|
||||
label = ''
|
||||
else:
|
||||
label = label.replace('"', '')
|
||||
label = convert(label, old='agr', new='str')
|
||||
sd = s.data
|
||||
sd = np.atleast_2d(sd)
|
||||
if s.type == 'xydy':
|
||||
|
@ -237,7 +237,7 @@ class CodeEditor(QtWidgets.QPlainTextEdit):
|
||||
if block.isVisible() and (bottom >= evt.rect().top()):
|
||||
number = str(block_number + 1)
|
||||
painter.setPen(QtCore.Qt.black)
|
||||
painter.drawText(0, top, self.current_linenumber.width() - 3, height,
|
||||
painter.drawText(0, int(top), self.current_linenumber.width() - 3, height,
|
||||
QtCore.Qt.AlignRight, number)
|
||||
|
||||
block = block.next()
|
||||
|
@ -52,19 +52,24 @@ class QDelayWidget(QtWidgets.QWidget):
|
||||
|
||||
class LineEdit(QtWidgets.QLineEdit):
|
||||
values_requested = QtCore.pyqtSignal()
|
||||
replace_single_values = QtCore.pyqtSignal()
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent=parent)
|
||||
|
||||
def contextMenuEvent(self, evt):
|
||||
menu = self.createStandardContextMenu()
|
||||
request_action = menu.addAction('Use value of sets')
|
||||
request_action = menu.addAction('Use numeric value of sets')
|
||||
set_value_action = menu.addAction('Replace single set values')
|
||||
|
||||
action = menu.exec(evt.globalPos())
|
||||
|
||||
if action == request_action:
|
||||
self.values_requested.emit()
|
||||
|
||||
elif action == set_value_action:
|
||||
self.replace_single_values.emit()
|
||||
|
||||
|
||||
class LineEditPost(QtWidgets.QLineEdit):
|
||||
values_requested = QtCore.pyqtSignal()
|
||||
|
53
src/gui_qt/lib/graph_items.py
Normal file
53
src/gui_qt/lib/graph_items.py
Normal file
@ -0,0 +1,53 @@
|
||||
from numpy import log10, arange, floor, ceil
|
||||
from pyqtgraph import PlotWidget, PlotItem
|
||||
|
||||
|
||||
__all__ = ['NMRPlotWidget', 'logTickValues']
|
||||
|
||||
|
||||
class NMRPlotWidget(PlotWidget):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
for orient in ['top', 'bottom', 'left', 'right']:
|
||||
# BAD HACK!!! but seems to work, see function for explanation
|
||||
self.plotItem.getAxis(orient).logTickValues = logTickValues
|
||||
|
||||
|
||||
class NMRPlotItem(PlotItem):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
for orient in ['top', 'bottom', 'left', 'right']:
|
||||
self.plotItem.getAxis(orient).logTickValues = logTickValues
|
||||
|
||||
|
||||
def logTickValues(minVal, maxVal, size, stdTicks):
|
||||
# TODO FIND A BETTER SOLUTION!!!
|
||||
# Sometimes minVal and maxVal are not log-scaled values and the loop from v1 to v2 is humongous,
|
||||
# The minor list then fills the RAM completely and freezes everything
|
||||
# Until there is a better solution, we overwrite this function for every AxesItem
|
||||
# and do not draw minor ticks at all if there are too many
|
||||
|
||||
# start with the tick spacing given by tickValues().
|
||||
# Any level whose spacing is < 1 needs to be converted to log scale
|
||||
ticks = []
|
||||
for (spacing, t) in stdTicks:
|
||||
if spacing >= 1.0:
|
||||
ticks.append((spacing, t))
|
||||
|
||||
if len(ticks) < 3:
|
||||
v1 = int(floor(minVal))
|
||||
v2 = int(ceil(maxVal))
|
||||
# major = list(range(v1+1, v2))
|
||||
minor = []
|
||||
|
||||
if v2 - v1 < 400:
|
||||
for v in range(v1, v2):
|
||||
minor.extend(v + log10(arange(1, 10)))
|
||||
minor = [x for x in minor if minVal < x < maxVal]
|
||||
ticks.append((None, minor))
|
||||
return ticks
|
||||
|
@ -375,9 +375,6 @@ class PlotItem(PlotDataItem):
|
||||
class RegionItem(LinearRegionItem):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.mode = kwargs.pop('mode', 'half')
|
||||
|
||||
print(args, kwargs)
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.logmode = False
|
||||
@ -475,11 +472,18 @@ class LegendItemBlock(LegendItem):
|
||||
def mouseDragEvent(self, ev):
|
||||
if ev.button() == QtCore.Qt.LeftButton:
|
||||
ev.accept()
|
||||
|
||||
dpos = ev.pos() - ev.lastPos()
|
||||
|
||||
upper_left = self.pos()
|
||||
lower_right = self.pos()
|
||||
lower_right.setX(lower_right.x() + self.width())
|
||||
lower_right.setY(lower_right.y() + self.height())
|
||||
|
||||
vb_rect = self.parentItem().rect()
|
||||
pos = self.pos()
|
||||
# upper left corner and a point a little more to the bottom right must be inside
|
||||
if vb_rect.contains(pos+dpos) and vb_rect.contains(pos+dpos+QtCore.QPointF(20., 20.)):
|
||||
self.autoAnchor(pos + dpos)
|
||||
|
||||
# upper left and lower right corner must be inside viewbox
|
||||
if vb_rect.contains(upper_left + dpos) and vb_rect.contains(lower_right + dpos):
|
||||
self.autoAnchor(upper_left + dpos)
|
||||
else:
|
||||
self.autoAnchor(pos)
|
||||
self.autoAnchor(upper_left)
|
||||
|
@ -29,3 +29,16 @@ class TreeWidget(QtWidgets.QTreeWidget):
|
||||
it.setCheckState(0, QtCore.Qt.Unchecked if it.checkState(0) == QtCore.Qt.Checked else QtCore.Qt.Checked)
|
||||
else:
|
||||
super().keyPressEvent(evt)
|
||||
|
||||
|
||||
class TableWidget(QtWidgets.QTableWidget):
|
||||
def keyPressEvent(self, evt: QtGui.QKeyEvent):
|
||||
if evt.key() == QtCore.Qt.Key.Key_Space:
|
||||
for idx in self.selectedIndexes():
|
||||
item = self.itemFromIndex(idx)
|
||||
cs = item.checkState()
|
||||
item.setCheckState(QtCore.Qt.CheckState.Unchecked if cs == QtCore.Qt.CheckState.Checked
|
||||
else QtCore.Qt.CheckState.Checked)
|
||||
else:
|
||||
super().keyPressEvent(evt)
|
||||
|
||||
|
@ -211,7 +211,6 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
|
||||
self.ptsselectwidget.points_selected.connect(self.management.extract_points)
|
||||
|
||||
self.t1tauwidget.newData.connect(self.management.add_new_data)
|
||||
self.t1tauwidget.newData.connect(self.management.add_new_data)
|
||||
|
||||
self.editsignalwidget.do_something.connect(self.management.apply)
|
||||
@ -917,10 +916,12 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
self.action_odr_fit: 'odr'
|
||||
}[self.ac_group.checkedAction()]
|
||||
|
||||
self.fit_dialog.fit_button.setEnabled(False)
|
||||
self.management.start_fit(parameter, links, fit_options)
|
||||
self.status.setText('Fit running...'.format(self.management.fitter.step))
|
||||
self.fit_timer.start(500)
|
||||
fit_is_ready = self.management.prepare_fit(parameter, links, fit_options)
|
||||
if fit_is_ready:
|
||||
self.management.start_fit()
|
||||
self.fit_dialog.fit_button.setEnabled(False)
|
||||
self.status.setText('Fit running...'.format(self.management.fitter.step))
|
||||
self.fit_timer.start(500)
|
||||
|
||||
@QtCore.pyqtSlot(dict, int, bool)
|
||||
def show_fit_preview(self, funcs: dict, num: int, show: bool):
|
||||
|
@ -58,11 +58,18 @@ class GraphDict(OrderedDict):
|
||||
def list(self):
|
||||
return [(k, v.title) for k, v in self.items()]
|
||||
|
||||
def active(self, key: str):
|
||||
if key:
|
||||
return [(self._data[i].id, self._data[i].name) for i in self[key]]
|
||||
else:
|
||||
def active(self, key: str, return_val: str = 'both'):
|
||||
if not key:
|
||||
return []
|
||||
else:
|
||||
if return_val == 'both':
|
||||
return [(self._data[i].id, self._data[i].name) for i in self[key]]
|
||||
elif return_val == 'id':
|
||||
return [self._data[i].id for i in self[key]]
|
||||
elif return_val == 'name':
|
||||
return [self._data[i].name for i in self[key]]
|
||||
else:
|
||||
raise ValueError(f'return_val got wrong value {return_val!r}')
|
||||
|
||||
def current_sets(self, key: str):
|
||||
if key:
|
||||
@ -148,6 +155,10 @@ class UpperManagement(QtCore.QObject):
|
||||
def active_sets(self):
|
||||
return self.graphs.active(self.current_graph)
|
||||
|
||||
@property
|
||||
def active_id(self):
|
||||
return self.graphs.active(self.current_graph, return_val='id')
|
||||
|
||||
def get_attributes(self, graph_id: str, attr: str) -> dict[str, Any]:
|
||||
return {self.data[i].id: getattr(self.data[i], attr) for i in self.graphs[graph_id].sets}
|
||||
|
||||
@ -413,9 +424,9 @@ class UpperManagement(QtCore.QObject):
|
||||
for d in self.data.values():
|
||||
d.mask = np.ones_like(d.mask, dtype=bool)
|
||||
|
||||
def start_fit(self, parameter: dict, links: list, fit_options: dict):
|
||||
def prepare_fit(self, parameter: dict, links: list, fit_options: dict) -> bool:
|
||||
if self._fit_active:
|
||||
return
|
||||
return False
|
||||
|
||||
self.__fit_options = (parameter, links, fit_options)
|
||||
|
||||
@ -423,60 +434,84 @@ class UpperManagement(QtCore.QObject):
|
||||
models = {}
|
||||
fit_limits = fit_options['limits']
|
||||
fit_mode = fit_options['fit_mode']
|
||||
we = fit_options['we']
|
||||
we_option = fit_options['we']
|
||||
|
||||
for model_id, model_p in parameter.items():
|
||||
m = Model(model_p['func'])
|
||||
models[model_id] = m
|
||||
self.fitter.fitmethod = fit_mode
|
||||
|
||||
m_complex = model_p['complex']
|
||||
# all-encompassing error catch
|
||||
try:
|
||||
for model_id, model_p in parameter.items():
|
||||
m = Model(model_p['func'])
|
||||
models[model_id] = m
|
||||
|
||||
for set_id, set_params in model_p['parameter'].items():
|
||||
data_i = self.data[set_id]
|
||||
if we.lower() == 'deltay':
|
||||
we = data_i.y_err**2
|
||||
m_complex = model_p['complex']
|
||||
|
||||
if m_complex is None or m_complex == 1:
|
||||
_y = data_i.y.real
|
||||
elif m_complex == 2 and np.iscomplexobj(data_i.y):
|
||||
_y = data_i.y.imag
|
||||
else:
|
||||
_y = data_i.y
|
||||
# sets are not in active order but in order they first appeared in fit dialog
|
||||
# iterate over order of set id in active order and access parameter inside loop
|
||||
# instead of directly looping
|
||||
list_ids = list(model_p['parameter'].keys())
|
||||
set_order = [self.active_id.index(i) for i in list_ids]
|
||||
for pos in set_order:
|
||||
set_id = list_ids[pos]
|
||||
|
||||
_x = data_i.x
|
||||
data_i = self.data[set_id]
|
||||
set_params = model_p['parameter'][set_id]
|
||||
|
||||
if fit_limits == 'none':
|
||||
inside = slice(None)
|
||||
elif fit_limits == 'x':
|
||||
x_lim, _ = self.graphs[self.current_graph].ranges
|
||||
inside = np.where((_x >= x_lim[0]) & (_x <= x_lim[1]))
|
||||
else:
|
||||
inside = np.where((_x >= fit_limits[0]) & (_x <= fit_limits[1]))
|
||||
if we_option.lower() == 'deltay':
|
||||
we = data_i.y_err**2
|
||||
else:
|
||||
we = we_option
|
||||
|
||||
if isinstance(we, str):
|
||||
d = fit_d.Data(_x[inside], _y[inside], we=we, idx=set_id)
|
||||
else:
|
||||
d = fit_d.Data(_x[inside], _y[inside], we=we[inside], idx=set_id)
|
||||
if m_complex is None or m_complex == 1:
|
||||
_y = data_i.y.real
|
||||
elif m_complex == 2 and np.iscomplexobj(data_i.y):
|
||||
_y = data_i.y.imag
|
||||
else:
|
||||
_y = data_i.y
|
||||
|
||||
d.set_model(m)
|
||||
d.set_parameter(set_params[0], var=model_p['var'],
|
||||
lb=model_p['lb'], ub=model_p['ub'],
|
||||
fun_kwargs=set_params[1])
|
||||
_x = data_i.x
|
||||
|
||||
self.fitter.add_data(d)
|
||||
if fit_limits == 'none':
|
||||
inside = slice(None)
|
||||
elif fit_limits == 'x':
|
||||
x_lim, _ = self.graphs[self.current_graph].ranges
|
||||
inside = np.where((_x >= x_lim[0]) & (_x <= x_lim[1]))
|
||||
else:
|
||||
inside = np.where((_x >= fit_limits[0]) & (_x <= fit_limits[1]))
|
||||
|
||||
model_globs = model_p['glob']
|
||||
if model_globs:
|
||||
for parameter_args in zip(*model_globs.values()):
|
||||
m.set_global_parameter(**{k: v for k, v in zip(model_globs.keys(), parameter_args)})
|
||||
# m.set_global_parameter(**model_p['glob'])
|
||||
if isinstance(we, str):
|
||||
d = fit_d.Data(_x[inside], _y[inside], we=we, idx=set_id)
|
||||
else:
|
||||
d = fit_d.Data(_x[inside], _y[inside], we=we[inside], idx=set_id)
|
||||
|
||||
for links_i in links:
|
||||
self.fitter.set_link_parameter((models[links_i[0]], links_i[1]),
|
||||
(models[links_i[2]], links_i[3]))
|
||||
d.set_model(m)
|
||||
d.set_parameter(set_params[0], var=model_p['var'],
|
||||
lb=model_p['lb'], ub=model_p['ub'],
|
||||
fun_kwargs=set_params[1])
|
||||
|
||||
self.fitter.add_data(d)
|
||||
|
||||
model_globs = model_p['glob']
|
||||
if model_globs:
|
||||
for parameter_args in zip(*model_globs.values()):
|
||||
m.set_global_parameter(**{k: v for k, v in zip(model_globs.keys(), parameter_args)})
|
||||
# m.set_global_parameter(**model_p['glob'])
|
||||
|
||||
for links_i in links:
|
||||
self.fitter.set_link_parameter((models[links_i[0]], links_i[1]),
|
||||
(models[links_i[2]], links_i[3]))
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logger.error('Fit preparation failed', *e.args)
|
||||
QtWidgets.QMessageBox.warning(QtWidgets.QWidget(),
|
||||
'Fit prep failed',
|
||||
f'Fit preparation failed with message\n{e.args}')
|
||||
return False
|
||||
|
||||
def start_fit(self):
|
||||
with busy_cursor():
|
||||
self.fit_worker = FitWorker(self.fitter, fit_mode)
|
||||
self.fit_worker = FitWorker(self.fitter)
|
||||
self.fit_thread = QtCore.QThread()
|
||||
self.fit_worker.moveToThread(self.fit_thread)
|
||||
|
||||
@ -512,7 +547,8 @@ class UpperManagement(QtCore.QObject):
|
||||
for set_id, set_parameter in parameter.items():
|
||||
new_values = [v.value for v in res[set_id].parameter.values()]
|
||||
parameter[set_id] = (new_values, set_parameter[1])
|
||||
self.start_fit(*self.__fit_options)
|
||||
if self.prepare_fit(*self.__fit_options):
|
||||
self.start_fit()
|
||||
|
||||
def make_fits(self, res: dict, opts: list, param_graph: str, show_fit: bool, parts: bool, extrapolate: list) -> None:
|
||||
"""
|
||||
@ -637,7 +673,7 @@ class UpperManagement(QtCore.QObject):
|
||||
|
||||
def save_fit_parameter(self, fname: str | pathlib.Path, fit_sets: list[str] = None):
|
||||
if fit_sets is None:
|
||||
fit_sets = [s for (s, _) in self.active_sets]
|
||||
fit_sets = [s for s in self.active_id]
|
||||
|
||||
for set_id in fit_sets:
|
||||
data = self.data[set_id]
|
||||
@ -843,13 +879,10 @@ class UpperManagement(QtCore.QObject):
|
||||
d_k = self.data[k]
|
||||
|
||||
if copy_data is None:
|
||||
d_k.x = d_k.x*v[1][0] + v[0][0]
|
||||
d_k.y = d_k.y*v[1][1] + v[0][1]
|
||||
d_k.shift_scale(v[0], v[1])
|
||||
else:
|
||||
new_data = d_k.copy(full=True)
|
||||
new_data.update({'shift': v[0], 'scale': v[1]})
|
||||
new_data.data.x = new_data.x*v[1][0] + v[0][0]
|
||||
new_data.y = new_data.y*v[1][1] + v[0][1]
|
||||
new_data.shift_scale(v[0], v[1])
|
||||
|
||||
sid = self.add(new_data)
|
||||
sid_list.append(sid)
|
||||
@ -1009,7 +1042,7 @@ class UpperManagement(QtCore.QObject):
|
||||
def show_statistics(self, mode):
|
||||
x, y, = [], []
|
||||
|
||||
for i, _ in self.active_sets:
|
||||
for i in self.active_id:
|
||||
_temp = self.data[i]
|
||||
try:
|
||||
x.append(float(_temp.name))
|
||||
@ -1020,7 +1053,7 @@ class UpperManagement(QtCore.QObject):
|
||||
@QtCore.pyqtSlot()
|
||||
def calc_magn(self):
|
||||
new_id = []
|
||||
for k, _ in self.active_sets:
|
||||
for k in self.active_id:
|
||||
dataset = self.data[k]
|
||||
if isinstance(dataset, SignalContainer):
|
||||
new_value = dataset.copy(full=True)
|
||||
@ -1032,7 +1065,7 @@ class UpperManagement(QtCore.QObject):
|
||||
@QtCore.pyqtSlot()
|
||||
def center(self):
|
||||
new_id = []
|
||||
for k, _ in self.active_sets:
|
||||
for k in self.active_id:
|
||||
new_value = self.data[k].copy(full=True)
|
||||
new_value.x -= new_value.x[np.argmax(new_value.y.real)]
|
||||
new_id.append(self.add(new_value))
|
||||
@ -1071,7 +1104,7 @@ class UpperManagement(QtCore.QObject):
|
||||
def bds_deriv(self):
|
||||
new_sets = []
|
||||
|
||||
for (set_id, _) in self.active_sets:
|
||||
for set_id in self.active_id:
|
||||
data_i = self.data[set_id]
|
||||
diff = data_i.data.diff(log=True)
|
||||
new_data = Points(x=diff.x, y=-np.pi/2*diff.y.real)
|
||||
@ -1098,7 +1131,7 @@ class UpperManagement(QtCore.QObject):
|
||||
self.newData.emit(new_sets, kwargs['graph'])
|
||||
|
||||
def skip_points(self, offset: int, step: int, invert: bool = False, copy: bool = False):
|
||||
for k, _ in self.active_sets:
|
||||
for k in self.active_id:
|
||||
src = self.data[k]
|
||||
if invert:
|
||||
mask = np.mod(np.arange(offset, src.x.size+offset), step) != 0
|
||||
@ -1253,16 +1286,15 @@ class UpperManagement(QtCore.QObject):
|
||||
class FitWorker(QtCore.QObject):
|
||||
finished = QtCore.pyqtSignal(list, bool)
|
||||
|
||||
def __init__(self, fitter, mode):
|
||||
def __init__(self, fitter):
|
||||
super().__init__()
|
||||
|
||||
self.fitter = fitter
|
||||
self.mode = mode
|
||||
|
||||
@QtCore.pyqtSlot()
|
||||
def run(self):
|
||||
try:
|
||||
res = self.fitter.run(mode=self.mode)
|
||||
res = self.fitter.run()
|
||||
success = True
|
||||
except Exception as e:
|
||||
res = [e]
|
||||
|
@ -19,7 +19,7 @@ class QRelaxCalc(QtWidgets.QDialog, Ui_Dialog):
|
||||
|
||||
self.graphs = {}
|
||||
|
||||
self.specdens = [ColeCole, ColeDavidson, HavriliakNegami, KWW]
|
||||
self.specdens = [ColeCole, ColeDavidson, HavriliakNegami, KWW, LogGaussian]
|
||||
self.coupling = [Quadrupolar, HomoDipolar, Czjzek]
|
||||
self.tau_parameter = []
|
||||
|
||||
@ -199,3 +199,9 @@ class QRelaxCalc(QtWidgets.QDialog, Ui_Dialog):
|
||||
def accept(self):
|
||||
self.calc_relaxation()
|
||||
super().accept()
|
||||
|
||||
@QtCore.pyqtSlot(QtWidgets.QAbstractButton)
|
||||
def on_buttonBox_clicked(self, button: QtWidgets.QAbstractButton):
|
||||
role = self.buttonBox.buttonRole(button)
|
||||
if role == self.buttonBox.ApplyRole:
|
||||
self.calc_relaxation()
|
||||
|
@ -61,6 +61,8 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
|
||||
self.freq_combox.currentIndexChanged.connect(lambda x: self.update_model())
|
||||
self.freq_spinbox.valueChanged.connect(lambda x: self.update_model())
|
||||
|
||||
self.checkBox_interpol.setVisible(False)
|
||||
|
||||
self.update_specdens(0)
|
||||
self.update_coupling(0)
|
||||
|
||||
|
@ -54,6 +54,9 @@ class ColeCole(Distribution):
|
||||
tau (array_like):
|
||||
alpha (float):
|
||||
"""
|
||||
if alpha == 1:
|
||||
return tau / (1 + omega**2 * tau**2)
|
||||
|
||||
omtau = (omega*tau)**alpha
|
||||
return np.sin(alpha*np.pi/2) * omtau / (1 + omtau**2 + 2*np.cos(alpha*np.pi/2)*omtau) / omega
|
||||
|
||||
|
@ -5,6 +5,7 @@ from typing import Callable
|
||||
|
||||
import numpy as np
|
||||
from scipy import LowLevelCallable
|
||||
from scipy.special import erf
|
||||
|
||||
from nmreval.lib.utils import ArrayLike
|
||||
|
||||
@ -32,7 +33,7 @@ class LogGaussian(Distribution):
|
||||
return np.exp(-0.5*(np.log(tau/tau0)/sigma)**2)/np.sqrt(2*np.pi)/sigma
|
||||
|
||||
@staticmethod
|
||||
def correlation(t, tau0, sigma: float):
|
||||
def correlation(t: ArrayLike, tau0: ArrayLike, sigma: float):
|
||||
_t = np.atleast_1d(t)
|
||||
_tau = np.atleast_1d(tau0)
|
||||
|
||||
@ -44,7 +45,7 @@ class LogGaussian(Distribution):
|
||||
return res.squeeze()
|
||||
|
||||
@staticmethod
|
||||
def susceptibility(omega, tau0, sigma: float):
|
||||
def susceptibility(omega: ArrayLike, tau0: ArrayLike, sigma: float):
|
||||
_omega = np.atleast_1d(omega)
|
||||
_tau = np.atleast_1d(tau0)
|
||||
|
||||
@ -68,6 +69,7 @@ class LogGaussian(Distribution):
|
||||
ret_val = _integration_parallel(_omega, _tau, sigma, _integrate_process_imag)
|
||||
|
||||
ret_val /= _omega[:, None]
|
||||
ret_val[_omega == 0, :] = tau[None, :] * np.exp(sigma**2 / 2)
|
||||
|
||||
return ret_val.squeeze()
|
||||
|
||||
@ -113,18 +115,16 @@ def _integrate_susc_c(lowfunc, highfunc, omega, tau, sigma):
|
||||
return res
|
||||
|
||||
|
||||
def _integrate_process_imag(args):
|
||||
omega_i, tau_j, sigma = args
|
||||
area = quad(_integrand_freq_imag_high, 0, 50, args=(omega_i, tau_j, sigma), epsabs=1e-12, epsrel=1e-12)[0]
|
||||
area += quad(_integrand_freq_imag_low, -50, 0, args=(omega_i, tau_j, sigma), epsabs=1e-12, epsrel=1e-12)[0]
|
||||
def _integrate_process_imag(omega, tau, sigma):
|
||||
area = quad(_integrand_freq_imag_high, 0, 50, args=(omega, tau, sigma), epsabs=1e-12, epsrel=1e-12)[0]
|
||||
area += quad(_integrand_freq_imag_low, -50, 0, args=(omega, tau, sigma), epsabs=1e-12, epsrel=1e-12)[0]
|
||||
|
||||
return area
|
||||
|
||||
|
||||
def _integrate_process_real(args):
|
||||
omega_i, tau_j, sigma = args
|
||||
area = quad(_integrand_freq_real_high, 0, 50, args=(omega_i, tau_j, sigma))[0]
|
||||
area += quad(_integrand_freq_real_low, -50, 0, args=(omega_i, tau_j, sigma))[0]
|
||||
def _integrate_process_real(omega: float, tau: float, sigma: float):
|
||||
area = quad(_integrand_freq_real_high, 0, 50, args=(omega, tau, sigma))[0]
|
||||
area += quad(_integrand_freq_real_low, -50, 0, args=(omega, tau, sigma))[0]
|
||||
|
||||
return area
|
||||
|
||||
@ -145,9 +145,8 @@ def _integrate_correlation_c(t, tau, sigma):
|
||||
return res
|
||||
|
||||
|
||||
def _integrate_process_time(args):
|
||||
omega_i, tau_j, sigma = args
|
||||
return quad(_integrand_time, -50, 50, args=(omega_i, tau_j, sigma), epsabs=1e-12, epsrel=1e-12)[0]
|
||||
def _integrate_process_time(omega, tau, sigma):
|
||||
return quad(_integrand_time, -50, 50, args=(omega, tau, sigma), epsabs=1e-12, epsrel=1e-12)[0]
|
||||
|
||||
|
||||
def _integrand_time(u, t, tau, sigma):
|
||||
|
@ -24,9 +24,10 @@ class ModelFactory:
|
||||
param_len.append(len(func['func'].params))
|
||||
|
||||
if func['children']:
|
||||
right, _, _ = ModelFactory.create_from_list(func['children'], left=func['func'], left_cnt=func['pos'],
|
||||
right, _, _ = ModelFactory.create_from_list(func['children'], left_cnt=func['pos'],
|
||||
func_order=func_order, param_len=param_len)
|
||||
right_cnt = None
|
||||
right = MultiModel(func['func'], right, func['children'][0]['op'], left_idx=func['cnt'], right_idx=None)
|
||||
else:
|
||||
right = func['func']
|
||||
right_cnt = func['cnt']
|
||||
@ -46,7 +47,13 @@ class MultiModel:
|
||||
str_op = {'+': operator.add, '*': operator.mul, '-': operator.sub, '/': operator.truediv}
|
||||
int_op = {0: operator.add, 1: operator.mul, 2: operator.sub, 3: operator.truediv}
|
||||
|
||||
def __init__(self, left: Any, right: Any, op: str | Callable | int = '+', left_idx=0, right_idx=1):
|
||||
def __init__(self,
|
||||
left: Any,
|
||||
right: Any,
|
||||
op: str | Callable | int = '+',
|
||||
left_idx: int | None = 0,
|
||||
right_idx: int | None = 1,
|
||||
):
|
||||
self._left = left
|
||||
self._right = right
|
||||
|
||||
|
@ -82,7 +82,7 @@ def _update_parameter(data: Data, varied_keys: list[str], parameter: list[float]
|
||||
|
||||
class FitRoutine(object):
|
||||
def __init__(self, mode='lsq'):
|
||||
self._fitmethod = mode
|
||||
self.fitmethod = mode
|
||||
self.data = []
|
||||
self.fit_model = None
|
||||
self._no_own_model = []
|
||||
@ -220,9 +220,12 @@ class FitRoutine(object):
|
||||
logger.info('Fit aborted by user')
|
||||
self._abort = True
|
||||
|
||||
def run(self, mode: str = 'lsq'):
|
||||
def run(self, mode: str=None):
|
||||
self._abort = False
|
||||
|
||||
if mode is None:
|
||||
mode = self.fitmethod
|
||||
|
||||
fit_groups, linked_parameter = self.prepare_links()
|
||||
for data_groups in fit_groups:
|
||||
if len(data_groups) == 1 and not self.linked:
|
||||
|
@ -15,7 +15,7 @@ NUMBERRE = re.compile(r'[0-9]\.*[0-9]*[Ee]*[+-]*[0-9]*')
|
||||
|
||||
|
||||
class AsciiReader:
|
||||
delimiters = ['\t', ' ', ',']
|
||||
# delimiters = ['\t', ' ', ',']
|
||||
|
||||
def __init__(self, fname):
|
||||
self.fname = None
|
||||
@ -49,7 +49,8 @@ class AsciiReader:
|
||||
with self.fname.open('r') as f:
|
||||
for i, line in enumerate(islice(f, len(self.header)+len(self.lines), num_lines)):
|
||||
line = line.rstrip('\n\t\r, ')
|
||||
line = re.split(r'[\s,;]', line)
|
||||
line = re.sub(r'[\t ;,] *', ';', line)
|
||||
line = line.split(';')
|
||||
|
||||
try:
|
||||
comment_start = line.index('#')
|
||||
|
@ -292,7 +292,7 @@ class DSCCalibrator:
|
||||
empty_y = empty_data[1]
|
||||
if self.sample.length(idx) != self.empty.length(idx_empty):
|
||||
with np.errstate(all='ignore'):
|
||||
empty_y = interp1d(empty_data[2], empty_data[1], fill_value='extrapolate')(sample_data[2])
|
||||
empty_y = interp1d(empty_data[2]-empty_data[2, 0], empty_data[1], fill_value='extrapolate')(sample_data[2, 0])
|
||||
|
||||
sample_data[1] -= empty_y
|
||||
drift_value = sample_data.copy()[(2, 1), :]
|
||||
|
@ -24,8 +24,8 @@ def interpolate(data, new_x, xlog=False, ylog=False, kind='cubic', extrapolate=T
|
||||
new_y = f(new_x)
|
||||
|
||||
if ylog:
|
||||
ret_val.set_data(x=new_x, y=10**new_y, y_err=None)
|
||||
ret_val.set_data(x=new_x, y=10**new_y, y_err=0)
|
||||
else:
|
||||
ret_val.set_data(x=new_x, y=new_y, y_err=None)
|
||||
ret_val.set_data(x=new_x, y=new_y, y_err=0)
|
||||
|
||||
return ret_val
|
||||
|
@ -54,14 +54,35 @@ class HavriliakNegamiBDS(_AbstractBDS):
|
||||
name = 'Havriliak-Negami'
|
||||
equation = r'\Delta\epsilon / [1-(i\omega\tau)^{\gamma}]^{\alpha}'
|
||||
params = _AbstractBDS.params + [r'\alpha', r'\gamma']
|
||||
bounds = _AbstractBDS.bounds + [(0, 1), (0, 1)]
|
||||
bounds = _AbstractBDS.bounds + [(0, 1), (0, None)]
|
||||
susceptibility = HavriliakNegami.susceptibility
|
||||
|
||||
|
||||
class HavriliakNegamiAlphaGammaBDS:
|
||||
type = 'Dielectric Spectroscopy'
|
||||
name = 'Havriliak-Negami (ind. slopes)'
|
||||
equation = r'\Delta\epsilon / [1-(i\omega\tau)^{\gamma}]^{\alpha}'
|
||||
params = [r'\Delta\epsilon', r'\tau_{0}', r'\alpha', r'\alpha\gamma']
|
||||
bounds = [(0, None), (0, None), (0, 1), (0, 1)]
|
||||
iscomplex = True
|
||||
|
||||
@staticmethod
|
||||
def func(x, deps, tau, alpha, alphagamma, complex_mode: int = 0, **kwargs):
|
||||
chi = deps * HavriliakNegami.susceptibility(2*np.pi*x, tau, alpha, alphagamma/alpha, **kwargs)
|
||||
if complex_mode == 0:
|
||||
return chi
|
||||
elif complex_mode == 1:
|
||||
return chi.real
|
||||
elif complex_mode == 2:
|
||||
return chi.imag
|
||||
else:
|
||||
raise ValueError(f'{complex_mode!r} is not 0, 1, 2')
|
||||
|
||||
|
||||
class KWWBDS(_AbstractBDS):
|
||||
name = 'KWW'
|
||||
params = _AbstractBDS.params + [r'\beta']
|
||||
bounds = _AbstractBDS.bounds + [(0, 1)]
|
||||
bounds = _AbstractBDS.bounds + [(0.1, 1)]
|
||||
susceptibility = KWW.susceptibility
|
||||
|
||||
|
||||
|
@ -149,7 +149,6 @@ class DiffusionGradients:
|
||||
else:
|
||||
tm = t2
|
||||
tp = x
|
||||
# T2 decay happens twice
|
||||
q2 = (g1**2 - g2**2) * (nucleus * tp)**2
|
||||
t_eff = (2 * tp) / 3 + tm
|
||||
|
||||
|
@ -66,7 +66,7 @@ class HavriliakNegamiFC(_AbstractFC):
|
||||
class KWWFC(_AbstractFC):
|
||||
name = 'KWW'
|
||||
params = _AbstractFC.params + [r'\beta']
|
||||
bounds = _AbstractFC.bounds + [(0, 1)]
|
||||
bounds = _AbstractFC.bounds + [(0.1, 1)]
|
||||
relax = Relaxation(distribution=KWW)
|
||||
|
||||
|
||||
|
@ -80,6 +80,10 @@ def _replace_delims(text, src, dest):
|
||||
return text
|
||||
|
||||
|
||||
def _replace_agr_controls(text: str):
|
||||
return re.sub(r'\\[hvzfx]\{(\d*.?\d+.?)?\}', '', text)
|
||||
|
||||
|
||||
def convert(text: str, old: str = 'tex', new: str = 'html', brackets: bool = True):
|
||||
t = {'latex': 0, 'tex': 0, 'html': 1,
|
||||
'agr': 2, 'plain': 3, 'str': 3}
|
||||
@ -101,5 +105,8 @@ def convert(text: str, old: str = 'tex', new: str = 'html', brackets: bool = Tru
|
||||
if idx_out == 3 and not brackets:
|
||||
text = text.replace('{', '').replace('}', '')
|
||||
|
||||
if idx_in == 2:
|
||||
text = _replace_agr_controls(text)
|
||||
|
||||
return text
|
||||
|
||||
|
@ -36,7 +36,7 @@
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item row="2" column="0">
|
||||
<widget class="PlotWidget" name="graphicsView">
|
||||
<widget class="NMRPlotWidget" name="graphicsView">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
@ -46,7 +46,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="PlotWidget" name="graphicsView_2"/>
|
||||
<widget class="NMRPlotWidget" name="graphicsView_2"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QComboBox" name="apodcombobox">
|
||||
@ -98,9 +98,9 @@
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>PlotWidget</class>
|
||||
<class>NMRPlotWidget</class>
|
||||
<extends>QGraphicsView</extends>
|
||||
<header>pyqtgraph</header>
|
||||
<header>..lib.graph_items</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
|
@ -53,7 +53,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="PlotWidget" name="graphicsView">
|
||||
<widget class="NMRPlotWidget" name="graphicsView">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
@ -66,9 +66,9 @@
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>PlotWidget</class>
|
||||
<class>NMRPlotWidget</class>
|
||||
<extends>QGraphicsView</extends>
|
||||
<header>pyqtgraph</header>
|
||||
<header>..lib.graph_items</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
|
@ -378,7 +378,7 @@
|
||||
<widget class="QWidget" name="layoutWidget">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="PlotWidget" name="raw_graph">
|
||||
<widget class="NMRPlotWidget" name="raw_graph">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
@ -394,7 +394,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="PlotWidget" name="calib_graph">
|
||||
<widget class="NMRPlotWidget" name="calib_graph">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
@ -410,7 +410,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="PlotWidget" name="baseline_graph">
|
||||
<widget class="NMRPlotWidget" name="baseline_graph">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
@ -426,7 +426,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="PlotWidget" name="end_graph">
|
||||
<widget class="NMRPlotWidget" name="end_graph">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
@ -449,9 +449,9 @@
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>PlotWidget</class>
|
||||
<class>NMRPlotWidget</class>
|
||||
<extends>QGraphicsView</extends>
|
||||
<header>pyqtgraph</header>
|
||||
<header>..lib.graph_items</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
|
@ -538,7 +538,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" rowspan="2">
|
||||
<widget class="PlotWidget" name="graphic">
|
||||
<widget class="NMRPlotWidget" name="graphic">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
@ -552,16 +552,16 @@
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>PlotWidget</class>
|
||||
<extends>QGraphicsView</extends>
|
||||
<header>pyqtgraph</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>QListWidgetSelect</class>
|
||||
<extends>QListWidget</extends>
|
||||
<header>..lib.listwidget</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>NMRPlotWidget</class>
|
||||
<extends>QGraphicsView</extends>
|
||||
<header>..lib.graph_items</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>logx_button</tabstop>
|
||||
|
@ -36,7 +36,7 @@
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item row="0" column="0" colspan="8">
|
||||
<widget class="PlotWidget" name="graphicsView">
|
||||
<widget class="NMRPlotWidget" name="graphicsView">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
@ -160,9 +160,9 @@
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>PlotWidget</class>
|
||||
<class>NMRPlotWidget</class>
|
||||
<extends>QGraphicsView</extends>
|
||||
<header>pyqtgraph</header>
|
||||
<header>..lib.graph_items</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
|
@ -317,7 +317,7 @@
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="PlotWidget" name="graphicsView">
|
||||
<widget class="NMRPlotWidget" name="graphicsView">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
@ -503,9 +503,9 @@
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>PlotWidget</class>
|
||||
<class>NMRPlotWidget</class>
|
||||
<extends>QGraphicsView</extends>
|
||||
<header>pyqtgraph</header>
|
||||
<header>..lib.graph_items</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>SciSpinBox</class>
|
||||
|
@ -451,6 +451,9 @@
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="checkBox_interpol">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use minimon interpolation</string>
|
||||
</property>
|
||||
|
@ -100,7 +100,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="PlotWidget" name="dsc_plot">
|
||||
<widget class="NMRPlotWidget" name="dsc_plot">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
@ -145,10 +145,10 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="PlotWidget" name="tghodge_graph"/>
|
||||
<widget class="NMRPlotWidget" name="tghodge_graph"/>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="PlotWidget" name="tau_plot">
|
||||
<widget class="NMRPlotWidget" name="tau_plot">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
@ -277,7 +277,7 @@
|
||||
<widget class="QWidget" name="page_3">
|
||||
<layout class="QGridLayout" name="gridLayout_6">
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="PlotWidget" name="tnmh_graphics"/>
|
||||
<widget class="NMRPlotWidget" name="tnmh_graphics"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QTreeWidget" name="tnmh_tree">
|
||||
@ -427,16 +427,16 @@
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>PlotWidget</class>
|
||||
<extends>QGraphicsView</extends>
|
||||
<header>pyqtgraph</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>QListWidgetSelect</class>
|
||||
<extends>QListWidget</extends>
|
||||
<header>..lib.listwidget</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>NMRPlotWidget</class>
|
||||
<extends>QGraphicsView</extends>
|
||||
<header>..lib.graph_items</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
|
Loading…
Reference in New Issue
Block a user