Source code for lys.widgets.canvas.interface.CanvasBase

import functools
import weakref

from lys.Qt import QtCore
from lys.errors import suppressLysWarnings


[docs]def saveCanvas(func): """ When methods of :class:`CanvasBase` or :class:'CanvasPart' that is decorated by *saveCanvas* is called, then *updated* signal of the canvas is emitted. """ @functools.wraps(func) def wrapper(*args, **kwargs): if isinstance(args[0], CanvasPart): canvas = args[0].canvas() else: canvas = args[0] if canvas._saveflg: res = func(*args, **kwargs) else: canvas._saveflg = True res = func(*args, **kwargs) canvas.updated.emit() canvas._saveflg = False return res return wrapper
[docs]def disableSaveCanvas(func): """ When methods of :class:`CanvasBase` or :class:'CanvasPart' that is decorated by *disableSaveCanvas* is called, then *updated* signal of the canvas is *not* emitted in that method. """ @functools.wraps(func) def wrapper(*args, **kwargs): if isinstance(args[0], CanvasPart): canvas = args[0].canvas() else: canvas = args[0] if canvas._saveflg: res = func(*args, **kwargs) else: canvas._saveflg = True res = func(*args, **kwargs) canvas._saveflg = False return res return wrapper
_saveCanvasDummy = saveCanvas
[docs]class CanvasBase(object): """ Base class for canvas. Canvas is composed of :class:`.Area.CanvasSize`, :class:`.Area.CanvasSize`, :class:`.Axes.CanvasAxis`, :class:`.Axes.CanvasTicks`, :class:`.AxisLabel.CanvasAxisLabel`, :class:`.AxisLabel.CanvasTickLabel`, :class:`Data.CanvasData`, and :class:`Annotation.CanvasAnnotation`. All of these classes inherits :class:`CanvasPart` and added by :meth:`addCanvasPart`. Users can access all public methods of the classes above. """ saveCanvas = QtCore.pyqtSignal(dict) """pyqtSignal that is emitted when :meth:`SaveAsDictionary` is called.""" loadCanvas = QtCore.pyqtSignal(dict) """pyqtSignal that is emitted when :meth:`LoadFromDictionary` is called.""" initCanvas = QtCore.pyqtSignal() """pyqtSignal that is emitted when the canvas is initialized.""" updated = QtCore.pyqtSignal() """pyqtSignal that is emitted when the canvas is updated.""" finalized = QtCore.pyqtSignal(object) """pyqtSignal that is emitted when the canvas is finalized.""" def __init__(self): self._saveflg = False self.__parts = []
[docs] def addCanvasPart(self, part): """ Add :class:`CanvasPart` as a part of the canvas. Args: part(CanvasPart): The part to be added. """ self.__parts.append(part)
def __getattr__(self, key): for part in self.__parts: if hasattr(part, key): return getattr(part, key) return super().__getattr__(key)
[docs] def SaveAsDictionary(self, dictionary=None): """ Save the content of the canvas as dictionary. Args: dictionary(dict): The content of the canvas is written in *dictionary*. Return: dict: The dictionary in which the information of the canvas is written """ if dictionary is None: dictionary = {} self.saveCanvas.emit(dictionary) return dictionary
[docs] @suppressLysWarnings @_saveCanvasDummy def LoadFromDictionary(self, dictionary): """ Load the content of the canvas as dictionary. Args: dictionary(dict): The content of the canvas is loaded from *dictionary*. """ self.loadCanvas.emit(dictionary)
[docs] def finalize(self): """ Finalize the canvas. Several graph library (including matplotlib) requires explicit finalization to break circular reference, which causes memory leak. Call this method to finalize the canvas, which is usually done by parent widget (such as Graph). """ self.finalized.emit(self)
[docs] def delayUpdate(self): """ This method should be used (as [*with*] block) when the canvas is heavily modified to avoid drawing repeatedly. """ return _CanvasLocker(self)
[docs] @staticmethod def dataTypes(wave): """ Return possible data type (image, vector, etc). Args: wave(Wave): The wave to be checked. Returns: list of str: Possible data type. """ if wave.ndim == 1: return ["line"] elif wave.ndim == 2: if wave.dtype == complex: return ["rgb", "vector"] else: return ["image", "contour"] elif wave.ndim == 3: if wave.shape[2] in [3, 4]: return ["rgb"] return []
class _CanvasLocker: def __init__(self, canvas): self.canvas = canvas def __enter__(self): self.canvas._saveflg = True def __exit__(self, exc_type, exc_value, traceback): self.canvas._saveflg = False self.canvas.updated.emit()
[docs]class CanvasPart(QtCore.QObject): """ The canvas that inherit :class:`CanvasBase` class is composed of multiple *CanvasPart*. """ def __init__(self, canvas): super().__init__() self._canvas = weakref.ref(canvas)
[docs] def canvas(self): """ Get the canvas that contains the CanvasPart. Return: CanvasBase: The canvas. """ return self._canvas()