Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bokeh server support #959

Merged
merged 30 commits into from Apr 7, 2017

Conversation

Projects
None yet
3 participants
@philippjfr
Copy link
Contributor

philippjfr commented Oct 31, 2016

Adds support for deploying any holoviews object as a bokeh server app.

  • BokehRenderer initializes server document
  • Initial support for handling stream events

To do:

  • Bokeh widget implementation to support DynamicMaps and HoloMaps with standard streams
  • Ensure that bokeh stream callbacks relying on cb_data and cb_obj work correctly.
  • Add example apps.

Optional/Future:

  • Provide easy way to tie a stream to any bokeh widget.
  • Support bokeh widgets in a notebook context.

Example app:

import numpy as np
import holoviews as hv
import holoviews.plotting.bokeh
from holoviews.operation.datashader import datashade

hv.Store.current_backend = 'bokeh'
renderer = hv.Store.renderers['bokeh'].instance(mode='server', holomap='server')
points = hv.HoloMap({i: hv.Points(np.random.multivariate_normal((0,0), [[0.1, 0.1], [0.1, 1.0]], (1000000,))) for i in range(10)})
datashaded = datashade(points, x_sampling=0.01, y_sampling=0.01)
doc, _ = renderer(datashaded)
doc.title = 'HoloViews Datashade'

hv_datashade_server

@philippjfr philippjfr added the WIP label Oct 31, 2016

@philippjfr philippjfr changed the title Bokeh server Bokeh server support Oct 31, 2016

@philippjfr philippjfr force-pushed the bokeh_server branch from 6cba793 to 2d80908 Nov 1, 2016

@philippjfr philippjfr added this to the Major feature request milestone Nov 16, 2016

@philippjfr philippjfr force-pushed the bokeh_server branch from 2d80908 to c3151cb Feb 3, 2017

@jlstevens

This comment has been minimized.

Copy link
Contributor

jlstevens commented Feb 3, 2017

Nice to have the examples!

That said, I feel they belong in contrib which is an entire repo dedicated to various examples. I would put them in the scripts directory here.

@philippjfr

This comment has been minimized.

Copy link
Contributor Author

philippjfr commented Feb 3, 2017

I do like the idea of contrib, but until it's been integrated into our doc building process and referenced throughout our documentation it just seems like no one will ever find it.

Edit: I do think it's the right place for these examples.

@jlstevens

This comment has been minimized.

Copy link
Contributor

jlstevens commented Feb 3, 2017

Given that we want to split out the bokeh backend eventually and this is definitely bokeh related, it should be in plotting.bokeh.examples if you don't want it in contrib.

@philippjfr

This comment has been minimized.

Copy link
Contributor Author

philippjfr commented Feb 3, 2017

it should be in plotting.bokeh.examples if you don't want it in contrib.

I did think contrib was the right place, but plotting.bokeh.examples might actually be even better if we are going to split it out.

@jlstevens

This comment has been minimized.

Copy link
Contributor

jlstevens commented Feb 3, 2017

I think it would be nice to keep all the examples together in contrib as it would show the breadth of what you can do with HoloViews. There is no restriction in contrib on backends or any other libraries necessary to make the examples work.

For this reason, I think we should move these examples to contrib right now - the bokeh backend repo could always link to the contrib examples to ensure people can discover them.

@philippjfr

This comment has been minimized.

Copy link
Contributor Author

philippjfr commented Mar 26, 2017

@jlstevens, @jbednar I've rebased this PR with the latest events PR and it's working as I want it to. The question is now about scope, I'll happily move the current examples to contrib, but my main question is about bokeh widgets. As of right now this PR ships with a small class that emulates our regular Dimension based widgets, and you can easily connect streams to other widgets and use the regular bokeh API to compose your new set of widgets into a layout with the plot(s).

Should we ship a basic widget class which generates widgets for HoloMap/DynamicMap key dimensions? You can see what that looks like in the gif example above. The implementation is fairly straightforward (~130 LOC) and means you can directly deploy standard HoloMaps/DynamicMaps you used and defined in a notebook without manually having to hook up widgets for key dimensions.

@jbednar

This comment has been minimized.

Copy link
Contributor

jbednar commented Mar 26, 2017

That all sounds good, but is there a reason not to just use Bokeh widgets all the time when we are using the Bokeh backend, even in the notebook? That seems like the way to have seamless interoperability with bokeh in its various possible usages.

@philippjfr

This comment has been minimized.

Copy link
Contributor Author

philippjfr commented Mar 26, 2017

If we had already done the widget refactor and implemented a general widget/comm manager as we are planning to do I'd say yes. However for the time being I'd have to come up with some ad hoc solution which I'm strongly against. So my answer is that once we have that we can easily retrofit this widget implementation to support it.

