delete graphs should be less leaky;

BDS: added CD/CC+HF
This commit is contained in:
dominik 2022-08-10 20:00:10 +02:00
parent 168d0fc72c
commit 5120c9d57c
10 changed files with 130 additions and 44 deletions

View File

@ -100,7 +100,9 @@ class MultiModel:
if v.default is not Parameter.empty} if v.default is not Parameter.empty}
for k, v in temp_dic.items(): for k, v in temp_dic.items():
key_ = f'{k}_{idx}' key_ = k
if k != 'complex_mode':
key_ = f'{k}_{idx}'
kw_dict[key_] = v kw_dict[key_] = v
self.fun_kwargs[key_] = v self.fun_kwargs[key_] = v
self._ext_int_kw[key_] = k self._ext_int_kw[key_] = k

View File

@ -1,6 +1,9 @@
import pathlib from __future__ import annotations
import re import re
from collections import OrderedDict from collections import OrderedDict
from pathlib import Path
from typing import Any
import numpy as np import numpy as np
from scipy.stats import f as fdist from scipy.stats import f as fdist
@ -14,7 +17,7 @@ from ..utils.text import convert
class FitResultCreator: class FitResultCreator:
@staticmethod @staticmethod
def make_from_session(x_orig, y_orig, idx, kwargs) -> (dict, list): def make_from_session(x_orig: np.ndarray, y_orig: np.ndarray, idx: int, kwargs: dict[Any]) -> (dict, list):
params = OrderedDict() params = OrderedDict()
for key, pbest, err in zip(kwargs['pnames'], kwargs['parameter'], kwargs['error']): for key, pbest, err in zip(kwargs['pnames'], kwargs['parameter'], kwargs['error']):
@ -191,9 +194,6 @@ class FitResult(Points):
def model_name(self): def model_name(self):
return self._model_name return self._model_name
def __len__(self):
return len(self.parameter)
def __repr__(self): def __repr__(self):
try: try:
return 'Fit: ' + self.name return 'Fit: ' + self.name
@ -265,7 +265,7 @@ class FitResult(Points):
return correlations return correlations
def savetxt(self, fname, err=True): def savetxt(self, fname: str | Path, err: bool = True):
header = self.name + '\n' header = self.name + '\n'
for pval in self.parameter.values(): for pval in self.parameter.values():
header += '{}\t{}\t{}\n'.format(convert(pval.name, old='tex', new='str'), pval.value, pval.error) header += '{}\t{}\t{}\n'.format(convert(pval.name, old='tex', new='str'), pval.value, pval.error)
@ -279,8 +279,8 @@ class FitResult(Points):
else: else:
np.savetxt(fname, np.c_[self.x, self.y], header=header) np.savetxt(fname, np.c_[self.x, self.y], header=header)
def save_parameter(self, fname: str, label: str = None, overwrite: bool = False): def save_parameter(self, fname: str | Path, label: str = None, overwrite: bool = False):
path = pathlib.Path(fname) path = Path(fname)
if not path.is_file(): if not path.is_file():
overwrite = True overwrite = True

View File

