{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from bokeh.plotting import figure, output_notebook, show\n",
    "from bokeh.models import ColumnDataSource, HoverTool, CustomJS"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "output_notebook()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# define some points and a little graph between them\n",
    "x = [2, 3, 5, 6, 8, 7]\n",
    "y = [6, 4, 3, 8, 7, 5]\n",
    "links = {\n",
    "    0: [1, 2],\n",
    "    1: [0, 3, 4],\n",
    "    2: [0, 5],\n",
    "    3: [1, 4],\n",
    "    4: [1, 3],\n",
    "    5: [2, 3, 4]\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "p = figure(width=400, height=400, tools=\"\", toolbar_location=None, title='Hover over points')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "source = ColumnDataSource({'x0': [], 'y0': [], 'x1': [], 'y1': []})\n",
    "sr = p.segment(x0='x0', y0='y0', x1='x1', y1='y1', color='olive', alpha=0.6, line_width=3, source=source, )\n",
    "cr = p.circle(x, y, color='olive', size=30, alpha=0.4, hover_color='olive', hover_alpha=1.0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Add a hover tool, that sets the link data for a hovered circle\n",
    "code = \"\"\"\n",
    "var links = %s;\n",
    "var data = {'x0': [], 'y0': [], 'x1': [], 'y1': []};\n",
    "var cdata = circle.data;\n",
    "var indices = cb_data.index['1d'].indices;\n",
    "for (i=0; i < indices.length; i++) {\n",
    "    ind0 = indices[i]\n",
    "    for (j=0; j < links[ind0].length; j++) {\n",
    "        ind1 = links[ind0][j];\n",
    "        data['x0'].push(cdata.x[ind0]);\n",
    "        data['y0'].push(cdata.y[ind0]);\n",
    "        data['x1'].push(cdata.x[ind1]);\n",
    "        data['y1'].push(cdata.y[ind1]);\n",
    "    }\n",
    "}\n",
    "segment.data = data;\n",
    "\"\"\" % links\n",
    "\n",
    "callback = CustomJS(args={'circle': cr.data_source, 'segment': sr.data_source}, code=code)\n",
    "p.add_tools(HoverTool(tooltips=None, callback=callback, renderers=[cr]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "show(p)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "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.4.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