In the long run we should find an easy and general way to map both dimensions and streams to specific widgets.

@philippjfr

This comment has been minimized.

Copy link
Contributor Author

philippjfr commented Mar 26, 2017

Waiting on bokeh/bokeh#6062 so that the cb_obj can be handled the same for the js_on_event and on_event cases.

I've also implemented an event queue on the python end which works fairly well. Once the PR has been merged I'll have to extend that implementation to handle different event types as I did on the JS end.

@philippjfr philippjfr force-pushed the bokeh_server branch from 8ad43db to 0f4e00f Mar 26, 2017

@philippjfr philippjfr force-pushed the bokeh_server branch from 9f9bf0d to 833fd87 Apr 6, 2017

@philippjfr philippjfr added the ready label Apr 6, 2017

@philippjfr

This comment has been minimized.

Copy link
Contributor Author

philippjfr commented Apr 6, 2017

@jlstevens This is now ready for review. All streams now work for both bokeh server and in the notebook. I'm happy to move the example apps elsewhere though.

@philippjfr philippjfr force-pushed the bokeh_server branch from 833fd87 to cc7a700 Apr 6, 2017

@philippjfr philippjfr force-pushed the bokeh_server branch from fba7bb4 to 3342b0a Apr 6, 2017

@philippjfr philippjfr force-pushed the bokeh_server branch from 4b63765 to 171e9ca Apr 6, 2017

if self.plot.renderer.mode == 'default':
self.attach_callbacks()
self.state = self.init_layout()
self._event_queue = []

This comment has been minimized.

@jlstevens

jlstevens Apr 7, 2017

Contributor

I would still rename this from _event_queue to just queue.

This comment has been minimized.

@jlstevens

jlstevens Apr 7, 2017

Contributor

Ah, this is for the widgets now.. so it might be ok.

This comment has been minimized.

@philippjfr

philippjfr Apr 7, 2017

Author Contributor

Although maybe better for consistency? I'll rename.

This comment has been minimized.

@jlstevens

jlstevens Apr 7, 2017

Contributor

This is in widgets now so my original comment was addressed. Might be worth renaming here too - up to you.

Philipp Rudiger Philipp Rudiger
def _init_plot_handles(self):
"""
Find all requested plotting handles and cache them along
with the IDs of the models callbacks will be attached to.

This comment has been minimized.

@jlstevens

jlstevens Apr 7, 2017

Contributor

Either an an extra word here or words missing. Either '... along with the IDs the model callbacks will be attached to' or '...along with the IDs of the model callbacks that they will be attached to'.

This comment has been minimized.

@philippjfr

philippjfr Apr 7, 2017

Author Contributor

Neither, it's missing a the:

along with the IDs of the models the callbacks will be attached to.

This comment has been minimized.

@jlstevens

jlstevens Apr 7, 2017

Contributor

That works too. I knew something was wrong!

def process_on_change(self):
if not self._queue:
return
self._queue = []

This comment has been minimized.

@jlstevens

jlstevens Apr 7, 2017

Contributor

How come the _queue isn't used for process_on_change?

This comment has been minimized.

@philippjfr

philippjfr Apr 7, 2017

Author Contributor

Because process_on_change just looks up the model values directly, that avoids having separate callbacks for each model change, which would be required otherwise.

the data sent by the callback before it is passed to the streams.
"""

def initialize(self):

This comment has been minimized.

@jlstevens

jlstevens Apr 7, 2017

Contributor

Much better! :-)


mode = param.ObjectSelector(default='default',
objects=['default', 'server'], doc="""
Whether to render the DynamicMap in regular or server mode. """)

This comment has been minimized.

@jlstevens

jlstevens Apr 7, 2017

Contributor

Is it only rendering DynamicMaps? Might want a bit more to say what server mode is about ...

This comment has been minimized.

@philippjfr

philippjfr Apr 7, 2017

Author Contributor

Hmm, not sure why I wrote that. It handles anything.



@classmethod
def create_widget(self, dim, holomap=None):

This comment has been minimized.

@jlstevens

jlstevens Apr 7, 2017

Contributor

Much nicer as a classmethod! Good for testing...

@jlstevens

This comment has been minimized.

Copy link
Contributor

jlstevens commented Apr 7, 2017

Fantastic!

Other than one docstring fix I am now very happy with this PR. The functionality is great and the code is now structured in a much more sensible way.

I'll merge once that is done.

@jlstevens

This comment has been minimized.

Copy link
Contributor

jlstevens commented Apr 7, 2017

All done! Merging.

@jlstevens jlstevens merged commit 3503bb0 into master Apr 7, 2017

1 check was pending

continuous-integration/travis-ci/pr The Travis CI build is in progress
Details

@philippjfr philippjfr deleted the bokeh_server branch Apr 11, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.