[plot] temporary fixes of unimplemented stuff

This commit is contained in:
Jan Grewe 2021-02-06 13:43:41 +01:00
parent feefa81cf8
commit 57c02b4484

View File

@ -3,7 +3,7 @@ from PyQt5.QtWidgets import QGroupBox, QHBoxLayout, QLabel, QPushButton, QSizePo
from PyQt5.QtCore import pyqtSignal, Qt from PyQt5.QtCore import pyqtSignal, Qt
import matplotlib import matplotlib
matplotlib.use('Qt5Agg') matplotlib.use('Qt5Agg')
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas, NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure from matplotlib.figure import Figure
import nixio as nix import nixio as nix
import numpy as np import numpy as np
@ -27,7 +27,7 @@ def create_label(item):
return label return label
class MplCanvas(FigureCanvasQTAgg): class MplCanvas(FigureCanvas):
view_changed = pyqtSignal() view_changed = pyqtSignal()
def __init__(self, parent=None, width=5, height=4, dpi=100): def __init__(self, parent=None, width=5, height=4, dpi=100):
@ -35,12 +35,45 @@ class MplCanvas(FigureCanvasQTAgg):
self.axis = figure.add_subplot(111) self.axis = figure.add_subplot(111)
super(MplCanvas, self).__init__(figure) super(MplCanvas, self).__init__(figure)
self._figure = figure self._figure = figure
self._figure.canvas.mpl_connect('figure_enter_event', self.on_enter_figure)
self._figure.canvas.mpl_connect('figure_leave_event', self.on_leave_figure)
self._figure.canvas.mpl_connect('axes_enter_event', self.on_enter_axes)
self._figure.canvas.mpl_connect('axes_leave_event', self.on_leave_axes)
self._figure.canvas.mpl_connect('pick_event', self.on_pick)
def on_enter_figure(self, event):
print('enter_figure', event.canvas.figure)
# event.canvas.figure.patch.set_facecolor('red')
# event.canvas.draw()
def on_leave_figure(self, event):
print('leave_figure', event.canvas.figure)
# event.canvas.figure.patch.set_facecolor('grey')
# event.canvas.draw()
def on_enter_axes(self, event):
print('enter_axes', event.inaxes)
# event.inaxes.patch.set_facecolor('yellow')
# event.canvas.draw()
def on_leave_axes(self, event):
print('leave_axes', event.inaxes)
# event.inaxes.patch.set_facecolor('white')
# event.canvas.draw()
def on_pick(self, event):
line = event.artist
print(line.label)
xdata, ydata = line.get_data()
ind = event.ind
print('on pick line:', np.array([xdata[ind], ydata[ind]]).T)
#def clear(self): #def clear(self):
# self.clear() # self.clear()
#@property #@property
#def figure(self): #def enter_figure(self):
# return self._fig # return self._fig
@ -51,10 +84,12 @@ class Plotter(MplCanvas):
self._item = item self._item = item
self._dataview = data_view self._dataview = data_view
def current_view(self): def current_view(self):
raise NotImplementedError("current_view is not implemented on the current plotter") raise NotImplementedError("current_view is not implemented on the current plotter")
def is_full_view(self):
raise NotImplementedError("is_full_view is not implemented on the current plotter")
class EventPlotter(Plotter): class EventPlotter(Plotter):
@ -63,6 +98,7 @@ class EventPlotter(Plotter):
self.array = data_array self.array = data_array
self.sc = None self.sc = None
self.dim_count = len(data_array.dimensions) self.dim_count = len(data_array.dimensions)
"""
if xdim == -1: if xdim == -1:
self.xdim = guess_best_xdim(self.array) self.xdim = guess_best_xdim(self.array)
elif xdim > 1: elif xdim > 1:
@ -70,6 +106,7 @@ class EventPlotter(Plotter):
"Cannot plot that kind of data") "Cannot plot that kind of data")
else: else:
self.xdim = xdim self.xdim = xdim
"""
def plot(self, axis=None): def plot(self, axis=None):
if axis is None: if axis is None:
@ -106,6 +143,7 @@ class CategoryPlotter(Plotter):
def __init__(self, data_array, xdim=-1): def __init__(self, data_array, xdim=-1):
self.array = data_array self.array = data_array
self.bars = [] self.bars = []
"""
if xdim == -1: if xdim == -1:
self.xdim = guess_best_xdim(self.array) self.xdim = guess_best_xdim(self.array)
elif xdim > 2: elif xdim > 2:
@ -113,6 +151,7 @@ class CategoryPlotter(Plotter):
"Cannot plot that kind of data") "Cannot plot that kind of data")
else: else:
self.xdim = xdim self.xdim = xdim
"""
def plot(self, axis=None): def plot(self, axis=None):
if axis is None: if axis is None:
@ -132,6 +171,7 @@ class CategoryPlotter(Plotter):
def plot_1d(self): def plot_1d(self):
data = self.array[:] data = self.array[:]
dim = self.array.dimensions[self.xdim] dim = self.array.dimensions[self.xdim]
categories = None
if dim.dimension_type == nix.DimensionType.Set: if dim.dimension_type == nix.DimensionType.Set:
categories = list(dim.labels) categories = list(dim.labels)
else: else:
@ -150,7 +190,7 @@ class CategoryPlotter(Plotter):
data = self.array[:] data = self.array[:]
if self.xdim == 1: if self.xdim == 1:
data = data.T data = data.T
categories = None
dim = self.array.dimensions[self.xdim] dim = self.array.dimensions[self.xdim]
if dim.dimension_type == nix.DimensionType.Set: if dim.dimension_type == nix.DimensionType.Set:
categories = list(dim.labels) categories = list(dim.labels)
@ -158,6 +198,7 @@ class CategoryPlotter(Plotter):
categories = ["Cat-%i" % i for i in range(data.shape[self.xdim])] categories = ["Cat-%i" % i for i in range(data.shape[self.xdim])]
dim = self.array.dimensions[1-self.xdim] dim = self.array.dimensions[1-self.xdim]
series_names = []
if dim.dimension_type == nix.DimensionType.Set: if dim.dimension_type == nix.DimensionType.Set:
series_names = list(dim.labels) series_names = list(dim.labels)
if len(series_names) == 0: if len(series_names) == 0:
@ -223,8 +264,14 @@ class LinePlotter(Plotter):
def __init__(self, file_handler, item, data_view, xdim=-1, parent=None): def __init__(self, file_handler, item, data_view, xdim=-1, parent=None):
super().__init__(file_handler, item, data_view, parent) super().__init__(file_handler, item, data_view, parent)
#self.canvas = FigureCanvas(self.figure)
#self.toolbar = NavigationToolbar(self.canvas, self)
self.dimensions = self._file_handler.request_dimensions(self._item.block_id, self._item.id) self.dimensions = self._file_handler.request_dimensions(self._item.block_id, self._item.id)
self._min_x = None
self._max_x = None
self._min_x = None
self.min_x = None
self.lines = [] self.lines = []
self.dim_count = len(self._dataview.full_shape) self.dim_count = len(self._dataview.full_shape)
if xdim == -1: if xdim == -1:
@ -234,6 +281,32 @@ class LinePlotter(Plotter):
"Cannot plot that kind of data") "Cannot plot that kind of data")
else: else:
self.xdim = xdim self.xdim = xdim
self.axis.callbacks.connect('xlim_changed', self.on_xlims_change)
self.axis.callbacks.connect('ylim_changed', self.on_ylims_change)
def on_xlims_change(self, event_ax):
print("updated xlims: ", event_ax.get_xlim())
def on_ylims_change(self, event_ax):
print("updated ylims: ", event_ax.get_ylim())
def current_view(self):
cv = []
return cv
@property
def is_full_view(self):
xlims = self.axis.get_xlim()
full = self._min_x == xlims[0] and self._max_x == xlims[-1]
full = full and self._dataview.fully_loaded
return full
def on_zoom_in(self, new_position):
print("plotter ZOOM In!", new_position)
def on_zoom_out(self, new_position):
print("plotter ZOOM out!", new_position)
def plot(self, maxpoints=100000): def plot(self, maxpoints=100000):
self.maxpoints = maxpoints self.maxpoints = maxpoints
@ -244,27 +317,18 @@ class LinePlotter(Plotter):
else: else:
self.plot_array_2d() self.plot_array_2d()
def __add_slider(self):
steps = self.array.shape[self.xdim] / self.maxpoints
slider_ax = self.fig.add_axes([0.15, 0.025, 0.8, 0.025])
self.slider = Slider(slider_ax, 'Slider', 1., steps, valinit=1.,
valstep=0.25)
self.slider.on_changed(self.__update)
def __update(self, val):
if len(self.lines) > 0:
minimum = val * self.maxpoints - self.maxpoints
start = minimum if minimum > 0 else 0
end = val * self.maxpoints
self.__draw(start, end)
self.fig.canvas.draw_idle()
def __draw(self, start, end): def __draw(self, start, end):
if self.dim_count == 1: if self.dim_count == 1:
self.__draw_1d(start, end) self.__draw_1d(start, end)
else: else:
self.__draw_2d(start, end) self.__draw_2d(start, end)
def _set_xlims(self, data_xmin, data_xmax):
if self._min_x is None or data_xmin < self._min_x:
self._min_x = data_xmin
if self._max_x is None or data_xmax > self._max_x:
self._max_x = data_xmax
def __draw_1d(self, start, end): def __draw_1d(self, start, end):
if start < 0: if start < 0:
start = 0 start = 0
@ -273,9 +337,9 @@ class LinePlotter(Plotter):
y = self._dataview._buffer[int(start):int(end)] 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) x = self._file_handler.request_axis(self._item.block_id, self._item.id, 0, len(y), start)
self._set_xlims(x[0], x[-1])
if len(self.lines) == 0: if len(self.lines) == 0:
l, = self.axis.plot(x, y, label=self._item.name) l, = self.axis.plot(x, y, label=self._item.name, picker=5)
self.lines.append(l) self.lines.append(l)
else: else:
self.lines[0].set_ydata(y) self.lines[0].set_ydata(y)
@ -292,6 +356,7 @@ class LinePlotter(Plotter):
x = self._file_handler.request_axis(self._item.block_id, self._item.id, self.xdim, int(end-start), start) x = self._file_handler.request_axis(self._item.block_id, self._item.id, self.xdim, int(end-start), start)
line_count = self._dataview.current_shape[1 - self.xdim] line_count = self._dataview.current_shape[1 - self.xdim]
line_labels = self._file_handler.request_axis(self._item.block_id, self._item.id, 1-self.xdim, line_count, 0) line_labels = self._file_handler.request_axis(self._item.block_id, self._item.id, 1-self.xdim, line_count, 0)
self._set_xlims(x[0], x[-1])
for i, l in enumerate(line_labels): for i, l in enumerate(line_labels):
if (self.xdim == 0): if (self.xdim == 0):
@ -300,7 +365,7 @@ class LinePlotter(Plotter):
y = self._dataview._buffer[i, int(start):int(end)] y = self._dataview._buffer[i, int(start):int(end)]
if len(self.lines) <= i: if len(self.lines) <= i:
ll, = self.axis.plot(x, y, label=l) ll, = self.axis.plot(x, y, label=l, picker=5)
self.lines.append(ll) self.lines.append(ll)
else: else:
self.lines[i].set_ydata(y) self.lines[i].set_ydata(y)
@ -357,6 +422,8 @@ class PlotScreen(QWidget):
self.layout().addWidget(close_btn) self.layout().addWidget(close_btn)
self._data_view = None self._data_view = None
self.zoom_position = 0
def _create_plot_controls(self): def _create_plot_controls(self):
plot_controls = QGroupBox() plot_controls = QGroupBox()
plot_controls.setFlat(True) plot_controls.setFlat(True)
@ -401,14 +468,23 @@ class PlotScreen(QWidget):
self.close_signal.emit() self.close_signal.emit()
def on_zoom(self, new_position): def on_zoom(self, new_position):
print("zoom", new_position) if self.zoom_position < new_position:
self.plotter.on_zoom_out(new_position)
else:
self.plotter.on_zoom_out(new_position)
self.zoom_position = new_position
def on_pan(self, new_position): def on_pan(self, new_position):
print("pan", new_position) print("pan", new_position)
def on_view_changed(self): def on_view_changed(self):
print("view changed!") print("view changed!")
print(self.plotter.current_view()) print(self.plotter.current_view())
if self.plotter.is_full_view:
self._zoom_slider.setSliderPosition(100)
self._pan_slider.setEnabled(not self.plotter.is_full_view)
def plot(self, item): def plot(self, item):
try: try:
@ -418,11 +494,13 @@ class PlotScreen(QWidget):
return return
if self._data_view is None: if self._data_view is None:
return return
while not self._data_view.fully_loaded: #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
if item.suggested_plotter == PlotterTypes.LinePlotter: if item.suggested_plotter == PlotterTypes.LinePlotter:
self.plotter = LinePlotter(self._file_handler, item, self._data_view) self.plotter = LinePlotter(self._file_handler, item, self._data_view)
self.plotter.view_changed.connect(self.on_view_changed) self.plotter.view_changed.connect(self.on_view_changed)
self._container.set_plotter(self.plotter) self._container.set_plotter(self.plotter)
self.plotter.plot() self.plotter.plot(maxpoints=10000)
self._zoom_slider.setSliderPosition(100)
self.zoom_position = 100