{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from math import log, sqrt" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import numpy as np\n", "import pandas as pd\n", "from six.moves import cStringIO as StringIO" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from bokeh.plotting import figure, output_notebook, show" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [], "source": [ "antibiotics = \"\"\"\n", "bacteria, penicillin, streptomycin, neomycin, gram\n", "Mycobacterium tuberculosis, 800, 5, 2, negative\n", "Salmonella schottmuelleri, 10, 0.8, 0.09, negative\n", "Proteus vulgaris, 3, 0.1, 0.1, negative\n", "Klebsiella pneumoniae, 850, 1.2, 1, negative\n", "Brucella abortus, 1, 2, 0.02, negative\n", "Pseudomonas aeruginosa, 850, 2, 0.4, negative\n", "Escherichia coli, 100, 0.4, 0.1, negative\n", "Salmonella (Eberthella) typhosa, 1, 0.4, 0.008, negative\n", "Aerobacter aerogenes, 870, 1, 1.6, negative\n", "Brucella antracis, 0.001, 0.01, 0.007, positive\n", "Streptococcus fecalis, 1, 1, 0.1, positive\n", "Staphylococcus aureus, 0.03, 0.03, 0.001, positive\n", "Staphylococcus albus, 0.007, 0.1, 0.001, positive\n", "Streptococcus hemolyticus, 0.001, 14, 10, positive\n", "Streptococcus viridans, 0.005, 10, 40, positive\n", "Diplococcus pneumoniae, 0.005, 11, 10, positive\n", "\"\"\"" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [], "source": [ "drug_color = {\n", " \"Penicillin\" : \"#0d3362\",\n", " \"Streptomycin\" : \"#c64737\",\n", " \"Neomycin\" : \"black\",\n", "}" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [], "source": [ "gram_color = {\n", " \"positive\" : \"#aeaeb8\",\n", " \"negative\" : \"#e69584\",\n", "}" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [], "source": [ "df = pd.read_csv(StringIO(antibiotics), skiprows=1, skipinitialspace=True, engine='python')" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [], "source": [ "width = 800\n", "height = 800\n", "inner_radius = 90\n", "outer_radius = 300 - 10\n", "\n", "minr = sqrt(log(.001 * 1E4))\n", "maxr = sqrt(log(1000 * 1E4))\n", "a = (outer_radius - inner_radius) / (minr - maxr)\n", "b = inner_radius - a * maxr\n", "\n", "big_angle = 2.0 * np.pi / (len(df) + 1)\n", "small_angle = big_angle / 7" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def rad(mic):\n", " return a * np.sqrt(np.log(mic * 1E4)) + b" ] }, { "cell_type": "code", "execution_count": 10, "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", " if (typeof (window._bokeh_onload_callbacks) === \"undefined\") {\n", " window._bokeh_onload_callbacks = [];\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", " };\n", "\n", " var js_urls = ['https://cdn.pydata.org/bokeh/release/bokeh-0.12.0.min.js', 'https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.12.0.min.js', 'https://cdn.pydata.org/bokeh/release/bokeh-compiler-0.12.0.min.js'];\n", "\n", " var inline_js = [\n", " function(Bokeh) {\n", " Bokeh.set_log_level(\"info\");\n", " },\n", " \n", " function(Bokeh) {\n", " Bokeh.$(\"#683105a2-c802-4202-b9f4-8665efa77840\").text(\"BokehJS successfully loaded\");\n", " },\n", " function(Bokeh) {\n", " console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-0.12.0.min.css\");\n", " Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-0.12.0.min.css\");\n", " console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.12.0.min.css\");\n", " Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.12.0.min.css\");\n", " }\n", " ];\n", "\n", " function run_inline_js() {\n", " for (var i = 0; i < inline_js.length; i++) {\n", " inline_js[i](window.Bokeh);\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": [ "output_notebook()" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [], "source": [ "p = figure(plot_width=width, plot_height=height, toolbar_sticky=False,\n", " x_axis_type=None, y_axis_type=None,\n", " x_range=(-420, 420), y_range=(-420, 420),\n", " min_border=0, outline_line_color=\"black\",\n", " background_fill_color=\"#f0e1d2\", border_fill_color=\"#f0e1d2\")" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# annular wedges\n", "angles = np.pi/2 - big_angle/2 - df.index.to_series()*big_angle\n", "colors = [gram_color[gram] for gram in df.gram]\n", "p.annular_wedge(0, 0, inner_radius, outer_radius, -big_angle+angles, angles, color=colors)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# small wedges\n", "p.annular_wedge(0, 0, inner_radius, rad(df.penicillin), -big_angle+angles + 5*small_angle, \n", " -big_angle+angles+6*small_angle, color=drug_color['Penicillin'])\n", "p.annular_wedge(0, 0, inner_radius, rad(df.streptomycin), -big_angle+angles + 3*small_angle, \n", " -big_angle+angles+4*small_angle, color=drug_color['Streptomycin'])\n", "p.annular_wedge(0, 0, inner_radius, rad(df.neomycin), -big_angle+angles + 1*small_angle, \n", " -big_angle+angles+2*small_angle, color=drug_color['Neomycin'])" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# circular axes and lables\n", "labels = np.power(10.0, np.arange(-3, 4))\n", "radii = a * np.sqrt(np.log(labels * 1E4)) + b\n", "p.circle(0, 0, radius=radii, fill_color=None, line_color=\"white\")\n", "p.text(0, radii[:-1], [str(r) for r in labels[:-1]], \n", " text_font_size=\"8pt\", text_align=\"center\", text_baseline=\"middle\")" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# radial axes\n", "p.annular_wedge(0, 0, inner_radius-10, outer_radius+10, \n", " -big_angle+angles, -big_angle+angles, color=\"black\")" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# bacteria labels\n", "xr = radii[0]*np.cos(np.array(-big_angle/2 + angles))\n", "yr = radii[0]*np.sin(np.array(-big_angle/2 + angles))\n", "label_angle=np.array(-big_angle/2+angles)\n", "label_angle[label_angle < -np.pi/2] += np.pi # easier to read labels on the left side\n", "p.text(xr, yr, df.bacteria, angle=label_angle, text_font_size=\"9pt\", text_align=\"center\", text_baseline=\"middle\")" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# OK, these hand drawn legends are pretty clunky, will be improved in future release\n", "p.circle([-40, -40], [-370, -390], color=list(gram_color.values()), radius=5)\n", "p.text([-30, -30], [-370, -390], text=[\"Gram-\" + x for x in gram_color.keys()], \n", " text_font_size=\"7pt\", text_align=\"left\", text_baseline=\"middle\")\n", "\n", "p.rect([-40, -40, -40], [18, 0, -18], width=30, height=13, color=list(drug_color.values()))\n", "p.text([-15, -15, -15], [18, 0, -18], text=list(drug_color.keys()),\n", " text_font_size=\"9pt\", text_align=\"left\", text_baseline=\"middle\")" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": false }, "outputs": [], "source": [ "p.xgrid.grid_line_color = None\n", "p.ygrid.grid_line_color = None" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "
\n", "
\n", "
\n", "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "

<Bokeh Notebook handle for In[19]>

" ], "text/plain": [ "" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "show(p)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "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.5.1" } }, "nbformat": 4, "nbformat_minor": 0 }