|
|
@@ -34,7 +34,6 @@ except ImportError:
|
|
|
# __all__ = ['Backend', 'PlotKind', 'PlotHandler', 'PlotManager', 'plot', 'follow', 'set_xlim', 'set_ylim',
|
|
|
# 'Arrow', 'StepPlot', 'ScatterPlot', 'LinePlot']
|
|
|
|
|
|
-# TODO: Bokeh (see TODOs)
|
|
|
# TODO: More Plot Kinds
|
|
|
|
|
|
class Backend:
|
|
|
@@ -190,8 +189,7 @@ class PlotHandler:
|
|
|
figure[0].canvas.mpl_connect('close_event', lambda _: self.__close_event())
|
|
|
elif Backend.compare("BOKEH", backend):
|
|
|
self.__periodic_callback = bokeh.io.curdoc().add_periodic_callback(lambda: self.update(), interval)
|
|
|
- # TODO (is this even possible?):
|
|
|
- bokeh.io.curdoc().on_session_destroyed(lambda ctx: self.__close_event())
|
|
|
+ # No need to do closing callback -- automatically done by simulator
|
|
|
|
|
|
def signal(self, name, *args):
|
|
|
"""
|
|
|
@@ -292,9 +290,6 @@ class PlotHandler:
|
|
|
"""
|
|
|
if self.kind.is_backend("MPL", "SNS"):
|
|
|
plt.close(self.figure[0])
|
|
|
- elif self.kind.is_backend("BOKEH"):
|
|
|
- # TODO
|
|
|
- pass
|
|
|
# Make sure we close the plot if the backend fails to do so
|
|
|
self.__close_event()
|
|
|
|
|
|
@@ -306,7 +301,6 @@ class PlotHandler:
|
|
|
This function is only used in the backend to prevent double
|
|
|
closing of the plots.
|
|
|
"""
|
|
|
- # print("closed")
|
|
|
if self.__opened:
|
|
|
self.__opened = False
|
|
|
self.stop()
|
|
|
@@ -565,11 +559,6 @@ class LinePlot(PlotKind):
|
|
|
- **matplotlib:** :func:`matplotlib.axes.Axes.plot`
|
|
|
- **bokeh:** :func:`bokeh.plotting.Figure.line`
|
|
|
- **seaborn:** :func:`seaborn.lineplot`
|
|
|
-
|
|
|
- See Also:
|
|
|
- - :class:`PlotKind`
|
|
|
- - :class:`StepPlot`
|
|
|
- - :class:`ScatterPlot`
|
|
|
"""
|
|
|
def create(self, figure):
|
|
|
if self.is_backend("MPL"):
|
|
|
@@ -577,9 +566,6 @@ class LinePlot(PlotKind):
|
|
|
line, = figure[1].plot([], [], *self.args, **self.kwargs)
|
|
|
return line
|
|
|
elif self.is_backend("BOKEH"):
|
|
|
- # source = bokeh.models.ColumnDataSource({'x': [], 'y': []})
|
|
|
- # figure.line(source=source, *self.args, **self.kwargs)
|
|
|
- # return source
|
|
|
return figure.line([], [], *self.args, **self.kwargs)
|
|
|
elif self.is_backend("SNS"):
|
|
|
# matplotlib: figure[1] is the axis
|
|
|
@@ -602,11 +588,6 @@ class StepPlot(PlotKind):
|
|
|
- **matplotlib:** :func:`matplotlib.axes.Axes.step`
|
|
|
- **bokeh:** :func:`bokeh.plotting.Figure.step`
|
|
|
- **seaborn:** :func:`seaborn.lineplot` with :code:`drawstyle='steps-pre'`
|
|
|
-
|
|
|
- See Also:
|
|
|
- - :class:`PlotKind`
|
|
|
- - :class:`LinePlot`
|
|
|
- - :class:`StepPlot`
|
|
|
"""
|
|
|
def create(self, figure):
|
|
|
if self.is_backend("MPL"):
|
|
|
@@ -636,11 +617,6 @@ class ScatterPlot(PlotKind):
|
|
|
- **matplotlib:** :func:`matplotlib.axes.Axes.scatter`
|
|
|
- **bokeh:** :func:`bokeh.plotting.Figure.scatter`
|
|
|
- **seaborn:** :func:`seaborn.scatterplot`
|
|
|
-
|
|
|
- See Also:
|
|
|
- - :class:`PlotKind`
|
|
|
- - :class:`LinePlot`
|
|
|
- - :class:`StepPlot`
|
|
|
"""
|
|
|
def create(self, figure):
|
|
|
if self.is_backend("MPL"):
|
|
|
@@ -661,47 +637,56 @@ class ScatterPlot(PlotKind):
|
|
|
elif self.is_backend("BOKEH"):
|
|
|
element.data_source.data.update(x=data[0], y=data[1])
|
|
|
|
|
|
+import math
|
|
|
|
|
|
class Arrow(PlotKind):
|
|
|
"""
|
|
|
- Draws a vector at the given position
|
|
|
+ Draws a "direction" arrow at a position, indicative of an angle.
|
|
|
+ This :class:`PlotKind` assumes that the y-component indicates the
|
|
|
+ angle.
|
|
|
|
|
|
Backend Information:
|
|
|
- **matplotlib:** :func:`matplotlib.axes.Axes.scatter`
|
|
|
- **bokeh:** Not available.
|
|
|
- **seaborn:** Not available.
|
|
|
"""
|
|
|
- def __init__(self, size, *args, **kwargs):
|
|
|
+ def __init__(self, size, position, *args, **kwargs):
|
|
|
PlotKind.__init__(self, *args, **kwargs)
|
|
|
- self.position = 0.0, 0.0
|
|
|
+ self.position = position
|
|
|
self.size = size
|
|
|
|
|
|
def create(self, figure):
|
|
|
- if self.is_backend("MPL"):
|
|
|
+ x, y = self.position
|
|
|
+ if self.is_backend("MPL", "SNS"):
|
|
|
# matplotlib: figure[1] is the axis
|
|
|
- x, y = self.position
|
|
|
- arrow = mplArrow(x, y, self.size, self.size, *self.args, **self.kwargs)
|
|
|
+ arrow = mplArrow(x, y, 0, 0, *self.args, **self.kwargs)
|
|
|
line = figure[1].add_patch(arrow)
|
|
|
line.set_zorder(20)
|
|
|
return line
|
|
|
- elif self.is_backend("BOKEH", "SNS"):
|
|
|
- raise NotImplementedError("This feature is not (yet) available for this backend.")
|
|
|
+ elif self.is_backend("BKH"):
|
|
|
+ arrow = bokeh.models.Arrow(x_start=x, y_start=y, x_end=x, y_end=y, **self.kwargs)
|
|
|
+ figure.add_layout(arrow)
|
|
|
+ return arrow
|
|
|
|
|
|
def update(self, element, *data):
|
|
|
heading = data[1]
|
|
|
- x = math.cos(heading[-1]) * self.size
|
|
|
- y = math.sin(heading[-1]) * self.size
|
|
|
+ dx = math.cos(heading[-1]) * self.size
|
|
|
+ dy = math.sin(heading[-1]) * self.size
|
|
|
+ x, y = self.position
|
|
|
|
|
|
- if self.is_backend("MPL"):
|
|
|
+ if self.is_backend("MPL", "SNS"):
|
|
|
ax = element.axes
|
|
|
element.remove()
|
|
|
- nx, ny = self.position
|
|
|
- arrow = mplArrow(nx, ny, x, y, *self.args, **self.kwargs)
|
|
|
+ arrow = mplArrow(x, y, dx, dy, *self.args, **self.kwargs)
|
|
|
line = ax.add_patch(arrow)
|
|
|
line.set_zorder(20)
|
|
|
return line
|
|
|
- elif self.is_backend("BOKEH", "SNS"):
|
|
|
- raise NotImplementedError("This feature is not (yet) available for this backend.")
|
|
|
+ elif self.is_backend("BKH"):
|
|
|
+ element.x_start = x
|
|
|
+ element.y_start = y
|
|
|
+ element.x_end = x + dx
|
|
|
+ element.y_end = y + dy
|
|
|
+ return element
|
|
|
|
|
|
|
|
|
class PlotManager:
|