2023-06-16 18:25:24 +00:00
|
|
|
import pprint
|
2023-05-31 15:20:51 +00:00
|
|
|
from itertools import cycle
|
|
|
|
|
2023-06-12 15:20:58 +00:00
|
|
|
from numpy import array, nan, isnan
|
|
|
|
from pyqtgraph import mkPen, mkBrush, LegendItem
|
2023-05-31 15:20:51 +00:00
|
|
|
|
2023-06-12 15:20:58 +00:00
|
|
|
from nmreval.dsc.hodge import tau_hodge
|
2023-05-31 15:20:51 +00:00
|
|
|
from nmreval.lib.colors import Tab10
|
2023-05-26 16:22:13 +00:00
|
|
|
from ..Qt import QtWidgets, QtCore
|
|
|
|
from .._py.tnmh_dialog import Ui_Dialog
|
|
|
|
from ..lib.pg_objects import PlotItem, RegionItem
|
|
|
|
|
|
|
|
from nmreval.data import DSC
|
2023-05-23 17:23:13 +00:00
|
|
|
|
|
|
|
|
2023-05-24 17:34:06 +00:00
|
|
|
class TgCalculator(QtWidgets.QDialog, Ui_Dialog):
|
|
|
|
def __init__(self, management, parent=None):
|
2023-05-23 17:23:13 +00:00
|
|
|
super().__init__(parent=parent)
|
|
|
|
|
2023-05-24 17:34:06 +00:00
|
|
|
self.setupUi(self)
|
|
|
|
self._management = management
|
2023-05-31 15:20:51 +00:00
|
|
|
self._colors = cycle(Tab10)
|
2023-05-24 17:34:06 +00:00
|
|
|
|
2023-05-31 15:20:51 +00:00
|
|
|
self._dsc = {}
|
2023-06-03 15:04:14 +00:00
|
|
|
self._plots = {}
|
|
|
|
self._tg_value = {}
|
2023-06-05 17:57:42 +00:00
|
|
|
self._fit = {}
|
2023-06-15 15:24:35 +00:00
|
|
|
self._hodge = {
|
|
|
|
'onset': (PlotItem(x=[], y=[], pen=None, symbol='o', symbolBrush=Tab10.TabBlue.rgb(), name='Onset'), None),
|
|
|
|
'mid': (PlotItem(x=[], y=[], pen=None, symbol='s', symbolBrush=Tab10.TabOrange.rgb(), name='Midpoint'), None),
|
|
|
|
'end': (PlotItem(x=[], y=[], pen=None, symbol='t', symbolBrush=Tab10.TabGreen.rgb(), name='End'), None),
|
|
|
|
'inflection': (PlotItem(x=[], y=[], pen=None, symbol='d', symbolBrush=Tab10.TabRed.rgb(), name='Inflection'), None),
|
2023-06-13 18:28:37 +00:00
|
|
|
# 'fictive': PlotItem(x=[], y=[], pen=None, symbol='t1', symbolBrush=Tab10.TabPurple.rgb(), name='Fictive'),
|
2023-06-12 15:20:58 +00:00
|
|
|
# 'TNMH': PlotItem(x=[], y=[], pen=None, symbol='star', symbolBrush=Tab10.TabPurple.rgb(), name='TNMH'),
|
|
|
|
}
|
2023-06-13 18:28:37 +00:00
|
|
|
self.tau_plot.getPlotItem().addLegend()
|
2023-06-15 15:24:35 +00:00
|
|
|
for plt, _ in self._hodge.values():
|
2023-06-13 18:28:37 +00:00
|
|
|
self.tau_plot.addItem(plt)
|
|
|
|
self.tau_plot.setLogMode(y=True)
|
2023-06-03 15:04:14 +00:00
|
|
|
|
2023-05-26 16:22:13 +00:00
|
|
|
self.limits = RegionItem(), RegionItem()
|
|
|
|
for lim in self.limits:
|
2023-06-13 18:28:37 +00:00
|
|
|
self.dsc_plot.addItem(lim)
|
2023-06-03 18:27:56 +00:00
|
|
|
self._limitless = True
|
2023-05-26 16:22:13 +00:00
|
|
|
|
|
|
|
self.add_sets()
|
|
|
|
|
2023-06-01 18:09:11 +00:00
|
|
|
self.listWidget.itemClicked.connect(self.show_tg_values)
|
|
|
|
|
2023-06-15 15:24:35 +00:00
|
|
|
self.new_graph_tau_combo.setEnabled(False)
|
|
|
|
self.new_graph_tau_check.stateChanged.connect(lambda state: self.new_graph_tau_combo.setEnabled(bool(state)))
|
2023-06-12 15:20:58 +00:00
|
|
|
|
2023-05-26 15:28:06 +00:00
|
|
|
def __call__(self):
|
|
|
|
self.clear()
|
2023-06-13 18:28:37 +00:00
|
|
|
self._colors = cycle(Tab10)
|
2023-05-26 15:28:06 +00:00
|
|
|
self.add_sets()
|
|
|
|
|
2023-06-13 18:28:37 +00:00
|
|
|
return self
|
|
|
|
|
2023-05-26 15:28:06 +00:00
|
|
|
def clear(self):
|
|
|
|
self.listWidget.clear()
|
2023-06-03 15:04:14 +00:00
|
|
|
for plots in self._plots.values():
|
|
|
|
for val in plots:
|
2023-06-13 18:28:37 +00:00
|
|
|
self.dsc_plot.removeItem(val)
|
2023-06-03 15:04:14 +00:00
|
|
|
self.graphicsView_2.removeItem(val)
|
2023-05-31 17:35:03 +00:00
|
|
|
|
2023-06-15 15:24:35 +00:00
|
|
|
for plt in self._hodge.values():
|
2023-06-12 15:20:58 +00:00
|
|
|
plt.setData(x=[], y=[])
|
|
|
|
|
2023-06-05 17:57:42 +00:00
|
|
|
self._dsc = {}
|
|
|
|
self._plots = {}
|
|
|
|
self._tg_value = {}
|
|
|
|
self._fit = {}
|
|
|
|
|
2023-05-26 15:28:06 +00:00
|
|
|
def add_sets(self):
|
2023-06-15 15:24:35 +00:00
|
|
|
self.new_graph_tau_combo.clear()
|
|
|
|
for graphs in self._management.graphs.list():
|
|
|
|
self.new_graph_tau_combo.addItem(graphs[1], userData=graphs[0])
|
|
|
|
|
2023-05-31 15:20:51 +00:00
|
|
|
min_x = 10_000_000
|
|
|
|
max_x = -10_000_000
|
|
|
|
for (key, name), c in zip(self._management.active_sets, self._colors):
|
|
|
|
data = self._management[key].data
|
|
|
|
if not isinstance(data, DSC):
|
2023-05-26 16:22:13 +00:00
|
|
|
continue
|
2023-05-26 15:28:06 +00:00
|
|
|
|
2023-05-31 15:20:51 +00:00
|
|
|
min_x = min(min_x, data.x.min())
|
|
|
|
max_x = max(max_x, data.x.max())
|
|
|
|
|
2023-05-26 15:28:06 +00:00
|
|
|
item = QtWidgets.QListWidgetItem(name)
|
2023-06-03 15:04:14 +00:00
|
|
|
item.setCheckState(QtCore.Qt.Checked)
|
2023-05-26 15:28:06 +00:00
|
|
|
item.setData(QtCore.Qt.UserRole, key)
|
2023-05-31 15:20:51 +00:00
|
|
|
item.setForeground(mkBrush(c.rgb()))
|
2023-05-30 15:36:44 +00:00
|
|
|
self.listWidget.addItem(item)
|
|
|
|
|
2023-06-05 17:57:42 +00:00
|
|
|
self._dsc[key] = (data, None)
|
2023-06-03 15:04:14 +00:00
|
|
|
|
|
|
|
data_plot = PlotItem(x=data.x, y=data.y, pen=mkPen(c.rgb()))
|
2023-06-13 18:28:37 +00:00
|
|
|
self.dsc_plot.addItem(data_plot)
|
2023-06-03 15:04:14 +00:00
|
|
|
|
|
|
|
glass = PlotItem()
|
|
|
|
glass.set_line(style=2, color=c)
|
2023-06-13 18:28:37 +00:00
|
|
|
self.dsc_plot.addItem(glass)
|
2023-06-03 15:04:14 +00:00
|
|
|
|
|
|
|
liquid = PlotItem()
|
|
|
|
liquid.set_line(style=2, color=c)
|
2023-06-13 18:28:37 +00:00
|
|
|
self.dsc_plot.addItem(liquid)
|
2023-06-03 15:04:14 +00:00
|
|
|
|
|
|
|
tangent = PlotItem()
|
|
|
|
tangent.set_line(style=2, color=c)
|
2023-06-13 18:28:37 +00:00
|
|
|
self.dsc_plot.addItem(tangent)
|
2023-06-03 15:04:14 +00:00
|
|
|
|
|
|
|
tg_plot = PlotItem(pen=None, symbolBrush=c.rgb(), symbol='o')
|
2023-06-13 18:28:37 +00:00
|
|
|
self.dsc_plot.addItem(tg_plot)
|
2023-06-03 15:04:14 +00:00
|
|
|
|
|
|
|
fictive_cp = PlotItem(pen=mkPen(c.rgb()))
|
|
|
|
self.graphicsView_2.addItem(fictive_cp)
|
|
|
|
|
|
|
|
tnmh_fit = PlotItem()
|
|
|
|
tnmh_fit.set_line(style=2, color=c)
|
|
|
|
self.graphicsView_2.addItem(tnmh_fit)
|
|
|
|
|
|
|
|
self._plots[key] = (data_plot, tg_plot, glass, liquid, tangent, fictive_cp, tnmh_fit)
|
2023-06-13 18:28:37 +00:00
|
|
|
self._tg_value[key] = {'onset': (nan, nan), 'mid': (nan, nan), 'end': (nan, nan), 'inflection': (nan, nan)} # , 'fictive': (nan, nan)}
|
2023-05-31 15:20:51 +00:00
|
|
|
|
2023-06-03 18:27:56 +00:00
|
|
|
if self._limitless:
|
|
|
|
dist = max_x - min_x
|
2023-06-12 15:20:58 +00:00
|
|
|
self.limits[0].setRegion((min_x, min_x+min(0.1*dist, 5)))
|
|
|
|
self.limits[1].setRegion((max_x-min(5, 0.1*dist), max_x))
|
2023-06-03 18:27:56 +00:00
|
|
|
self._limitless = False
|
2023-05-30 15:36:44 +00:00
|
|
|
|
2023-06-13 18:28:37 +00:00
|
|
|
@QtCore.pyqtSlot(name='on_calctg_button_clicked')
|
2023-05-30 15:36:44 +00:00
|
|
|
def calc_tg(self):
|
|
|
|
baselines = tuple(lim.getRegion() for lim in self.limits)
|
|
|
|
if baselines[0][0] > baselines[1][0]:
|
|
|
|
baselines = baselines[1], baselines[0]
|
|
|
|
|
|
|
|
for idx in range(self.listWidget.count()):
|
2023-05-31 15:20:51 +00:00
|
|
|
item = self.listWidget.item(idx)
|
2023-06-03 18:27:56 +00:00
|
|
|
if item.checkState() == QtCore.Qt.Unchecked:
|
|
|
|
continue
|
2023-06-03 15:04:14 +00:00
|
|
|
|
2023-06-03 18:27:56 +00:00
|
|
|
key = item.data(QtCore.Qt.UserRole)
|
2023-06-03 15:04:14 +00:00
|
|
|
plot = self._plots[key]
|
2023-06-05 17:57:42 +00:00
|
|
|
data, _ = self._dsc[key]
|
2023-06-03 15:04:14 +00:00
|
|
|
|
2023-05-31 15:20:51 +00:00
|
|
|
tg_results, glass, liquid, tangent = data.glass_transition(*baselines)
|
2023-05-30 15:36:44 +00:00
|
|
|
|
2023-06-03 15:04:14 +00:00
|
|
|
for i, line in enumerate((glass, liquid, tangent)):
|
|
|
|
plot[i+2].setData(x=line[:, 0], y=line[:, 1])
|
|
|
|
|
2023-06-05 17:57:42 +00:00
|
|
|
self._tg_value[key].update(tg_results)
|
|
|
|
|
2023-06-12 15:20:58 +00:00
|
|
|
self._update_tg_plots()
|
2023-05-30 15:36:44 +00:00
|
|
|
|
2023-06-01 18:09:11 +00:00
|
|
|
def show_tg_values(self, item):
|
2023-06-03 15:04:14 +00:00
|
|
|
values = self._tg_value.get(item.data(QtCore.Qt.UserRole))
|
2023-06-01 18:09:11 +00:00
|
|
|
|
|
|
|
if values is not None:
|
2023-06-03 18:27:56 +00:00
|
|
|
label = '\n'.join((f'{name.capitalize()}: {pos[0]:.2f} K' for name, pos in values.items()))
|
2023-06-13 18:28:37 +00:00
|
|
|
self.tg_value_label.setText(label)
|
2023-06-05 17:57:42 +00:00
|
|
|
|
|
|
|
fit = self._fit.get(item.data(QtCore.Qt.UserRole))
|
|
|
|
if fit is not None:
|
|
|
|
self.label_5.setText(fit._parameter_string())
|
2023-06-03 18:27:56 +00:00
|
|
|
|
2023-06-12 15:20:58 +00:00
|
|
|
def _update_tg_plots(self):
|
|
|
|
for idx in range(self.listWidget.count()):
|
|
|
|
item = self.listWidget.item(idx)
|
|
|
|
|
|
|
|
key = item.data(QtCore.Qt.UserRole)
|
|
|
|
plot = self._plots[key]
|
|
|
|
data, _ = self._dsc[key]
|
|
|
|
|
|
|
|
plot[1].setData(array(list(self._tg_value[key].values())))
|
|
|
|
|
|
|
|
self.hodge()
|
|
|
|
|
2023-06-03 18:27:56 +00:00
|
|
|
@QtCore.pyqtSlot(QtWidgets.QListWidgetItem, name='on_listWidget_itemChanged')
|
|
|
|
def change_visibility(self, item: QtWidgets.QListWidgetItem):
|
|
|
|
is_checked = bool(item.checkState())
|
|
|
|
plot = self._plots[item.data(QtCore.Qt.UserRole)]
|
|
|
|
for val in plot:
|
|
|
|
val.setVisible(is_checked)
|
2023-06-01 18:09:11 +00:00
|
|
|
|
|
|
|
@QtCore.pyqtSlot(name='on_pushButton_2_clicked')
|
|
|
|
def get_fictive(self):
|
|
|
|
baselines = tuple(lim.getRegion() for lim in self.limits)
|
|
|
|
if baselines[0][0] > baselines[1][0]:
|
|
|
|
baselines = baselines[1], baselines[0]
|
|
|
|
|
|
|
|
for idx in range(self.listWidget.count()):
|
|
|
|
item = self.listWidget.item(idx)
|
2023-06-03 18:27:56 +00:00
|
|
|
if item.checkState() == QtCore.Qt.Unchecked:
|
|
|
|
continue
|
2023-06-03 15:04:14 +00:00
|
|
|
|
2023-06-03 18:27:56 +00:00
|
|
|
key = item.data(QtCore.Qt.UserRole)
|
2023-06-03 15:04:14 +00:00
|
|
|
plot = self._plots[key]
|
2023-06-05 17:57:42 +00:00
|
|
|
data, _ = self._dsc[key]
|
2023-06-03 18:27:56 +00:00
|
|
|
|
2023-06-01 18:09:11 +00:00
|
|
|
cp, tg = data.get_fictive_cp(*baselines)
|
|
|
|
|
2023-06-03 15:04:14 +00:00
|
|
|
plot[5].setData(cp.x, cp.y)
|
2023-06-05 17:57:42 +00:00
|
|
|
self._dsc[key] = (data, cp)
|
2023-06-01 18:09:11 +00:00
|
|
|
|
2023-06-03 15:04:14 +00:00
|
|
|
self._tg_value[key]['fictive'] = (tg, 0)
|
|
|
|
|
2023-06-12 15:20:58 +00:00
|
|
|
self._update_tg_plots()
|
2023-06-01 18:09:11 +00:00
|
|
|
|
2023-06-05 17:57:42 +00:00
|
|
|
@QtCore.pyqtSlot(name='on_pushButton_3_clicked')
|
|
|
|
def make_tnmh(self):
|
|
|
|
baselines = tuple(lim.getRegion() for lim in self.limits)
|
|
|
|
if baselines[0][0] > baselines[1][0]:
|
|
|
|
baselines = baselines[1], baselines[0]
|
|
|
|
|
|
|
|
for idx in range(self.listWidget.count()):
|
|
|
|
item = self.listWidget.item(idx)
|
|
|
|
if item.checkState() == QtCore.Qt.Unchecked:
|
|
|
|
continue
|
|
|
|
|
|
|
|
key = item.data(QtCore.Qt.UserRole)
|
|
|
|
plot = self._plots[key]
|
|
|
|
_, data = self._dsc[key]
|
|
|
|
|
|
|
|
if data is None:
|
|
|
|
continue
|
|
|
|
|
|
|
|
res = data.calculate_tnmh([60, 0.5, 1, 2e5], *baselines, return_fictive=False)
|
|
|
|
self._fit[key] = res
|
2023-06-03 15:04:14 +00:00
|
|
|
plot[-1].setData(res.x, res.y)
|
2023-06-01 18:09:11 +00:00
|
|
|
|
2023-06-12 15:20:58 +00:00
|
|
|
def hodge(self):
|
2023-06-15 15:24:35 +00:00
|
|
|
for tg_type, (plot, data) in self._hodge.items():
|
|
|
|
|
2023-06-12 15:20:58 +00:00
|
|
|
m = []
|
|
|
|
for idx in range(self.listWidget.count()):
|
|
|
|
item = self.listWidget.item(idx)
|
|
|
|
|
|
|
|
key = item.data(QtCore.Qt.UserRole)
|
|
|
|
data, _ = self._dsc[key]
|
|
|
|
|
|
|
|
tg_value = self._tg_value[key][tg_type][0]
|
|
|
|
if isnan(tg_value):
|
|
|
|
continue
|
|
|
|
|
|
|
|
m.append([tg_value, data.value])
|
|
|
|
|
|
|
|
if len(m) > 1:
|
2023-06-15 15:24:35 +00:00
|
|
|
data = tau_hodge(*array(m).T)
|
|
|
|
plot.setData(data.x, data.y)
|
2023-06-12 15:20:58 +00:00
|
|
|
|
2023-05-30 15:36:44 +00:00
|
|
|
def close(self) -> bool:
|
|
|
|
self.clear()
|
|
|
|
return super().close()
|
2023-06-15 15:24:35 +00:00
|
|
|
|
|
|
|
def accept(self) -> None:
|
|
|
|
if self.new_graph_tau_check.isChecked():
|
|
|
|
graph_id = ''
|
|
|
|
else:
|
|
|
|
graph_id = self.new_graph_tau_combo.currentData()
|
|
|
|
|
|
|
|
print(graph_id)
|
2023-06-16 18:25:24 +00:00
|
|
|
|
|
|
|
ret_dic = {}
|
|
|
|
|
|
|
|
for key, tg in self._tg_value.items():
|
|
|
|
plts = self._plots[key]
|
|
|
|
ret_dic[key] = (tg, plts[1].getData(), plts[2].getData(), plts[3].getData(), plts[4].getData())
|
|
|
|
|
|
|
|
pprint.pprint(ret_dic)
|
|
|
|
pprint.pprint(self._hodge)
|