Merge branch 'more_bugs'
This commit is contained in:
commit
8e2ebfc765
@ -44,6 +44,7 @@ AppDir:
|
|||||||
- python3.9-minimal
|
- python3.9-minimal
|
||||||
- python3-numpy
|
- python3-numpy
|
||||||
- python3-scipy
|
- python3-scipy
|
||||||
|
- gnuplot-nox
|
||||||
- python3-bsddb3
|
- python3-bsddb3
|
||||||
- python3-h5py
|
- python3-h5py
|
||||||
- python3-pyqt5
|
- python3-pyqt5
|
||||||
@ -59,7 +60,6 @@ AppDir:
|
|||||||
- qtbase5-dev-tools
|
- qtbase5-dev-tools
|
||||||
- qtchooser
|
- qtchooser
|
||||||
- pyqt5-dev-tools
|
- pyqt5-dev-tools
|
||||||
- qtchooser
|
|
||||||
- libavahi-client3
|
- libavahi-client3
|
||||||
- libavahi-common-data
|
- libavahi-common-data
|
||||||
- libavahi-common3
|
- libavahi-common3
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from nmreval.lib.logger import logger
|
||||||
from nmreval.lib.colors import available_cycles
|
from nmreval.lib.colors import available_cycles
|
||||||
|
|
||||||
from .properties import PropWidget
|
from .properties import PropWidget
|
||||||
@ -19,6 +20,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
saveFits = QtCore.pyqtSignal(list)
|
saveFits = QtCore.pyqtSignal(list)
|
||||||
extendFits = QtCore.pyqtSignal(list)
|
extendFits = QtCore.pyqtSignal(list)
|
||||||
|
|
||||||
|
# noinspection PyUnresolvedReferences
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent=parent)
|
super().__init__(parent=parent)
|
||||||
|
|
||||||
@ -229,7 +231,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
|
|
||||||
def sort(self, graph_item: QtWidgets.QTreeWidgetItem, mode: str = 'value'):
|
def sort(self, graph_item: QtWidgets.QTreeWidgetItem, mode: str = 'value'):
|
||||||
graph_id = graph_item.data(0, QtCore.Qt.UserRole)
|
graph_id = graph_item.data(0, QtCore.Qt.UserRole)
|
||||||
sets = self.management.get_attributes(graph_id, mode)
|
sets = self.management.get_attributes(graph_id, mode)
|
||||||
sets = [el[0] for el in sorted(sets.items(), key=lambda x: x[1])]
|
sets = [el[0] for el in sorted(sets.items(), key=lambda x: x[1])]
|
||||||
|
|
||||||
self.management.move_sets(sets, graph_id, graph_id, pos=-1)
|
self.management.move_sets(sets, graph_id, graph_id, pos=-1)
|
||||||
@ -247,7 +249,6 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
|
|
||||||
self.blockSignals(False)
|
self.blockSignals(False)
|
||||||
|
|
||||||
|
|
||||||
def update_indexes(self):
|
def update_indexes(self):
|
||||||
graph_cnt = -1
|
graph_cnt = -1
|
||||||
set_cnt = 0
|
set_cnt = 0
|
||||||
@ -342,7 +343,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
self.setDragEnabled(idx.column() == 0)
|
self.setDragEnabled(idx.column() == 0)
|
||||||
super().mousePressEvent(evt)
|
super().mousePressEvent(evt)
|
||||||
|
|
||||||
def remove_item(self, ids: list):
|
def remove_item(self, ids: list[str]):
|
||||||
iterator = QtWidgets.QTreeWidgetItemIterator(self)
|
iterator = QtWidgets.QTreeWidgetItemIterator(self)
|
||||||
while iterator.value():
|
while iterator.value():
|
||||||
item = iterator.value()
|
item = iterator.value()
|
||||||
@ -356,7 +357,10 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
idx = self.invisibleRootItem().indexOfChild(item)
|
idx = self.invisibleRootItem().indexOfChild(item)
|
||||||
self.invisibleRootItem().takeChild(idx)
|
self.invisibleRootItem().takeChild(idx)
|
||||||
self._checked_graphs.remove(_id)
|
try:
|
||||||
|
self._checked_graphs.remove(_id)
|
||||||
|
except KeyError:
|
||||||
|
logger.warn(f'Graph {_id} already removed, skip')
|
||||||
|
|
||||||
iterator += 1
|
iterator += 1
|
||||||
|
|
||||||
@ -523,6 +527,7 @@ class DataWidget(QtWidgets.QWidget, Ui_DataWidget):
|
|||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
self.tree = DataTree(self)
|
self.tree = DataTree(self)
|
||||||
self.verticalLayout.addWidget(self.tree)
|
self.verticalLayout.addWidget(self.tree)
|
||||||
|
# noinspection PyUnresolvedReferences
|
||||||
self.tree.selectionModel().selectionChanged.connect(lambda x, y: self.show_property(x))
|
self.tree.selectionModel().selectionChanged.connect(lambda x, y: self.show_property(x))
|
||||||
|
|
||||||
self.tree.keyChanged.connect(lambda x, y: self.keyChanged.emit(x, y))
|
self.tree.keyChanged.connect(lambda x, y: self.keyChanged.emit(x, y))
|
||||||
@ -550,7 +555,7 @@ class DataWidget(QtWidgets.QWidget, Ui_DataWidget):
|
|||||||
self.tree.add_item(loi, gid)
|
self.tree.add_item(loi, gid)
|
||||||
self.tree.blockSignals(False)
|
self.tree.blockSignals(False)
|
||||||
|
|
||||||
def remove_item(self, key):
|
def remove_item(self, key: list[str]):
|
||||||
self.tree.remove_item(key)
|
self.tree.remove_item(key)
|
||||||
|
|
||||||
def show_property(self, _: QtCore.QModelIndex = None):
|
def show_property(self, _: QtCore.QModelIndex = None):
|
||||||
|
@ -148,6 +148,13 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
|
|||||||
Add name and id of dataset to list.
|
Add name and id of dataset to list.
|
||||||
"""
|
"""
|
||||||
self.data_table.load(ids)
|
self.data_table.load(ids)
|
||||||
|
|
||||||
|
# deselect all fit sets
|
||||||
|
for i in range(self.data_table.rowCount()):
|
||||||
|
data_id = self.data_table.item(i, 0).data(QtCore.Qt.UserRole+1)
|
||||||
|
if self._management[data_id].mode == 'fit':
|
||||||
|
self.data_table.item(i, 0).setCheckState(QtCore.Qt.Unchecked)
|
||||||
|
|
||||||
if self.models:
|
if self.models:
|
||||||
for m in self.models.keys():
|
for m in self.models.keys():
|
||||||
self.data_table.add_model(m)
|
self.data_table.add_model(m)
|
||||||
|
@ -54,6 +54,8 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
|||||||
self._external_items = []
|
self._external_items = []
|
||||||
self.closable = True
|
self.closable = True
|
||||||
|
|
||||||
|
self._block = False
|
||||||
|
|
||||||
self.log = [False, False]
|
self.log = [False, False]
|
||||||
|
|
||||||
self.scene = self.plotItem.scene()
|
self.scene = self.plotItem.scene()
|
||||||
@ -150,6 +152,16 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
|||||||
|
|
||||||
return tuple(r)
|
return tuple(r)
|
||||||
|
|
||||||
|
def block(self, state: bool):
|
||||||
|
self._block = state
|
||||||
|
|
||||||
|
if not self._block:
|
||||||
|
self.graphic.enableAutoRange()
|
||||||
|
self._update_zorder()
|
||||||
|
self.show_legend()
|
||||||
|
else:
|
||||||
|
self.graphic.disableAutoRange()
|
||||||
|
|
||||||
def add(self, name: str | list, plots: list):
|
def add(self, name: str | list, plots: list):
|
||||||
if isinstance(name, str):
|
if isinstance(name, str):
|
||||||
name = [name]
|
name = [name]
|
||||||
@ -201,8 +213,9 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
|||||||
|
|
||||||
self.listWidget.blockSignals(False)
|
self.listWidget.blockSignals(False)
|
||||||
|
|
||||||
self._update_zorder()
|
if not self._block:
|
||||||
self.show_legend()
|
self._update_zorder()
|
||||||
|
self.show_legend()
|
||||||
|
|
||||||
def move_sets(self, sets: list, position: int):
|
def move_sets(self, sets: list, position: int):
|
||||||
move_plots = []
|
move_plots = []
|
||||||
@ -484,6 +497,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
|||||||
self.ymax_lineedit.setText('%.5g' % r[1][1])
|
self.ymax_lineedit.setText('%.5g' % r[1][1])
|
||||||
|
|
||||||
def _update_zorder(self):
|
def _update_zorder(self):
|
||||||
|
print('update yorder')
|
||||||
for i, sid in enumerate(self.sets):
|
for i, sid in enumerate(self.sets):
|
||||||
plt = self.real_plots[sid]
|
plt = self.real_plots[sid]
|
||||||
if plt.zValue() != 2*i+1:
|
if plt.zValue() != 2*i+1:
|
||||||
@ -501,6 +515,10 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
|||||||
self.checkBox.setVisible(visible)
|
self.checkBox.setVisible(visible)
|
||||||
|
|
||||||
def update_legend(self, sid, name):
|
def update_legend(self, sid, name):
|
||||||
|
if self._block:
|
||||||
|
return
|
||||||
|
|
||||||
|
print('update legend')
|
||||||
self.listWidget.blockSignals(True)
|
self.listWidget.blockSignals(True)
|
||||||
|
|
||||||
for i in range(self.listWidget.count()):
|
for i in range(self.listWidget.count()):
|
||||||
@ -512,6 +530,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
|||||||
self.show_legend()
|
self.show_legend()
|
||||||
|
|
||||||
def show_legend(self):
|
def show_legend(self):
|
||||||
|
print('show legend')
|
||||||
if not self.legend.isVisible():
|
if not self.legend.isVisible():
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import pathlib
|
import pathlib
|
||||||
|
|
||||||
from nmreval.io.fcbatchreader import FCReader
|
from nmreval.io.fcbatchreader import FCReader
|
||||||
@ -31,6 +33,10 @@ class QFCReader(QtWidgets.QDialog, Ui_FCEval_dialog):
|
|||||||
|
|
||||||
return super().eventFilter(src, evt)
|
return super().eventFilter(src, evt)
|
||||||
|
|
||||||
|
def add_graphs(self, graphs: list[tuple[str, str]]):
|
||||||
|
for gid, graph_name in graphs:
|
||||||
|
self.graph_comboBox.addItem(graph_name, gid)
|
||||||
|
|
||||||
@QtCore.pyqtSlot(int, name='on_region_checkBox_stateChanged')
|
@QtCore.pyqtSlot(int, name='on_region_checkBox_stateChanged')
|
||||||
def use_region(self, state: int):
|
def use_region(self, state: int):
|
||||||
self.start_lineedit.setEnabled(state == QtCore.Qt.Checked)
|
self.start_lineedit.setEnabled(state == QtCore.Qt.Checked)
|
||||||
@ -43,17 +49,17 @@ class QFCReader(QtWidgets.QDialog, Ui_FCEval_dialog):
|
|||||||
infiles, _ = QtWidgets.QFileDialog.getOpenFileNames(caption='Select HDF files',
|
infiles, _ = QtWidgets.QFileDialog.getOpenFileNames(caption='Select HDF files',
|
||||||
directory=str(self.path),
|
directory=str(self.path),
|
||||||
filter='HDF files (*.h5)')
|
filter='HDF files (*.h5)')
|
||||||
if infiles:
|
|
||||||
self.listWidget.addItems(infiles)
|
|
||||||
self.label.setText(str(pathlib.Path(infiles[-1]).parent))
|
|
||||||
else:
|
else:
|
||||||
infiles = QtWidgets.QFileDialog.getExistingDirectory(caption='Select input directory',
|
infiles = QtWidgets.QFileDialog.getExistingDirectory(caption='Select input directory',
|
||||||
directory=str(self.path),
|
directory=str(self.path),
|
||||||
options=QtWidgets.QFileDialog.ShowDirsOnly)
|
options=QtWidgets.QFileDialog.ShowDirsOnly)
|
||||||
|
infiles = [infiles] if infiles else infiles
|
||||||
|
|
||||||
if infiles:
|
if infiles:
|
||||||
self.listWidget.addItem(infiles)
|
self.listWidget.addItems(infiles)
|
||||||
self.label.setText(str(pathlib.Path(infiles).parent))
|
self.path = pathlib.Path(infiles[-1]).parent
|
||||||
|
self.label.setText(str(self.path))
|
||||||
|
|
||||||
@QtCore.pyqtSlot(name='on_savebutton_clicked')
|
@QtCore.pyqtSlot(name='on_savebutton_clicked')
|
||||||
def save_path(self):
|
def save_path(self):
|
||||||
@ -72,7 +78,7 @@ class QFCReader(QtWidgets.QDialog, Ui_FCEval_dialog):
|
|||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
def read(self, items):
|
def read(self, items):
|
||||||
region = (None, None)
|
region = None
|
||||||
if self.region_box.isChecked():
|
if self.region_box.isChecked():
|
||||||
start = None
|
start = None
|
||||||
if self.start_lineedit.text():
|
if self.start_lineedit.text():
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
from numpy import argsort
|
from numpy import argsort
|
||||||
@ -216,33 +218,55 @@ class DeleteGraphCommand(QtWidgets.QUndoCommand):
|
|||||||
|
|
||||||
|
|
||||||
class DeleteCommand(QtWidgets.QUndoCommand):
|
class DeleteCommand(QtWidgets.QUndoCommand):
|
||||||
def __init__(self, container, key, signal1, signal2):
|
def __init__(self, container: dict, keys: list[str], graphs: dict, graphid: str,
|
||||||
|
signal1: QtCore.pyqtSignal, signal2: QtCore.pyqtSignal):
|
||||||
super().__init__('Delete data')
|
super().__init__('Delete data')
|
||||||
|
|
||||||
self.__container = container
|
self.__container = container
|
||||||
self.__value = self.__container[key]
|
self.__graph_container = graphs
|
||||||
self.__key = key
|
self.__graph_key = graphid
|
||||||
|
self.__value = {}
|
||||||
|
for k in keys:
|
||||||
|
self.__value[k] = self.__container[k]
|
||||||
|
self.__keys = tuple(keys)
|
||||||
self.__signal_add = signal1
|
self.__signal_add = signal1
|
||||||
self.__signal_remove = signal2
|
self.__signal_remove = signal2
|
||||||
|
|
||||||
def redo(self):
|
def redo(self):
|
||||||
self.__signal_remove.emit(self.__key)
|
# stop graph from rescaling and updating legend
|
||||||
if isinstance(self.__value, FitContainer):
|
self.__graph_container[self.__graph_key].block(True)
|
||||||
try:
|
|
||||||
self.__container[self.__value.fitted_key]._fits.remove(self.__key)
|
self.__signal_remove.emit(list(self.__keys[::-1]))
|
||||||
except KeyError:
|
for sid in self.__keys[::-1]:
|
||||||
pass
|
val = self.__value[sid]
|
||||||
del self.__container[self.__key]
|
|
||||||
|
if isinstance(val, FitContainer):
|
||||||
|
try:
|
||||||
|
self.__container[sid].fitted_key._fits.remove(sid)
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
del self.__container[sid]
|
||||||
|
|
||||||
|
self.__graph_container[self.__graph_key].block(False)
|
||||||
|
|
||||||
def undo(self):
|
def undo(self):
|
||||||
self.__container[self.__key] = self.__value
|
# stop graph from rescaling and updating legend
|
||||||
if isinstance(self.__value, FitContainer):
|
self.__graph_container[self.__graph_key].block(True)
|
||||||
try:
|
|
||||||
self.__container[self.__value.fitted_key]._fits.append(self.__key)
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
self.__signal_add.emit([self.__key], self.__value.graph)
|
for sid in self.__keys:
|
||||||
|
val = self.__value[sid]
|
||||||
|
self.__container[sid] = val
|
||||||
|
|
||||||
|
if isinstance(val, FitContainer):
|
||||||
|
try:
|
||||||
|
self.__container[val.fitted_key]._fits.append(sid)
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
self.__signal_add.emit(list(self.__keys), self.__graph_key)
|
||||||
|
|
||||||
|
self.__graph_container[self.__graph_key].block(False)
|
||||||
|
|
||||||
|
|
||||||
class EvalCommand(QtWidgets.QUndoCommand):
|
class EvalCommand(QtWidgets.QUndoCommand):
|
||||||
|
@ -254,6 +254,7 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
@QtCore.pyqtSlot(name='on_actionOpen_FC_triggered')
|
@QtCore.pyqtSlot(name='on_actionOpen_FC_triggered')
|
||||||
def read_fc(self):
|
def read_fc(self):
|
||||||
reader = QFCReader(path=self.path, parent=self)
|
reader = QFCReader(path=self.path, parent=self)
|
||||||
|
reader.add_graphs(self.management.graphs.list())
|
||||||
reader.data_read.connect(self.management.add_new_data)
|
reader.data_read.connect(self.management.add_new_data)
|
||||||
reader.exec()
|
reader.exec()
|
||||||
|
|
||||||
@ -347,7 +348,7 @@ 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
|
val_figure = self.valuewidget.connected_figure
|
||||||
self.valuewidget.remove_graph()
|
self.valuewidget.remove_graph()
|
||||||
|
|
||||||
@ -732,10 +733,11 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
|
|
||||||
self.datawidget.set_name(sid, self.management[sid].name)
|
self.datawidget.set_name(sid, self.management[sid].name)
|
||||||
|
|
||||||
@QtCore.pyqtSlot(str)
|
@QtCore.pyqtSlot(list)
|
||||||
def delete_data(self, sid):
|
def delete_data(self, sid: list[str]):
|
||||||
if self.valuewidget.shown_set == sid:
|
for key in sid:
|
||||||
self.tabWidget.setCurrentIndex(0)
|
if self.valuewidget.shown_set == key:
|
||||||
|
self.tabWidget.setCurrentIndex(0)
|
||||||
|
|
||||||
self.datawidget.remove_item(sid)
|
self.datawidget.remove_item(sid)
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ class UpperManagement(QtCore.QObject):
|
|||||||
restoreGraph = QtCore.pyqtSignal(str)
|
restoreGraph = QtCore.pyqtSignal(str)
|
||||||
deleteGraph = QtCore.pyqtSignal(str)
|
deleteGraph = QtCore.pyqtSignal(str)
|
||||||
newData = QtCore.pyqtSignal(list, str)
|
newData = QtCore.pyqtSignal(list, str)
|
||||||
deleteData = QtCore.pyqtSignal(str)
|
deleteData = QtCore.pyqtSignal(list)
|
||||||
dataChanged = QtCore.pyqtSignal(str)
|
dataChanged = QtCore.pyqtSignal(str)
|
||||||
fitFinished = QtCore.pyqtSignal(list)
|
fitFinished = QtCore.pyqtSignal(list)
|
||||||
stopFit = QtCore.pyqtSignal()
|
stopFit = QtCore.pyqtSignal()
|
||||||
@ -234,9 +234,17 @@ class UpperManagement(QtCore.QObject):
|
|||||||
for k in plotkeys:
|
for k in plotkeys:
|
||||||
self.data[k].graph = gid
|
self.data[k].graph = gid
|
||||||
|
|
||||||
@QtCore.pyqtSlot(str)
|
@QtCore.pyqtSlot(list)
|
||||||
def plot_from_graph(self, key: str):
|
def plot_from_graph(self, key: list[str]):
|
||||||
self.graphs[self.data[key].graph].remove(key)
|
sort_graph = {}
|
||||||
|
for sid in key:
|
||||||
|
v = self.data[sid].graph
|
||||||
|
if v not in sort_graph:
|
||||||
|
sort_graph[v] = []
|
||||||
|
sort_graph[v].append(sid)
|
||||||
|
|
||||||
|
for gid, sets in sort_graph.items():
|
||||||
|
self.graphs[gid].remove(sets)
|
||||||
|
|
||||||
@QtCore.pyqtSlot(list, str, str)
|
@QtCore.pyqtSlot(list, str, str)
|
||||||
def move_sets(self, sets: list, dest: str, src: (str|list), pos: int = -1):
|
def move_sets(self, sets: list, dest: str, src: (str|list), pos: int = -1):
|
||||||
@ -287,15 +295,26 @@ class UpperManagement(QtCore.QObject):
|
|||||||
|
|
||||||
self.undostack.beginMacro('Delete')
|
self.undostack.beginMacro('Delete')
|
||||||
|
|
||||||
|
rm_set_by_graph = {}
|
||||||
|
|
||||||
for k in rm_sets[::-1]:
|
for k in rm_sets[::-1]:
|
||||||
if k in self.data:
|
if k in self.data:
|
||||||
cmd = DeleteCommand(self.data, k, self.newData, self.deleteData)
|
parent_graph = self.data[k].graph
|
||||||
self.undostack.push(cmd)
|
if parent_graph not in rm_set_by_graph:
|
||||||
|
rm_set_by_graph[parent_graph] = []
|
||||||
|
|
||||||
|
rm_set_by_graph[parent_graph].append(k)
|
||||||
|
|
||||||
elif k in self.graphs:
|
elif k in self.graphs:
|
||||||
rm_graphs.append(k)
|
rm_graphs.append(k)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logger.warning(f'delete_sets: {k} is not in data or graph found')
|
logger.warning(f'delete_sets: {k} is not in data or graph found')
|
||||||
|
|
||||||
|
for gid, sid_list in rm_set_by_graph.items():
|
||||||
|
cmd = DeleteCommand(self.data, sid_list, self.graphs, gid, self.newData, self.deleteData)
|
||||||
|
self.undostack.push(cmd)
|
||||||
|
|
||||||
for k in rm_graphs:
|
for k in rm_graphs:
|
||||||
cmd = DeleteGraphCommand(self.graphs, k, self.restoreGraph, self.deleteGraph)
|
cmd = DeleteGraphCommand(self.graphs, k, self.restoreGraph, self.deleteGraph)
|
||||||
self.undostack.push(cmd)
|
self.undostack.push(cmd)
|
||||||
@ -605,6 +624,7 @@ class UpperManagement(QtCore.QObject):
|
|||||||
if not graph_id:
|
if not graph_id:
|
||||||
graph_id = ''
|
graph_id = ''
|
||||||
|
|
||||||
|
# TODO add flag that new window will not get focus, because it messes up the data_table in fitwindow
|
||||||
self.newData.emit(p_id_list, graph_id)
|
self.newData.emit(p_id_list, graph_id)
|
||||||
|
|
||||||
def save_fit_parameter(self, fname: str | pathlib.Path, fit_sets: list[str] = None):
|
def save_fit_parameter(self, fname: str | pathlib.Path, fit_sets: list[str] = None):
|
||||||
|
@ -2,6 +2,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import pathlib
|
import pathlib
|
||||||
|
|
||||||
|
from matplotlib import pyplot as plt
|
||||||
# import matplotlib.pyplot as plt
|
# import matplotlib.pyplot as plt
|
||||||
from scipy.optimize import curve_fit
|
from scipy.optimize import curve_fit
|
||||||
import numpy as np
|
import numpy as np
|
||||||
@ -25,8 +26,6 @@ class FCReader:
|
|||||||
self.t_params = {}
|
self.t_params = {}
|
||||||
self.f_params = {}
|
self.f_params = {}
|
||||||
|
|
||||||
self._scipt_type = 'old'
|
|
||||||
|
|
||||||
def __call__(self, fname: (list | str | pathlib.Path)):
|
def __call__(self, fname: (list | str | pathlib.Path)):
|
||||||
if isinstance(fname, (str, pathlib.Path)):
|
if isinstance(fname, (str, pathlib.Path)):
|
||||||
self.fnames = [fname]
|
self.fnames = [fname]
|
||||||
@ -77,9 +76,16 @@ class FCReader:
|
|||||||
def _read_from_hdf(self, filename: (str | pathlib.Path)) -> dict:
|
def _read_from_hdf(self, filename: (str | pathlib.Path)) -> dict:
|
||||||
_temp = {}
|
_temp = {}
|
||||||
reader = HdfReader(filename)
|
reader = HdfReader(filename)
|
||||||
mag_directory = 'mag' if self._scipt_type == 'old' else 'Magnetization'
|
|
||||||
for mag in reader.get_selected(mag_directory, dtype='points'):
|
mag_directory = None
|
||||||
_temp[mag.value] = mag
|
for m in ['Magnetization', 'mag']:
|
||||||
|
if m in reader:
|
||||||
|
mag_directory = m
|
||||||
|
break
|
||||||
|
|
||||||
|
if m is not None:
|
||||||
|
for mag in reader.get_selected(mag_directory, dtype='points'):
|
||||||
|
_temp[mag.value] = mag
|
||||||
|
|
||||||
return _temp
|
return _temp
|
||||||
|
|
||||||
@ -97,21 +103,15 @@ class FCReader:
|
|||||||
|
|
||||||
return _temp
|
return _temp
|
||||||
|
|
||||||
@staticmethod
|
def _read_signals(self, filename, region: tuple = None) -> dict:
|
||||||
def _read_signals(filename, region: tuple = None) -> dict:
|
|
||||||
reader = HdfReader(filename)
|
reader = HdfReader(filename)
|
||||||
start = 0
|
|
||||||
stop = 30e-5
|
|
||||||
|
|
||||||
# This is one set with attributes to find default start:stop values
|
# This is one set with attributes to find default start:stop values (with some
|
||||||
try:
|
p = reader.parameters('/ABS_ACC_FID')
|
||||||
p = reader.parameters('/ABS_ACC_FID')
|
start = p.get('stainte') or p.get('start') or 0
|
||||||
start = p['start']
|
stop = p.get('stointe') or p.get('stop') or 30e-5
|
||||||
stop = p['stop']
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if region is None:
|
if region == (None, None) or region is None:
|
||||||
region = (start, stop)
|
region = (start, stop)
|
||||||
|
|
||||||
if region[0] is None:
|
if region[0] is None:
|
||||||
@ -119,15 +119,45 @@ class FCReader:
|
|||||||
if region[1] is None:
|
if region[1] is None:
|
||||||
region = (region[0], stop)
|
region = (region[0], stop)
|
||||||
|
|
||||||
sig = reader.get_selected('/data/B=*/ACC_ABS_FID*', dtype='signal')
|
|
||||||
_temp = {}
|
_temp = {}
|
||||||
for s in sig:
|
bevo_groups = reader['data'].children
|
||||||
pts = s.points([region])
|
no_bevo = False
|
||||||
b = s.group
|
for grp in bevo_groups.values():
|
||||||
if b not in _temp:
|
for k in grp.data():
|
||||||
_temp[b] = []
|
try:
|
||||||
|
# look for parameter, should be missing in older scripts
|
||||||
|
bevo = k.parameter['bevo']
|
||||||
|
except KeyError:
|
||||||
|
no_bevo = True
|
||||||
|
break
|
||||||
|
|
||||||
_temp[b].append([s.value, *[pp[1] for pp in pts]])
|
if str(k.parent) != 'ACC_ABS_FID_sig (group)':
|
||||||
|
continue
|
||||||
|
|
||||||
|
tevo = k.parameter['tevo']
|
||||||
|
|
||||||
|
s = reader.make_signal(k, flag='fid', value='tevo', group='bevo')
|
||||||
|
pts = s.points([region])
|
||||||
|
|
||||||
|
if bevo not in _temp:
|
||||||
|
_temp[bevo] = []
|
||||||
|
|
||||||
|
_temp[bevo].append((tevo, *[pp[1] for pp in pts]))
|
||||||
|
|
||||||
|
if no_bevo:
|
||||||
|
break
|
||||||
|
|
||||||
|
if no_bevo:
|
||||||
|
# hopefully only for old scripts
|
||||||
|
sig = reader.get_selected('/data/B=*/ACC_ABS_FID*', dtype='signal')
|
||||||
|
_temp = {}
|
||||||
|
for s in sig:
|
||||||
|
pts = s.points([region])
|
||||||
|
b = s.group
|
||||||
|
if b not in _temp:
|
||||||
|
_temp[b] = []
|
||||||
|
|
||||||
|
_temp[b].append([s.value, *[pp[1] for pp in pts]])
|
||||||
|
|
||||||
for b, m in sorted(_temp.items()):
|
for b, m in sorted(_temp.items()):
|
||||||
m = np.array(m)
|
m = np.array(m)
|
||||||
@ -148,9 +178,9 @@ class FCReader:
|
|||||||
fit_path = fname_no_ext.joinpath('fit')
|
fit_path = fname_no_ext.joinpath('fit')
|
||||||
fit_path.mkdir(parents=True, exist_ok=True)
|
fit_path.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
# if save_fig:
|
if save_fig:
|
||||||
# image_path = fname_no_ext.joinpath('png')
|
image_path = fname_no_ext.joinpath('png')
|
||||||
# image_path.mkdir(parents=True, exist_ok=True)
|
image_path.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
header = 'm0\tt1\tbeta\toff\n'
|
header = 'm0\tt1\tbeta\toff\n'
|
||||||
|
|
||||||
@ -189,16 +219,16 @@ class FCReader:
|
|||||||
np.savetxt(fit_path.joinpath(save_name), np.c_[xplot, yplot],
|
np.savetxt(fit_path.joinpath(save_name), np.c_[xplot, yplot],
|
||||||
header=header+'\t'.join([f'{p}+/-{err}' for p, err in zip(p0, perr)]))
|
header=header+'\t'.join([f'{p}+/-{err}' for p, err in zip(p0, perr)]))
|
||||||
|
|
||||||
# if save_fig:
|
if save_fig:
|
||||||
# fig, ax = plt.subplots()
|
fig, ax = plt.subplots()
|
||||||
# ax.set_xlabel('t / s')
|
ax.set_xlabel('t / s')
|
||||||
# ax.set_ylabel('M')
|
ax.set_ylabel('M')
|
||||||
# axheader = f'T1: {p0[2]:.4g}(+/-{perr[2]:.4g}) beta: {p0[3]:.4g}(+/-{perr[3]:.4g})'
|
axheader = f'T1: {p0[2]:.4g}(+/-{perr[2]:.4g}) beta: {p0[3]:.4g}(+/-{perr[3]:.4g})'
|
||||||
# ax.set_title(f'f = {k:.4g} Hz\n{axheader}')
|
ax.set_title(f'f = {k:.4g} Hz\n{axheader}')
|
||||||
# ax.semilogx(v.x, v.y, 'o')
|
ax.semilogx(v.x, v.y, 'o')
|
||||||
# ax.semilogx(xplot, yplot, '-')
|
ax.semilogx(xplot, yplot, '-')
|
||||||
# fig.savefig(image_path.joinpath(save_name).with_suffix('.png'))
|
fig.savefig(image_path.joinpath(save_name).with_suffix('.png'))
|
||||||
# plt.close(fig)
|
plt.close(fig)
|
||||||
|
|
||||||
freqs = np.asanyarray(freqs)
|
freqs = np.asanyarray(freqs)
|
||||||
params = np.asanyarray(params)
|
params = np.asanyarray(params)
|
||||||
@ -290,45 +320,45 @@ class FCReader:
|
|||||||
path = pathlib.Path(path)
|
path = pathlib.Path(path)
|
||||||
path.mkdir(parents=True, exist_ok=True)
|
path.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
# fig_mag, ax_mag = plt.subplots()
|
fig_mag, ax_mag = plt.subplots()
|
||||||
# fig_t1, ax_t1 = plt.subplots()
|
fig_t1, ax_t1 = plt.subplots()
|
||||||
# fig_beta, ax_beta = plt.subplots()
|
fig_beta, ax_beta = plt.subplots()
|
||||||
#
|
|
||||||
# if kind == 'temp':
|
if kind == 'temp':
|
||||||
# _params = self.t_params
|
_params = self.t_params
|
||||||
# else:
|
else:
|
||||||
# _params = self.f_params
|
_params = self.f_params
|
||||||
#
|
|
||||||
# save_path = path.joinpath(kind)
|
save_path = path.joinpath(kind)
|
||||||
# if not save_path.exists():
|
if not save_path.exists():
|
||||||
# save_path.mkdir(parents=True)
|
save_path.mkdir(parents=True)
|
||||||
#
|
|
||||||
# for key, par in _params.items():
|
for key, par in _params.items():
|
||||||
# pl, = ax_mag.plot(par[:, 0], par[:, 1], 'o', label=key)
|
pl, = ax_mag.plot(par[:, 0], par[:, 1], 'o', label=key)
|
||||||
# ax_mag.plot(par[:, 0], par[:, 3], 's', color=pl.get_color())
|
ax_mag.plot(par[:, 0], par[:, 3], 's', color=pl.get_color())
|
||||||
# ax_t1.plot(par[:, 0], par[:, 5], 'o', label=key)
|
ax_t1.plot(par[:, 0], par[:, 5], 'o', label=key)
|
||||||
# ax_beta.plot(par[:, 0], par[:, 7], 'o', label=key)
|
ax_beta.plot(par[:, 0], par[:, 7], 'o', label=key)
|
||||||
#
|
|
||||||
# for a in [ax_mag, ax_t1, ax_beta]:
|
for a in [ax_mag, ax_t1, ax_beta]:
|
||||||
# if kind == 'freq':
|
if kind == 'freq':
|
||||||
# a.legend(loc='upper left', bbox_to_anchor=(1, 1), ncol=2)
|
a.legend(loc='upper left', bbox_to_anchor=(1, 1), ncol=2)
|
||||||
# a.set_xlabel('T / K')
|
a.set_xlabel('T / K')
|
||||||
# else:
|
else:
|
||||||
# a.set_xscale('log')
|
a.set_xscale('log')
|
||||||
# a.legend(loc='upper left', bbox_to_anchor=(1, 1))
|
a.legend(loc='upper left', bbox_to_anchor=(1, 1))
|
||||||
# a.set_xlabel('f / Hz')
|
a.set_xlabel('f / Hz')
|
||||||
#
|
|
||||||
# ax_t1.set_yscale('log')
|
ax_t1.set_yscale('log')
|
||||||
# ax_t1.set_ylabel('T1 / s')
|
ax_t1.set_ylabel('T1 / s')
|
||||||
# ax_beta.set_ylabel('beta')
|
ax_beta.set_ylabel('beta')
|
||||||
# ax_mag.set_ylabel('M0 (squares), Offset (circles)')
|
ax_mag.set_ylabel('M0 (squares), Offset (circles)')
|
||||||
#
|
|
||||||
# fig_beta.savefig(path.joinpath(f'beta_{kind}.png'), bbox_inches="tight")
|
fig_beta.savefig(path.joinpath(f'beta_{kind}.png'), bbox_inches="tight")
|
||||||
# fig_mag.savefig(path.joinpath(f'mag_{kind}.png'), bbox_inches="tight")
|
fig_mag.savefig(path.joinpath(f'mag_{kind}.png'), bbox_inches="tight")
|
||||||
# fig_t1.savefig(path.joinpath(f't1_{kind}.png'), bbox_inches="tight")
|
fig_t1.savefig(path.joinpath(f't1_{kind}.png'), bbox_inches="tight")
|
||||||
# plt.close(fig_mag)
|
plt.close(fig_mag)
|
||||||
# plt.close(fig_beta)
|
plt.close(fig_beta)
|
||||||
# plt.close(fig_t1)
|
plt.close(fig_t1)
|
||||||
|
|
||||||
def get_parameter(self, parameter='all', kind='freq', path=None, write=True, plot=True):
|
def get_parameter(self, parameter='all', kind='freq', path=None, write=True, plot=True):
|
||||||
param_list = []
|
param_list = []
|
||||||
@ -389,101 +419,3 @@ class FCReader:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def kww(x, m0, off, t1, beta):
|
def kww(x, m0, off, t1, beta):
|
||||||
return m0 * np.exp(-(x/t1)**beta) + off
|
return m0 * np.exp(-(x/t1)**beta) + off
|
||||||
|
|
||||||
|
|
||||||
class FCFileReader:
|
|
||||||
def __init__(self, fname: str):
|
|
||||||
self.filename = pathlib.Path(fname)
|
|
||||||
self._is_dir = self.filename.is_dir()
|
|
||||||
self._script_type = None
|
|
||||||
self.reader = None
|
|
||||||
if not self._is_dir:
|
|
||||||
self.reader = HdfReader(self.filename)
|
|
||||||
if 'mag' in self.reader:
|
|
||||||
self._script_type = 'old'
|
|
||||||
elif 'Magnetization' in self.reader:
|
|
||||||
self._script_type = '2022_09'
|
|
||||||
|
|
||||||
self._temperature = get_temperature(self.filename.stem)
|
|
||||||
|
|
||||||
def load_magnetization(self, region=None):
|
|
||||||
if self._is_dir:
|
|
||||||
_temp = self._read_from_dir()
|
|
||||||
|
|
||||||
else:
|
|
||||||
if region is None:
|
|
||||||
_temp = self._read_from_hdf()
|
|
||||||
else:
|
|
||||||
_temp = self._read_signals(region)
|
|
||||||
|
|
||||||
if not _temp:
|
|
||||||
raise OSError(-666, f'No magnetization found for {self.filename.name}.', self.filename.name)
|
|
||||||
|
|
||||||
|
|
||||||
def _read_from_hdf(self) -> dict:
|
|
||||||
_temp = {}
|
|
||||||
mag_directory = 'mag' if self._script_type == 'old' else 'Magnetization'
|
|
||||||
for mag in self.reader.get_selected(mag_directory, dtype='points'):
|
|
||||||
_temp[mag.value] = mag
|
|
||||||
|
|
||||||
return _temp
|
|
||||||
|
|
||||||
def _read_from_dir(self) -> dict:
|
|
||||||
fname_no_ext = self.filename.with_suffix('')
|
|
||||||
data_path = fname_no_ext / 'data'
|
|
||||||
_temp = {}
|
|
||||||
|
|
||||||
for mag in data_path.glob('*.dat'):
|
|
||||||
d = AsciiReader(mag).export()
|
|
||||||
for v in d:
|
|
||||||
_temp[v.value] = v
|
|
||||||
break
|
|
||||||
|
|
||||||
return _temp
|
|
||||||
|
|
||||||
def _read_signals(self, region: tuple = None) -> dict:
|
|
||||||
start = 0
|
|
||||||
stop = 30e-5
|
|
||||||
|
|
||||||
# This is one set with attributes to find default start:stop values
|
|
||||||
try:
|
|
||||||
p = self.reader.parameters('/ABS_ACC_FID')
|
|
||||||
start = p['start']
|
|
||||||
stop = p['stop']
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if region is None:
|
|
||||||
region = (start, stop)
|
|
||||||
|
|
||||||
if region[0] is None:
|
|
||||||
region = (start, region[1])
|
|
||||||
if region[1] is None:
|
|
||||||
region = (region[0], stop)
|
|
||||||
|
|
||||||
sig = self.reader.get_selected('/data/B=*/ACC_ABS_FID*', dtype='signal')
|
|
||||||
_temp = {}
|
|
||||||
for s in sig:
|
|
||||||
pts = s.points([region])
|
|
||||||
b = s.group
|
|
||||||
if b not in _temp:
|
|
||||||
_temp[b] = []
|
|
||||||
|
|
||||||
_temp[b].append([s.value, *[pp[1] for pp in pts]])
|
|
||||||
|
|
||||||
for b, m in sorted(_temp.items()):
|
|
||||||
m = np.array(m)
|
|
||||||
_temp[b] = Points(x=m[:, 0], y=m[:, 1], value=b, name=f'B={b}').sort()
|
|
||||||
|
|
||||||
return _temp
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
from pprint import pprint
|
|
||||||
test = FCReader('/autohome/dominik/nmreval/testdata/fc_test/2022-09-15_1344_new_script.h5')
|
|
||||||
# test = FCReader('/autohome/dominik/nmreval/testdata/fc_test/314K_2015-09-03_1605.h5')
|
|
||||||
|
|
||||||
test.load_magnetization()
|
|
||||||
test.load_magnetization(region=(0, 10e-6))
|
|
||||||
# pprint(test.data)
|
|
||||||
|
@ -27,7 +27,7 @@ class HdfNode:
|
|||||||
'num_signals', 'num_pts', 'num_grp',
|
'num_signals', 'num_pts', 'num_grp',
|
||||||
'title_parameter', 'parameter']
|
'title_parameter', 'parameter']
|
||||||
|
|
||||||
def __init__(self, name, ref, parent):
|
def __init__(self, name: str, ref, parent: HdfNode | None):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.type = 'group'
|
self.type = 'group'
|
||||||
self.reference = ref
|
self.reference = ref
|
||||||
@ -59,7 +59,6 @@ class HdfNode:
|
|||||||
|
|
||||||
return key in self.children
|
return key in self.children
|
||||||
|
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
self.name = ''
|
self.name = ''
|
||||||
self.type = 'group'
|
self.type = 'group'
|
||||||
@ -281,16 +280,16 @@ class HdfReader(HdfNode):
|
|||||||
for child in val.data(dtype=dtype):
|
for child in val.data(dtype=dtype):
|
||||||
try:
|
try:
|
||||||
if child.type == 'points':
|
if child.type == 'points':
|
||||||
ret_val.append(self._make_point(child))
|
ret_val.append(self.make_point(child))
|
||||||
elif child.type == 'signal':
|
elif child.type == 'signal':
|
||||||
ret_val.append(self._make_signal(child, flag=flag, value=value, group=group))
|
ret_val.append(self.make_signal(child, flag=flag, value=value, group=group))
|
||||||
except IOError:
|
except IOError:
|
||||||
print('something went wrong for ' + child.name)
|
print('something went wrong for ' + child.name)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
return ret_val
|
return ret_val
|
||||||
|
|
||||||
def _make_point(self, node):
|
def make_point(self, node):
|
||||||
data = self.file[node.reference]
|
data = self.file[node.reference]
|
||||||
|
|
||||||
val = None
|
val = None
|
||||||
@ -300,7 +299,7 @@ class HdfReader(HdfNode):
|
|||||||
|
|
||||||
return Points(x=data['x'], y=data['y'], yerr=data['y_err'], name=node.name, value=val)
|
return Points(x=data['x'], y=data['y'], yerr=data['y_err'], name=node.name, value=val)
|
||||||
|
|
||||||
def _make_signal(self, node, flag: str = 'fid', value: str = None, group: str = None):
|
def make_signal(self, node, flag: str = 'fid', value: str = None, group: str = None):
|
||||||
if value is None:
|
if value is None:
|
||||||
value = self._get_parameter_values(node, node.parameter)
|
value = self._get_parameter_values(node, node.parameter)
|
||||||
else:
|
else:
|
||||||
|
@ -224,9 +224,9 @@ class ExpFunc:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def func(x, c, x0, beta, pm: int = -1, mode: str = 'time'):
|
def func(x, c, x0, beta, pm: int = -1, mode: str = 'time'):
|
||||||
if mode == 'time':
|
if mode == 'time':
|
||||||
return c * np.exp(np.sign(pm) * (x0 * x) ** beta)
|
|
||||||
elif mode == 'rate':
|
|
||||||
return c * np.exp(np.sign(pm) * (x / x0) ** beta)
|
return c * np.exp(np.sign(pm) * (x / x0) ** beta)
|
||||||
|
elif mode == 'rate':
|
||||||
|
return c * np.exp(np.sign(pm) * (x * x0) ** beta)
|
||||||
else:
|
else:
|
||||||
raise ValueError('Unknown mode %s. Use either "rate" or "time".' % str(mode))
|
raise ValueError('Unknown mode %s. Use either "rate" or "time".' % str(mode))
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user