{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/html": [ " \n", " \n", " \n", " \n", "
\n", " \n", " BokehJS successfully loaded.\n", "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import pandas as pd\n", "from bokeh.plotting import show, output_notebook\n", "output_notebook()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Here we build the visualization up to the point where we need the server" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Get the data" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
namexsyscountry_idwat_valuesan_valuewat_colorsan_coloryear
0Algeria[11.9995056495, 8.57289310063, 5.67756595218, ...[23.4716684026, 21.5656607122, 19.6012069768, ...36--#CCCCCC#CCCCCC1990
1Angola[16.3265283546, 16.5731799659, 16.8601908708, ...[-5.87747039147, -6.62264454512, -7.2222978654...18--#CCCCCC#CCCCCC1990
2Benin[2.69170169436, 1.86524051271, 1.61895063641, ...[6.25881724693, 6.14215770103, 6.83203807213, ...4857.15.0#62abc7#d455001990
3Botswana[25.6491634458, 25.8503914731, 26.1647908872, ...[-18.5360258928, -18.7144129371, -19.293085625...4291.938.6#3fc0f0#eb941f1990
4Burkina Faso[-2.82749630371, -3.51189897299, -3.9804491845...[9.64246084232, 9.90032623946, 9.86234406172, ...143.67.7#6aa6bd#d455001990
\n", "
" ], "text/plain": [ " name xs \\\n", "0 Algeria [11.9995056495, 8.57289310063, 5.67756595218, ... \n", "1 Angola [16.3265283546, 16.5731799659, 16.8601908708, ... \n", "2 Benin [2.69170169436, 1.86524051271, 1.61895063641, ... \n", "3 Botswana [25.6491634458, 25.8503914731, 26.1647908872, ... \n", "4 Burkina Faso [-2.82749630371, -3.51189897299, -3.9804491845... \n", "\n", " ys country_id wat_value \\\n", "0 [23.4716684026, 21.5656607122, 19.6012069768, ... 36 - \n", "1 [-5.87747039147, -6.62264454512, -7.2222978654... 18 - \n", "2 [6.25881724693, 6.14215770103, 6.83203807213, ... 48 57.1 \n", "3 [-18.5360258928, -18.7144129371, -19.293085625... 42 91.9 \n", "4 [9.64246084232, 9.90032623946, 9.86234406172, ... 1 43.6 \n", "\n", " san_value wat_color san_color year \n", "0 - #CCCCCC #CCCCCC 1990 \n", "1 - #CCCCCC #CCCCCC 1990 \n", "2 5.0 #62abc7 #d45500 1990 \n", "3 38.6 #3fc0f0 #eb941f 1990 \n", "4 7.7 #6aa6bd #d45500 1990 " ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# You can see how this was made in the map_data.py under washmap/washmap\n", "\n", "data = pd.read_hdf('static_map_data.hdf', 'df') # note we have to use hdf, not csv for the xs & ys lists\n", "data.head()" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "### Make a plot" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false, "slideshow": { "slide_type": "-" } }, "outputs": [], "source": [ "from bokeh.models import Plot, Range1d\n", "from chart_constants import PLOT_FORMATS\n", "\n", "x_range = Range1d(0, 250)\n", "y_range = Range1d(0, 120)\n", "\n", "text_box = Plot(\n", " x_range=x_range, y_range=y_range, title=\"\", \n", " plot_width=250, plot_height=120, min_border=0, \n", " **PLOT_FORMATS\n", ") " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "### Add some simple glyphs" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from bokeh.models import Text, Rect, Triangle\n", "from chart_constants import FONT_PROPS_SM, BLUE, ORANGE, ORANGE_SHADOW\n", "\n", "text_box.add_glyph(\n", " Text(x=95, y=20, text=['of people had'], **FONT_PROPS_SM)\n", ")\n", "text_box.add_glyph(\n", " Text(x=95, y=5, text=['access in'], **FONT_PROPS_SM)\n", ")\n", "text_box.add_glyph(\n", " Rect(x=75, y=55, width=200, height=5, \n", " fill_color=BLUE, line_color=None)\n", ")\n", "text_box.add_glyph(\n", " Triangle(x=150, y=65, size=25, \n", " fill_color=ORANGE_SHADOW, line_color=None)\n", ")\n", "text_box.add_glyph(\n", " Rect(x=200, y=60, width=100, height=40, \n", " fill_color=ORANGE, line_color=None)\n", ")\n", "show(text_box)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "## Making a map" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false, "slideshow": { "slide_type": "-" } }, "outputs": [], "source": [ "def setup_map_plot():\n", " x_start, x_end = (-20, 60)\n", " y_start, y_end = (-40, 40)\n", " aspect_ratio = (x_end - x_start) / (y_end - y_start)\n", " x_range = Range1d(x_start, x_end)\n", " y_range = Range1d(y_start, y_end)\n", " plot_height = 400 \n", " return Plot(x_range=x_range, y_range=y_range, title=\"\", plot_width=int(plot_height * aspect_ratio), plot_height=plot_height, **PLOT_FORMATS)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "### Make a source" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
xsyswat_color
0[11.9995056495, 8.57289310063, 5.67756595218, ...[23.4716684026, 21.5656607122, 19.6012069768, ...#CCCCCC
1[16.3265283546, 16.5731799659, 16.8601908708, ...[-5.87747039147, -6.62264454512, -7.2222978654...#CCCCCC
2[2.69170169436, 1.86524051271, 1.61895063641, ...[6.25881724693, 6.14215770103, 6.83203807213, ...#62abc7
\n", "
" ], "text/plain": [ " xs \\\n", "0 [11.9995056495, 8.57289310063, 5.67756595218, ... \n", "1 [16.3265283546, 16.5731799659, 16.8601908708, ... \n", "2 [2.69170169436, 1.86524051271, 1.61895063641, ... \n", "\n", " ys wat_color \n", "0 [23.4716684026, 21.5656607122, 19.6012069768, ... #CCCCCC \n", "1 [-5.87747039147, -6.62264454512, -7.2222978654... #CCCCCC \n", "2 [6.25881724693, 6.14215770103, 6.83203807213, ... #62abc7 " ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from bokeh.models import ColumnDataSource\n", "\n", "source = ColumnDataSource(data)\n", "data[['xs', 'ys', 'wat_color']].head(3)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "### Add glyph linked to data" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from bokeh.models import Patches\n", "\n", "countries = Patches(\n", " xs='xs', \n", " ys='ys',\n", " fill_color='wat_color', \n", " line_color=\"#FFFFFF\", \n", ")\n", "map_box = setup_map_plot()\n", "map_box.add_glyph(ColumnDataSource(data), countries)\n", "show(map_box)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Add the tap tool" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from bokeh.models import TapTool\n", "\n", "map_box = setup_map_plot()\n", "map_box.add_glyph(ColumnDataSource(data), countries)\n", "map_box.add_tools(TapTool())\n", "show(map_box)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Make selection style correctly" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "selected_countries = Patches(\n", " xs='xs', \n", " ys='ys',\n", " fill_color='wat_color', \n", " line_color=ORANGE, \n", " line_width=5,\n", ")\n", "\n", "map_box = setup_map_plot()\n", "map_box.add_glyph(ColumnDataSource(data), countries, selection_glyph=selected_countries, nonselection_glyph=countries)\n", "map_box.add_tools(TapTool())\n", "show(map_box)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Try playing with setting up new sources\n", "\n", "You may want to try specifying the same source for each of the above three plots." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Add hover tool\n", "\n", "Note that in the washmap app we add extra html and then style it" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from bokeh.models import HoverTool\n", "\n", "map_box = setup_map_plot()\n", "map_box.add_glyph(ColumnDataSource(data), countries, selection_glyph=selected_countries, nonselection_glyph=countries)\n", "map_box.add_tools(TapTool())\n", "map_box.add_tools(HoverTool(tooltips=\"@year
@name
@wat_value %\"))\n", "show(map_box)" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def make_map(source, fill_color_string='wat_color', value_string='wat_value'):\n", " \n", " countries = Patches(\n", " xs='xs', \n", " ys='ys',\n", " fill_color=fill_color_string, \n", " line_color=\"#FFFFFF\", \n", " )\n", " selected_countries = Patches(\n", " xs='xs', \n", " ys='ys',\n", " fill_color=fill_color_string, \n", " line_color=ORANGE, \n", " line_width=5,\n", " )\n", " map_box = setup_map_plot()\n", " map_box.add_glyph(source, countries, selection_glyph=selected_countries, nonselection_glyph=countries)\n", " map_box.add_tools(TapTool())\n", " tooltips = \"@year
@name
@\" + value_string + \" %\"\n", " map_box.add_tools(HoverTool(tooltips=tooltips))\n", " return map_box\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Make the text box and have it accept a source" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from bokeh.models import Text\n", "from chart_constants import FONT_PROPS_SM, FONT_PROPS_MD, FONT_PROPS_LG\n", "\n", "def construct_text_box(source, value_string, color_string, bar_color): \n", " # Plot and axes \n", " xdr = Range1d(0, 220) \n", " ydr = Range1d(0, 120) \n", " \n", " plot = Plot( \n", " x_range=xdr, \n", " y_range=ydr, \n", " title=\"\", \n", " plot_width=250, \n", " plot_height=120, \n", " min_border=0, \n", " **PLOT_FORMATS \n", " ) \n", " # Add the writing \n", " country = Text(x=5, y=50, text='name', **FONT_PROPS_MD) \n", " percent = Text(x=15, y=10, text=value_string, text_color=color_string, **FONT_PROPS_LG) # nopep8\n", " percent_sign = Text(x=69, y=10, text=['%'], text_color=color_string, **FONT_PROPS_LG) # nopep8\n", " line_one = Text(x=90, y=28, text=['of people had'], **FONT_PROPS_SM) \n", " line_two_p1 = Text(x=90, y=14, text=['access in'], **FONT_PROPS_SM) \n", " line_two_p2 = Text(x=136, y=14, text='year', **FONT_PROPS_SM) \n", " plot.add_glyph(source, Text(), selection_glyph=country) \n", " plot.add_glyph(source, Text(), selection_glyph=percent) \n", " plot.add_glyph(source, Text(), selection_glyph=percent_sign) \n", " plot.add_glyph(line_one) \n", " plot.add_glyph(line_two_p1) \n", " plot.add_glyph(source, Text(), selection_glyph=line_two_p2) \n", " \n", " # Add the orange box with year \n", " shadow = Triangle(x=150, y=109, size=25, fill_color=ORANGE_SHADOW, line_color=None) # nopep8\n", " plot.add_glyph(shadow) \n", " # Add the blue bar \n", " rect = Rect(x=75, y=99, width=150, height=5, fill_color=bar_color, line_color=None) # nopep8\n", " plot.add_glyph(rect) \n", " box = Rect(x=200, y=100, width=100, height=40, fill_color=ORANGE, line_color=None) # nopep8\n", " plot.add_glyph(box) \n", " year = Text(x=160, y=85, text='year', text_font_size='18pt', text_color=\"#FFFFF\", text_font_style=\"bold\") # nopep8\n", " plot.add_glyph(source, Text(), selection_glyph=year) \n", " \n", " return plot \n", "\n", "show(construct_text_box(source, 'wat_value', 'wat_color', BLUE))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Construct map and text box with same source\n", "\n", "If you click on a country it will update the text" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from bokeh.plotting import hplot, vplot\n", "\n", "source = ColumnDataSource(data)\n", "\n", "map_plot = make_map(source)\n", "text_box = construct_text_box(source, 'wat_value', 'wat_color', BLUE)\n", "\n", "show(hplot(vplot(map_plot), vplot(text_box)))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Use widgets to make water & sanitation" ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from bokeh.models.widgets import Tabs, Panel\n", "from chart_constants import GREEN\n", "\n", "# Select a country by default\n", "source = ColumnDataSource(data)\n", "source.selected = [30]\n", "\n", "water_plot = make_map(source, 'wat_color', 'wat_value')\n", "water_text = construct_text_box(source, 'wat_value', 'wat_color', BLUE)\n", "sanitation_plot = make_map(source, 'san_color', 'san_value')\n", "sanitation_text = construct_text_box(source, 'san_value', 'san_color', GREEN)\n", "\n", "\n", "tabs = Tabs(tabs=[\n", " Panel(title=\"Water\", child=hplot(vplot(water_plot), vplot(water_text))),\n", " Panel(title=\"Sanitation\", child=hplot(vplot(sanitation_plot), vplot(sanitation_text)))\n", " ])\n", "\n", "show(vplot(tabs))" ] } ], "metadata": { "kernelspec": { "display_name": "Django Shell-Plus", "language": "python", "name": "django_extensions" }, "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.9" } }, "nbformat": 4, "nbformat_minor": 0 }