from math import inf from contextlib import contextmanager from numpy import linspace from scipy.interpolate import interp1d from ..Qt import QtGui, QtWidgets @contextmanager def busy_cursor(): try: cursor = QtGui.QCursor(QtGui.QPixmap('/autohome/dominik/Downloads/slowbro.gif')) QtWidgets.QApplication.setOverrideCursor(cursor) yield finally: QtWidgets.QApplication.restoreOverrideCursor() class SciSpinBox(QtWidgets.QDoubleSpinBox): def __init__(self, parent=None): super().__init__(parent=parent) self.validator = QtGui.QDoubleValidator(self) self.setMinimum(-inf) self.setMaximum(inf) self.setDecimals(1000) self.precision = 0.001 self._prev_value = float(self.lineEdit().text()) def valueFromText(self, text: str) -> float: try: self._prev_value = float(self.cleanText()) except ValueError: pass return self._prev_value def textFromValue(self, value: float) -> str: if value == 0: return '0' else: return f'{value:.3e}' def stepBy(self, step: int): self._prev_value = self.value() new_value = self._prev_value if new_value != 0.0: new_value *= 10**(step/19.) else: new_value = 0.001 self.setValue(new_value) self.lineEdit().setText(f'{new_value:.3e}') def validate(self, text, pos): return self.validator.validate(text, pos) class RdBuCMap: # taken from Excel sheet from colorbrewer.org _rdbu = [ (103, 0, 31), (178, 24, 43), (214, 96, 77), (244, 165, 130), (253, 219, 199), (247, 247, 247), (209, 229, 240), (146, 197, 222), (67, 147, 195), (33, 102, 172), (5, 48, 97) ] def __init__(self, vmin=-1., vmax=1.): self.min = vmin self.max = vmax self.spline = [interp1d(linspace(self.max, self.min, num=11), [rgb[i] for rgb in RdBuCMap._rdbu]) for i in range(3)] def color(self, val: float): if val > self.max: col = QtGui.QColor.fromRgb(*RdBuCMap._rdbu[0]) elif val < self.min: col = QtGui.QColor.fromRgb(*RdBuCMap._rdbu[-1]) else: col = QtGui.QColor.fromRgb(*(float(self.spline[i](val)) for i in range(3))) return col