@ -22,7 +22,7 @@ class ValueEditWidget(QtWidgets.QWidget, Ui_MaskDialog):
self.setupUi(self) self.setupUi(self)
self.graph_shown = None self.connected_figure = None
self.shown_set = None self.shown_set = None
self.items = {} self.items = {}
@ -49,7 +49,7 @@ class ValueEditWidget(QtWidgets.QWidget, Ui_MaskDialog):
self.graph_combobox.addItem(k[1], userData=k[0]) self.graph_combobox.addItem(k[1], userData=k[0])
self.graph_combobox.blockSignals(False) self.graph_combobox.blockSignals(False)
idx = self.graph_combobox.findData(self.graph_shown) idx = self.graph_combobox.findData(self.connected_figure)
if idx == -1: if idx == -1:
idx = 0 idx = 0
@ -66,7 +66,7 @@ class ValueEditWidget(QtWidgets.QWidget, Ui_MaskDialog):
self.set_combobox.blockSignals(True) self.set_combobox.blockSignals(True)
self.set_combobox.clear() self.set_combobox.clear()
self.graph_shown = self.graph_combobox.currentData() self.connected_figure = self.graph_combobox.currentData()
if self.items: if self.items:
for sid, name in self.items[(self.graph_combobox.currentData(), self.graph_combobox.currentText())]: for sid, name in self.items[(self.graph_combobox.currentData(), self.graph_combobox.currentText())]:
@ -91,6 +91,16 @@ class ValueEditWidget(QtWidgets.QWidget, Ui_MaskDialog):
self.model.loadData(data, mask) self.model.loadData(data, mask)
self.spinBox.setMaximum(self.model.rowCount()) self.spinBox.setMaximum(self.model.rowCount())
def remove_graph(self):
# remove everything
self.connected_figure = None
self.items = {}
self.selection_model.clear()
while self.model.rowCount():
self.model.removeRow(0)
self.graph_combobox.clear()
self.set_combobox.clear()
def ctx(self, pos: QtCore.QPoint): def ctx(self, pos: QtCore.QPoint):
idx = self.tableView.indexAt(pos) idx = self.tableView.indexAt(pos)
if not idx.isValid(): if not idx.isValid():
@ -185,7 +195,7 @@ class ValueEditWidget(QtWidgets.QWidget, Ui_MaskDialog):
except ValueError: except ValueError:
yvals.append(complex(self.model.data(idx.sibling(idx.row(), 1))).real) yvals.append(complex(self.model.data(idx.sibling(idx.row(), 1))).real)
self.values_selected.emit(self.graph_shown, xvals, yvals) self.values_selected.emit(self.connected_figure, xvals, yvals)
@QtCore.pyqtSlot(name='on_toolButton_clicked') @QtCore.pyqtSlot(name='on_toolButton_clicked')
def goto(self): def goto(self):
@ -323,6 +333,8 @@ class ValueModel(QtCore.QAbstractTableModel):
self.mask.pop(pos) self.mask.pop(pos)
self.endRemoveRows() self.endRemoveRows()
self.total_rows -= rows
return True return True
def addRows(self, num=1): def addRows(self, num=1):

View File

@ -270,7 +270,8 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
else: else:
new_param = self.data_values[set_id] new_param = self.data_values[set_id]
for i in range(len(new_param)): min_len = min(len(new_param), len(parameter))
for i in range(min_len):
new_param[i] = parameter[i] new_param[i] = parameter[i]
self.change_data(self.comboBox.currentIndex()) self.change_data(self.comboBox.currentIndex())

View File

@ -181,8 +181,8 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
for pi, pj, corr, pcorr in c: for pi, pj, corr, pcorr in c:
cnt = self.corr_tableWidget.rowCount() cnt = self.corr_tableWidget.rowCount()
self.corr_tableWidget.insertRow(cnt) self.corr_tableWidget.insertRow(cnt)
self.corr_tableWidget.setItem(cnt, 0, QtWidgets.QTableWidgetItem(convert(pi, old='tex', new='html'))) self.corr_tableWidget.setItem(cnt, 0, QtWidgets.QTableWidgetItem(convert(pi, old='tex', new='str')))
self.corr_tableWidget.setItem(cnt, 1, QtWidgets.QTableWidgetItem(convert(pj, old='tex', new='html'))) self.corr_tableWidget.setItem(cnt, 1, QtWidgets.QTableWidgetItem(convert(pj, old='tex', new='str')))
for i, val in enumerate([corr, pcorr]): for i, val in enumerate([corr, pcorr]):
if isnan(val): if isnan(val):

View File

