1.x updates
This commit is contained in:
69
README.md
69
README.md
@@ -1,26 +1,59 @@
|
||||
# Garmin → local SQLite
|
||||
# openrun — endurance running analytics
|
||||
|
||||
A small, self-contained pipeline that pulls Garmin Connect data into a local SQLite database and a stack of pandas notebooks. The aim is a *reference* you can run against your own data — not a polished product — so this README focuses on what's in the data, what gets computed from it, and exactly how each derived metric is defined.
|
||||
A local-first, open-source endurance-training analysis pipeline. Garmin data in (live API or official export), SQLite on disk, pandas notebooks out. Banister CTL/ATL/TSB, Pa:HR decoupling (per-mile and per-second from FIT), Garmin-configured HR-zone time-in-zone, route clustering, race-plan projection with forward CTL/ATL/TSB.
|
||||
|
||||
This README focuses on what's in the data, what gets computed from it, and how each derived metric is defined. The package name `openrun` is provisional; the local repo can be renamed without code changes.
|
||||
|
||||
```
|
||||
garmin/
|
||||
├── auth.py # Path B: OAuth login for live API
|
||||
├── sync.py # Path B: incremental sync via garth
|
||||
├── ingest_export.py # Path A: parse Garmin Connect data export
|
||||
├── link_fit_files.py # match Takeout FIT files to activities by start_time
|
||||
├── compute_time_in_zone.py # cache per-activity HR-zone breakdowns
|
||||
├── analysis.py # shared loaders + derived metrics
|
||||
├── db.py # schema + connection helpers
|
||||
├── data/garmin.db # SQLite (created on first run)
|
||||
└── notebooks/
|
||||
├── 01_overview.ipynb # data coverage, recent activity
|
||||
├── 02_running.ipynb # volume, pace, ACWR, PRs
|
||||
├── 03_recovery.ipynb # sleep, HRV, RHR, body battery
|
||||
├── 04_efficiency.ipynb # m/beat trends year over year
|
||||
├── 05_intra_run.ipynb # decoupling, cadence, routes, HR zones
|
||||
└── 06_race_plan.ipynb # build a periodised plan + adherence tracker
|
||||
openrun/
|
||||
├── pyproject.toml # packaged as `openrun` (src layout, hatchling)
|
||||
├── openrun.toml # user config (HR zones, weight, LTHR, race calendar)
|
||||
├── src/openrun/
|
||||
│ ├── __init__.py # re-exports the common API
|
||||
│ ├── config.py # UserProfile, HRZones, BanisterParams, TOML loader
|
||||
│ ├── db.py # SQLite schema + connection helper
|
||||
│ ├── model.py # loaders + derived metrics (was analysis.py)
|
||||
│ └── ingest/
|
||||
│ ├── auth.py # Garmin OAuth login
|
||||
│ ├── garmin_api.py # Path B: incremental sync via garth
|
||||
│ ├── garmin_export.py # Path A: parse Connect/Takeout JSON + index FITs
|
||||
│ ├── fit_linker.py # match Takeout FITs to activities by session.start_time
|
||||
│ └── time_in_zone.py # cache per-activity HR-zone breakdowns
|
||||
├── examples/notebooks/
|
||||
│ ├── 01_overview.ipynb # data coverage, recent activity
|
||||
│ ├── 02_running.ipynb # volume, pace, PMC (Banister), PRs
|
||||
│ ├── 03_recovery.ipynb # sleep, HRV, RHR, body battery
|
||||
│ ├── 04_efficiency.ipynb # m/beat trends year over year
|
||||
│ ├── 05_intra_run.ipynb # decoupling, cadence, routes, HR zones
|
||||
│ └── 06_race_plan.ipynb # periodised plan + tracker + projected PMC
|
||||
├── data/garmin.db # SQLite (created on first run)
|
||||
└── {auth,sync,ingest_export,link_fit_files,compute_time_in_zone,db,analysis}.py
|
||||
# thin top-level shims for back-compat
|
||||
```
|
||||
|
||||
Most callers want:
|
||||
|
||||
```python
|
||||
from openrun import open_conn, load_activities, banister, daily_training_load_series
|
||||
conn = open_conn()
|
||||
runs = load_activities(conn, type='running')
|
||||
pmc = banister(daily_training_load_series(conn))
|
||||
```
|
||||
|
||||
User-specific values (HR zones, LTHR, weight, race calendar) live in `openrun.toml` — config discovery walks up from cwd looking for it. See [openrun.toml](openrun.toml) for the schema.
|
||||
|
||||
CLI entry points (after `uv sync`):
|
||||
|
||||
```bash
|
||||
openrun-auth # OAuth login (Path B)
|
||||
openrun-sync [--full] # incremental Garmin Connect sync
|
||||
openrun-ingest <export> # parse a Connect/Takeout export
|
||||
openrun-link-fit <export> # match Takeout FITs to activities by content
|
||||
openrun-time-in-zone # populate the activity_time_in_zone cache
|
||||
```
|
||||
|
||||
Top-level shims (`uv run sync.py`, `uv run ingest_export.py`, etc.) still work — they re-export `main()` from the corresponding `openrun.ingest.*` module.
|
||||
|
||||
---
|
||||
|
||||
## 1 — Source data
|
||||
|
||||
Reference in New Issue
Block a user