From e3541c920e0b4b6358ed81e4bb9d54c95b3f1110 Mon Sep 17 00:00:00 2001 From: Jan Grewe Date: Thu, 21 Jan 2021 08:44:12 +0100 Subject: [PATCH] [plotscree] change inheritance and make 1D line plotter working ... so far only for static data, no interaction --- nixview/ui/plotscreen.py | 137 ++++++++++++++++++++++----------------- 1 file changed, 78 insertions(+), 59 deletions(-) diff --git a/nixview/ui/plotscreen.py b/nixview/ui/plotscreen.py index 45dc377..793128e 100644 --- a/nixview/ui/plotscreen.py +++ b/nixview/ui/plotscreen.py @@ -1,3 +1,6 @@ +from nixview.data_models.tree_model import PropertyTreeItem +from nixview.util import dataview +from nixview.util.enums import PlotterTypes from PyQt5.QtWidgets import QHBoxLayout, QPushButton, QVBoxLayout, QWidget from PyQt5.QtCore import QObject, pyqtSignal, Qt import matplotlib @@ -14,18 +17,38 @@ from nixview.util.dataview import DataView from nixview.communicator import communicator -def create_label(entity): +def create_label(item): label = "" - if hasattr(entity, "label"): - label += (entity.label if entity.label is not None else "") - if len(label) == 0 and hasattr(entity, "name"): - label += entity.name - if hasattr(entity, "unit") and entity.unit is not None: - label += " [%s]" % entity.unit + if hasattr(item, "label"): + label += (item.label if item.label is not None else "") + if len(label) == 0 and hasattr(item, "name"): + label += item.name + if hasattr(item, "unit") and item.unit is not None: + label += " [%s]" % item.unit return label -class Plotter(object): +class MplCanvas(FigureCanvasQTAgg): + + def __init__(self, parent=None, width=5, height=4, dpi=100): + figure = Figure(figsize=(width, height), dpi=dpi) + self.axes = figure.add_subplot(111) + super(MplCanvas, self).__init__(figure) + self._figure = figure + + #def clear(self): + # self.clear() + + #@property + #def figure(self): + # return self._fig + + +class Plotter(MplCanvas): + def __init__(self, file_handler, item, parent=None) -> None: + super().__init__(parent=parent) + self._file_handler = file_handler + self._item = item def show(self): plt.show() @@ -195,34 +218,25 @@ class ImagePlotter(Plotter): class LinePlotter(Plotter): - def __init__(self, data_array, xdim=-1): - self.array = data_array + def __init__(self, file_handler, item, data_view, xdim=-1, parent=None): + super().__init__(file_handler, item, parent) + self._dataview = data_view + self.dimensions = self._file_handler.request_dimensions(self._item.block_id, self._item.id) self.lines = [] - self.dim_count = len(data_array.dimensions) + self.dim_count = len(self._dataview.full_shape) if xdim == -1: - self.xdim = guess_best_xdim(self.array) + self.xdim = item.best_xdim elif xdim > 2: raise ValueError("LinePlotter: xdim is larger than 2! " "Cannot plot that kind of data") else: self.xdim = xdim - self.fig = None - self.axis = None - def plot(self, axis=None, maxpoints=100000): + def plot(self, maxpoints=100000): self.maxpoints = maxpoints - if axis is None: - self.fig = plt.figure() - self.axis = self.fig.add_axes([0.15, .2, 0.8, 0.75]) - self.axis.set_title(self.array.name) - self.__add_slider() - else: - self.axis = axis - - dim_count = len(self.array.dimensions) - if dim_count > 2: + if self.dim_count > 2: return - if dim_count == 1: + if self.dim_count == 1: return self.plot_array_1d() else: return self.plot_array_2d() @@ -251,21 +265,20 @@ class LinePlotter(Plotter): def __draw_1d(self, start, end): if start < 0: start = 0 - if end > self.array.shape[self.xdim]: - end = self.array.shape[self.xdim] + if end > self._dataview.current_shape[self.xdim]: + end = self._dataview.current_shape[self.xdim] - y = self.array[int(start):int(end)] - dim = self.array.dimensions[self.xdim] - x = np.asarray(dim.axis(len(y), int(start))) + y = self._dataview._buffer[int(start):int(end)] + x = self._file_handler.request_axis(self._item.block_id, self._item.id, 0, len(y), start) if len(self.lines) == 0: - l, = self.axis.plot(x, y, label=self.array.name) + l, = self.axes.plot(x, y, label=self._item.name) self.lines.append(l) else: self.lines[0].set_ydata(y) self.lines[0].set_xdata(x) - self.axis.set_xlim([x[0], x[-1]]) + self.axes.set_xlim([x[0], x[-1]]) def __draw_2d(self, start, end): if start < 0: @@ -297,11 +310,12 @@ class LinePlotter(Plotter): def plot_array_1d(self): self.__draw_1d(0, self.maxpoints) - xlabel = create_label(self.array.dimensions[self.xdim]) - ylabel = create_label(self.array) - self.axis.set_xlabel(xlabel) - self.axis.set_ylabel(ylabel) - return self.axis + + xlabel = create_label(self.dimensions[self.xdim]) + ylabel = create_label(self._item) + self.axes.set_xlabel(xlabel) + self.axes.set_ylabel(ylabel) + return self.axes def plot_array_2d(self): self.__draw_2d(0, self.maxpoints) @@ -312,30 +326,32 @@ class LinePlotter(Plotter): self.axis.legend(loc=1) return self.axis - -class MplCanvas(FigureCanvasQTAgg): - - def __init__(self, parent=None, width=5, height=4, dpi=100): - self._fig = Figure(figsize=(width, height), dpi=dpi) - self.axes = self._fig.add_subplot(111) - super(MplCanvas, self).__init__(self._fig) - - +class PlotContainer(QWidget): + def __init__(self, parent=None) -> None: + super().__init__(parent=parent) + self.setLayout(QVBoxLayout()) + self.plotter = None + + def set_plotter(self, plotter): + if not self.layout().isEmpty(): + self.layout().removeWidget(self.plotter) + self.layout().addWidget(plotter) + self.plotter = plotter + class PlotScreen(QWidget): close_signal = pyqtSignal() - + def __init__(self, parent=None) -> None: super().__init__(parent=parent) self._file_handler = FileHandler() - self._screen = MplCanvas(self, width=5, height=4, dpi=100) - self._screen.axes.plot([0,1,2,3,4], [10,1,20,3,40]) - + self.setLayout(QVBoxLayout()) - self.layout().addWidget(self._screen) - + self._container = PlotContainer(self) + self.layout().addWidget(self._container) + close_btn = QPushButton("close") close_btn.clicked.connect(self.on_close) - + self.layout().addWidget(close_btn) self._data_view = None @@ -343,14 +359,17 @@ class PlotScreen(QWidget): self.close_signal.emit() def plot(self, item): - print("plot!", item) - print(item.entity_type, item.shape) try: self._data_view = DataView(item, self._file_handler) except ValueError as e: communicator.plot_error.emit("error in plotscreen.plot %s" % e) return - - self._data_view.request_more() # TODO this is just a test, needs to be removed - print(self._data_view) + if self._data_view is None: + return + while not self._data_view.fully_loaded: + self._data_view.request_more() # TODO this is just a test, needs to be removed + if item.suggested_plotter == PlotterTypes.LinePlotter: + self.plotter = LinePlotter(self._file_handler, item, self._data_view) + self._container.set_plotter(self.plotter) + self.plotter.plot()