@ -146,7 +146,8 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
toplevel = len(self.sets) toplevel = len(self.sets)
self.sets.append(n) self.sets.append(n)
real_plot.setZValue(2*toplevel+1) if real_plot:
real_plot.setZValue(2*toplevel+1)
if imag_plot: if imag_plot:
imag_plot.setZValue(2*toplevel+1) imag_plot.setZValue(2*toplevel+1)
if err_plot: if err_plot:
@ -221,20 +222,15 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
if a not in self.active: if a not in self.active:
self.active.append(a) self.active.append(a)
if self.imag_button.isChecked(): for (bttn, plot_dic) in [
item = self.imag_plots[a] (self.real_button, self.real_plots),
if (item is not None) and (item not in self.graphic.items()): (self.imag_button, self.imag_plots),
self.graphic.addItem(item) (self.error_button, self.error_plots),
]:
if self.real_button.isChecked(): if bttn.isChecked():
item = self.real_plots[a] item = plot_dic[a]
if (item is not None) and item not in self.graphic.items(): if (item is not None) and (item not in self.graphic.items()):
self.graphic.addItem(item) self.graphic.addItem(item)
if self.error_button.isChecked():
item = self.error_plots[a]
if (item is not None) and (item not in self.graphic.items()):
self.graphic.addItem(item)
self.show_legend() self.show_legend()

View File

@ -319,11 +319,15 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
@QtCore.pyqtSlot(str) @QtCore.pyqtSlot(str)
def remove_graph(self, gid: str): def remove_graph(self, gid: str):
self.datawidget.remove_item(gid) self.datawidget.remove_item(gid)
val_figure = self.valuewidget.connected_figure
self.valuewidget.remove_graph()
w = None w = None
for w in self.area.subWindowList(): for w in self.area.subWindowList():
wdgt = w.widget() wdgt = w.widget()
if wdgt.id == gid: if wdgt.id == gid:
wdgt.disconnect() wdgt.disconnect()
wdgt.scene.disconnect()
if wdgt == self.current_graph_widget: if wdgt == self.current_graph_widget:
if self.ptsselectwidget.connected_figure == gid: if self.ptsselectwidget.connected_figure == gid:
self.ptsselectwidget.connected_figure = None self.ptsselectwidget.connected_figure = None
@ -338,20 +342,35 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
for item in self.fit_dialog.preview_lines: for item in self.fit_dialog.preview_lines:
self.current_graph_widget.remove_external(item) self.current_graph_widget.remove_external(item)
if self.valuewidget.graph_shown == gid: if val_figure == gid:
self.tabWidget.setCurrentIndex(0) self.tabWidget.setCurrentIndex(0)
self.current_graph_widget.enable_picking(False)
self.current_graph_widget = None self.current_graph_widget = None
self.management.current_graph = '' self.management.current_graph = ''
self.current_plotitem = None self.current_plotitem = None
wdgt.setParent(None)
try:
wdgt.deleteLater()
except AttributeError:
pass
break break
if w is not None: if w is not None:
self.area.removeSubWindow(w)
w.close() w.close()
try:
w.deleteLater()
except AttributeError:
pass
if self.current_graph_widget is None: if self.current_graph_widget is None:
self.area.activateNextSubWindow() if self.area.subWindowList():
self.area.activateNextSubWindow()
@QtCore.pyqtSlot(str) @QtCore.pyqtSlot(str)
def set_graph(self, key: str): def set_graph(self, key: str):
@ -500,11 +519,11 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
if onoff: # Values if onoff: # Values
self.valuewidget(self.management.graphs.tree()) self.valuewidget(self.management.graphs.tree())
self.valuewidget.connected_figure = self.management.current_graph self.valuewidget.connected_figure = self.management.current_graph
if self.valuewidget.graph_shown is not None: if self.valuewidget.connected_figure is not None:
self.management.graphs[self.valuewidget.graph_shown].add_external(self._values_plot) self.management.graphs[self.valuewidget.connected_figure].add_external(self._values_plot)
else: else:
if self.valuewidget.graph_shown is not None: if self.valuewidget.connected_figure is not None:
self.management.graphs[self.valuewidget.graph_shown].remove_external(self._values_plot) self.management.graphs[self.valuewidget.connected_figure].remove_external(self._values_plot)
def _select_integralwidget(self, onoff: bool, pick_required: bool): def _select_integralwidget(self, onoff: bool, pick_required: bool):
if self.current_graph_widget is None: if self.current_graph_widget is None:
@ -736,7 +755,7 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
def plot_selected_values(self, gid: str, x: list, y: list): def plot_selected_values(self, gid: str, x: list, y: list):
self._values_plot.setData(x=x, y=y) self._values_plot.setData(x=x, y=y)
if gid != self.valuewidget.connected_figure: if gid != self.valuewidget.connected_figure and self.valuewidget.connected_figure is not None:
self.management.graphs[self.valuewidget.connected_figure].remove_external(self._values_plot) self.management.graphs[self.valuewidget.connected_figure].remove_external(self._values_plot)
self.management.graphs[gid].add_external(self._values_plot) self.management.graphs[gid].add_external(self._values_plot)
self.valuewidget.connected_figure = gid self.valuewidget.connected_figure = gid

