From 80d98e37586fc30caf35f53bf5d22da7e0ca7df0 Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Tue, 16 May 2017 11:42:37 +0100 Subject: [PATCH 1/3] Set notebook type when loading bokeh extension --- holoviews/plotting/bokeh/renderer.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/holoviews/plotting/bokeh/renderer.py b/holoviews/plotting/bokeh/renderer.py index 4a443ffa7f..87393a4959 100644 --- a/holoviews/plotting/bokeh/renderer.py +++ b/holoviews/plotting/bokeh/renderer.py @@ -19,7 +19,7 @@ from ..plot import GenericElementPlot from ..renderer import Renderer, MIME_TYPES from .widgets import BokehScrubberWidget, BokehSelectionWidget, BokehServerWidgets -from .util import compute_static_patch, serialize_json, attach_periodic +from .util import compute_static_patch, serialize_json, attach_periodic, bokeh_version @@ -217,4 +217,5 @@ def load_nb(cls, inline=True): """ Loads the bokeh notebook resources. """ - load_notebook(hide_banner=True, resources=INLINE if inline else CDN) + kwargs = {'notebook_type': 'jupyter'} if bokeh_version > '0.12.5' else {} + load_notebook(hide_banner=True, resources=INLINE if inline else CDN, **kwargs) From c121eca525629960df49f277f16a2d8ca7044083 Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Tue, 16 May 2017 11:43:27 +0100 Subject: [PATCH 2/3] Added doc argument to BokehRenderer.get_plot --- holoviews/plotting/bokeh/renderer.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/holoviews/plotting/bokeh/renderer.py b/holoviews/plotting/bokeh/renderer.py index 87393a4959..388428b9dd 100644 --- a/holoviews/plotting/bokeh/renderer.py +++ b/holoviews/plotting/bokeh/renderer.py @@ -84,10 +84,24 @@ def __call__(self, obj, fmt=None, doc=None): elif fmt == 'json': return self.diff(plot), info + + @bothmethod + def get_plot(self_or_cls, obj, doc=None, renderer=None): + """ + Given a HoloViews Viewable return a corresponding plot instance. + Allows supplying a document attach the plot to, useful when + combining the bokeh model with another plot. + """ + plot = super(BokehRenderer, self_or_cls).get_plot(obj, renderer) + if doc is not None: + plot.document = doc + return plot + + @bothmethod - def get_widget(self_or_cls, plot, widget_type, **kwargs): + def get_widget(self_or_cls, plot, widget_type, doc=None, **kwargs): if not isinstance(plot, Plot): - plot = self_or_cls.get_plot(plot) + plot = self_or_cls.get_plot(plot, doc) if self_or_cls.mode == 'server': return BokehServerWidgets(plot, renderer=self_or_cls.instance(), **kwargs) else: From 460b18ef6a879056175fccc40aafe49aaef74a57 Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Tue, 16 May 2017 11:44:06 +0100 Subject: [PATCH 3/3] Added options to BokehRenderer.app --- holoviews/plotting/bokeh/renderer.py | 44 ++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/holoviews/plotting/bokeh/renderer.py b/holoviews/plotting/bokeh/renderer.py index 388428b9dd..12f6439dcf 100644 --- a/holoviews/plotting/bokeh/renderer.py +++ b/holoviews/plotting/bokeh/renderer.py @@ -7,12 +7,13 @@ from bokeh.application import Application from bokeh.charts import Chart from bokeh.document import Document -from bokeh.embed import notebook_div -from bokeh.io import load_notebook, curdoc, show +from bokeh.embed import notebook_div, autoload_server +from bokeh.io import load_notebook, curdoc, show as bkshow from bokeh.models import (Row, Column, Plot, Model, ToolbarBox, WidgetBox, Div, DataTable, Tabs) from bokeh.plotting import Figure from bokeh.resources import CDN, INLINE +from bokeh.server.server import Server from ...core import Store, HoloMap from ..comms import JupyterComm, Comm @@ -109,25 +110,49 @@ def get_widget(self_or_cls, plot, widget_type, doc=None, **kwargs): @bothmethod - def app(self_or_cls, plot, notebook=False): + def app(self_or_cls, plot, show=False, new_window=False): """ Creates a bokeh app from a HoloViews object or plot. By default simply uses attaches plot to bokeh's curdoc and - returns the Document, if notebook option is supplied creates - an Application instance, displays it and returns it. + returns the Document, if show option is supplied creates + an Application instance and displays it either in a browser + window or inline if notebook extension has been loaded. + Using the new_window option the app may be displayed in a + new browser tab once the notebook extension has been loaded. """ renderer = self_or_cls.instance(mode='server') - if not notebook: + # If show=False and not in noteboook context return document + if not show and not self_or_cls.notebook_context: doc, _ = renderer(plot) return doc def modify_doc(doc): renderer(plot, doc=doc) - handler = FunctionHandler(modify_doc) app = Application(handler) - show(app) - return app + + if not show: + # If not showing and in notebook context return app + return app + elif self_or_cls.notebook_context and not new_window: + # If in notebook, show=True and no new window requested + # display app inline + return bkshow(app) + + # If app shown outside notebook or new_window requested + # start server and open in new browser tab + from tornado.ioloop import IOLoop + loop = IOLoop.current() + server = Server({'/': app}, port=0, loop=loop) + def show_callback(): + server.show('/') + server.io_loop.add_callback(show_callback) + server.start() + try: + loop.start() + except RuntimeError: + pass + return server def server_doc(self, plot, doc=None): @@ -170,6 +195,7 @@ def diff(self, plot, serialize=True): processed = self._apply_post_render_hooks(patch, plot, 'json') return serialize_json(processed) if serialize else processed + @classmethod def plot_options(cls, obj, percent_size): """