README update + new Screenshot of the FIT app Version
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
An interactive Python Dash app to visualize, analyze, and explore your jogging or running sessions recorded as GPX/FIT files.
|
An interactive Python Dash app to visualize, analyze, and explore your jogging or running sessions recorded as GPX/FIT files.
|
||||||
|
|
||||||
<p align="left">
|
<p align="left">
|
||||||
<img src="WebAppGPXDashboard.jpg" alt="Description" width="800">
|
<img src="WebAppFITDashboard.png" alt="Description" width="800">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
BIN
WebAppFITDashboard.png
Normal file
BIN
WebAppFITDashboard.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.1 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 643 KiB |
BIN
WebAppGPXDashboard.png
Normal file
BIN
WebAppGPXDashboard.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.1 MiB |
77
fit_app.py
77
fit_app.py
@@ -27,13 +27,10 @@ from fitparse import FitFile
|
|||||||
|
|
||||||
# === Helper Functions ===
|
# === Helper Functions ===
|
||||||
def list_fit_files():
|
def list_fit_files():
|
||||||
folder = './fit_files' # Ordnerpfad anpassen
|
folder = './fit_files'
|
||||||
if not os.path.exists(folder):
|
|
||||||
os.makedirs(folder)
|
|
||||||
|
|
||||||
files = [f for f in os.listdir(folder) if f.lower().endswith('.fit')]
|
files = [f for f in os.listdir(folder) if f.lower().endswith('.fit')]
|
||||||
|
|
||||||
# Datum extrahieren für Sortierung
|
# Extract date from the start of the filename and sort descending
|
||||||
def extract_date(filename):
|
def extract_date(filename):
|
||||||
try:
|
try:
|
||||||
return datetime.datetime.strptime(filename[:10], '%d.%m.%Y') # Format DD.MM.YYYY
|
return datetime.datetime.strptime(filename[:10], '%d.%m.%Y') # Format DD.MM.YYYY
|
||||||
@@ -523,6 +520,7 @@ def create_heart_rate_plot(df):
|
|||||||
mode='lines',
|
mode='lines',
|
||||||
#name='Geglättete Herzfrequenz',
|
#name='Geglättete Herzfrequenz',
|
||||||
line=dict(color='#E43D70', width=2),
|
line=dict(color='#E43D70', width=2),
|
||||||
|
showlegend=False,
|
||||||
hovertemplate=(
|
hovertemplate=(
|
||||||
"Zeit: %{x}<br>" +
|
"Zeit: %{x}<br>" +
|
||||||
"Herzfrequenz: %{y:.0f} bpm<br>" +
|
"Herzfrequenz: %{y:.0f} bpm<br>" +
|
||||||
@@ -530,18 +528,18 @@ def create_heart_rate_plot(df):
|
|||||||
)
|
)
|
||||||
))
|
))
|
||||||
|
|
||||||
# Optional: Raw Heart Rate als dünnere, transparente Linie
|
# # Optional: Raw Heart Rate als dünnere, transparente Linie
|
||||||
if not df['heart_rate'].isna().all():
|
# if not df['heart_rate'].isna().all():
|
||||||
fig.add_trace(go.Scatter(
|
# fig.add_trace(go.Scatter(
|
||||||
x=df['time'],
|
# x=df['time'],
|
||||||
y=df['heart_rate'],
|
# y=df['heart_rate'],
|
||||||
mode='lines',
|
# mode='lines',
|
||||||
name='Raw Herzfrequenz',
|
# name='Raw Herzfrequenz',
|
||||||
line=dict(color='#E43D70', width=1, dash='dot'),
|
# line=dict(color='#E43D70', width=1, dash='dot'),
|
||||||
opacity=0.3,
|
# opacity=0.3,
|
||||||
showlegend=False,
|
# showlegend=False,
|
||||||
hoverinfo='skip'
|
# hoverinfo='skip'
|
||||||
))
|
# ))
|
||||||
|
|
||||||
# Durchschnittslinie
|
# Durchschnittslinie
|
||||||
if mean_hr > 0:
|
if mean_hr > 0:
|
||||||
@@ -569,31 +567,30 @@ def create_heart_rate_plot(df):
|
|||||||
|
|
||||||
# Heart Rate Zonen (optional)
|
# Heart Rate Zonen (optional)
|
||||||
if mean_hr > 0:
|
if mean_hr > 0:
|
||||||
# Geschätzte maximale Herzfrequenz (220 - Alter, hier als Beispiel 190)
|
# Geschätzte maximale Herzfrequenz (Beispiel: 200 bpm)
|
||||||
max_hr_estimated = 190 # Du kannst das anpassen
|
# Heart Rate Zonen (optional)
|
||||||
|
# Geschätzte maximale Herzfrequenz
|
||||||
|
max_hr_estimated = 200 # oder z. B. 220 - alter
|
||||||
|
|
||||||
# Zone 1: Sehr leicht (50-60% HRmax)
|
# Definiere feste HR-Zonen in BPM
|
||||||
zone1_lower = max_hr_estimated * 0.5
|
zones = [
|
||||||
zone1_upper = max_hr_estimated * 0.6
|
{"name": "Zone 1", "lower": 0, "upper": 124, "color": "#F4A4A3"},
|
||||||
|
{"name": "Zone 2", "lower": 124, "upper": 154, "color": "#EF7476"},
|
||||||
|
{"name": "Zone 3", "lower": 154, "upper": 169, "color": "#EA4748"},
|
||||||
|
{"name": "Zone 4", "lower": 169, "upper": 184, "color": "#E02628"},
|
||||||
|
{"name": "Zone 5", "lower": 184, "upper": max_hr_estimated, "color": "#B71316"},
|
||||||
|
]
|
||||||
|
|
||||||
# Zone 2: Leicht (60-70% HRmax)
|
# Zeichne Zonen als Hintergrund (horizontale Rechtecke)
|
||||||
zone2_upper = max_hr_estimated * 0.7
|
for zone in zones:
|
||||||
|
fig.add_hrect(
|
||||||
# Zone 3: Moderat (70-80% HRmax)
|
y0=zone["lower"], y1=zone["upper"],
|
||||||
zone3_upper = max_hr_estimated * 0.8
|
fillcolor=zone["color"],
|
||||||
|
opacity=0.1,
|
||||||
# Zone 4: Hart (80-90% HRmax) #update: bis 100%
|
line_width=0,
|
||||||
zone4_upper = max_hr_estimated * 1.0
|
annotation_text=zone["name"], # optional: Name der Zone einblenden
|
||||||
|
annotation_position="top left"
|
||||||
# Füge Zonen-Bereiche als Hintergrundbereiche hinzu
|
)
|
||||||
fig.add_hrect(y0=zone1_lower, y1=zone1_upper,
|
|
||||||
fillcolor="green", opacity=0.1, line_width=0)
|
|
||||||
fig.add_hrect(y0=zone1_upper, y1=zone2_upper,
|
|
||||||
fillcolor="yellow", opacity=0.1, line_width=0)
|
|
||||||
fig.add_hrect(y0=zone2_upper, y1=zone3_upper,
|
|
||||||
fillcolor="orange", opacity=0.1, line_width=0)
|
|
||||||
fig.add_hrect(y0=zone3_upper, y1=zone4_upper,
|
|
||||||
fillcolor="red", opacity=0.1, line_width=0)
|
|
||||||
|
|
||||||
# Layout
|
# Layout
|
||||||
title_text = f'Herzfrequenz über die Zeit (geglättete)'
|
title_text = f'Herzfrequenz über die Zeit (geglättete)'
|
||||||
|
|||||||
Reference in New Issue
Block a user