nmreval/src/gui_qt/data/shift_graphs.py

189 lines
7.3 KiB
Python
Raw Normal View History

2022-03-08 09:27:40 +00:00
import numpy as np
from itertools import cycle
from pyqtgraph import mkColor, mkPen
2022-10-20 15:23:15 +00:00
from nmreval.lib.colors import Tab10
2022-03-08 09:27:40 +00:00
from ..Qt import QtGui, QtCore, QtWidgets
from .._py.shift_scale_dialog import Ui_shift_dialog
from ..lib.pg_objects import PlotItem
from ..lib.spinboxes import SciSpinBox
2022-03-08 09:27:40 +00:00
class QShift(QtWidgets.QDialog, Ui_shift_dialog):
valuesChanged = QtCore.pyqtSignal(dict, tuple)
def __init__(self, parent=None):
super().__init__(parent=parent)
self.setupUi(self)
self.graphicsView.setMenuEnabled(False)
self.splitter.setSizes([int(self.width()/4), int(self.width()*2/3)])
self.movements = {}
self.data = {}
self._colors = cycle(Tab10)
self.graphicsView.plotItem.ctrl.logXCheck.blockSignals(True)
self.graphicsView.plotItem.ctrl.logYCheck.blockSignals(True)
2022-03-08 09:27:40 +00:00
delegate = SpinBoxDelegate()
delegate.valueChanged.connect(self.shift)
self.shift_table.setItemDelegate(delegate)
self.x_shift_spinbox.valueChanged.connect(lambda: self.glob_shift('h'))
self.y_shift_spinbox.valueChanged.connect(lambda: self.glob_shift('v'))
delegate = SpinBoxDelegate()
delegate.valueChanged.connect(self.scale)
self.scale_table.setItemDelegate(delegate)
self.x_scale_spinbox.valueChanged.connect(lambda: self.glob_scale('h'))
self.y_scale_spinbox.valueChanged.connect(lambda: self.glob_scale('v'))
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))]
2022-03-08 09:27:40 +00:00
else:
pl = [PlotItem(x=x, y=y, name=name, pen=mkPen(color=color))]
2022-03-08 09:27:40 +00:00
self.data[idx] = (pl, x, y)
# [[horizontal shift, vertical shift], [horizontal scale, vertical scale]]
self.movements[idx] = [[0, 0], [1, 1]]
for i, tw in enumerate([self.shift_table, self.scale_table]):
tw.blockSignals(True)
row = tw.rowCount()
tw.insertRow(row)
item = QtWidgets.QTableWidgetItem(name)
item.setForeground(QtGui.QBrush(color))
item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled)
item.setCheckState(QtCore.Qt.Checked)
item.setData(QtCore.Qt.UserRole, idx)
tw.setItem(row, 0, item)
tw.setItem(row, 1, QtWidgets.QTableWidgetItem(str(i)))
tw.setItem(row, 2, QtWidgets.QTableWidgetItem(str(i)))
tw.blockSignals(False)
for i in pl:
self.graphicsView.addItem(i)
def set_graphs(self, graphs: list):
for key, name in graphs:
self.data_combobox.addItem(name, userData=key)
self.values_combobox.addItem(name, userData=key)
def glob_shift_scale(self, widget: QtWidgets.QTableWidget, mode: int, col: int, value: float):
for row in range(widget.rowCount()):
if widget.item(row, 0).checkState() == QtCore.Qt.Checked:
item = widget.item(row, col)
item.setText(str(value))
self.shift_scale(widget, mode, row, col-1, value)
def glob_shift(self, direction: str):
if direction == 'h':
val = self.x_shift_spinbox.value()
self.glob_shift_scale(self.shift_table, 0, 1, val)
else:
val = self.y_shift_spinbox.value()
self.glob_shift_scale(self.shift_table, 0, 2, val)
def glob_scale(self, direction: str):
if direction == 'h':
val = self.x_scale_spinbox.value()
self.glob_shift_scale(self.scale_table, 1, 1, val)
else:
val = self.y_scale_spinbox.value()
self.glob_shift_scale(self.scale_table, 1, 2, val)
def shift_scale(self, widget: QtWidgets.QTableWidget, mode: int,
row: int, col: int, value: float):
item = widget.item(row, 0)
key = item.data(QtCore.Qt.UserRole)
self.movements[key][mode][col] = value
(x_off, y_off), (x_scale, y_scale) = self.movements[key]
pl, x, y = self.data[key]
y_part = [np.real, np.imag]
for i, item in enumerate(pl):
item.setData(x=x*x_scale+x_off, y=y_part[i](y) * y_scale + y_off)
@QtCore.pyqtSlot(int, int, float)
def shift(self, row: int, column: int, value: float):
self.shift_scale(self.shift_table, 0, row, column-1, value)
@QtCore.pyqtSlot(int, int, float)
def scale(self, row: int, column: int, value: float):
self.shift_scale(self.scale_table, 1, row, column-1, value)
@QtCore.pyqtSlot(int, name='on_xlog_checkbox_stateChanged')
@QtCore.pyqtSlot(int, name='on_ylog_checkbox_stateChanged')
def set_log(self, state: int):
if self.sender() == self.xlog_checkbox:
log_state = self.graphicsView.plotItem.ctrl.logXCheck
func = self.graphicsView.setXRange
2022-03-08 09:27:40 +00:00
else:
log_state = self.graphicsView.plotItem.ctrl.logYCheck
func = self.graphicsView.setYRange
2022-03-08 09:27:40 +00:00
log_state.setCheckState(state)
self.graphicsView.plotItem.updateLogMode()
# For some combinations of Python, pyqt, and pyqtgraph, updateLogMode does not update
# view range to log values and logTickValues generates LOTS of ticks, which freezes everything.
# -> Call setRange to interrupt the loop.
func(0, 1)
self.graphicsView.enableAutoRange()
2022-03-08 09:27:40 +00:00
def on_overwrite_checkbox_stateChanged(self, state: int):
self.data_newgraph.setVisible(state != QtCore.Qt.Checked)
self.data_combobox.setVisible(state != QtCore.Qt.Checked)
def on_value_checkbox_stateChanged(self, state: int):
self.values_newgraph.setVisible(state == QtCore.Qt.Checked)
self.values_combobox.setVisible(state == QtCore.Qt.Checked)
def on_data_newgraph_stateChanged(self, state: int):
self.data_combobox.setEnabled(state != QtCore.Qt.Checked)
def on_values_newgraph_stateChanged(self, state: int):
self.values_combobox.setEnabled(state != QtCore.Qt.Checked)
def accept(self):
data_saving = None
if not self.overwrite_checkbox.isChecked():
if self.data_newgraph.isChecked():
data_saving = ''
else:
data_saving = self.data_combobox.currentData()
value_saving = None
if self.value_checkbox.isChecked():
if self.values_newgraph.isChecked():
value_saving = ''
else:
value_saving = self.values_combobox.currentData()
self.valuesChanged.emit(self.movements, (data_saving, value_saving))
self.close()
class SpinBoxDelegate(QtWidgets.QStyledItemDelegate):
valueChanged = QtCore.pyqtSignal(int, int, float)
def createEditor(self, parent: QtWidgets.QWidget, option: QtWidgets.QStyleOptionViewItem,
idx: QtCore.QModelIndex) -> QtWidgets.QWidget:
editor = SciSpinBox(parent)
editor.valueChanged.connect(self.new_value)
return editor
def new_value(self, val):
# geht bestimmt besser...
table = self.sender().parent().parent()
self.valueChanged.emit(table.currentRow(), table.currentColumn(), val)