[plotscree] change inheritance and make 1D line plotter working ...

so far only for static data, no interaction
This commit is contained in:
Jan Grewe 2021-01-21 08:44:12 +01:00
parent 207fd47d86
commit e3541c920e

View File

@ -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.QtWidgets import QHBoxLayout, QPushButton, QVBoxLayout, QWidget
from PyQt5.QtCore import QObject, pyqtSignal, Qt from PyQt5.QtCore import QObject, pyqtSignal, Qt
import matplotlib import matplotlib
@ -14,18 +17,38 @@ from nixview.util.dataview import DataView
from nixview.communicator import communicator from nixview.communicator import communicator
def create_label(entity): def create_label(item):
label = "" label = ""
if hasattr(entity, "label"): if hasattr(item, "label"):
label += (entity.label if entity.label is not None else "") label += (item.label if item.label is not None else "")
if len(label) == 0 and hasattr(entity, "name"): if len(label) == 0 and hasattr(item, "name"):
label += entity.name label += item.name
if hasattr(entity, "unit") and entity.unit is not None: if hasattr(item, "unit") and item.unit is not None:
label += " [%s]" % entity.unit label += " [%s]" % item.unit
return label 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): def show(self):
plt.show() plt.show()
@ -195,34 +218,25 @@ class ImagePlotter(Plotter):
class LinePlotter(Plotter): class LinePlotter(Plotter):
def __init__(self, data_array, xdim=-1): def __init__(self, file_handler, item, data_view, xdim=-1, parent=None):
self.array = data_array 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.lines = []
self.dim_count = len(data_array.dimensions) self.dim_count = len(self._dataview.full_shape)
if xdim == -1: if xdim == -1:
self.xdim = guess_best_xdim(self.array) self.xdim = item.best_xdim
elif xdim > 2: elif xdim > 2:
raise ValueError("LinePlotter: xdim is larger than 2! " raise ValueError("LinePlotter: xdim is larger than 2! "
"Cannot plot that kind of data") "Cannot plot that kind of data")
else: else:
self.xdim = xdim self.xdim = xdim
self.fig = None
self.axis = None
def plot(self, axis=None, maxpoints=100000): def plot(self, maxpoints=100000):
self.maxpoints = maxpoints self.maxpoints = maxpoints
if axis is None: if self.dim_count > 2:
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:
return return
if dim_count == 1: if self.dim_count == 1:
return self.plot_array_1d() return self.plot_array_1d()
else: else:
return self.plot_array_2d() return self.plot_array_2d()
@ -251,21 +265,20 @@ class LinePlotter(Plotter):
def __draw_1d(self, start, end): def __draw_1d(self, start, end):
if start < 0: if start < 0:
start = 0 start = 0
if end > self.array.shape[self.xdim]: if end > self._dataview.current_shape[self.xdim]:
end = self.array.shape[self.xdim] end = self._dataview.current_shape[self.xdim]
y = self.array[int(start):int(end)] y = self._dataview._buffer[int(start):int(end)]
dim = self.array.dimensions[self.xdim] x = self._file_handler.request_axis(self._item.block_id, self._item.id, 0, len(y), start)
x = np.asarray(dim.axis(len(y), int(start)))
if len(self.lines) == 0: 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) self.lines.append(l)
else: else:
self.lines[0].set_ydata(y) self.lines[0].set_ydata(y)
self.lines[0].set_xdata(x) 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): def __draw_2d(self, start, end):
if start < 0: if start < 0:
@ -297,11 +310,12 @@ class LinePlotter(Plotter):
def plot_array_1d(self): def plot_array_1d(self):
self.__draw_1d(0, self.maxpoints) self.__draw_1d(0, self.maxpoints)
xlabel = create_label(self.array.dimensions[self.xdim])
ylabel = create_label(self.array) xlabel = create_label(self.dimensions[self.xdim])
self.axis.set_xlabel(xlabel) ylabel = create_label(self._item)
self.axis.set_ylabel(ylabel) self.axes.set_xlabel(xlabel)
return self.axis self.axes.set_ylabel(ylabel)
return self.axes
def plot_array_2d(self): def plot_array_2d(self):
self.__draw_2d(0, self.maxpoints) self.__draw_2d(0, self.maxpoints)
@ -312,14 +326,17 @@ class LinePlotter(Plotter):
self.axis.legend(loc=1) self.axis.legend(loc=1)
return self.axis return self.axis
class PlotContainer(QWidget):
def __init__(self, parent=None) -> None:
super().__init__(parent=parent)
self.setLayout(QVBoxLayout())
self.plotter = None
class MplCanvas(FigureCanvasQTAgg): def set_plotter(self, plotter):
if not self.layout().isEmpty():
def __init__(self, parent=None, width=5, height=4, dpi=100): self.layout().removeWidget(self.plotter)
self._fig = Figure(figsize=(width, height), dpi=dpi) self.layout().addWidget(plotter)
self.axes = self._fig.add_subplot(111) self.plotter = plotter
super(MplCanvas, self).__init__(self._fig)
class PlotScreen(QWidget): class PlotScreen(QWidget):
close_signal = pyqtSignal() close_signal = pyqtSignal()
@ -327,11 +344,10 @@ class PlotScreen(QWidget):
def __init__(self, parent=None) -> None: def __init__(self, parent=None) -> None:
super().__init__(parent=parent) super().__init__(parent=parent)
self._file_handler = FileHandler() 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.setLayout(QVBoxLayout())
self.layout().addWidget(self._screen) self._container = PlotContainer(self)
self.layout().addWidget(self._container)
close_btn = QPushButton("close") close_btn = QPushButton("close")
close_btn.clicked.connect(self.on_close) close_btn.clicked.connect(self.on_close)
@ -343,14 +359,17 @@ class PlotScreen(QWidget):
self.close_signal.emit() self.close_signal.emit()
def plot(self, item): def plot(self, item):
print("plot!", item)
print(item.entity_type, item.shape)
try: try:
self._data_view = DataView(item, self._file_handler) self._data_view = DataView(item, self._file_handler)
except ValueError as e: except ValueError as e:
communicator.plot_error.emit("error in plotscreen.plot %s" % e) communicator.plot_error.emit("error in plotscreen.plot %s" % e)
return return
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 self._data_view.request_more() # TODO this is just a test, needs to be removed
print(self._data_view) 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()