{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import sys\n",
    "sys.path.insert(0, '/Users/joel/src/thundr/tracker/')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "os.environ.update({\n",
    "    'UC_MYSQL_HOST': 'unicron.cluster-cbn1zk7uet6r.eu-west-1.rds.amazonaws.com',\n",
    "    'UC_MYSQL_PASSWORD': 'tydz5cy9xbvchqpa249rfekhcg9sey',\n",
    "})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy\n",
    "import requests"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "import random\n",
    "import datetime\n",
    "import matplotlib.pyplot as plt\n",
    "import matplotlib.dates as mdates"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "from tracker.unicorn import mysql\n",
    "from tracker.unicorn.mysql import get_cursor"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "def _sql_to_dataframe(sql_statement, columns=None, sql_args=[], index_column=None):\n",
    "    with get_cursor(False) as cur:\n",
    "        cur.execute(sql_statement, sql_args)\n",
    "        rows = cur.fetchall()\n",
    "        columns = [c[0] for c in cur.description] if columns is None else columns\n",
    "        df = pd.DataFrame(data=rows, columns=columns)\n",
    "        if index_column:\n",
    "            df = df.set_index(index_column)\n",
    "        return df\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "dfraw = _sql_to_dataframe(\n",
    "    '''select ts, listeners from before_i_go_listeners ''', \n",
    "    columns=['ts', 'listeners'],\n",
    "    index_column='ts'\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.axes._subplots.AxesSubplot at 0x112f497b8>"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 720x216 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "dfraw.resample('1H').mean().rolling(24).mean().plot(title=\"B4IGO Rolling 24 Hour\", figsize=(10,3))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def smooth(y, box_pts):\n",
    "    box = numpy.ones(box_pts)/box_pts\n",
    "    y_smooth = numpy.convolve(y, box, mode='same')\n",
    "    return y_smooth\n",
    "\n",
    "def resample_and_remove_bad_points(dframe):\n",
    "    df1 = dframe.resample('1Min').mean().interpolate('time')\n",
    "    w = 50\n",
    "    df1[f'sm'] = smooth(df1.listeners, w)\n",
    "    df1[f'delt'] = df1.listeners - df1[f'sm']\n",
    "    smoothness = numpy.sqrt((df1.delt ** 2).rolling(10).max() / df1.sm)\n",
    "    return df1\n",
    "#     return df1[(smoothness <= 20) | (df1.index > (df1.index.max() - numpy.timedelta64(30, 'm')))].resample('5Min').mean()\n",
    "#     return df1[\n",
    "#         ((df1.delt ** 2).rolling(10).max() < 1e6) | (df1.index > (df1.index.max() - numpy.timedelta64(30, 'm')))\n",
    "#     ].resample('5Min').mean()\n",
    "\n",
    "# excluded_points = df1.copy()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "dfraw.listeners.plot()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "resampled = resample_and_remove_bad_points(dfraw)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "mean = numpy.abs(resampled.delt).mean()\n",
    "std = numpy.abs(resampled.delt).std()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "smoothed = resampled[numpy.abs(resampled.delt) < (mean + std)].listeners.resample('5Min').mean()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "oops = dfraw.resample('5Min').mean().iloc[-100:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "oops.listeners.idxmax(), oops.listeners.idxmin()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "oops.loc[numpy.datetime64(\"2020-04-08 14:00\")]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def to_minutes(dt):\n",
    "    \"\"\"Return floating point number of hours through the day in `datetime` dt.\"\"\"\n",
    "    return dt.hour*60 + dt.minute + dt.second / 60\n",
    "\n",
    "def to_day(dt):\n",
    "    return dt.date()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def pivot_by_days(dframe):\n",
    "    excluded_points = resample_and_remove_bad_points(dframe)\n",
    "    excluded_points['dday'] = excluded_points.index.map(to_day)\n",
    "    excluded_points['tday'] = excluded_points.index.map(to_minutes).astype(int)\n",
    "    return excluded_points.pivot(index='tday', columns='dday', values=['listeners'])\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fmpv2[fmpv2.columns[-1:]].plot(figsize=(10,9))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "x = numpy.linspace(0,2*numpy.pi,100)\n",
    "y = numpy.sin(x) + numpy.random.random(100) * 0.8\n",
    "\n",
    "\n",
    "plt.plot(x, y,'o')\n",
    "plt.plot(x, smooth(y,3), 'r-', lw=2)\n",
    "plt.plot(x, smooth(y,19), 'g-', lw=2)\n",
    "\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df1.listeners.plot(figsize=(10,6))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "errors = (df1.del10 ** 2).rolling(5).mean()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "errors[errors < 1e7].plot(),  errors[errors < 1e6].plot()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "with get_cursor() as cur:\n",
    "    cur.execute('select ts, listeners from deathbed_listeners limit 10')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "[c[0] for c in cur.description]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "len(df1.index)\n",
    "df1.loc > numpy.datetime64"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df1.index.max() - numpy.timedelta64(20, 'm')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# YouTube Views"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "ds = _sql_to_dataframe('select as_of, streams from before_i_go_daily_streams')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.axes._subplots.AxesSubplot at 0x1133fbf28>"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "ds.plot()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "yt1 = _sql_to_dataframe('''select ts, views1 + views2, comments1 from before_i_go_youtubes''', columns=['ts', 'views', 'comments'])\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.axes._subplots.AxesSubplot at 0x1135bb550>"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "yt1.set_index('ts').resample('1H').max().diff().rolling(24).mean().views.plot()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "yt1 = _sql_to_dataframe('''select ts, views1 + views2 + views3, comments1 from skechers_youtubes''', columns=['ts', 'views', 'comments'])\n",
    "\n",
    "yt1['views_per_minute'] = (yt1.views.diff() / yt1.ts.astype(int).diff() * 1e9 * 60)\n",
    "yt1['comments_per_minute'] = (yt1.comments.diff() / yt1.ts.astype(int).diff() * 1e9 * 60)\n",
    "yt1 = yt1.set_index('ts')\n",
    "\n",
    "yt1[['views_per_minute']].resample('1H').mean().iloc[-21*24:].rolling(24).mean().plot(figsize=(10,3), title=\"YouTube Views / Minute\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.axes._subplots.AxesSubplot at 0x112ef65c0>"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Error in callback <function install_repl_displayhook.<locals>.post_execute at 0x10e46f7b8> (for post_execute):\n"
     ]
    },
    {
     "ename": "ValueError",
     "evalue": "view limit minimum -36877.231166666665 is less than 1 and is an invalid Matplotlib date value. This often happens if you pass a non-datetime value to an axis that has datetime units",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m-------------------------------------------------------\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m            Traceback (most recent call last)",
      "\u001b[0;32m~/src/thundr/tracker/venv/lib/python3.7/site-packages/matplotlib/pyplot.py\u001b[0m in \u001b[0;36mpost_execute\u001b[0;34m()\u001b[0m\n\u001b[1;32m    107\u001b[0m             \u001b[0;32mdef\u001b[0m \u001b[0mpost_execute\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    108\u001b[0m                 \u001b[0;32mif\u001b[0m \u001b[0mmatplotlib\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mis_interactive\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 109\u001b[0;31m                     \u001b[0mdraw_all\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    110\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    111\u001b[0m             \u001b[0;31m# IPython >= 2\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/src/thundr/tracker/venv/lib/python3.7/site-packages/matplotlib/_pylab_helpers.py\u001b[0m in \u001b[0;36mdraw_all\u001b[0;34m(cls, force)\u001b[0m\n\u001b[1;32m    126\u001b[0m         \u001b[0;32mfor\u001b[0m \u001b[0mf_mgr\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mcls\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_all_fig_managers\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    127\u001b[0m             \u001b[0;32mif\u001b[0m \u001b[0mforce\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0mf_mgr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcanvas\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfigure\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstale\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 128\u001b[0;31m                 \u001b[0mf_mgr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcanvas\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdraw_idle\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    129\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    130\u001b[0m \u001b[0matexit\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mregister\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mGcf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdestroy_all\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/src/thundr/tracker/venv/lib/python3.7/site-packages/matplotlib/backend_bases.py\u001b[0m in \u001b[0;36mdraw_idle\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m   1914\u001b[0m         \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_is_idle_drawing\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1915\u001b[0m             \u001b[0;32mwith\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_idle_draw_cntx\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1916\u001b[0;31m                 \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdraw\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1917\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1918\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0mdraw_cursor\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mevent\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/src/thundr/tracker/venv/lib/python3.7/site-packages/matplotlib/backends/backend_agg.py\u001b[0m in \u001b[0;36mdraw\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m    386\u001b[0m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrenderer\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_renderer\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcleared\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    387\u001b[0m         \u001b[0;32mwith\u001b[0m \u001b[0mRendererAgg\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlock\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 388\u001b[0;31m             \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfigure\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdraw\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrenderer\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    389\u001b[0m             \u001b[0;31m# A GUI class may be need to update a window using this draw, so\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    390\u001b[0m             \u001b[0;31m# don't forget to call the superclass.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/src/thundr/tracker/venv/lib/python3.7/site-packages/matplotlib/artist.py\u001b[0m in \u001b[0;36mdraw_wrapper\u001b[0;34m(artist, renderer, *args, **kwargs)\u001b[0m\n\u001b[1;32m     36\u001b[0m                 \u001b[0mrenderer\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstart_filter\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     37\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 38\u001b[0;31m             \u001b[0;32mreturn\u001b[0m \u001b[0mdraw\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0martist\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mrenderer\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     39\u001b[0m         \u001b[0;32mfinally\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     40\u001b[0m             \u001b[0;32mif\u001b[0m \u001b[0martist\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_agg_filter\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/src/thundr/tracker/venv/lib/python3.7/site-packages/matplotlib/figure.py\u001b[0m in \u001b[0;36mdraw\u001b[0;34m(self, renderer)\u001b[0m\n\u001b[1;32m   1707\u001b[0m             \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpatch\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdraw\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrenderer\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1708\u001b[0m             mimage._draw_list_compositing_images(\n\u001b[0;32m-> 1709\u001b[0;31m                 renderer, self, artists, self.suppressComposite)\n\u001b[0m\u001b[1;32m   1710\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1711\u001b[0m             \u001b[0mrenderer\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mclose_group\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'figure'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/src/thundr/tracker/venv/lib/python3.7/site-packages/matplotlib/image.py\u001b[0m in \u001b[0;36m_draw_list_compositing_images\u001b[0;34m(renderer, parent, artists, suppress_composite)\u001b[0m\n\u001b[1;32m    133\u001b[0m     \u001b[0;32mif\u001b[0m \u001b[0mnot_composite\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mhas_images\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    134\u001b[0m         \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0martists\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 135\u001b[0;31m             \u001b[0ma\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdraw\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrenderer\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    136\u001b[0m     \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    137\u001b[0m         \u001b[0;31m# Composite any adjacent images together\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/src/thundr/tracker/venv/lib/python3.7/site-packages/matplotlib/artist.py\u001b[0m in \u001b[0;36mdraw_wrapper\u001b[0;34m(artist, renderer, *args, **kwargs)\u001b[0m\n\u001b[1;32m     36\u001b[0m                 \u001b[0mrenderer\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstart_filter\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     37\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 38\u001b[0;31m             \u001b[0;32mreturn\u001b[0m \u001b[0mdraw\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0martist\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mrenderer\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     39\u001b[0m         \u001b[0;32mfinally\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     40\u001b[0m             \u001b[0;32mif\u001b[0m \u001b[0martist\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_agg_filter\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/src/thundr/tracker/venv/lib/python3.7/site-packages/matplotlib/axes/_base.py\u001b[0m in \u001b[0;36mdraw\u001b[0;34m(self, renderer, inframe)\u001b[0m\n\u001b[1;32m   2645\u001b[0m             \u001b[0mrenderer\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstop_rasterizing\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   2646\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2647\u001b[0;31m         \u001b[0mmimage\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_draw_list_compositing_images\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrenderer\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0martists\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   2648\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   2649\u001b[0m         \u001b[0mrenderer\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mclose_group\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'axes'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/src/thundr/tracker/venv/lib/python3.7/site-packages/matplotlib/image.py\u001b[0m in \u001b[0;36m_draw_list_compositing_images\u001b[0;34m(renderer, parent, artists, suppress_composite)\u001b[0m\n\u001b[1;32m    133\u001b[0m     \u001b[0;32mif\u001b[0m \u001b[0mnot_composite\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mhas_images\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    134\u001b[0m         \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0martists\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 135\u001b[0;31m             \u001b[0ma\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdraw\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrenderer\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    136\u001b[0m     \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    137\u001b[0m         \u001b[0;31m# Composite any adjacent images together\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/src/thundr/tracker/venv/lib/python3.7/site-packages/matplotlib/artist.py\u001b[0m in \u001b[0;36mdraw_wrapper\u001b[0;34m(artist, renderer, *args, **kwargs)\u001b[0m\n\u001b[1;32m     36\u001b[0m                 \u001b[0mrenderer\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstart_filter\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     37\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 38\u001b[0;31m             \u001b[0;32mreturn\u001b[0m \u001b[0mdraw\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0martist\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mrenderer\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     39\u001b[0m         \u001b[0;32mfinally\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     40\u001b[0m             \u001b[0;32mif\u001b[0m \u001b[0martist\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_agg_filter\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/src/thundr/tracker/venv/lib/python3.7/site-packages/matplotlib/axis.py\u001b[0m in \u001b[0;36mdraw\u001b[0;34m(self, renderer, *args, **kwargs)\u001b[0m\n\u001b[1;32m   1201\u001b[0m         \u001b[0mrenderer\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mopen_group\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0m__name__\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1202\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1203\u001b[0;31m         \u001b[0mticks_to_draw\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_update_ticks\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1204\u001b[0m         ticklabelBoxes, ticklabelBoxes2 = self._get_tick_bboxes(ticks_to_draw,\n\u001b[1;32m   1205\u001b[0m                                                                 renderer)\n",
      "\u001b[0;32m~/src/thundr/tracker/venv/lib/python3.7/site-packages/matplotlib/axis.py\u001b[0m in \u001b[0;36m_update_ticks\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m   1077\u001b[0m         \u001b[0mthe\u001b[0m \u001b[0maxes\u001b[0m\u001b[0;34m.\u001b[0m  \u001b[0mReturn\u001b[0m \u001b[0mthe\u001b[0m \u001b[0mlist\u001b[0m \u001b[0mof\u001b[0m \u001b[0mticks\u001b[0m \u001b[0mthat\u001b[0m \u001b[0mwill\u001b[0m \u001b[0mbe\u001b[0m \u001b[0mdrawn\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1078\u001b[0m         \"\"\"\n\u001b[0;32m-> 1079\u001b[0;31m         \u001b[0mmajor_locs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_majorticklocs\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1080\u001b[0m         \u001b[0mmajor_labels\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmajor\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformatter\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat_ticks\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmajor_locs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1081\u001b[0m         \u001b[0mmajor_ticks\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_major_ticks\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmajor_locs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/src/thundr/tracker/venv/lib/python3.7/site-packages/matplotlib/axis.py\u001b[0m in \u001b[0;36mget_majorticklocs\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m   1322\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0mget_majorticklocs\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1323\u001b[0m         \u001b[0;34m\"\"\"Get the array of major tick locations in data coordinates.\"\"\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1324\u001b[0;31m         \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmajor\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlocator\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1325\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1326\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0mget_minorticklocs\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/src/thundr/tracker/venv/lib/python3.7/site-packages/matplotlib/dates.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m   1426\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0m__call__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1427\u001b[0m         \u001b[0;34m'Return the locations of the ticks'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1428\u001b[0;31m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrefresh\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1429\u001b[0m         \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_locator\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1430\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/src/thundr/tracker/venv/lib/python3.7/site-packages/matplotlib/dates.py\u001b[0m in \u001b[0;36mrefresh\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m   1446\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0mrefresh\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1447\u001b[0m         \u001b[0;34m'Refresh internal information based on current limits.'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1448\u001b[0;31m         \u001b[0mdmin\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdmax\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mviewlim_to_dt\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1449\u001b[0m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_locator\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_locator\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdmin\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdmax\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1450\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/src/thundr/tracker/venv/lib/python3.7/site-packages/matplotlib/dates.py\u001b[0m in \u001b[0;36mviewlim_to_dt\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m   1197\u001b[0m                              \u001b[0;34m'often happens if you pass a non-datetime '\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1198\u001b[0m                              \u001b[0;34m'value to an axis that has datetime units'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1199\u001b[0;31m                              .format(vmin))\n\u001b[0m\u001b[1;32m   1200\u001b[0m         \u001b[0;32mreturn\u001b[0m \u001b[0mnum2date\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvmin\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtz\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnum2date\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvmax\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtz\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1201\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mValueError\u001b[0m: view limit minimum -36877.231166666665 is less than 1 and is an invalid Matplotlib date value. This often happens if you pass a non-datetime value to an axis that has datetime units"
     ]
    },
    {
     "ename": "ValueError",
     "evalue": "view limit minimum -36877.231166666665 is less than 1 and is an invalid Matplotlib date value. This often happens if you pass a non-datetime value to an axis that has datetime units",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m-------------------------------------------------------\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m            Traceback (most recent call last)",
      "\u001b[0;32m~/src/thundr/tracker/venv/lib/python3.7/site-packages/ipykernel/pylab/backend_inline.py\u001b[0m in \u001b[0;36mshow\u001b[0;34m(close, block)\u001b[0m\n\u001b[1;32m     37\u001b[0m             display(\n\u001b[1;32m     38\u001b[0m                 \u001b[0mfigure_manager\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcanvas\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfigure\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 39\u001b[0;31m                 \u001b[0mmetadata\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0m_fetch_figure_metadata\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfigure_manager\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcanvas\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfigure\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     40\u001b[0m             )\n\u001b[1;32m     41\u001b[0m     \u001b[0;32mfinally\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/src/thundr/tracker/venv/lib/python3.7/site-packages/ipykernel/pylab/backend_inline.py\u001b[0m in \u001b[0;36m_fetch_figure_metadata\u001b[0;34m(fig)\u001b[0m\n\u001b[1;32m    175\u001b[0m         \u001b[0;31m# the background is transparent\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    176\u001b[0m         ticksLight = _is_light([label.get_color()\n\u001b[0;32m--> 177\u001b[0;31m                                 \u001b[0;32mfor\u001b[0m \u001b[0maxes\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mfig\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0maxes\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    178\u001b[0m                                 \u001b[0;32mfor\u001b[0m \u001b[0maxis\u001b[0m \u001b[0;32min\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0maxes\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mxaxis\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0maxes\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0myaxis\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    179\u001b[0m                                 for label in axis.get_ticklabels()])\n",
      "\u001b[0;32m~/src/thundr/tracker/venv/lib/python3.7/site-packages/ipykernel/pylab/backend_inline.py\u001b[0m in \u001b[0;36m<listcomp>\u001b[0;34m(.0)\u001b[0m\n\u001b[1;32m    177\u001b[0m                                 \u001b[0;32mfor\u001b[0m \u001b[0maxes\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mfig\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0maxes\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    178\u001b[0m                                 \u001b[0;32mfor\u001b[0m \u001b[0maxis\u001b[0m \u001b[0;32min\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0maxes\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mxaxis\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0maxes\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0myaxis\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 179\u001b[0;31m                                 for label in axis.get_ticklabels()])\n\u001b[0m\u001b[1;32m    180\u001b[0m         \u001b[0;32mif\u001b[0m \u001b[0mticksLight\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msize\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mticksLight\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0mticksLight\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mall\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    181\u001b[0m             \u001b[0;31m# there are one or more tick labels, all with the same lightness\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/src/thundr/tracker/venv/lib/python3.7/site-packages/matplotlib/axis.py\u001b[0m in \u001b[0;36mget_ticklabels\u001b[0;34m(self, minor, which)\u001b[0m\n\u001b[1;32m   1294\u001b[0m         \u001b[0;32mif\u001b[0m \u001b[0mminor\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1295\u001b[0m             \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_minorticklabels\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1296\u001b[0;31m         \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_majorticklabels\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1297\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1298\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0mget_majorticklines\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/src/thundr/tracker/venv/lib/python3.7/site-packages/matplotlib/axis.py\u001b[0m in \u001b[0;36mget_majorticklabels\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m   1250\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0mget_majorticklabels\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1251\u001b[0m         \u001b[0;34m'Return a list of Text instances for the major ticklabels.'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1252\u001b[0;31m         \u001b[0mticks\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_major_ticks\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1253\u001b[0m         \u001b[0mlabels1\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mtick\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlabel1\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mtick\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mticks\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mtick\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlabel1\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_visible\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1254\u001b[0m         \u001b[0mlabels2\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mtick\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlabel2\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mtick\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mticks\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mtick\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlabel2\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_visible\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/src/thundr/tracker/venv/lib/python3.7/site-packages/matplotlib/axis.py\u001b[0m in \u001b[0;36mget_major_ticks\u001b[0;34m(self, numticks)\u001b[0m\n\u001b[1;32m   1405\u001b[0m         \u001b[0;34m'Get the tick instances; grow as necessary.'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1406\u001b[0m         \u001b[0;32mif\u001b[0m \u001b[0mnumticks\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1407\u001b[0;31m             \u001b[0mnumticks\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_majorticklocs\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1408\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1409\u001b[0m         \u001b[0;32mwhile\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmajorTicks\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m<\u001b[0m \u001b[0mnumticks\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/src/thundr/tracker/venv/lib/python3.7/site-packages/matplotlib/axis.py\u001b[0m in \u001b[0;36mget_majorticklocs\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m   1322\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0mget_majorticklocs\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1323\u001b[0m         \u001b[0;34m\"\"\"Get the array of major tick locations in data coordinates.\"\"\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1324\u001b[0;31m         \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmajor\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlocator\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1325\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1326\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0mget_minorticklocs\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/src/thundr/tracker/venv/lib/python3.7/site-packages/matplotlib/dates.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m   1426\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0m__call__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1427\u001b[0m         \u001b[0;34m'Return the locations of the ticks'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1428\u001b[0;31m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrefresh\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1429\u001b[0m         \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_locator\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1430\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/src/thundr/tracker/venv/lib/python3.7/site-packages/matplotlib/dates.py\u001b[0m in \u001b[0;36mrefresh\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m   1446\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0mrefresh\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1447\u001b[0m         \u001b[0;34m'Refresh internal information based on current limits.'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1448\u001b[0;31m         \u001b[0mdmin\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdmax\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mviewlim_to_dt\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1449\u001b[0m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_locator\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_locator\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdmin\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdmax\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1450\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/src/thundr/tracker/venv/lib/python3.7/site-packages/matplotlib/dates.py\u001b[0m in \u001b[0;36mviewlim_to_dt\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m   1197\u001b[0m                              \u001b[0;34m'often happens if you pass a non-datetime '\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1198\u001b[0m                              \u001b[0;34m'value to an axis that has datetime units'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1199\u001b[0;31m                              .format(vmin))\n\u001b[0m\u001b[1;32m   1200\u001b[0m         \u001b[0;32mreturn\u001b[0m \u001b[0mnum2date\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvmin\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtz\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnum2date\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvmax\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtz\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1201\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mValueError\u001b[0m: view limit minimum -36877.231166666665 is less than 1 and is an invalid Matplotlib date value. This often happens if you pass a non-datetime value to an axis that has datetime units"
     ]
    }
   ],
   "source": [
    "yt1.plot()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Tiktok videos"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tt1 = _sql_to_dataframe('''select ts, videos1, videos2, videos3 from skechers_tiktoks''', index_column='ts')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tt1['total'] = tt1.sum(axis=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "hourly = tt1.resample('1H').max()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "after = numpy.datetime64('2020-04-01 17:34:22')\n",
    "before =  numpy.datetime64('2020-04-06 19:10:28')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "removed_bad = tt1[~(tt1.index >= after) | ~(tt1.index <= before)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(removed_bad.resample('1H').max().interpolate('time').diff().total / 60).plot(figsize=(13,5))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "hourly.interpolate('time').total.plot()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "hourly.total.interpolate()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tt1[['videos_per_minute']].resample('1H').mean().rolling(24).mean().plot(figsize=(10,3), legend=False, title='Deathbed TikToks / minute')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tt1[['videos_per_minute']].resample('24H').median().plot(figsize=(10,3))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## SoundCloud\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sc1 = _sql_to_dataframe('''select ts, plays_1 + plays_2 + plays_3 from skechers_sc_plays''', columns=['ts', 'plays'])\n",
    "\n",
    "sc1['plays_per_minute'] = (sc1.plays.diff() / sc1.ts.astype(int).diff() * 1e9 * 60)\n",
    "sc1 = sc1.set_index('ts')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sc1[['plays_per_minute']].resample('1H').mean().rolling(24).mean().plot(figsize=(10,3), legend=False, title='Skechers SoundCloud Plays / minute')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sc1.plays.resample('1H').max().diff().resample('24H').max().plot(figsize=(10,5), title=\"Canada Goose, Peak Hourly Plays, last 10 days\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# could store this in the db using spartus?\n",
    "def refresh_request_headers():\n",
    "    global headers\n",
    "    cookies = {\n",
    "        'sp_dc': 'AQAbb-xbg9Nm8VmJkpOLMHDWTQsGQ6-6iRsDn54H5InejBBarQbZeelQFeTBpDaxTTcKJYKqdBgRw94ann0E_b9_T2rp6mBGwNUSIZtuvi0',\n",
    "        'sp_key': '0eee0e06-6b39-4a63-b40d-0571506e7001'   \n",
    "    }\n",
    "\n",
    "    tokenRequest = requests.get(\n",
    "        \"https://generic.wg.spotify.com/creator-auth-proxy/v1/web/token?client_id=6cf79a93be894c2086b8cbf737e0796b\", \n",
    "        headers={\n",
    "            \"accept\":\"application/json\",\n",
    "            \"accept-language\":\"en-GB,en-US;q=0.9,en;q=0.8\",\n",
    "            \"sec-fetch-dest\":\"empty\",\n",
    "            \"sec-fetch-mode\":\"cors\",\n",
    "            \"sec-fetch-site\":\"same-site\",\n",
    "            \"origin\": \"https://artists.spotify.com\",\n",
    "            \"User-Agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36\",\n",
    "            \"referrer\":\"https://artists.spotify.com/c/artist/6bmlMHgSheBauioMgKv2tn/song/7eJMfftS33KTjuF7lTsMCx/stats?segment-filter=streams&time-filter=7day\",\n",
    "        }, cookies=cookies)\n",
    "    tokenRequest\n",
    "\n",
    "    accessToken = tokenRequest.json()['access_token']\n",
    "\n",
    "    headers = {\n",
    "        'authority': 'generic.wg.spotify.com',\n",
    "        'authorization': f'Bearer {accessToken}',\n",
    "        'content-type': 'application/json',\n",
    "        'accept': 'application/json',\n",
    "        'sec-fetch-dest': 'empty',\n",
    "        'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36',\n",
    "        'spotify-app-version': '1.0.0.3229887',\n",
    "        'app-platform': 'Browser',\n",
    "        'origin': 'https://artists.spotify.com',\n",
    "        'sec-fetch-site': 'same-site',\n",
    "        'sec-fetch-mode': 'cors',\n",
    "        'referer': 'https://artists.spotify.com/c/artist/6bmlMHgSheBauioMgKv2tn/song/7eJMfftS33KTjuF7lTsMCx/stats?segment-filter=streams&time-filter=7day',\n",
    "        'accept-language': 'en-GB,en-US;q=0.9,en;q=0.8',\n",
    "    }\n",
    "    return headers"
   ]
  }
 ],
 "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.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
