Skip to content

Commit

Permalink
Factored out utility to update existing plot instances
Browse files Browse the repository at this point in the history
  • Loading branch information
philippjfr committed Feb 8, 2016
1 parent 2736821 commit 5f82daf
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 29 deletions.
25 changes: 2 additions & 23 deletions holoviews/plotting/bokeh/chart.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from ..util import compute_sizes, get_sideplot_ranges, match_spec
from .element import ElementPlot, line_properties, fill_properties
from .path import PathPlot, PolygonPlot
from .util import map_colors, get_cmap, mpl_to_bokeh
from .util import map_colors, get_cmap, mpl_to_bokeh, update_plot


class PointPlot(ElementPlot):
Expand Down Expand Up @@ -416,28 +416,7 @@ def update_frame(self, key, ranges=None, plot=None, element=None):
def _update_chart(self, key, element, ranges):
new_chart = self._init_chart(element, ranges)
old_chart = self.handles['plot']
old_renderers = old_chart.select(type=GlyphRenderer)
new_renderers = new_chart.select(type=GlyphRenderer)

old_chart.y_range.update(**new_chart.y_range.properties_with_values())
updated = []
for new_r in new_renderers:
for old_r in old_renderers:
if type(old_r.glyph) == type(new_r.glyph):
old_renderers.pop(old_renderers.index(old_r))
new_props = new_r.properties_with_values()
source = new_props.pop('data_source')
old_r.glyph.update(**new_r.glyph.properties_with_values())
old_r.update(**new_props)
old_r.data_source.data.update(source.data)
updated.append(old_r)
break

for old_r in old_renderers:
if old_r not in updated:
emptied = {k: [] for k in old_r.data_source.data}
old_r.data_source.data.update(emptied)

update_plot(old_chart, new_chart)
properties = self._plot_properties(key, old_chart, element)
old_chart.update(**properties)

Expand Down
39 changes: 33 additions & 6 deletions holoviews/plotting/bokeh/element.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from .callbacks import Callbacks
from .plot import BokehPlot
from .renderer import bokeh_lt_011
from .util import mpl_to_bokeh, convert_datetime
from .util import mpl_to_bokeh, convert_datetime, update_plot


# Define shared style properties for bokeh plots
Expand Down Expand Up @@ -538,17 +538,44 @@ def __init__(self, element, plot=None, **params):

def initialize_plot(self, ranges=None, plot=None, plots=None):
self.mplplot.initialize_plot(ranges)
plot = mpl.to_bokeh(self.mplplot.state)

plot = plot if plot else self.handles.get('plot')
new_plot = mpl.to_bokeh(self.mplplot.state)
if plot:
update_plot(plot, new_plot)
else:
plot = new_plot

self.handles['plot'] = plot
if not self.overlaid:
self._update_plot(self.keys[-1], plot, self.hmap.last)
return plot


def update_frame(self, key, ranges=None):
if key in self.hmap:
self.mplplot.update_frame(key, ranges)
self.handles['plot'] = mpl.to_bokeh(self.mplplot.state)
def _update_plot(self, key, plot, element=None):
"""
Updates plot parameters on every frame
"""
plot.set(**self._plot_properties(key, plot, element))
props = {axis: self._axis_properties(axis, key, plot, element)
for axis in ['x', 'y']}


def update_frame(self, key, ranges=None, plot=None, element=None, empty=False):
self.mplplot.update_frame(key, ranges)

reused = isinstance(self.hmap, DynamicMap) and self.overlaid
if not reused and element is None:
element = self._get_frame(key)
else:
self.current_key = key
self.current_frame = element

plot = mpl.to_bokeh(self.mplplot.state)
update_plot(self.handles['plot'], plot)
if not self.overlaid:
self._update_plot(key, self.handles['plot'], element)


class BokehMPLRawWrapper(BokehMPLWrapper):
"""
Expand Down
32 changes: 32 additions & 0 deletions holoviews/plotting/bokeh/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
from bokeh.core.enums import Palette
from bokeh.models.plots import Plot
bokeh_lt_011 = False

from bokeh.models import GlyphRenderer
from bokeh.plotting import Figure

# Conversion between matplotlib and bokeh markers
Expand Down Expand Up @@ -177,3 +179,33 @@ def hsv_to_rgb(hsv):
rgb = clist[order[i], np.arange(np.prod(shape))[:,None]]

return rgb.reshape(shape+(3,))


def update_plot(old, new):
"""
Updates an existing plot or figure with a new plot,
useful for bokeh charts and mpl conversions, which do
not allow updating an existing plot easily.
"""
old_renderers = old.select(type=GlyphRenderer)
new_renderers = new.select(type=GlyphRenderer)

old.x_range.update(**new.x_range.properties_with_values())
old.y_range.update(**new.y_range.properties_with_values())
updated = []
for new_r in new_renderers:
for old_r in old_renderers:
if type(old_r.glyph) == type(new_r.glyph):
old_renderers.pop(old_renderers.index(old_r))
new_props = new_r.properties_with_values()
source = new_props.pop('data_source')
old_r.glyph.update(**new_r.glyph.properties_with_values())
old_r.update(**new_props)
old_r.data_source.data.update(source.data)
updated.append(old_r)
break

for old_r in old_renderers:
if old_r not in updated:
emptied = {k: [] for k in old_r.data_source.data}
old_r.data_source.data.update(emptied)

0 comments on commit 5f82daf

Please sign in to comment.