ocactivity-gen je python nástroj a konzolová aplikace pro generování estetických grafických kartogramů a vizualizací sportovních aktivit (běh, chůze, turistika, cyklistika apod.).
Dokáže zpracovat soubory Garmin FIT a GPX, extrahovat z nich metriky (vzdálenost, čas, tempo, rychlost, stoupání, klesání, tep, teplotu, kalorie, kroky) a vykreslit trasy na mapové podklady z OpenStreetMap / Mapy.com nebo jiné společně s výškovým profilem a statistikami.
Testováno na Garmin FIT souborech z hodinek, ale mělo by to fungovat i od jiných. Jen pozor na to, že ne každý FIT soubor obsahuje všechny informace. Takže výsledek se může lišit.
V případě vlastní implementace jde hodně věcí přizpůsobit na míru, ale ve výchozím nastavení jsou obrázky vždy 1440x1440 a mají levý zatmavený panel kam se vkládají statistiky.
💪 Ukázky výstupu
🛠️ Hlavní funkce
- Podpora Garmin FIT & GPX: Automatické vytěžování telemetrie, GPS trasy a časových dat.
- Inteligentní vyhlazování GPX: Filtr GPS šumu pomocí 2D Kalmanova filtru.
- Rychlá analýza dat: Adaptivní prahy pohybů a hysterézní filtr převýšení pro přesný výpočet stoupání a času v pohybu.
- Generování výškového profilu: Graf nadmořské výšky se zvýrazněním nejnižšího a nejvyššího bodu.
- Flexibilní mapa: Stahování a kešování mapových dlaždic (OSM / Mapy.com) s automatickým přizpůsobením zoomu.
- Dynamic Element Stacking: Zobrazované statistiky se řadí dynamicky bez mezer i v případě, že některé metriky chybí.
- Podpora vlastních fotek: Možnost nahradit mapu vlastním obrázkem na pozadí.
- Vodoznak a EXIF metadata: Vkládání loga / vodoznaku a zápis autorství do EXIF/PNG metadat.
- Export obrázku: Možnost exportovat do JPG nebo PNG.
- Vlastní aktivita: Možnost vytvoření úplně nové aktivity podle vstupních parametrů (bez trasy, ta vyžaduje min. GPX na vstupu).
📦 Instalace
Aplikaci lze nainstalovat přímo z PyPI pomocí pip:
pip install ocactivity-gen
🚀 Použití z příkazové řádky (CLI)
Po instalaci je ihned k dispozici příkaz ocactivity-gen.
Příklady použití:
- Vygenerování obrázku z FIT souboru:
ocactivity-gen -file "aktivity/zavod.fit" -name "Horský Ultra Běh 🏔️"
- Vygenerování z GPX souboru s vlastní fotkou na pozadí:
ocactivity-gen -file "vylet.gpx" -bg "moje_fotka.jpg" -name "Víkendová procházka" -out "vylet.png"
- Ruční vytvoření aktivity bez datového souboru:
ocactivity-gen -type "Běh" -distance 10500 -pace "4:45" -avgspeed "12.6" -ascent 250 -time 2980 -name "Ranní desítka"
- Přepsání načtených hodnot z FIT souboru a skrytí grafu a teploty:
ocactivity-gen -file "zavod.fit" -nograph -avgtemp -999 -name "Závod bez grafu a teploty"
- Pokud je potřeba použít jiné mapové podklady, třeba mapy.com. Je dobré změnit i cache, aby se nepoužívali staré podklady pro OSM (výchozí).
ocactivity-gen -file "activity.fit" -mapcache "mapy" -mapurl "https://api.mapy.cz/v1/maptiles/basic/256/{z}/{x}/{y}?apikey={YOUR_API_KEY}" -name "Nedělní výlet"
- Více příkladů v help:
ocactivity-gen -h
🎛️ Přehled parametrů CLI
Zde jsou nejčastější parametry. Pro více parametrů je potřeba se podívat do -h help.
| Parametr | Popis |
|---|---|
| -file | Cesta k FIT nebo GPX souboru. |
| -bg | Cesta k obrázku, která bude na pozadí místo mapy. |
| -name | Název nebo popis aktivity. |
| -type | Typ aktivity (např. "Chůze", "Běh", "Turistika", ...). |
| -distance | Vzdálenost v metrech. |
| -avgspeed | Průměrná rychlost v km/h (např. 7.5). |
| -maxspeed | Maximální rychlost v km/h. |
| -pace | Tempo v min/km (např. "4:30"). Musí být text, jinak se to bere jako m/s. |
| -ascent | Stoupání v metrech. |
| -descent | Klesání v metrech. |
| -time | Čas v pohybu v sekundách. |
| -avghr | Průměrná tepová frekvence (bpm). |
| -maxhr | Maximální tepová frekvence (bpm). |
| -avgtemp | Průměrná teplota (°C). |
| -maxtemp | Maximální teplota (°C). |
| -kcal | Spálené kalorie. |
| -steps | Počet kroků. |
| -cdate | Datum a čas spuštění aktivity ve formátu YYYY-MM-DD HH:MM:SS. |
| -fdate | Datum a čas zastavení aktivity ve formátu YYYY-MM-DD HH:MM:SS. |
| -elapsedtime | Celkový čas aktivity v sekundách včetně přestávek. |
| -idletime | Součet času odpočinku nebo čekání v sekundách. |
| -nograph | Vypne vykreslování grafu převýšení. |
| -nogpx | Vypne vykreslování trasy na mapě. |
| -grayscale | Použije na pozadí částečný (asi 25%) černobílý efekt, aby se snížila intenzita barev. |
| -kmstep | Nastaví vzdálenost v kilometrech mezi značkami na trase. |
| -lang | Nastaví lokalizaci popisků (CZ, EN). |
| -out | Cílová cesta pro uložení obrázku. Může být jen adresář nebo i celá cesta včetně názvu. |
| -mapurl | URL adresa pro mapové podklady. Výchozí je na OSM. |
| -mapcache | Název cache adresáře, do kterého se budou ukládat mapové dlaždice. Pokud se změní URL, tak změnit i toto nebo prvně smazat cache. |
| -ccache | Smaže mapové podklady z cache. |
🐍 Použití v kódu (pro vývojáře)
Díky modularitě lze knihovnu importovat do vlastního python skriptu:
A) Podobný styl obrázku, který je generován nativně:
- Vlastní definice metrik (parametry aktivity).
from pyactivity import (
ActivityGenerator,
ActivityMetrics,
ActivityParser,
ElementStyle,
ElevationGraphConfig,
GeneratorConfig,
GPXConfig,
WatermarkConfig,
create_element,
default_viewport_callback,
format_activity_type,
)
# Vytvoření metrik
metrics = ActivityMetrics(
name="Nedělní procházka",
activity_type="Chůze",
distance=12345, # Metry (12.3 km)
moving_time=7173 # Sekundy (1h 59m 33s)
)
# Sestavení konfigurace a generátoru
config = GeneratorConfig(
# Vlastní konfigurace GPX trasy (ZDE není potřeba)
gpx=GPXConfig(),
# Konfigurace grafu převýšení (pouze pro FIT a ZDE též není potřeba)
elevation=ElevationGraphConfig(),
# Vlastní konfigurace vodoznaku
watermark=WatermarkConfig(),
# Vykreslení prvků na obrázek
# Název klíče musí odpovídat atributu v metrice!
# Pokud je potřeba vlastní element, tak musí začínat prefixem: custom_
elements={
# Název aktivity
"name": ElementStyle(
is_absolute=True,
value_pos=(360, 1180),
value_font_size=40,
auto_shrink=True, # Když bude text dlouhý, tak se začne změnšovat
value_color=(255, 255, 255, 255)
),
# Typ aktivity
"activity_type": create_element("Aktivita"),
# Ikonka pro typ
"custom_activity_type_marker": create_element(
"🎯",
is_absolute=True,
take_pos_y_from_prev_label=True
),
# Vzdálenost
"distance": create_element("Vzdálenost"),
# Ikonka pro vzdálenost
"custom_distance_marker": create_element(
"📍",
is_absolute=True,
take_pos_y_from_prev_label=True
),
# Čas pohybu
"moving_time": create_element("Čas"),
# Ikonka pro čas pohybu
"custom_moving_time_marker": create_element(
"🕒",
is_absolute=True,
take_pos_y_from_prev_label=True
)
}
)
# Uložení obrázku
generator = ActivityGenerator(metrics=metrics, config=config)
generator.save(output_path="vystup.jpg", quality=90)
B) Načtení vlastního FIT souboru:
- Bude použit stejný kód jako v bodě (A), ale musí se udělat několik úprav.
- Celý objekt s metrikami se vytvoří z FIT souboru, takže není ho potřeba vytvářet ručně.
Přidání mapování typu aktivity:
Protože FIT soubor má vlastní typy, tak se hodnoty musí přemapovat na vlastní název.
ACTIVITY_MAPPING: dict[str | None, str] = {
"walk": "Chůze",
"walking": "Chůze",
"run": "Běh",
"running": "Běh"
}
Načtení FIT souboru a metrik:
Místo vytvoření vlastních metrik je načteme z FIT souboru.
# Načtení FIT souboru a těžba dat
fit_file = Path("activity.fit")
fit_data = ActivityParser().parse_fit(fit_file)
# Získání metrik s možností je přepsat
metrics = fit_data.metrics
metrics.name = "Název aktivity" # FIT neobsahuje název
Úprava konfigurace - GeneratorConfig:
Do GeneratorConfig přidáme následující konfiguraci. Pro ukázku obsahuje více věcí, které lze taky nastavit.
# Obecná konfigurace
edge_vignette=False, # Okraje obrázku nebudou mít gradient
elevation_graph_enabled=True, # Vygeneruje graf převýšení
# Konfigurace GPX trasy
gpx=GPXConfig(
gpx_enabled=True, # Povolí vykreslení trasy
gpx_path=fit_file, # Může být GPX i FIT
gpx_points=fit_data.gpx_points, # Musí být vždy vyplněno
gpx_points_with_elev=fit_data.gpx_points_with_elev, # Tohle pouze pro FIT, protože GPX nemá převýšení
# Pokud se generuje i graf převýšení, tak je dobré použít vlastní viewport, aby trasa nezasahovala do grafu
viewport=default_viewport_callback,
show_start_finish=True, # Vykreslí začátek a konec trasy
show_km_markers=True # Vykreslí kilometrové značky na trase
),
# Konfigurace grafu převýšení (pouze pro FIT)
elevation=ElevationGraphConfig(
show_bubble_interval=True, # Značky každých N-km
show_bubble_extreme=True # Značka na nejvyšším a nejnižším místě
),
Úprava activity_type v elements:
Aby bylo možné použít vlastní mapování pro typ aktivity, tak musíme přidat mapper.
"activity_type": create_element(
"Aktivita",
formatter=lambda _cfg, _met, val: format_activity_type(val, ACTIVITY_MAPPING),
),
Celkové toho nastavení je mnoho. Tady je použit pouze nutný výčet a nějaké nice-to-have. Často je možné nastavit vše, od pozice, barvy, různých hodnot. Stačí projít konfigurační objekty.
Metadata
Release files for ocactivity-gen 1.0.12
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ocactivity_gen-1.0.12.tar.gz | 12.4 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ocactivity_gen-1.0.12-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 24.9 MB
Release files / ocactivity_gen-1.0.12.tar.gz
| Download URL | ocactivity_gen-1.0.12.tar.gz |
|---|---|
| Size | 12.4 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
cc5430e6c7dab424c0efd15ab13a8aaddc3f27835da4151a85220354376527d3
|
|
BLAKE2b-256 checksum How to use checksums |
cecf1b22a2e92ba65468507f9b2a08a44ba3e4bce69195e41ed05e9f18fbf915
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.8
|
Release files / ocactivity_gen-1.0.12-py3-none-any.whl
| Download URL | ocactivity_gen-1.0.12-py3-none-any.whl |
|---|---|
| Size | 12.5 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
691e3830b019aaf00366edda6a0a9c819bb3f355902f90ed0dc55dcd7eed6cf7
|
|
BLAKE2b-256 checksum How to use checksums |
4043c578436f04363334456a88e1cf449b4371561494f393e6337297ec8b5e57
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.8
|