Created
May 16, 2017 22:51
-
-
Save ruoyu0088/2bf4f1e91cf6dd7a911e228ac402a541 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# 将Bokeh的图表嵌入到ipywidget控件中" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"本节介绍如何将Bokeh的图表嵌入到ipywidget的控件界面中,并实现Python和Javascript之间双向通信。" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 22, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"\n", | |
" <div class=\"bk-root\">\n", | |
" <a href=\"http://bokeh.pydata.org\" target=\"_blank\" class=\"bk-logo bk-logo-small bk-logo-notebook\"></a>\n", | |
" <span id=\"4eb5636d-2fb8-4448-8655-42657a987aef\">Loading BokehJS ...</span>\n", | |
" </div>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
}, | |
{ | |
"data": { | |
"application/javascript": [ | |
"\n", | |
"(function(global) {\n", | |
" function now() {\n", | |
" return new Date();\n", | |
" }\n", | |
"\n", | |
" var force = true;\n", | |
"\n", | |
" if (typeof (window._bokeh_onload_callbacks) === \"undefined\" || force === true) {\n", | |
" window._bokeh_onload_callbacks = [];\n", | |
" window._bokeh_is_loading = undefined;\n", | |
" }\n", | |
"\n", | |
"\n", | |
" \n", | |
" if (typeof (window._bokeh_timeout) === \"undefined\" || force === true) {\n", | |
" window._bokeh_timeout = Date.now() + 5000;\n", | |
" window._bokeh_failed_load = false;\n", | |
" }\n", | |
"\n", | |
" var NB_LOAD_WARNING = {'data': {'text/html':\n", | |
" \"<div style='background-color: #fdd'>\\n\"+\n", | |
" \"<p>\\n\"+\n", | |
" \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n", | |
" \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n", | |
" \"</p>\\n\"+\n", | |
" \"<ul>\\n\"+\n", | |
" \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n", | |
" \"<li>use INLINE resources instead, as so:</li>\\n\"+\n", | |
" \"</ul>\\n\"+\n", | |
" \"<code>\\n\"+\n", | |
" \"from bokeh.resources import INLINE\\n\"+\n", | |
" \"output_notebook(resources=INLINE)\\n\"+\n", | |
" \"</code>\\n\"+\n", | |
" \"</div>\"}};\n", | |
"\n", | |
" function display_loaded() {\n", | |
" if (window.Bokeh !== undefined) {\n", | |
" var el = document.getElementById(\"4eb5636d-2fb8-4448-8655-42657a987aef\");\n", | |
" el.textContent = \"BokehJS \" + Bokeh.version + \" successfully loaded.\";\n", | |
" } else if (Date.now() < window._bokeh_timeout) {\n", | |
" setTimeout(display_loaded, 100)\n", | |
" }\n", | |
" }\n", | |
"\n", | |
" function run_callbacks() {\n", | |
" window._bokeh_onload_callbacks.forEach(function(callback) { callback() });\n", | |
" delete window._bokeh_onload_callbacks\n", | |
" console.info(\"Bokeh: all callbacks have finished\");\n", | |
" }\n", | |
"\n", | |
" function load_libs(js_urls, callback) {\n", | |
" window._bokeh_onload_callbacks.push(callback);\n", | |
" if (window._bokeh_is_loading > 0) {\n", | |
" console.log(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n", | |
" return null;\n", | |
" }\n", | |
" if (js_urls == null || js_urls.length === 0) {\n", | |
" run_callbacks();\n", | |
" return null;\n", | |
" }\n", | |
" console.log(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n", | |
" window._bokeh_is_loading = js_urls.length;\n", | |
" for (var i = 0; i < js_urls.length; i++) {\n", | |
" var url = js_urls[i];\n", | |
" var s = document.createElement('script');\n", | |
" s.src = url;\n", | |
" s.async = false;\n", | |
" s.onreadystatechange = s.onload = function() {\n", | |
" window._bokeh_is_loading--;\n", | |
" if (window._bokeh_is_loading === 0) {\n", | |
" console.log(\"Bokeh: all BokehJS libraries loaded\");\n", | |
" run_callbacks()\n", | |
" }\n", | |
" };\n", | |
" s.onerror = function() {\n", | |
" console.warn(\"failed to load library \" + url);\n", | |
" };\n", | |
" console.log(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", | |
" document.getElementsByTagName(\"head\")[0].appendChild(s);\n", | |
" }\n", | |
" };var element = document.getElementById(\"4eb5636d-2fb8-4448-8655-42657a987aef\");\n", | |
" if (element == null) {\n", | |
" console.log(\"Bokeh: ERROR: autoload.js configured with elementid '4eb5636d-2fb8-4448-8655-42657a987aef' but no matching script tag was found. \")\n", | |
" return false;\n", | |
" }\n", | |
"\n", | |
" var js_urls = [\"./static/js/bokeh.min.js\", \"./static/js/bokeh-widgets.min.js\"];\n", | |
"\n", | |
" var inline_js = [\n", | |
" function(Bokeh) {\n", | |
" Bokeh.set_log_level(\"info\");\n", | |
" },\n", | |
" \n", | |
" function(Bokeh) {\n", | |
" \n", | |
" },\n", | |
" \n", | |
" function(Bokeh) {\n", | |
" \n", | |
" document.getElementById(\"4eb5636d-2fb8-4448-8655-42657a987aef\").textContent = \"BokehJS is loading...\";\n", | |
" },\n", | |
" function(Bokeh) {\n", | |
" console.log(\"Bokeh: injecting CSS: ./static/css/bokeh.min.css\");\n", | |
" Bokeh.embed.inject_css(\"./static/css/bokeh.min.css\");\n", | |
" console.log(\"Bokeh: injecting CSS: ./static/css/bokeh-widgets.min.css\");\n", | |
" Bokeh.embed.inject_css(\"./static/css/bokeh-widgets.min.css\");\n", | |
" }\n", | |
" ];\n", | |
"\n", | |
" function run_inline_js() {\n", | |
" \n", | |
" if ((window.Bokeh !== undefined) || (force === true)) {\n", | |
" for (var i = 0; i < inline_js.length; i++) {\n", | |
" inline_js[i](window.Bokeh);\n", | |
" }if (force === true) {\n", | |
" display_loaded();\n", | |
" }} else if (Date.now() < window._bokeh_timeout) {\n", | |
" setTimeout(run_inline_js, 100);\n", | |
" } else if (!window._bokeh_failed_load) {\n", | |
" console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n", | |
" window._bokeh_failed_load = true;\n", | |
" } else if (force !== true) {\n", | |
" var cell = $(document.getElementById(\"4eb5636d-2fb8-4448-8655-42657a987aef\")).parents('.cell').data().cell;\n", | |
" cell.output_area.append_execute_result(NB_LOAD_WARNING)\n", | |
" }\n", | |
"\n", | |
" }\n", | |
"\n", | |
" if (window._bokeh_is_loading === 0) {\n", | |
" console.log(\"Bokeh: BokehJS loaded, going straight to plotting\");\n", | |
" run_inline_js();\n", | |
" } else {\n", | |
" load_libs(js_urls, function() {\n", | |
" console.log(\"Bokeh: BokehJS plotting callback run at\", now());\n", | |
" run_inline_js();\n", | |
" });\n", | |
" }\n", | |
"}(this));" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"from bokehelp import output_notebook, show_figure\n", | |
"#from bokeh.io import output_notebook #如果希望从CDN载入bokeh.js,则取消该行注释\n", | |
"from bokeh.plotting import Figure\n", | |
"from bokeh.models import ColumnDataSource\n", | |
"\n", | |
"output_notebook()" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"使用`bokeh.embed.notebook_div()`将图表对象转换为HTML代码,然后将HTML代码用`ipywidgets.HTML`显示即可实现图表的嵌入。不过为了实现双向通信,还需要进一步的处理。\n", | |
"\n", | |
"下面的`BokehFigure`类从`ipywidgets.HTML`继承,其`value`属性即为图表对应的HTML代码。\n", | |
"\n", | |
"❶我们需要模拟`bokeh.io.show()`显示图表的功能,这样才能使用`push_notebook()`实现Python到Javascript的通信。本段代码仿照`bokeh.embed`中显示图表的程序。Python->Javascript的通信由`_CommsHandle`对象实现,由于该对象必须在图表显示之后运行,因此这里覆盖基类的`_ipython_display_`方法,在调用` super()._ipython_display_(**kwargs)`之后,❹创建通信用的`_CommsHandle`对象。调用Bokeh提供的`push_notebook()`函数更新图表时,将`Document`、`State`和`_CommsHandle`等对象作为参数传递给它即可实现被嵌入图表的更新。\n", | |
"\n", | |
"❷调用`notebook_div()`生成图表的HTML之后,添加实现Javascript->Python通信的代码。它为Javascript中的`Figure`对象添加`send_data()`方法。然后通过`comm_manager.register_target()`添加Python端的通信处理函数。当在Javascript中调用`Figure.send_data()`发送信息时,将调用`on_recv()`方法,在该方法中会调用用户提供的回调函数`callback`。" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 23, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"from bokeh.core.state import State\n", | |
"from bokeh.document import Document\n", | |
"from bokeh.io import _CommsHandle, push_notebook\n", | |
"from bokeh.embed import notebook_div\n", | |
"from bokeh.util.notebook import get_comms\n", | |
"from IPython import get_ipython\n", | |
"from ipywidgets import HTML\n", | |
"from jinja2 import Template\n", | |
"\n", | |
"JSCode = Template(\"\"\"\n", | |
"<script>\n", | |
"(function(){\n", | |
" var fig = Bokeh.index['{{fid}}'];\n", | |
" fig.model.send_data = function(data){\n", | |
" var comm = Jupyter.notebook.kernel.comm_manager.new_comm('{{fid}}', data);\n", | |
" comm.close();\n", | |
" };\n", | |
"})();\n", | |
"</script>\n", | |
"\"\"\")\n", | |
"\n", | |
"class BokehFigure(HTML):\n", | |
" def __init__(self, fig, callback=None, **kwargs):\n", | |
" super().__init__(**kwargs)\n", | |
" self.callback = callback\n", | |
"\n", | |
" #❶ 本段代码参考Bokeh中显示图表的程序\n", | |
" self.state = State()\n", | |
" self.doc = Document()\n", | |
" self.state._document = self.doc\n", | |
" self.state.output_notebook = True\n", | |
" self.fig = fig\n", | |
" self.doc.add_root(self.fig)\n", | |
" \n", | |
" #❷ 生成HTML代码,并添加实现Javascript->Python通信的代码\n", | |
" self.comms_target = self.fig._id\n", | |
" self.value = notebook_div(fig, self.comms_target) \n", | |
" self.value += JSCode.render(fid=self.fig._id)\n", | |
" comm_manager = get_ipython().kernel.comm_manager\n", | |
" comm_manager.register_target(self.fig._id, self.on_recv)\n", | |
" \n", | |
" self._handle = None\n", | |
" \n", | |
" def on_recv(self, comm, data):\n", | |
" if self.callback is not None:\n", | |
" self.callback(data[\"content\"][\"data\"]) \n", | |
" \n", | |
" @property\n", | |
" def handle(self): #❸\n", | |
" if self._handle is not None:\n", | |
" return self._handle\n", | |
" self._handle = _CommsHandle(get_comms(self.comms_target), \n", | |
" self.state.document, \n", | |
" self.state.document.to_json())\n", | |
" self.state.last_comms_handle = self._handle\n", | |
" return self._handle\n", | |
" \n", | |
" def __del__(self):\n", | |
" self.handle.comms.close()\n", | |
" \n", | |
" def _ipython_display_(self, **kwargs):\n", | |
" super()._ipython_display_(**kwargs)\n", | |
" _ = self.handle #❹\n", | |
" \n", | |
" def push_notebook(self):\n", | |
" push_notebook(self.doc, self.state, self.handle) #❺" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 24, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div style=\"display: table;\"><div style=\"display: table-row;\"><div style=\"display: table-cell;\"><b title=\"bokeh.plotting.figure.Figure\">Figure</b>(</div><div style=\"display: table-cell;\">id = 'f3828bfb-badb-4613-abcf-d7204df7888b', <span id=\"4bbebcda-530c-4e06-82a7-54d3ebbd69e1\" style=\"cursor: pointer;\">…)</span></div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">above = [],</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">background_fill_alpha = {'value': 1.0},</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">background_fill_color = {'value': '#ffffff'},</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">below = [LinearAxis(id='0a686c2b-051b-4aae-8032-ffe85535e145', ...)],</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">border_fill_alpha = {'value': 1.0},</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">border_fill_color = {'value': '#ffffff'},</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">css_classes = None,</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">disabled = False,</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">extra_x_ranges = {},</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">extra_y_ranges = {},</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">h_symmetry = True,</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">height = None,</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">hidpi = True,</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">js_event_callbacks = {},</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">js_property_callbacks = {},</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">left = [LinearAxis(id='32445e78-47c8-4155-a48e-34436560f5c7', ...)],</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">lod_factor = 10,</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">lod_interval = 300,</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">lod_threshold = 2000,</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">lod_timeout = 500,</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">min_border = 5,</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">min_border_bottom = None,</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">min_border_left = None,</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">min_border_right = None,</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">min_border_top = None,</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">name = None,</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">outline_line_alpha = {'value': 1.0},</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">outline_line_cap = 'butt',</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">outline_line_color = {'value': '#e5e5e5'},</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">outline_line_dash = [],</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">outline_line_dash_offset = 0,</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">outline_line_join = 'miter',</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">outline_line_width = {'value': 1},</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">plot_height = 600,</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">plot_width = 600,</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">renderers = [LinearAxis(id='0a686c2b-051b-4aae-8032-ffe85535e145', ...), Grid(id='03a92ebc-3859-472d-a09f-89e02d7bbf7b', ...), LinearAxis(id='32445e78-47c8-4155-a48e-34436560f5c7', ...), Grid(id='9484d9d9-b6e8-4ff7-b405-302818f996f3', ...), BoxAnnotation(id='f7622ce0-1383-4efd-a4e7-cd5224d74d2e', ...)],</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">right = [],</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">sizing_mode = 'fixed',</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">subscribed_events = [],</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">tags = [],</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">title = Title(id='e58eeadb-e596-43fd-81e0-3bcf3f40750b', ...),</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">title_location = 'above',</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">tool_events = ToolEvents(id='c6ed3b42-fb43-4128-acc8-47c6a30e12fd', ...),</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">toolbar = Toolbar(id='3eab735f-9b18-4cc3-beb4-ae18c2a3af30', ...),</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">toolbar_location = 'right',</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">toolbar_sticky = True,</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">v_symmetry = False,</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">webgl = False,</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">width = None,</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">x_mapper_type = 'auto',</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">x_range = Range1d(id='a1fe4407-fb72-4aea-995b-a104cd093118', ...),</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">y_mapper_type = 'auto',</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">y_range = DataRange1d(id='63475366-ae8a-4615-b3cb-17d819920692', ...))</div></div></div>\n", | |
"<script>\n", | |
"(function() {\n", | |
" var expanded = false;\n", | |
" var ellipsis = document.getElementById(\"4bbebcda-530c-4e06-82a7-54d3ebbd69e1\");\n", | |
" ellipsis.addEventListener(\"click\", function() {\n", | |
" var rows = document.getElementsByClassName(\"af9b72c0-3512-40ef-b308-d8e37f575f01\");\n", | |
" for (var i = 0; i < rows.length; i++) {\n", | |
" var el = rows[i];\n", | |
" el.style.display = expanded ? \"none\" : \"table-row\";\n", | |
" }\n", | |
" ellipsis.innerHTML = expanded ? \"…)\" : \"‹‹‹\";\n", | |
" expanded = !expanded;\n", | |
" });\n", | |
"})();\n", | |
"</script>\n" | |
], | |
"text/plain": [ | |
"Figure(id='f3828bfb-badb-4613-abcf-d7204df7888b', ...)" | |
] | |
}, | |
"execution_count": 24, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"Figure(x_range=[-2, 3])" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 25, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"import numpy as np\n", | |
"from bokeh.models import CustomJS\n", | |
"from ipywidgets import FloatSlider, VBox, HBox, Textarea\n", | |
"\n", | |
"N = 100\n", | |
"src_data = np.random.randn(N, 2)\n", | |
"r = 1.4\n", | |
"theta = np.linspace(0, 2*np.pi, N)\n", | |
"dst_data = np.c_[r * np.sin(2*theta), r * np.cos(theta)]\n", | |
"color = [\"#{:02x}{:02x}{:02x}\".format(*row) for row in np.random.randint(0, 200, (N, 3))]\n", | |
"\n", | |
"fig = Figure(tools=\"lasso_select\", x_range=[-3, 3], y_range=[-3, 3], \n", | |
" plot_width=350, plot_height=350)\n", | |
"source = ColumnDataSource(data={\"x\":src_data[:, 0], \"y\":dst_data[:, 1], \"color\":color})\n", | |
"source.callback = CustomJS(args=dict(fig=fig), code=\"\"\"\n", | |
" fig.send_data(cb_obj.get('selected')['1d'].indices);\n", | |
" \"\"\")\n", | |
"fig.circle(x=\"x\", y=\"y\", color=\"color\", size=10, source=source)\n", | |
"\n", | |
"selected_info = Textarea(width=300)\n", | |
"\n", | |
"def on_select(data):\n", | |
" selected_info.value = str(data)\n", | |
" \n", | |
"bokeh_fig = BokehFigure(fig, callback=on_select)\n", | |
"w_slider = FloatSlider(min=0, max=1, step=0.01, value=0, description=\"k:\", width=250)\n", | |
"\n", | |
"def f(evt):\n", | |
" k = evt[\"new\"]\n", | |
" new_data = (1 - k) * src_data + k * dst_data\n", | |
" source.data[\"x\"] = new_data[:, 0]\n", | |
" source.data[\"y\"] = new_data[:, 1]\n", | |
" bokeh_fig.push_notebook()\n", | |
"\n", | |
"w_slider.observe(f, names=[\"value\"])\n", | |
"box = HBox([selected_info, VBox([w_slider, bokeh_fig])])\n", | |
"box" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [] | |
} | |
], | |
"metadata": { | |
"anaconda-cloud": {}, | |
"kernelspec": { | |
"display_name": "Python [default]", | |
"language": "python", | |
"name": "python3" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 3 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython3", | |
"version": "3.5.2" | |
}, | |
"widgets": { | |
"state": { | |
"e31eb11da7d349eaad6662cf602cf5f0": { | |
"views": [ | |
{ | |
"cell_index": 6 | |
} | |
] | |
} | |
}, | |
"version": "1.2.0" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 1 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment