[plot] works for 1 and 2d categories
This commit is contained in:
@@ -1,12 +1,10 @@
|
||||
from nixview.util import dataview
|
||||
from nixview.util.enums import PlotterTypes
|
||||
from PyQt5.QtWidgets import QGroupBox, QHBoxLayout, QLabel, QPushButton, QSizePolicy, QSlider, QVBoxLayout, QWidget
|
||||
from PyQt5.QtCore import pyqtSignal, Qt
|
||||
import matplotlib
|
||||
matplotlib.use('Qt5Agg')
|
||||
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas, NavigationToolbar2QT as NavigationToolbar
|
||||
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
|
||||
from matplotlib.figure import Figure
|
||||
import nixio as nix
|
||||
import numpy as np
|
||||
try:
|
||||
import matplotlib.pyplot as plt
|
||||
@@ -50,7 +48,6 @@ class MplCanvas(FigureCanvas):
|
||||
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')
|
||||
@@ -62,7 +59,7 @@ class MplCanvas(FigureCanvas):
|
||||
# event.canvas.figure.patch.set_facecolor('grey')
|
||||
# event.canvas.draw()
|
||||
pass
|
||||
|
||||
|
||||
def on_enter_axes(self, event):
|
||||
# print('enter_axes', event.inaxes)
|
||||
# event.inaxes.patch.set_facecolor('yellow')
|
||||
@@ -84,7 +81,7 @@ class MplCanvas(FigureCanvas):
|
||||
|
||||
#def clear(self):
|
||||
# self.clear()
|
||||
|
||||
|
||||
#@property
|
||||
#def enter_figure(self):
|
||||
# return self._fig
|
||||
@@ -116,7 +113,7 @@ class EventPlotter(Plotter):
|
||||
def __init__(self, file_handler, item, data_view, xdim=-1, parent=None):
|
||||
super().__init__(file_handler, item, data_view, parent)
|
||||
self.dim_count = len(self._dataview.full_shape)
|
||||
|
||||
|
||||
if xdim == -1:
|
||||
self.xdim = self._item.best_xdim
|
||||
else:
|
||||
@@ -149,22 +146,22 @@ class EventPlotter(Plotter):
|
||||
@property
|
||||
def horizontal_pan_position(self):
|
||||
return self._view_xmax/self._abs_xmax
|
||||
|
||||
|
||||
def horizontal_pan_to_position(self, new_position, zoomlevel):
|
||||
new_xmax = int(np.min([np.ceil(new_position * self._abs_xmax), self._abs_xmax]))
|
||||
segment_length = zoomlevel * self._abs_xmax
|
||||
start = np.max([0, new_xmax - segment_length])
|
||||
while not self._dataview.fully_loaded and new_xmax < self._dataview.current_shape[self.xdim]:
|
||||
self._dataview.request_more()
|
||||
|
||||
|
||||
self.plot(start, zoomlevel)
|
||||
|
||||
|
||||
def plot(self, start=0, zoomlevel=1.0):
|
||||
if zoomlevel > 1:
|
||||
zoomlevel = 1.0
|
||||
self._segment_length = zoomlevel * self._abs_xmax
|
||||
self._zoom_level = zoomlevel
|
||||
|
||||
|
||||
if self.dim_count == 1:
|
||||
return self.plot_1d(start)
|
||||
else:
|
||||
@@ -196,7 +193,7 @@ class EventPlotter(Plotter):
|
||||
self.figure.canvas.draw_idle()
|
||||
# self.axis.set_ylim([np.min(y_values), np.max(y_values)])
|
||||
self.axis.set_xlim([x_values[0], x_values[-1]])
|
||||
|
||||
|
||||
self.axis.set_ylim([0.5, 1.5])
|
||||
self.axis.set_yticks([1.])
|
||||
self.axis.set_yticklabels([])
|
||||
@@ -207,82 +204,55 @@ class EventPlotter(Plotter):
|
||||
|
||||
class CategoryPlotter(Plotter):
|
||||
|
||||
def __init__(self, data_array, xdim=-1):
|
||||
self.array = data_array
|
||||
def __init__(self, file_handler, item, data_view, parent=None):
|
||||
super().__init__(file_handler, item, data_view, parent)
|
||||
self.dim_count = len(self._dataview.full_shape)
|
||||
self._xdim = self._item.best_xdim
|
||||
self.bars = []
|
||||
"""
|
||||
if xdim == -1:
|
||||
self.xdim = guess_best_xdim(self.array)
|
||||
elif xdim > 2:
|
||||
raise ValueError("CategoryPlotter: xdim is larger than 2! "
|
||||
"Cannot plot that kind of data")
|
||||
else:
|
||||
self.xdim = xdim
|
||||
"""
|
||||
|
||||
def plot(self, axis=None):
|
||||
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)
|
||||
else:
|
||||
self.fig = axis.figure
|
||||
self.axis = axis
|
||||
if len(self.array.dimensions) == 1:
|
||||
def plot(self):
|
||||
if len(self._dataview.full_shape) == 1:
|
||||
return self.plot_1d()
|
||||
elif len(self.array.dimensions) == 2:
|
||||
elif len(self._dataview.full_shape) == 2:
|
||||
return self.plot_2d()
|
||||
else:
|
||||
else:
|
||||
return None
|
||||
|
||||
def plot_1d(self):
|
||||
data = self.array[:]
|
||||
dim = self.array.dimensions[self.xdim]
|
||||
categories = None
|
||||
if dim.dimension_type == nix.DimensionType.Set:
|
||||
categories = list(dim.labels)
|
||||
else:
|
||||
return None
|
||||
if categories is None:
|
||||
categories = ["Cat-%i" % i for i in range(len(data))]
|
||||
ylabel = create_label(self.array)
|
||||
if len(categories) == 0:
|
||||
raise ValueError("Cannot plot a bar chart without any labels")
|
||||
self.bars.append(self.axis.bar(range(1, len(categories)+1), data,
|
||||
tick_label=categories))
|
||||
ylabel = create_label(self._item)
|
||||
categories = self._file_handler.request_axis(self._item.block_id, self._item.id, self._item.best_xdim, self._item.shape[self._item.best_xdim])
|
||||
if categories is None or len(categories) == 0:
|
||||
categories = ["Cat-%i" % i for i in range(len(categories))]
|
||||
ylabel = create_label(self._item)
|
||||
|
||||
self.bars.append(self.axis.bar(range(1, len(categories) + 1), self._dataview._buffer, tick_label=categories))
|
||||
self.axis.set_ylabel(ylabel)
|
||||
return self.axis
|
||||
|
||||
def plot_2d(self):
|
||||
data = self.array[:]
|
||||
if self.xdim == 1:
|
||||
data = data.T
|
||||
categories = None
|
||||
dim = self.array.dimensions[self.xdim]
|
||||
if dim.dimension_type == nix.DimensionType.Set:
|
||||
categories = list(dim.labels)
|
||||
if len(categories) == 0:
|
||||
categories = ["Cat-%i" % i for i in range(data.shape[self.xdim])]
|
||||
ylabel = create_label(self._item)
|
||||
data = self._dataview._buffer
|
||||
if self._item.best_xdim == 1:
|
||||
data = data.T
|
||||
categories = self._file_handler.request_axis(self._item.block_id, self._item.id, self._item.best_xdim, self._item.shape[self._item.best_xdim])
|
||||
if categories is None or len(categories) == 0:
|
||||
categories = ["Cat-%i" % i for i in range(self._item.shape[self._item.best_xdim])]
|
||||
|
||||
dim = self.array.dimensions[1-self.xdim]
|
||||
series_names = []
|
||||
if dim.dimension_type == nix.DimensionType.Set:
|
||||
series_names = list(dim.labels)
|
||||
if len(series_names) == 0:
|
||||
series_names = ["Series-%i" % i
|
||||
for i in range(data.shape[1-self.xdim])]
|
||||
series = self._file_handler.request_axis(self._item.block_id, self._item.id, 1 - self._item.best_xdim, self._item.shape[1 - self._item.best_xdim])
|
||||
if len(series) == 0:
|
||||
series = ["Series-%i" % i for i in range(self._item.shape[1 - self._item.best_xdim])]
|
||||
|
||||
bar_width = 1/data.shape[1] * 0.75
|
||||
for i in range(data.shape[1]):
|
||||
x_values = np.arange(data.shape[0]) + i * bar_width
|
||||
self.bars.append(self.axis.bar(x_values, data[:, i],
|
||||
width=bar_width,
|
||||
align="center")[0])
|
||||
self.axis.set_xticks(np.arange(data.shape[0]) +
|
||||
data.shape[1] * bar_width/2)
|
||||
ylabel = create_label(self._item)
|
||||
bar_width = 1/len(series) * 0.75
|
||||
for i in range(len(series)):
|
||||
x_values = np.arange(len(categories)) + i * bar_width
|
||||
self.bars.append(self.axis.bar(x_values, data[:, i], width=bar_width, align="center")[0])
|
||||
self.axis.set_xticks(np.arange(len(categories)) + len(series) * bar_width/2)
|
||||
self.axis.set_xticklabels(categories)
|
||||
self.axis.legend(self.bars, series_names, loc=1)
|
||||
return self.axis
|
||||
self.axis.legend(self.bars, series, loc=1)
|
||||
self.axis.set_ylabel(ylabel)
|
||||
|
||||
|
||||
class ImagePlotter(Plotter):
|
||||
@@ -359,7 +329,7 @@ class LinePlotter(Plotter):
|
||||
self._segment_length = 0
|
||||
# self.axis.callbacks.connect('xlim_changed', self.on_xlims_change)
|
||||
# self.axis.callbacks.connect('ylim_changed', self.on_ylims_change)
|
||||
|
||||
|
||||
@property
|
||||
def is_full_view(self):
|
||||
full = self._data_xmin == self._view_xmin and self._data_xmax == self._view_xmax
|
||||
@@ -368,7 +338,7 @@ class LinePlotter(Plotter):
|
||||
@property
|
||||
def can_pan_horizontally(self):
|
||||
return self.can_pan_left or self.can_pan_right
|
||||
|
||||
|
||||
@property
|
||||
def can_pan_left(self):
|
||||
return self._view_xmin > self._abs_xmin
|
||||
@@ -380,7 +350,7 @@ class LinePlotter(Plotter):
|
||||
@property
|
||||
def horizontal_pan_position(self):
|
||||
return self._view_xmax/self._abs_xmax
|
||||
|
||||
|
||||
def horizontal_pan_to_position(self, new_position, zoomlevel):
|
||||
new_xmax = int(np.min([np.ceil(new_position * self._abs_xmax), self._abs_xmax]))
|
||||
segment_length = zoomlevel * self._abs_xmax
|
||||
@@ -389,13 +359,13 @@ class LinePlotter(Plotter):
|
||||
self._dataview.request_more()
|
||||
|
||||
self.plot(start, zoomlevel)
|
||||
|
||||
|
||||
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, start=0, zoomlevel=1.0):
|
||||
if zoomlevel > 1:
|
||||
zoomlevel = 1.0
|
||||
@@ -413,11 +383,11 @@ class LinePlotter(Plotter):
|
||||
self._data_xmin = display_x_min
|
||||
if self._data_xmax is None or display_xmax > self._data_xmax:
|
||||
self._data_xmax = display_xmax
|
||||
|
||||
|
||||
def _update_current_view(self, current_xmin, current_xmax):
|
||||
self._view_xmax = current_xmax
|
||||
self._view_xmin = current_xmin
|
||||
|
||||
|
||||
def __draw_1d(self, start, end):
|
||||
""" draw the data from start to end index.
|
||||
|
||||
@@ -519,7 +489,7 @@ class PlotScreen(QWidget):
|
||||
self._create_plot_controls()
|
||||
self.layout().addWidget(close_btn)
|
||||
self._data_view = None
|
||||
|
||||
|
||||
self._software_slide = False
|
||||
self.plotter = None
|
||||
|
||||
@@ -616,3 +586,11 @@ class PlotScreen(QWidget):
|
||||
self.plotter = EventPlotter(self._file_handler, item, self._data_view)
|
||||
self._container.set_plotter(self.plotter)
|
||||
self.plotter.plot()
|
||||
elif item.suggested_plotter == PlotterTypes.CategoryPlotter:
|
||||
self._zoom_slider.setEnabled(False)
|
||||
self._pan_slider.setEnabled(False)
|
||||
self.plotter = CategoryPlotter(self._file_handler, item, self._data_view)
|
||||
self._container.set_plotter(self.plotter)
|
||||
self.plotter.plot()
|
||||
else:
|
||||
self._container.set_plotter(None)
|
||||
|
||||
Reference in New Issue
Block a user