{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "from math import log, sqrt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "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": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "from bokeh.plotting import figure, show, output_notebook"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "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": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "drug_color = {\n",
    "    \"Penicillin\"   : \"#0d3362\",\n",
    "    \"Streptomycin\" : \"#c64737\",\n",
    "    \"Neomycin\"     : \"black\",\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "gram_color = {\n",
    "    \"positive\" : \"#aeaeb8\",\n",
    "    \"negative\" : \"#e69584\",\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "df = pd.read_csv(StringIO(antibiotics), skiprows=1, skipinitialspace=True, engine='python')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "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\n",
    "\n",
    "x = np.zeros(len(df))\n",
    "y = np.zeros(len(df))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "def rad(mic):\n",
    "    return a * np.sqrt(np.log(mic * 1E4)) + b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "output_notebook()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "p = figure(plot_width=width, plot_height=height, title=\"\",\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=\"#f0e1d2\", border_fill=\"#f0e1d2\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "p.line(x+1, y+1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "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(x, y, inner_radius, outer_radius, -big_angle+angles, angles, color=colors)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# small wedges\n",
    "p.annular_wedge(x, y, 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(x, y, 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(x, y, 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": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "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(x, y, radius=radii, fill_color=None, line_color=\"white\")\n",
    "p.text(x[:-1], 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": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# radial axes\n",
    "p.annular_wedge(x, y, inner_radius-10, outer_radius+10, \n",
    "                -big_angle+angles, -big_angle+angles, color=\"black\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "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": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "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": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "p.xgrid.grid_line_color = None\n",
    "p.ygrid.grid_line_color = None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "show(p)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "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.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