View File

@ -393,12 +393,12 @@ class UpperManagement(QtCore.QObject):
for set_id, set_params in model_p['parameter'].items(): for set_id, set_params in model_p['parameter'].items():
data_i = self.data[set_id] data_i = self.data[set_id]
if we == 'Deltay': if we.lower() == 'deltay':
we = data_i.y_err**2 we = data_i.y_err**2
if m_complex is None or m_complex == 1: if m_complex is None or m_complex == 1:
_y = data_i.y.real _y = data_i.y.real
elif m_complex == 2 and np.iscomplexobj(self.data[set_id].y): elif m_complex == 2 and np.iscomplexobj(data_i.y):
_y = data_i.y.imag _y = data_i.y.imag
else: else:
_y = data_i.y _y = data_i.y
@ -507,7 +507,9 @@ class UpperManagement(QtCore.QObject):
accepted.append(fit) accepted.append(fit)
data_name = f' ({data_k.name})'
if show_fit: if show_fit:
fit.name += data_name
f_id = self.add(fit, color=color, src=k) f_id = self.add(fit, color=color, src=k)
f_id_list.append(f_id) f_id_list.append(f_id)
@ -516,9 +518,11 @@ class UpperManagement(QtCore.QObject):
gid = data_k.graph gid = data_k.graph
if k in parts and show_fit: if k in parts and show_fit:
for subfunc, col in zip(parts[k], TUColorsC): color_scheme = available_cycles['colorblind']
for subfunc, col in zip(parts[k], cycle(color_scheme)):
subfunc.value = data_k.value subfunc.value = data_k.value
subfunc.group = data_k.group subfunc.group = data_k.group
subfunc.name += data_name
sub_f_id = self.add(subfunc, color=col, linestyle=LineStyle.Dashed, symbol=SymbolStyle.No) sub_f_id = self.add(subfunc, color=col, linestyle=LineStyle.Dashed, symbol=SymbolStyle.No)
f_id_list.append(sub_f_id) f_id_list.append(sub_f_id)

View File

@ -88,6 +88,58 @@ class EpsInfty:
return ret_val return ret_val
class CCwithHFW:
name = 'CC + HF wing'
type = 'Dielectric Spectroscopy'
equation = r'\Delta\epsilon CC(\omega, \tau, \alpha) / CD(\omega, \tau_{c}, \beta-\delta)'
params = [r'\Delta\epsilon', r'\tau', r'\alpha', r'\tau_{c}', '\delta']
bounds = [(0, None), (0, None), (0, 1), (0, None), (0, 1)]
iscomplex = True
@staticmethod
def func(x, deps, tau, alpha, tauc, delta, complex_mode: int = 0):
w = 2*np.pi*x
numerator = (1 + 1j*w*tauc)**(alpha-delta)
denominator = 1 + (1j*w*tau)**alpha
epsilon = deps * np.conjugate(numerator / denominator)
if complex_mode == 0:
return epsilon
elif complex_mode == 1:
return epsilon.real
elif complex_mode == 2:
return epsilon.imag
else:
raise ValueError(f'{complex_mode!r} has not value 0, 1, or 2')
class CDwithHFW:
name = 'CD + HF wing'
type = 'Dielectric Spectroscopy'
equation = r'\Delta\epsilon CD(\omega, \tau, \gamma) / CD(\omega, \tau_{c}, \gamma-\delta)'
params = [r'\Delta\epsilon', r'\tau', r'\gamma', r'\tau_{c}', '\delta']
bounds = [(0, None), (0, None), (0, 1), (0, None), (0, 1)]
iscomplex = True
@staticmethod
def func(x, deps, tau, gamma, tauc, delta, complex_mode: int = 0):
w = 2*np.pi*x
numerator = (1 + 1j*w*tauc)**(gamma-delta)
denominator = (1 + 1j*w*tau)**gamma
epsilon = deps * np.conjugate(numerator / denominator)
if complex_mode == 0:
return epsilon
elif complex_mode == 1:
return epsilon.real
elif complex_mode == 2:
return epsilon.imag
else:
raise ValueError(f'{complex_mode!r} has not value 0, 1, or 2')
class PowerLawBDS: class PowerLawBDS:
name = 'Power Law' name = 'Power Law'
type = 'Dielectric Spectroscopy' type = 'Dielectric Spectroscopy'

