{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", " \n", " Loading BokehJS ...\n", "
" ] }, "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", " \"
\\n\"+\n", " \"

\\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", " \"

\\n\"+\n", " \"\\n\"+\n", " \"\\n\"+\n", " \"from bokeh.resources import INLINE\\n\"+\n", " \"output_notebook(resources=INLINE)\\n\"+\n", " \"\\n\"+\n", " \"
\"}};\n", "\n", " function display_loaded() {\n", " if (window.Bokeh !== undefined) {\n", " document.getElementById(\"ac54ac7b-4b9c-45dc-a1c0-f2992219ab7d\").textContent = \"BokehJS 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(\"ac54ac7b-4b9c-45dc-a1c0-f2992219ab7d\");\n", " if (element == null) {\n", " console.log(\"Bokeh: ERROR: autoload.js configured with elementid 'ac54ac7b-4b9c-45dc-a1c0-f2992219ab7d' but no matching script tag was found. \")\n", " return false;\n", " }\n", "\n", " var js_urls = [\"https://cdn.pydata.org/bokeh/release/bokeh-0.12.4.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.12.4.min.js\"];\n", "\n", " var inline_js = [\n", " function(Bokeh) {\n", " Bokeh.set_log_level(\"info\");\n", " },\n", " \n", " function(Bokeh) {\n", " \n", " document.getElementById(\"ac54ac7b-4b9c-45dc-a1c0-f2992219ab7d\").textContent = \"BokehJS is loading...\";\n", " },\n", " function(Bokeh) {\n", " console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-0.12.4.min.css\");\n", " Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-0.12.4.min.css\");\n", " console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.12.4.min.css\");\n", " Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.12.4.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(\"ac54ac7b-4b9c-45dc-a1c0-f2992219ab7d\")).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" }, { "data": { "text/html": [ "\n", "\n", "
\n", "
\n", "
\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Author : Dheepak Krishnamurthy\n", "# License : BSD 3 Clause\n", "# Title : Custom HoverTool for linked hover tooltips\n", "# Based on example from Bokeh Docs\n", "\n", "from bokeh.io import output_notebook, show\n", "from bokeh.layouts import gridplot\n", "from bokeh.models import ColumnDataSource\n", "from bokeh.plotting import figure\n", "from bokeh.models import HoverTool, CustomJS\n", "\n", "output_notebook()\n", "\n", "JS_CODE = \"\"\"\n", "import {HoverToolView, HoverTool} from \"models/tools/inspectors/hover_tool\"\n", "import * as hittest from \"core/hittest\"\n", "\n", "export class CustomHoverToolView extends HoverToolView\n", " bind_bokeh_events: () ->\n", " super()\n", " for r in @model.computed_renderers\n", " @listenTo(r.data_source, 'cross-link', @_cross_link)\n", "\n", " _cross_link: (indices, geometry, tool) -> \n", " # Probably not necessary\n", " if ( @.model.id != tool.id ) \n", " return\n", " \n", " result = hittest.create_hit_test_result()\n", " result['1d'].indices = indices\n", " \n", " r = @model.computed_renderers[0] \n", " ds = r.data_source\n", " @._update(result, @, @plot_view.renderer_views[r.id], ds, {geometry})\n", " \n", "export class CustomHoverTool extends HoverTool\n", " default_view: CustomHoverToolView\n", " type: \"CustomHoverTool\"\n", " tool_name: \"CustomHover\"\n", " icon: \"bk-tool-icon-hover\"\n", "\"\"\"\n", "\n", "class CustomHoverTool(HoverTool):\n", " __implementation__ = JS_CODE\n", "\n", "x = list(range(0, 10))\n", "y0 = [abs(xx) for xx in x]\n", "y1 = y0\n", "\n", "# create a column data source for the plots to share\n", "source = ColumnDataSource(data=dict(x=x, y0=y0, y1=y1))\n", "\n", "TOOLS = \"box_select,lasso_select,help\"\n", "\n", "# create a new plot and add a renderer\n", "left = figure(tools=TOOLS, width=300, height=300, title=None)\n", "left.circle('x', 'y0', source=source, radius=.25)\n", "\n", "# create another new plot and add a renderer\n", "right = figure(tools=TOOLS, width=300, height=300, title=None)\n", "right.circle('x', 'y1', source=source, radius=.25)\n", "\n", "h1 = CustomHoverTool(tooltips='''
x: @x
y: @y0
''')\n", "h2 = CustomHoverTool()\n", "\n", "h2.callback = CustomJS(args=dict(hover=h1, source=source), code='''\n", "\n", "var indices = cb_data.index['1d'].indices;\n", "source.trigger('cross-link', indices, cb_data.geometry, hover)\n", "\n", "''')\n", "\n", "left.add_tools(h1)\n", "right.add_tools(h2)\n", "\n", "p = gridplot([[left, right]])\n", "\n", "show(p)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.12" } }, "nbformat": 4, "nbformat_minor": 1 }