new interplot relations, elev_plot hovering position displays blue marker on line_map now
This commit is contained in:
92
fit_app.py
92
fit_app.py
@@ -14,7 +14,7 @@ import datetime
|
|||||||
from math import radians, sin, cos, sqrt, asin
|
from math import radians, sin, cos, sqrt, asin
|
||||||
|
|
||||||
import dash
|
import dash
|
||||||
from dash import dcc, html, Input, Output, Dash
|
from dash import dcc, html, Input, Output, Dash, State
|
||||||
import dash_bootstrap_components as dbc
|
import dash_bootstrap_components as dbc
|
||||||
|
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
@@ -340,7 +340,7 @@ def create_info_banner(df):
|
|||||||
'justifyContent': 'space-around',
|
'justifyContent': 'space-around',
|
||||||
'backgroundColor': '#1e1e1e',
|
'backgroundColor': '#1e1e1e',
|
||||||
'color': 'white',
|
'color': 'white',
|
||||||
'padding': '20px',
|
'padding': '5px',
|
||||||
'marginBottom': '5px',
|
'marginBottom': '5px',
|
||||||
'borderRadius': '10px',
|
'borderRadius': '10px',
|
||||||
'width': '100%',
|
'width': '100%',
|
||||||
@@ -355,25 +355,6 @@ def create_info_banner(df):
|
|||||||
# START OF THE PLOTS
|
# START OF THE PLOTS
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
def create_map_plot(df):
|
def create_map_plot(df):
|
||||||
# fig = px.line_map(
|
|
||||||
# df,
|
|
||||||
# lat='lat',
|
|
||||||
# lon='lon',
|
|
||||||
# hover_name='time',
|
|
||||||
# hover_data={
|
|
||||||
# 'cum_dist_km': ':.2f',
|
|
||||||
# 'duration_hms': True,
|
|
||||||
# 'lat': False,
|
|
||||||
# 'lon': False,
|
|
||||||
# 'time': False
|
|
||||||
# },
|
|
||||||
# labels={
|
|
||||||
# 'cum_dist_km': 'Distance (km) ',
|
|
||||||
# 'duration_hms': 'Elapsed Time '
|
|
||||||
# },
|
|
||||||
# zoom=13,
|
|
||||||
# height=800
|
|
||||||
# )
|
|
||||||
fig = px.line_map(
|
fig = px.line_map(
|
||||||
df,
|
df,
|
||||||
lat='lat',
|
lat='lat',
|
||||||
@@ -394,9 +375,9 @@ def create_map_plot(df):
|
|||||||
customdata=df[['cum_dist_km', 'speed_kmh', 'heart_rate', 'duration_hms']]
|
customdata=df[['cum_dist_km', 'speed_kmh', 'heart_rate', 'duration_hms']]
|
||||||
)
|
)
|
||||||
# Define map style and the line ontop
|
# Define map style and the line ontop
|
||||||
fig.update_layout(map_style="open-street-map")
|
fig.update_layout(map_style="open-street-map") #My-Fav: open-street-map, satellite-streets, dark, white-bg
|
||||||
# The built-in plotly.js styles are: carto-darkmatter, carto-positron, open-street-map, stamen-terrain, stamen-toner, stamen-watercolor, white-bg
|
# Possible Options:
|
||||||
# The built-in Mapbox styles are: basic, streets, outdoors, light, dark, satellite, satellite-streets
|
# 'basic', 'carto-darkmatter', 'carto-darkmatter-nolabels', 'carto-positron', 'carto-positron-nolabels', 'carto-voyager', 'carto-voyager-nolabels', 'dark', 'light', 'open-street-map', 'outdoors', 'satellite', 'satellite-streets', 'streets', 'white-bg'.
|
||||||
fig.update_traces(line=dict(color="#f54269", width=3))
|
fig.update_traces(line=dict(color="#f54269", width=3))
|
||||||
|
|
||||||
# Start / Stop marker
|
# Start / Stop marker
|
||||||
@@ -410,17 +391,33 @@ def create_map_plot(df):
|
|||||||
lat=[end['lat']], lon=[end['lon']], mode='markers+text',
|
lat=[end['lat']], lon=[end['lon']], mode='markers+text',
|
||||||
marker=dict(size=12, color='#b9fc62'), text=['Stop'], name='Stop', textposition='bottom left'
|
marker=dict(size=12, color='#b9fc62'), text=['Stop'], name='Stop', textposition='bottom left'
|
||||||
))
|
))
|
||||||
fig.update_layout(paper_bgcolor='#1e1e1e', font=dict(color='white'))
|
# THIS IS MY ELEVATION-PLOT SHOW POSITION-MARKER IN MAP-PLOT:
|
||||||
|
fig.add_trace(go.Scattermap(
|
||||||
|
lat=[],
|
||||||
|
lon=[],
|
||||||
|
mode="markers",
|
||||||
|
marker=dict(size=18, color="#42B1E5", symbol="circle"),
|
||||||
|
name="Hovered Point"
|
||||||
|
))
|
||||||
|
# KOMPAKTE LAYOUT-EINSTELLUNGEN
|
||||||
fig.update_layout(
|
fig.update_layout(
|
||||||
legend=dict(
|
paper_bgcolor='#1e1e1e',
|
||||||
orientation='h', # horizontal layout
|
font=dict(color='white'),
|
||||||
yanchor='top',
|
# Margins reduzieren für kompakteren Plot
|
||||||
y=-0.01, # move legend below the map
|
margin=dict(l=60, r=45, t=10, b=50), # Links, Rechts, Oben, Unten
|
||||||
xanchor='center',
|
# Plotly-Toolbar konfigurieren
|
||||||
x=0.5,
|
showlegend=True,
|
||||||
font=dict(color='white')
|
# Kompakte Legend
|
||||||
|
legend=dict(
|
||||||
|
orientation='h', # horizontal layout
|
||||||
|
yanchor='top',
|
||||||
|
y=-0.02, # move legend below the map
|
||||||
|
xanchor='center',
|
||||||
|
x=0.5,
|
||||||
|
font=dict(color='white', size=10) # Kleinere Schrift
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
return fig
|
return fig
|
||||||
|
|
||||||
|
|
||||||
@@ -881,18 +878,20 @@ app.layout = html.Div([
|
|||||||
)
|
)
|
||||||
def load_fit_data(path):
|
def load_fit_data(path):
|
||||||
df = process_fit(path)
|
df = process_fit(path)
|
||||||
|
|
||||||
return df.to_json(date_format='iso', orient='split')
|
return df.to_json(date_format='iso', orient='split')
|
||||||
|
|
||||||
# Callback 2: Update All Plots
|
# Callback 2: Update All (static) Plots
|
||||||
@app.callback(
|
@app.callback(
|
||||||
Output('info-banner', 'children'),
|
Output('info-banner', 'children'),
|
||||||
Output('fig-map', 'figure'),
|
Output('fig-map', 'figure', allow_duplicate=True),
|
||||||
Output('fig-elevation', 'figure'),
|
Output('fig-elevation', 'figure'),
|
||||||
Output('fig_deviation', 'figure'),
|
Output('fig_deviation', 'figure'),
|
||||||
Output('fig_speed', 'figure'),
|
Output('fig_speed', 'figure'),
|
||||||
Output('fig_hr', 'figure'),
|
Output('fig_hr', 'figure'),
|
||||||
Output('fig_pace_bars', 'figure'),
|
Output('fig_pace_bars', 'figure'),
|
||||||
Input('stored-df', 'data')
|
Input('stored-df', 'data'),
|
||||||
|
prevent_initial_call=True
|
||||||
)
|
)
|
||||||
def update_all_plots(json_data):
|
def update_all_plots(json_data):
|
||||||
df = pd.read_json(io.StringIO(json_data), orient='split')
|
df = pd.read_json(io.StringIO(json_data), orient='split')
|
||||||
@@ -908,6 +907,27 @@ def update_all_plots(json_data):
|
|||||||
return info, fig_map, fig_elev, fig_dev, fig_speed, fig_hr, fig_pace
|
return info, fig_map, fig_elev, fig_dev, fig_speed, fig_hr, fig_pace
|
||||||
|
|
||||||
|
|
||||||
|
# Callback 3: Hover → update only hover (dynamic) marker
|
||||||
|
@app.callback(
|
||||||
|
Output('fig-map', 'figure'),
|
||||||
|
Input('fig-elevation', 'hoverData'),
|
||||||
|
State('fig-map', 'figure'),
|
||||||
|
State('stored-df', 'data'),
|
||||||
|
prevent_initial_call=True
|
||||||
|
)
|
||||||
|
def highlight_map(hoverData, fig_map, json_data):
|
||||||
|
df = pd.read_json(io.StringIO(json_data), orient='split')
|
||||||
|
|
||||||
|
if hoverData is not None:
|
||||||
|
point_index = hoverData['points'][0]['pointIndex']
|
||||||
|
lat, lon = df.iloc[point_index][['lat', 'lon']]
|
||||||
|
|
||||||
|
# update the last trace (the empty Hovered Point trace)
|
||||||
|
fig_map['data'][-1]['lat'] = [lat]
|
||||||
|
fig_map['data'][-1]['lon'] = [lon]
|
||||||
|
|
||||||
|
return fig_map
|
||||||
|
|
||||||
# === Run Server ===
|
# === Run Server ===
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app.run(debug=True, port=8051)
|
app.run(debug=True, port=8051)
|
||||||
|
|||||||
Reference in New Issue
Block a user