View File

@ -61,7 +61,7 @@ class SatRec:
equation = r'\DeltaM(1-exp(-(x/T_{1})^{\beta})) + M_{0}' equation = r'\DeltaM(1-exp(-(x/T_{1})^{\beta})) + M_{0}'
params = [r'\DeltaM', 'T_{1}', r'\beta', 'M_{0}'] params = [r'\DeltaM', 'T_{1}', r'\beta', 'M_{0}']
choices = [('Type', 'is_inv', {'Saturation': False, 'Inversion': True})] choices = [('Type', 'is_inv', {'Saturation': False, 'Inversion': True})]
bounds = [(0, None), (None, None), (0, 1), (0, None)] bounds = [(0, None), (0, None), (0, 1), (None, None)]
@staticmethod @staticmethod
def func(x, dm, t1, beta, m0, is_inv: bool = True): def func(x, dm, t1, beta, m0, is_inv: bool = True):
@ -77,7 +77,7 @@ class TwoSatRecAbsolute:
equation = r'M_{0} + \Sigma \DeltaM_{i}(1-exp(-(x/T_{1,i})^{\beta_{i}}))' equation = r'M_{0} + \Sigma \DeltaM_{i}(1-exp(-(x/T_{1,i})^{\beta_{i}}))'
params = [r'\DeltaM_{1}', 'T_{1,1}', r'\beta_{1}', r'\DeltaM_{2}', 'T_{1,2}', r'\beta_{2}', 'M_{0}'] params = [r'\DeltaM_{1}', 'T_{1,1}', r'\beta_{1}', r'\DeltaM_{2}', 'T_{1,2}', r'\beta_{2}', 'M_{0}']
choices = [('Type', 'is_inv', {'Saturation': False, 'Inversion': True})] choices = [('Type', 'is_inv', {'Saturation': False, 'Inversion': True})]
bounds = [(None, None), (0, None), (0, 1), (None, None), (0, None), (0, 1), (None, None)] bounds = [(0, None), (0, None), (0, 1), (0, None), (0, None), (0, 1), (None, None)]
@staticmethod @staticmethod
def func(x, dm1, t11, beta1, dm2, t12, beta2, m0, is_inv: bool = False): def func(x, dm1, t11, beta1, dm2, t12, beta2, m0, is_inv: bool = False):
@ -94,7 +94,7 @@ class TwoSatRecRelative:
r'(1-R)(1-exp(-(x/T_{1,2})^{\beta_{2}}))]' r'(1-R)(1-exp(-(x/T_{1,2})^{\beta_{2}}))]'
params = [r'\DeltaM', 'M_{0}', 'T_{1,1}', r'\beta_{1}', 'T_{1,2}', r'\beta_{2}', 'R'] params = [r'\DeltaM', 'M_{0}', 'T_{1,1}', r'\beta_{1}', 'T_{1,2}', r'\beta_{2}', 'R']
choices = [('Type', 'kind', {'Saturation': 'sat', 'Inversion': 'inv'})] choices = [('Type', 'kind', {'Saturation': 'sat', 'Inversion': 'inv'})]
bounds = [(None, None), (0, None), (0, 1), (None, None), (0, None), (0, 1), (None, None)] bounds = [(0, None), (None, None), (0, None), (0, 1), (0, None), (0, 1), (0, 1)]
@staticmethod @staticmethod
def func(x, dm, m0, t11, beta1, t12, beta2, ratio, kind='sat'): def func(x, dm, m0, t11, beta1, t12, beta2, ratio, kind='sat'):