{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-10-13T18:33:03.847543Z",
     "start_time": "2019-10-13T18:33:02.917045Z"
    }
   },
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "import pandas as pd\n",
    "\n",
    "from mapboxgl.utils import create_color_stops, df_to_geojson\n",
    "from mapboxgl.viz import CircleViz"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-10-13T18:34:51.321063Z",
     "start_time": "2019-10-13T18:34:51.276476Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Avg Total Payments</th>\n",
       "      <th>Avg Covered Charges</th>\n",
       "      <th>Total Discharges</th>\n",
       "      <th>Avg Medicare Payments</th>\n",
       "      <th>admin1_id</th>\n",
       "      <th>Provider Id</th>\n",
       "      <th>admin2_id</th>\n",
       "      <th>lon</th>\n",
       "      <th>lat</th>\n",
       "      <th>date</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>8749.025109</td>\n",
       "      <td>35247.02815</td>\n",
       "      <td>58.750000</td>\n",
       "      <td>7678.214348</td>\n",
       "      <td>USA101</td>\n",
       "      <td>10001</td>\n",
       "      <td>USA201069</td>\n",
       "      <td>-85.362856</td>\n",
       "      <td>31.216215</td>\n",
       "      <td>1/1/14 12:00 AM</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>6812.131224</td>\n",
       "      <td>16451.09204</td>\n",
       "      <td>28.959184</td>\n",
       "      <td>5793.631429</td>\n",
       "      <td>USA101</td>\n",
       "      <td>10005</td>\n",
       "      <td>USA201119</td>\n",
       "      <td>-88.142797</td>\n",
       "      <td>32.452976</td>\n",
       "      <td>1/2/14 12:00 AM</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>8197.237907</td>\n",
       "      <td>36942.35744</td>\n",
       "      <td>45.360465</td>\n",
       "      <td>7145.959535</td>\n",
       "      <td>USA101</td>\n",
       "      <td>10006</td>\n",
       "      <td>USA201077</td>\n",
       "      <td>-87.682872</td>\n",
       "      <td>34.794052</td>\n",
       "      <td>1/3/14 12:00 AM</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>4860.829091</td>\n",
       "      <td>12079.53682</td>\n",
       "      <td>27.409091</td>\n",
       "      <td>4047.025455</td>\n",
       "      <td>USA101</td>\n",
       "      <td>10007</td>\n",
       "      <td>USA201039</td>\n",
       "      <td>-86.254597</td>\n",
       "      <td>31.291993</td>\n",
       "      <td>1/4/14 12:00 AM</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>5898.136667</td>\n",
       "      <td>16148.75222</td>\n",
       "      <td>17.888889</td>\n",
       "      <td>4963.547778</td>\n",
       "      <td>USA101</td>\n",
       "      <td>10008</td>\n",
       "      <td>USA201041</td>\n",
       "      <td>-86.265102</td>\n",
       "      <td>31.693554</td>\n",
       "      <td>1/5/14 12:00 AM</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   Avg Total Payments  Avg Covered Charges  Total Discharges  \\\n",
       "0         8749.025109          35247.02815         58.750000   \n",
       "1         6812.131224          16451.09204         28.959184   \n",
       "2         8197.237907          36942.35744         45.360465   \n",
       "3         4860.829091          12079.53682         27.409091   \n",
       "4         5898.136667          16148.75222         17.888889   \n",
       "\n",
       "   Avg Medicare Payments admin1_id  Provider Id  admin2_id        lon  \\\n",
       "0            7678.214348    USA101        10001  USA201069 -85.362856   \n",
       "1            5793.631429    USA101        10005  USA201119 -88.142797   \n",
       "2            7145.959535    USA101        10006  USA201077 -87.682872   \n",
       "3            4047.025455    USA101        10007  USA201039 -86.254597   \n",
       "4            4963.547778    USA101        10008  USA201041 -86.265102   \n",
       "\n",
       "         lat             date  \n",
       "0  31.216215  1/1/14 12:00 AM  \n",
       "1  32.452976  1/2/14 12:00 AM  \n",
       "2  34.794052  1/3/14 12:00 AM  \n",
       "3  31.291993  1/4/14 12:00 AM  \n",
       "4  31.693554  1/5/14 12:00 AM  "
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data_url='/pi/ai/map/points.csv'\n",
    "df = pd.read_csv(data_url)\n",
    "df.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-10-13T18:41:13.351226Z",
     "start_time": "2019-10-13T18:41:13.346470Z"
    }
   },
   "outputs": [],
   "source": [
    "token='pk.eyJ1Ijoic2FtbGV0IiwiYSI6ImNpeXgyM3llZTAwMnAycXJ4ajZ0bHZkYXYifQ.X1Pa-iyXQ3Y4BxcUZNC2MA'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-10-13T18:41:19.564460Z",
     "start_time": "2019-10-13T18:41:17.900692Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<iframe id=\"map\", srcdoc=\"<!DOCTYPE html>\n",
       "<html>\n",
       "<head>\n",
       "<title>mapboxgl-jupyter viz</title>\n",
       "<meta charset='UTF-8' />\n",
       "<meta name='viewport'\n",
       "      content='initial-scale=1,maximum-scale=1,user-scalable=no' />\n",
       "<script type='text/javascript'\n",
       "        src='https://api.tiles.mapbox.com/mapbox-gl-js/v1.0.0/mapbox-gl.js'></script>\n",
       "<link type='text/css'\n",
       "      href='https://api.tiles.mapbox.com/mapbox-gl-js/v1.0.0/mapbox-gl.css' \n",
       "      rel='stylesheet' />\n",
       "\n",
       "<style type='text/css'>\n",
       "    body { margin:0; padding:0; }\n",
       "    .map { position: absolute; top:0; bottom:0; width:100%; }\n",
       "    .legend {\n",
       "        background-color: white;\n",
       "        color: #6e6e6e;\n",
       "        border-radius: 3px;\n",
       "        bottom: 10px;\n",
       "        box-shadow: 0 1px 2px rgba(0, 0, 0, 0.10);\n",
       "        font: 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif;\n",
       "        padding: 0;\n",
       "        position: absolute;\n",
       "        right: 10px;\n",
       "        z-index: 1;\n",
       "        min-width: 100px;\n",
       "    }\n",
       "   .legend.horizontal {bottom: 10px; text-align: left;}\n",
       "\n",
       "    /* legend header */\n",
       "    .legend .legend-header { border-radius: 3px 3px 0 0; background: white; }\n",
       "    .legend .legend-title {\n",
       "        padding: 6px 12px 6px 12px;\n",
       "        text-shadow: 0 0 2px white;\n",
       "        text-transform: capitalize;\n",
       "        text-align: center;\n",
       "        font-weight: bold !important;\n",
       "        font-size: 14px;\n",
       "        font: 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif;\n",
       "        max-width: 160px;\n",
       "    }\n",
       "    .legend-title {padding: 6px 12px 6px 12px; text-shadow: 0 0 2px #FFF; text-transform: capitalize; text-align: center; max-width: 160px; font-size: 0.9em; font-weight: bold;}\n",
       "    .legend.horizontal .legend-title {text-align: left;}\n",
       "\n",
       "    /* legend items */\n",
       "    .legend-content {margin: 6px 12px 6px 12px; overflow: hidden; padding: 0; float: left; list-style: none; font-size: 0.8em;}\n",
       "    .legend.vertical .legend-item {white-space: nowrap;}\n",
       "    .legend-value {display: inline-block; line-height: 18px; vertical-align: top;}\n",
       "    .legend.horizontal ul.legend-content li.legend-item .legend-value,\n",
       "    .legend.horizontal ul.legend-content li.legend-item {display: inline-block; float: left; width: 30px; margin-bottom: 0; text-align: center; min-height: 30px;}\n",
       "\n",
       "    /* legend key styles */\n",
       "    .legend-key {display: inline-block; height: 10px;}\n",
       "    .legend-key.default, .legend-key.square {border-radius: 0;}\n",
       "    .legend-key.circle {border-radius: 50%;}\n",
       "    .legend-key.rounded-square {border-radius: 20%;}\n",
       "    .legend.vertical .legend-key {width: 10px; margin-right: 5px; margin-left: 1px;}\n",
       "    .legend.horizontal .legend-key {width: 30px; margin-right: 0; margin-top: 1px; float: left;}\n",
       "    .legend.horizontal .legend-key.square, .legend.horizontal .legend-key.rounded-square, .legend.horizontal .legend-key.circle {margin-left: 10px; width: 10px;}\n",
       "    .legend.horizontal .legend-key.line {margin-left: 5px;}\n",
       "    .legend.horizontal .legend-key.line, .legend.vertical .legend-key.line {border-radius: 10%; width: 20px; height: 3px; margin-bottom: 2px;}\n",
       "\n",
       "    /* gradient bar alignment */\n",
       "    .gradient-bar {margin: 6px 12px 6px 12px;}\n",
       "    .legend.horizontal .gradient-bar {width: 88%; height: 10px;}\n",
       "    .legend.vertical .gradient-bar {width: 10px; min-height: 50px; position: absolute; bottom: 4px;}\n",
       "\n",
       "    /* contiguous vertical bars (discrete) */\n",
       "    .legend.vertical.contig .legend-key {height: 15px; width: 10px;}\n",
       "    .legend.vertical.contig li.legend-item {height: 15px;}\n",
       "    .legend.vertical.contig {padding-bottom: 6px;}\n",
       "\n",
       "    /* vertical radius legend */\n",
       "    .legend.horizontal.legend-variable-radius ul.legend-content li.legend-item .legend-value,\n",
       "    .legend.horizontal.legend-variable-radius ul.legend-content li.legend-item {width: 30px; min-height: 20px;}\n",
       "\n",
       "    /* scale annotation */\n",
       "    .mapboxgl-ctrl.mapboxgl-ctrl-scale { border-color: #6e6e6e; \n",
       "                                         background-color: white; \n",
       "                                         color: #131516; }\n",
       "</style>\n",
       "\n",
       "\n",
       "<style>\n",
       "    .gradient-bar.bordered, .legend-key.bordered { border: solid grey 0.1px; }\n",
       "</style>\n",
       "\n",
       "\n",
       "</head>\n",
       "<body>\n",
       "\n",
       "<div id='map' class='map'></div>\n",
       "\n",
       "<script type='text/javascript'>\n",
       "\n",
       "var legendHeader;\n",
       "\n",
       "function calcColorLegend(myColorStops, title) {\n",
       "    // create legend\n",
       "    var legend = document.createElement('div'),\n",
       "        legendContainer = document.getElementsByClassName('mapboxgl-ctrl-bottom-right')[0];\n",
       "\n",
       "    if ('circle' === 'contiguous-bar') {\n",
       "        legend.className = 'legend vertical contig';\n",
       "    }\n",
       "    else {\n",
       "        legend.className = 'legend vertical';\n",
       "    }\n",
       "    legend.id = 'legend-0';\n",
       "    document.body.appendChild(legend);\n",
       "    // add legend header and content elements\n",
       "    var mytitle = document.createElement('div'),\n",
       "        legendContent = document.createElement('ul');\n",
       "    legendHeader = document.createElement('div');\n",
       "    mytitle.textContent = title;\n",
       "    mytitle.className = 'legend-title'\n",
       "    legendHeader.className = 'legend-header'\n",
       "    legendContent.className = 'legend-content'\n",
       "    legendHeader.appendChild(mytitle);\n",
       "    legend.appendChild(legendHeader);\n",
       "    legend.appendChild(legendContent);\n",
       "    if (false === true) {\n",
       "        var gradientText = 'linear-gradient(to right, ',\n",
       "            gradient = document.createElement('div');\n",
       "        gradient.className = 'gradient-bar';\n",
       "        legend.appendChild(gradient);\n",
       "    }\n",
       "    // calculate a legend entries on a Mapbox GL Style Spec property function stops array\n",
       "    for (p = 0; p < myColorStops.length; p++) {\n",
       "        if (!!document.getElementById('legend-color-points-value-' + p)) {\n",
       "            // update the legend if it already exists\n",
       "            document.getElementById('legend-color-points-value-' + p).textContent = myColorStops[p][0];\n",
       "            document.getElementById('legend-color-points-id-' + p).style.backgroundColor = myColorStops[p][1];\n",
       "        }\n",
       "        else {\n",
       "            // create the legend if it doesn't yet exist\n",
       "            var item = document.createElement('li');\n",
       "            item.className = 'legend-item';\n",
       "            var key = document.createElement('span');\n",
       "            key.className = 'legend-key circle';\n",
       "            key.id = 'legend-color-points-id-' + p;\n",
       "            key.style.backgroundColor = myColorStops[p][1];\n",
       "            var value = document.createElement('span');\n",
       "            value.className = 'legend-value';\n",
       "            value.id = 'legend-color-points-value-' + p;\n",
       "            item.appendChild(key);\n",
       "            item.appendChild(value);\n",
       "            legendContent.appendChild(item);\n",
       "            \n",
       "            data = document.getElementById('legend-color-points-value-' + p)\n",
       "            // round number values in legend if precision defined\n",
       "            if ((typeof(myColorStops[p][0]) == 'number') && (typeof(null) == 'number')) {\n",
       "                data.textContent = myColorStops[p][0].toFixed(null);\n",
       "            }\n",
       "            else {\n",
       "                data.textContent = myColorStops[p][0];\n",
       "            }\n",
       "            // add color stop to gradient list\n",
       "            if (false === true) {\n",
       "                if (p < myColorStops.length - 1) {\n",
       "                    gradientText = gradientText + myColorStops[p][1] + ', ';\n",
       "                }\n",
       "                else {\n",
       "                    gradientText = gradientText + myColorStops[p][1] + ')';\n",
       "                }\n",
       "                if ('vertical' === 'vertical') {\n",
       "                    gradientText = gradientText.replace('to right', 'to bottom');\n",
       "                }\n",
       "            }\n",
       "        }\n",
       "    }\n",
       "    if (false === true) {\n",
       "        // convert to gradient scale appearance\n",
       "        gradient.style.background = gradientText;\n",
       "        // hide legend keys generated above\n",
       "        var keys = document.getElementsByClassName('legend-key');\n",
       "        for (var i=0; i < keys.length; i++) {\n",
       "            keys[i].style.visibility = 'hidden';\n",
       "        }\n",
       "        if ('vertical' === 'vertical') {\n",
       "            gradient.style.height = (legendContent.offsetHeight - 6) + 'px';\n",
       "        }\n",
       "    }\n",
       "    // add class for styling bordered legend keys\n",
       "    if (true) {\n",
       "        var keys = document.getElementsByClassName('legend-key');\n",
       "        for (var i=0; i < keys.length; i++) {\n",
       "            if (keys[i]) {\n",
       "                keys[i].classList.add('bordered');\n",
       "            }\n",
       "        }\n",
       "        var gradientBars = document.getElementsByClassName('gradient-bar');\n",
       "        for (var i=0; i < keys.length; i++) {\n",
       "            if (gradientBars[i]) {\n",
       "                gradientBars[i].classList.add('bordered');\n",
       "            }\n",
       "        }\n",
       "    }\n",
       "    // update right-margin for compact Mapbox attribution based on calculated legend width\n",
       "    updateAttribMargin(legend);\n",
       "    updateLegendMargin(legend);\n",
       "}\n",
       "\n",
       "\n",
       "function calcRadiusLegend(myRadiusStops, title, color) {\n",
       "\n",
       "    // maximum legend item height\n",
       "    var maxLegendItemHeight = 2 * myRadiusStops[myRadiusStops.length - 1][1];\n",
       "\n",
       "    // create legend\n",
       "    var legend = document.createElement('div');\n",
       "    legend.className = 'legend vertical legend-variable-radius';\n",
       "\n",
       "    legend.id = 'legend-1';\n",
       "    document.body.appendChild(legend);\n",
       "\n",
       "    // add legend header and content elements\n",
       "    var mytitle = document.createElement('div'),\n",
       "        legendContent = document.createElement('ul');\n",
       "    legendHeader = document.createElement('div');\n",
       "    mytitle.textContent = title;\n",
       "    mytitle.className = 'legend-title'\n",
       "    legendHeader.className = 'legend-header'\n",
       "    legendContent.className = 'legend-content'\n",
       "    legendHeader.appendChild(mytitle);\n",
       "    legend.appendChild(legendHeader);\n",
       "    legend.appendChild(legendContent);\n",
       "\n",
       "    // calculate a legend entries on a Mapbox GL Style Spec property function stops array\n",
       "    for (p = 0; p < myRadiusStops.length; p++) {\n",
       "        if (!!document.getElementById('legend-radius-points-value-' + p)) {\n",
       "            //update the legend if it already exists\n",
       "            document.getElementById('legend-radius-points-value-' + p).textContent = myRadiusStops[p][0];\n",
       "            document.getElementById('legend-radius-points-id-' + p).style.backgroundColor = color;\n",
       "        }\n",
       "        else {\n",
       "            // create the legend if it doesn't yet exist\n",
       "            var item = document.createElement('li');\n",
       "            item.className = 'legend-item';\n",
       "            item.height = '' + maxLegendItemHeight + 'px';\n",
       "\n",
       "            var key = document.createElement('span');\n",
       "            key.className = 'legend-key circle';\n",
       "            key.id = 'legend-radius-points-id-' + p;\n",
       "            key.style.backgroundColor = color;   \n",
       "\n",
       "            key.style.width = '' + myRadiusStops[p][1] * 2 + 'px';\n",
       "            key.style.height = '' + myRadiusStops[p][1] * 2 + 'px';\n",
       "\n",
       "            keyVerticalMargin = (maxLegendItemHeight - myRadiusStops[p][1] * 2) * 0.5;\n",
       "            key.style.marginTop = '' + keyVerticalMargin + 'px';\n",
       "            key.style.marginBottom = '' + keyVerticalMargin + 'px';\n",
       "\n",
       "            var value = document.createElement('span');\n",
       "            value.className = 'legend-value';\n",
       "            value.id = 'legend-radius-points-value-' + p;\n",
       "\n",
       "            item.appendChild(key);\n",
       "            item.appendChild(value);\n",
       "            legendContent.appendChild(item);\n",
       "            \n",
       "            data = document.getElementById('legend-radius-points-value-' + p)\n",
       "\n",
       "            // round number values in legend if precision defined\n",
       "            if ((typeof(myRadiusStops[p][0]) == 'number') && (typeof(null) == 'number')) {\n",
       "                data.textContent = myRadiusStops[p][0].toFixed(null);\n",
       "            }\n",
       "            else {\n",
       "                data.textContent = myRadiusStops[p][0];\n",
       "            }\n",
       "        }\n",
       "    }\n",
       "\n",
       "    // add class for styling bordered legend keys\n",
       "    if (true) {\n",
       "        var keys = document.getElementsByClassName('legend-key');\n",
       "        for (var i=0; i < keys.length; i++) {\n",
       "            if (keys[i]) {\n",
       "                keys[i].classList.add('bordered');\n",
       "            }\n",
       "        }\n",
       "    }\n",
       "\n",
       "    // update right-margin for compact Mapbox attribution based on calculated legend width\n",
       "    updateAttribMargin(legend);\n",
       "    updateLegendMargin(legend);\n",
       "\n",
       "}\n",
       "\n",
       "\n",
       "function updateAttribMargin(legend) {\n",
       "\n",
       "    // default margin is based on calculated legend width\n",
       "    var attribMargin = legend.offsetWidth + 15;\n",
       "    \n",
       "    // if horizontal legend layout (multiple legends are stacked vertically)\n",
       "    if ('vertical' === 'horizontal') {\n",
       "        document.getElementsByClassName('mapboxgl-ctrl-attrib')[0].style.marginRight = (attribMargin).toString() + 'px';\n",
       "    }\n",
       "    // vertical legend layout means multiple legends are side-by-side\n",
       "    else if ('vertical' === 'vertical') {\n",
       "        var currentMargin = Number(document.getElementsByClassName('mapboxgl-ctrl-attrib')[0].style.marginRight.replace('px', ''));\n",
       "        document.getElementsByClassName('mapboxgl-ctrl-attrib')[0].style.marginRight = (attribMargin + currentMargin).toString() + 'px';\n",
       "    }\n",
       "}\n",
       "\n",
       "\n",
       "function updateLegendMargin(legend) {\n",
       "\n",
       "    var verticalLegends = document.getElementsByClassName('legend vertical'),\n",
       "        horizontalLegends = document.getElementsByClassName('legend horizontal');\n",
       "\n",
       "    if (verticalLegends.length > 1) {\n",
       "        for (i = 1; i < verticalLegends.length; i++) {\n",
       "            verticalLegends[i].style.marginRight = (legend.offsetWidth - 5).toString() + 'px';\n",
       "            var legend = verticalLegends[i];\n",
       "        }\n",
       "    }\n",
       "    else if (horizontalLegends.length > 1) {\n",
       "        for (i = 1; i < horizontalLegends.length; i++) {\n",
       "            horizontalLegends[i].style.marginBottom = (legend.offsetHeight + 15).toString() + 'px';\n",
       "            var legend = horizontalLegends[i];\n",
       "        }\n",
       "    }\n",
       "}\n",
       "\n",
       "\n",
       "function generateInterpolateExpression(propertyValue, stops) {\n",
       "    var expression;\n",
       "    if (propertyValue == 'zoom') {\n",
       "        expression = ['interpolate', ['exponential', 1.2], ['zoom']]\n",
       "    }\n",
       "    else if (propertyValue == 'heatmap-density') {\n",
       "        expression = ['interpolate', ['linear'], ['heatmap-density']]\n",
       "    }\n",
       "    else {\n",
       "        expression = ['interpolate', ['linear'], ['get', propertyValue]]\n",
       "    }\n",
       "\n",
       "    for (var i=0; i<stops.length; i++) {\n",
       "        expression.push(stops[i][0], stops[i][1])\n",
       "    }\n",
       "    return expression\n",
       "}\n",
       "\n",
       "\n",
       "function generateMatchExpression(propertyValue, stops, defaultValue) {\n",
       "    var expression;\n",
       "    expression = ['match', ['get', propertyValue]]\n",
       "    for (var i=0; i<stops.length; i++) {\n",
       "        expression.push(stops[i][0], stops[i][1])\n",
       "    }\n",
       "    expression.push(defaultValue)\n",
       "    \n",
       "    return expression\n",
       "}\n",
       "\n",
       "\n",
       "function generatePropertyExpression(expressionType, propertyValue, stops, defaultValue) {\n",
       "    var expression;\n",
       "    if (expressionType == 'match') {\n",
       "        expression = generateMatchExpression(propertyValue, stops, defaultValue)\n",
       "    }\n",
       "    else if (propertyValue == 'identity') {\n",
       "        expression = ['get', propertyValue]\n",
       "    }\n",
       "    else {\n",
       "        expression = generateInterpolateExpression(propertyValue, stops)\n",
       "    }\n",
       "\n",
       "    return expression\n",
       "}\n",
       "\n",
       "</script>\n",
       "\n",
       "<!-- main map creation code, extended by mapboxgl/templates/circle.html -->\n",
       "<script type='text/javascript'>\n",
       "\n",
       "    mapboxgl.accessToken = 'pk.eyJ1Ijoic2FtbGV0IiwiYSI6ImNpeXgyM3llZTAwMnAycXJ4ajZ0bHZkYXYifQ.X1Pa-iyXQ3Y4BxcUZNC2MA';\n",
       "\n",
       "    var transformRequest = function(url, resourceType) {\n",
       "        const isMapboxRequest = url.slice(8, 22) === 'api.mapbox.com' ||\n",
       "          url.slice(10, 26) === 'tiles.mapbox.com';\n",
       "      \n",
       "        return {\n",
       "          url: isMapboxRequest ? url.replace('?', '?pluginName=PythonMapboxgl&') : url\n",
       "        }\n",
       "    };\n",
       "\n",
       "    var map = new mapboxgl.Map({\n",
       "        container: 'map',\n",
       "        attributionControl: false,\n",
       "        style: 'mapbox://styles/mapbox/light-v10?optimize=true',\n",
       "        center: [-95, 40],\n",
       "        zoom: 3,\n",
       "        pitch: 0,\n",
       "        bearing: 0,\n",
       "        scrollZoom: true,\n",
       "        touchZoom: true,\n",
       "        doubleClickZoom: true,\n",
       "        boxZoom: true,\n",
       "        preserveDrawingBuffer: false,\n",
       "        transformRequest: transformRequest\n",
       "    });\n",
       "\n",
       "    \n",
       "    \n",
       "        map.addControl(new mapboxgl.AttributionControl({ compact: true }));\n",
       "\n",
       "    \n",
       "\n",
       "    \n",
       "\n",
       "        map.addControl(new mapboxgl.NavigationControl());\n",
       "\n",
       "    \n",
       "\n",
       "    \n",
       "\n",
       "    \n",
       "        \n",
       "            calcColorLegend([[0, 'rgb(255,255,204)'], [10, 'rgb(161,218,180)'], [100, 'rgb(65,182,196)'], [1000, 'rgb(44,127,184)'], [10000, 'rgb(37,52,148)']] , 'Avg Medicare Payments');\n",
       "        \n",
       "    \n",
       "        \n",
       "\n",
       "\n",
       "    \n",
       "        \n",
       "        \n",
       "\n",
       "    \n",
       "\n",
       "    \n",
       "\n",
       "    map.on('style.load', function() {\n",
       "        \n",
       "        \n",
       "\n",
       "        map.addSource('data', {\n",
       "            'type': 'geojson',\n",
       "            'data': 'points.geojson',\n",
       "            'buffer': 1,\n",
       "            'maxzoom': 14,\n",
       "            'generateId': true\n",
       "        });\n",
       "\n",
       "        map.addLayer({\n",
       "            'id': 'label',\n",
       "            'source': 'data',\n",
       "            'type': 'symbol',\n",
       "            'maxzoom': 24,\n",
       "            'minzoom': 0,\n",
       "            'layout': {\n",
       "                \n",
       "                'text-size' : generateInterpolateExpression('zoom', [[0, 8],[22, 3* 8]] ),\n",
       "                'text-offset': [0,-1]\n",
       "            },\n",
       "            'paint': {\n",
       "                'text-halo-color': 'white',\n",
       "                'text-halo-width': generatePropertyExpression('interpolate', 'zoom', [[0,1], [18,5* 1]]),\n",
       "                'text-color': ['case',\n",
       "                    ['boolean', ['feature-state', 'hover'], false], \n",
       "                    'black', \n",
       "                    '#131516']\n",
       "            }\n",
       "        }, 'waterway-label' )\n",
       "        \n",
       "        map.addLayer({\n",
       "            'id': 'circle',\n",
       "            'source': 'data',\n",
       "            'type': 'circle',\n",
       "            'maxzoom': 24,\n",
       "            'minzoom': 0,\n",
       "            'paint': {\n",
       "                \n",
       "                    'circle-color': ['case',\n",
       "                        ['boolean', ['feature-state', 'hover'], false], \n",
       "                        'black',\n",
       "                        generatePropertyExpression('interpolate', 'Avg Medicare Payments', [[0, 'rgb(255,255,204)'], [10, 'rgb(161,218,180)'], [100, 'rgb(65,182,196)'], [1000, 'rgb(44,127,184)'], [10000, 'rgb(37,52,148)']], 'grey' )],\n",
       "                    \n",
       "                'circle-radius' : generatePropertyExpression('interpolate', 'zoom', [[0,1], [22,10 * 1]]),\n",
       "                'circle-stroke-color': ['case',\n",
       "                    ['boolean', ['feature-state', 'hover'], false], \n",
       "                    'black', \n",
       "                    'grey'],\n",
       "                'circle-stroke-width': generatePropertyExpression('interpolate', 'zoom', [[0,0.1], [18,5* 0.1]]),\n",
       "                'circle-opacity' : 1,\n",
       "                'circle-stroke-opacity' : 1\n",
       "            }\n",
       "        }, 'label');\n",
       "        \n",
       "        \n",
       "\n",
       "        // Popups\n",
       "        \n",
       "            var popupAction = 'mousemove',\n",
       "                popupSettings =  {\n",
       "                    closeButton: false,\n",
       "                    closeOnClick: false\n",
       "                };\n",
       "        \n",
       "\n",
       "        // Create a popup\n",
       "        var popup = new mapboxgl.Popup(popupSettings);\n",
       "\n",
       "        \n",
       "\n",
       "        var hoveredStateId = 0;\n",
       "        \n",
       "        // Show the popup on mouseover\n",
       "        map.on(popupAction, function(e) {\n",
       "            \n",
       "            var features = map.queryRenderedFeatures(e.point, {layers: ['circle', 'label'] });\n",
       "\n",
       "            if (features.length > 0) {\n",
       "                map.getCanvas().style.cursor = 'pointer';\n",
       "                var f = features[0];\n",
       "                newHoveredStateId = f.id;\n",
       "                if (newHoveredStateId != hoveredStateId) {\n",
       "                    map.removeFeatureState({source: 'data', id: hoveredStateId});\n",
       "                    hoveredStateId = newHoveredStateId;\n",
       "                }\n",
       "                map.setFeatureState({source: 'data', id: hoveredStateId}, { hover: true});\n",
       "                let popup_html = '<div><li><b>Location</b>: ' + f.geometry.coordinates[0].toPrecision(6) + \n",
       "                    ', ' + f.geometry.coordinates[1].toPrecision(6) + '</li>';\n",
       "\n",
       "                for (key in f.properties) {\n",
       "                    popup_html += '<li><b> ' + key + '</b>: ' + f.properties[key] + ' </li>'\n",
       "                }\n",
       "\n",
       "                popup_html += '</div>'\n",
       "                popup.setLngLat(e.lngLat)\n",
       "                    .setHTML(popup_html)\n",
       "                    .addTo(map);\n",
       "            }\n",
       "            else {\n",
       "                map.getCanvas().style.cursor = '';\n",
       "                popup.remove();\n",
       "                map.removeFeatureState({source: 'data', id: hoveredStateId});\n",
       "            }\n",
       "        });\n",
       "\n",
       "        \n",
       "        \n",
       "        // Fly to on click\n",
       "        map.on('click', 'circle', function(e) {\n",
       "            map.easeTo({\n",
       "                center: e.features[0].geometry.coordinates\n",
       "            });\n",
       "        });\n",
       "    });\n",
       "\n",
       "\n",
       "\n",
       "</script>\n",
       "\n",
       "<!-- add capability to export map or legend to image file -->\n",
       "\n",
       "\n",
       "</body>\n",
       "</html>\" style=\"width: 100%; height: 400px;\"></iframe>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Must be a public token, starting with `pk`\n",
    "# token = os.getenv('MAPBOX_ACCESS_TOKEN')\n",
    "\n",
    "# Create a geojson file export from a Pandas dataframe\n",
    "df_to_geojson(df, filename='points.geojson',\n",
    "              properties=['Avg Medicare Payments', 'Avg Covered Charges', 'date'],\n",
    "              lat='lat', lon='lon', precision=3)\n",
    "\n",
    "# Generate data breaks and color stops from colorBrewer\n",
    "color_breaks = [0,10,100,1000,10000]\n",
    "color_stops = create_color_stops(color_breaks, colors='YlGnBu')\n",
    "\n",
    "# Create the viz from the dataframe\n",
    "viz = CircleViz('points.geojson',\n",
    "                access_token=token,\n",
    "                height='400px',\n",
    "                color_property = \"Avg Medicare Payments\",\n",
    "                color_stops = color_stops,\n",
    "                center = (-95, 40),\n",
    "                zoom = 3,\n",
    "                below_layer = 'waterway-label'\n",
    "              )\n",
    "viz.show()"
   ]
  }
 ],
 "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.7.3"
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
