Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save ruoyu0088/2bf4f1e91cf6dd7a911e228ac402a541 to your computer and use it in GitHub Desktop.
Save ruoyu0088/2bf4f1e91cf6dd7a911e228ac402a541 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"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&nbsp;=&nbsp;'f3828bfb-badb-4613-abcf-d7204df7888b', <span id=\"4bbebcda-530c-4e06-82a7-54d3ebbd69e1\" style=\"cursor: pointer;\">&hellip;)</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&nbsp;=&nbsp;[],</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&nbsp;=&nbsp;{'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&nbsp;=&nbsp;{'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&nbsp;=&nbsp;[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&nbsp;=&nbsp;{'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&nbsp;=&nbsp;{'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&nbsp;=&nbsp;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&nbsp;=&nbsp;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&nbsp;=&nbsp;{},</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&nbsp;=&nbsp;{},</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&nbsp;=&nbsp;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&nbsp;=&nbsp;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&nbsp;=&nbsp;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&nbsp;=&nbsp;{},</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&nbsp;=&nbsp;{},</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">left&nbsp;=&nbsp;[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&nbsp;=&nbsp;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&nbsp;=&nbsp;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&nbsp;=&nbsp;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&nbsp;=&nbsp;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&nbsp;=&nbsp;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&nbsp;=&nbsp;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&nbsp;=&nbsp;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&nbsp;=&nbsp;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&nbsp;=&nbsp;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&nbsp;=&nbsp;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&nbsp;=&nbsp;{'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&nbsp;=&nbsp;'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&nbsp;=&nbsp;{'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&nbsp;=&nbsp;[],</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&nbsp;=&nbsp;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&nbsp;=&nbsp;'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&nbsp;=&nbsp;{'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&nbsp;=&nbsp;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&nbsp;=&nbsp;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&nbsp;=&nbsp;[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&nbsp;=&nbsp;[],</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&nbsp;=&nbsp;'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&nbsp;=&nbsp;[],</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">tags&nbsp;=&nbsp;[],</div></div><div class=\"af9b72c0-3512-40ef-b308-d8e37f575f01\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">title&nbsp;=&nbsp;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&nbsp;=&nbsp;'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&nbsp;=&nbsp;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&nbsp;=&nbsp;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&nbsp;=&nbsp;'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&nbsp;=&nbsp;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&nbsp;=&nbsp;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&nbsp;=&nbsp;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&nbsp;=&nbsp;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&nbsp;=&nbsp;'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&nbsp;=&nbsp;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&nbsp;=&nbsp;'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&nbsp;=&nbsp;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 ? \"&hellip;)\" : \"&lsaquo;&lsaquo;&lsaquo;\";\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