Skip to content

Commit

Permalink
Improved handling of boomeranging events in bokeh backend
Browse files Browse the repository at this point in the history
  • Loading branch information
philippjfr committed Mar 26, 2017
1 parent 16a6338 commit 2c37278
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 21 deletions.
16 changes: 6 additions & 10 deletions holoviews/plotting/bokeh/callbacks.py
Original file line number Diff line number Diff line change
Expand Up @@ -373,22 +373,18 @@ def trigger(self):
if attr_path[0] == 'cb_obj':
attr_path = self.models[0]
obj = self.plot_handles.get(attr_path[0])
attr_val = obj
if not obj:
raise Exception('Bokeh plot attribute %s could not be found' % path)
for p in attr_path[1:]:
if p == 'attributes':
continue
if isinstance(obj, dict):
obj = obj.get(p)
if isinstance(attr_val, dict):
attr_val = attr_val.get(p)
else:
obj = getattr(obj, p, None)
values[attr] = obj
values = self._process_msg(values)
if any(v is None for v in values.values()):
return
for stream in self.streams:
stream.update(trigger=False, **values)
Stream.trigger(self.streams)
attr_val = getattr(attr_val, p, None)
values[attr] = {'id': obj.ref['id'], 'value': attr_val}
self.on_msg(values)
self._event_queue = []


Expand Down
32 changes: 21 additions & 11 deletions holoviews/plotting/bokeh/element.py
Original file line number Diff line number Diff line change
Expand Up @@ -530,8 +530,10 @@ def _update_ranges(self, element, ranges):
xfactors, yfactors = None, None
if any(isinstance(ax_range, FactorRange) for ax_range in [x_range, y_range]):
xfactors, yfactors = self._get_factors(element)
self._update_range(x_range, l, r, xfactors, self.invert_xaxis, self._shared['x'])
self._update_range(y_range, b, t, yfactors, self.invert_yaxis, self._shared['y'])
if not self.model_changed(x_range):
self._update_range(x_range, l, r, xfactors, self.invert_xaxis, self._shared['x'])
if not self.model_changed(y_range):
self._update_range(y_range, b, t, yfactors, self.invert_yaxis, self._shared['y'])


def _update_range(self, axis_range, low, high, factors, invert, shared):
Expand Down Expand Up @@ -788,6 +790,21 @@ def update_frame(self, key, ranges=None, plot=None, element=None, empty=False):
self._execute_hooks(element)


def model_changed(self, model):
"""
Determines if the bokeh model was just changed on the frontend.
Useful to suppress boomeranging events, e.g. when the frontend
just sent an update to the x_range this should not trigger an
update on the backend.
"""
callbacks = [cb for cbs in self.traverse(lambda x: x.callbacks)
for cb in cbs]
stream_metadata = [stream._metadata for cb in callbacks
for stream in cb.streams if stream._metadata]
return any(md['id'] == model.ref['id'] for models in stream_metadata
for md in models.values())


@property
def current_handles(self):
"""
Expand Down Expand Up @@ -821,15 +838,8 @@ def current_handles(self):
if not self.apply_ranges:
rangex, rangey = False, False
elif isinstance(self.hmap, DynamicMap):
callbacks = [cb for cbs in self.traverse(lambda x: x.callbacks)
for cb in cbs]
stream_metadata = [stream._metadata for cb in callbacks
for stream in cb.streams if stream._metadata]
ranges = ['%s_range' % ax for ax in 'xy']
event_ids = [md[ax]['id'] for md in stream_metadata
for ax in ranges if ax in md]
rangex = plot.x_range.ref['id'] not in event_ids and framewise
rangey = plot.y_range.ref['id'] not in event_ids and framewise
rangex = not self.model_changed(plot.x_range) and framewise
rangey = not self.model_changed(plot.y_range) and framewise
elif self.framewise:
rangex, rangey = True, True
else:
Expand Down

0 comments on commit 2c37278

Please sign in to comment.