{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 01 — Overview\n",
    "\n",
    "Sanity-check the synced data: what's there, how complete it is, and what you've been up to recently.\n",
    "\n",
    "**Kernel:** pick the `.venv` from `garmin/` (top-right of this notebook)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import sys\n",
    "sys.path.insert(0, '..')  # so we can import analysis.py from the project root\n",
    "\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "from openrun import open_conn, load_activities, load_wellness\n",
    "\n",
    "pd.options.display.float_format = '{:.2f}'.format\n",
    "conn = open_conn()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Data coverage"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "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>table</th>\n",
       "      <th>rows</th>\n",
       "      <th>from</th>\n",
       "      <th>to</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>activities</td>\n",
       "      <td>378</td>\n",
       "      <td>1658945478000.0</td>\n",
       "      <td>2026-05-10 10:43:58</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>activity_fit_files</td>\n",
       "      <td>349</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>activity_splits</td>\n",
       "      <td>2285</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>activity_time_in_zone</td>\n",
       "      <td>345</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>daily_body_battery</td>\n",
       "      <td>365</td>\n",
       "      <td>2025-05-13</td>\n",
       "      <td>2026-05-12</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>daily_hrv</td>\n",
       "      <td>363</td>\n",
       "      <td>2025-05-13</td>\n",
       "      <td>2026-05-12</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>daily_intensity_minutes</td>\n",
       "      <td>365</td>\n",
       "      <td>2025-05-13</td>\n",
       "      <td>2026-05-12</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>daily_resting_hr</td>\n",
       "      <td>363</td>\n",
       "      <td>2025-05-13</td>\n",
       "      <td>2026-05-11</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>daily_sleep</td>\n",
       "      <td>1462</td>\n",
       "      <td>2022-04-08</td>\n",
       "      <td>2026-05-17</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>daily_steps</td>\n",
       "      <td>1497</td>\n",
       "      <td>2022-04-08</td>\n",
       "      <td>2026-05-17</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>daily_stress</td>\n",
       "      <td>365</td>\n",
       "      <td>2025-05-13</td>\n",
       "      <td>2026-05-12</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>manual_activities</td>\n",
       "      <td>0</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12</th>\n",
       "      <td>race_plan</td>\n",
       "      <td>0</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13</th>\n",
       "      <td>sqlite_sequence</td>\n",
       "      <td>0</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>14</th>\n",
       "      <td>sync_state</td>\n",
       "      <td>3</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                      table  rows             from                   to\n",
       "0                activities   378  1658945478000.0  2026-05-10 10:43:58\n",
       "1        activity_fit_files   349                                      \n",
       "2           activity_splits  2285                                      \n",
       "3     activity_time_in_zone   345                                      \n",
       "4        daily_body_battery   365       2025-05-13           2026-05-12\n",
       "5                 daily_hrv   363       2025-05-13           2026-05-12\n",
       "6   daily_intensity_minutes   365       2025-05-13           2026-05-12\n",
       "7          daily_resting_hr   363       2025-05-13           2026-05-11\n",
       "8               daily_sleep  1462       2022-04-08           2026-05-17\n",
       "9               daily_steps  1497       2022-04-08           2026-05-17\n",
       "10             daily_stress   365       2025-05-13           2026-05-12\n",
       "11        manual_activities     0                                      \n",
       "12                race_plan     0                                      \n",
       "13          sqlite_sequence     0                                      \n",
       "14               sync_state     3                                      "
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "summary = []\n",
    "for (table,) in conn.execute(\"SELECT name FROM sqlite_master WHERE type='table' ORDER BY name\"):\n",
    "    n = conn.execute(f'SELECT COUNT(*) FROM \"{table}\"').fetchone()[0]\n",
    "    date_col = 'start_time_local' if table == 'activities' else ('calendar_date' if table.startswith('daily_') else None)\n",
    "    if date_col and n:\n",
    "        mn, mx = conn.execute(f'SELECT MIN({date_col}), MAX({date_col}) FROM {table}').fetchone()\n",
    "    else:\n",
    "        mn = mx = ''\n",
    "    summary.append({'table': table, 'rows': n, 'from': mn, 'to': mx})\n",
    "pd.DataFrame(summary)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Activity types"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "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>count</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>activity_type</th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>running</th>\n",
       "      <td>335</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>trail_running</th>\n",
       "      <td>15</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>cycling</th>\n",
       "      <td>9</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>transition_v2</th>\n",
       "      <td>7</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>open_water_swimming</th>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>multi_sport</th>\n",
       "      <td>4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>assistance</th>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mountain_biking</th>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                     count\n",
       "activity_type             \n",
       "running                335\n",
       "trail_running           15\n",
       "cycling                  9\n",
       "transition_v2            7\n",
       "open_water_swimming      6\n",
       "multi_sport              4\n",
       "assistance               1\n",
       "mountain_biking          1"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "activities = load_activities(conn)\n",
    "activities['activity_type'].value_counts().to_frame('count')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Last 10 activities"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "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>start_time_local</th>\n",
       "      <th>activity_type</th>\n",
       "      <th>activity_name</th>\n",
       "      <th>distance_km</th>\n",
       "      <th>duration_min</th>\n",
       "      <th>pace_min_per_km</th>\n",
       "      <th>avg_hr</th>\n",
       "      <th>training_load</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>NaT</td>\n",
       "      <td>running</td>\n",
       "      <td>Milford Running</td>\n",
       "      <td>12.94</td>\n",
       "      <td>105.89</td>\n",
       "      <td>8.09</td>\n",
       "      <td>163.00</td>\n",
       "      <td>101.28</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>NaT</td>\n",
       "      <td>transition_v2</td>\n",
       "      <td>Transition</td>\n",
       "      <td>24.03</td>\n",
       "      <td>75.39</td>\n",
       "      <td>3.01</td>\n",
       "      <td>116.00</td>\n",
       "      <td>90.98</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>NaT</td>\n",
       "      <td>open_water_swimming</td>\n",
       "      <td>Open Water Swimming</td>\n",
       "      <td>0.52</td>\n",
       "      <td>23.45</td>\n",
       "      <td>NaN</td>\n",
       "      <td>137.00</td>\n",
       "      <td>55.14</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>NaT</td>\n",
       "      <td>running</td>\n",
       "      <td>Running</td>\n",
       "      <td>4.88</td>\n",
       "      <td>25.64</td>\n",
       "      <td>5.17</td>\n",
       "      <td>169.00</td>\n",
       "      <td>134.45</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>NaT</td>\n",
       "      <td>transition_v2</td>\n",
       "      <td>Transition 2</td>\n",
       "      <td>3.89</td>\n",
       "      <td>715.77</td>\n",
       "      <td>NaN</td>\n",
       "      <td>107.00</td>\n",
       "      <td>10.10</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>NaT</td>\n",
       "      <td>cycling</td>\n",
       "      <td>Cycling</td>\n",
       "      <td>18.98</td>\n",
       "      <td>56.46</td>\n",
       "      <td>NaN</td>\n",
       "      <td>100.00</td>\n",
       "      <td>10.10</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>NaT</td>\n",
       "      <td>transition_v2</td>\n",
       "      <td>Transition 1</td>\n",
       "      <td>4.44</td>\n",
       "      <td>2117.33</td>\n",
       "      <td>NaN</td>\n",
       "      <td>87.00</td>\n",
       "      <td>8.48</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>NaT</td>\n",
       "      <td>open_water_swimming</td>\n",
       "      <td>Open Water Swimming</td>\n",
       "      <td>0.80</td>\n",
       "      <td>32.80</td>\n",
       "      <td>NaN</td>\n",
       "      <td>106.00</td>\n",
       "      <td>8.48</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>NaT</td>\n",
       "      <td>running</td>\n",
       "      <td>Running</td>\n",
       "      <td>5.09</td>\n",
       "      <td>25.35</td>\n",
       "      <td>4.97</td>\n",
       "      <td>162.00</td>\n",
       "      <td>173.71</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>NaT</td>\n",
       "      <td>transition_v2</td>\n",
       "      <td>Transition 2</td>\n",
       "      <td>0.77</td>\n",
       "      <td>137.95</td>\n",
       "      <td>NaN</td>\n",
       "      <td>118.00</td>\n",
       "      <td>5.90</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  start_time_local        activity_type        activity_name  distance_km  \\\n",
       "0              NaT              running      Milford Running        12.94   \n",
       "1              NaT        transition_v2           Transition        24.03   \n",
       "2              NaT  open_water_swimming  Open Water Swimming         0.52   \n",
       "3              NaT              running              Running         4.88   \n",
       "4              NaT        transition_v2         Transition 2         3.89   \n",
       "5              NaT              cycling              Cycling        18.98   \n",
       "6              NaT        transition_v2         Transition 1         4.44   \n",
       "7              NaT  open_water_swimming  Open Water Swimming         0.80   \n",
       "8              NaT              running              Running         5.09   \n",
       "9              NaT        transition_v2         Transition 2         0.77   \n",
       "\n",
       "   duration_min  pace_min_per_km  avg_hr  training_load  \n",
       "0        105.89             8.09  163.00         101.28  \n",
       "1         75.39             3.01  116.00          90.98  \n",
       "2         23.45              NaN  137.00          55.14  \n",
       "3         25.64             5.17  169.00         134.45  \n",
       "4        715.77              NaN  107.00          10.10  \n",
       "5         56.46              NaN  100.00          10.10  \n",
       "6       2117.33              NaN   87.00           8.48  \n",
       "7         32.80              NaN  106.00           8.48  \n",
       "8         25.35             4.97  162.00         173.71  \n",
       "9        137.95              NaN  118.00           5.90  "
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cols = ['start_time_local', 'activity_type', 'activity_name', 'distance_km', 'duration_min', 'pace_min_per_km', 'avg_hr', 'training_load']\n",
    "activities[cols].tail(10).iloc[::-1].reset_index(drop=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "20e72ec0",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Monthly running mileage, year-over-year"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 115880 characters]",
      "text/plain": [
       "<Figure size 1100x400 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "runs = activities[activities['activity_type'].str.contains('running', case=False, na=False)].copy()\n",
    "monthly = (runs.assign(month_no=runs['start_time_local'].dt.month)\n",
    "                .groupby(['year', 'month_no'])['distance_km'].sum()\n",
    "                .unstack('year'))\n",
    "\n",
    "fig, ax = plt.subplots(figsize=(11, 4))\n",
    "monthly.plot(ax=ax, marker='o')\n",
    "ax.set_xticks(range(1, 13))\n",
    "ax.set_xticklabels(['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'])\n",
    "ax.set_ylabel('km')\n",
    "ax.set_xlabel('')\n",
    "ax.set_title('Monthly running km — year over year')\n",
    "ax.legend(title='Year')\n",
    "ax.grid(alpha=0.3)\n",
    "plt.tight_layout()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Wellness completeness (last 90 days)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "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>% missing</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>total_steps</th>\n",
       "      <td>0.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>sleep_score</th>\n",
       "      <td>100.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>avg_stress</th>\n",
       "      <td>6.67</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>hrv_last_night</th>\n",
       "      <td>13.33</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>resting_hr</th>\n",
       "      <td>7.78</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>bb_charged</th>\n",
       "      <td>7.78</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                % missing\n",
       "total_steps          0.00\n",
       "sleep_score        100.00\n",
       "avg_stress           6.67\n",
       "hrv_last_night      13.33\n",
       "resting_hr           7.78\n",
       "bb_charged           7.78"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "w = load_wellness(conn).tail(90)\n",
    "missing = w[['total_steps','sleep_score','avg_stress','hrv_last_night','resting_hr','bb_charged']].isna().mean().to_frame('% missing') * 100\n",
    "missing"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "garmin (3.13.13)",
   "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.13.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
