-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdashboard.py
More file actions
166 lines (143 loc) · 5.62 KB
/
dashboard.py
File metadata and controls
166 lines (143 loc) · 5.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
import pickle
import numpy as np
import pandas as pd
import plotly.graph_objs as go
import dash
from dash import dcc, html
from dash.dependencies import Input, Output
import plotly.express as px
import json
from line_finder import LineFinder
from station_explorer import StationExplorer
line_explorer = LineFinder()
stop_explorer = StationExplorer()
# Load the data
df = pd.read_pickle('dataframe.pkl')
with open('data_map/landesforstinventar-kantone_2056.geojson') as f:
data = json.load(f)
# Filtering Data
df = df[['Stop name' , 'N_coord' , 'E_coord', 'Line']]
#Lets alphabetically order the cities , we will use it in the dashboard
sorted_cities = df.sort_values(by='Stop name')
##### Set up main dashboard with radio items #####
app = dash.Dash(__name__, suppress_callback_exceptions=True)
app.layout = html.Div([
html.Div([
html.H1('SBB Platform Manager')
]),
dcc.RadioItems(
id = 'radio_items',
options = [
{'label': 'Interactive map of Switzerland', 'value': 'map'},
{'label': 'Served stations for a trainline', 'value': 'get_served_stations'}
],
value = 'map' # set default value
),
html.Br(),
html.Div(id = 'station_selecting_dropdown_with_map'),
html.Br(),
html.Div(id = 'line_selecting_dropdown_with_text_field')
])
##### Display conditional station selecting dropdown with map #####
@app.callback(
Output('station_selecting_dropdown_with_map', 'children'),
[Input('radio_items', 'value')]
)
def display_conditional_content1(selected_option):
if selected_option == 'get_served_stations':
return None # don't show dropdown and map
elif selected_option == 'map': # Show the dropdown and the map
return [
html.Br(),
html.Div("Please select the desired station to see all stations that are connected to it via a common line:"),
html.Br(),
dcc.Dropdown(
id = 'station',
options = [{'label': stop, 'value': stop} for stop in sorted_cities['Stop name'].unique()],
value = 'Bern' # set default value
),
html.Br(),
dcc.Graph(id = 'map_graph')
]
##### Update the map for the selected station #####
@app.callback(
Output('map_graph', 'figure'),
[Input('station', 'value')]
)
def update_map(selected_stop):
lines = line_explorer.get_the_lines(selected_stop)
reachable_stops = set()
for line in lines:
stations = stop_explorer.ordered_served_stations(line)
reachable_stops.update(stations)
# Filter data for reachable stops
filtered_data = df[df['Stop name'].isin(reachable_stops)]
# Create an empty figure
fig = go.Figure()
for line in lines:
line_stops = stop_explorer.ordered_served_stations(line)
# Create a DataFrame to preserve the order of stops
ordered_stops = pd.DataFrame(line_stops, columns=['Stop name'])
line_data = ordered_stops.merge(df, on='Stop name')
latitudes = line_data['N_coord'].tolist()
longitudes = line_data['E_coord'].tolist()
fig.add_trace(go.Scattermapbox(
lat=latitudes,
lon=longitudes,
mode='lines+markers',
marker=go.scattermapbox.Marker(size=9),
line=go.scattermapbox.Line(width=4),
name=f'Line {line}'
))
fig.update_layout(
mapbox=dict(
style="open-street-map",
zoom=7, # Adjust zoom level to focus on Switzerland more closely
center={"lat": 46.8, "lon": 8.2} # Center of Switzerland
),
margin={"r":0, "t":0, "l":0, "b":0},
title="Reachable Cities from Selected Stop"
)
return fig
'''Note that it is correct that there is e.g. only one line passing the station "Zürich HB" (and only three
lines are passing the station "Bern"), since the lines given in our dataset don't correspond to the "lines"
passengers talk about (like the line S4 or the line Bern-Zürich etc.) but correspond to the technical line
numbers mostly used for internal communication within SBB staff.'''
##### Display conditional line-selecting dropdown with text field #####
@app.callback(
Output('line_selecting_dropdown_with_text_field', 'children'),
[Input('radio_items', 'value')]
)
def display_conditional_content2(selected_option):
if selected_option == 'map':
return None # don't show the dropdown
elif selected_option == 'get_served_stations': # Show the dropdown and the text field
return [
html.Div("Please select the line for which you would like to know the stations:"),
html.Br(),
dcc.Dropdown(
id = 'line',
options = [{'label': line_number, 'value': line_number} for line_number in np.unique(df['Line'])],
),
html.Br(),
html.Div(
id = 'text_field'
)
]
##### Update the text field for the selected line number #####
@app.callback(
Output('text_field', 'children'),
[Input('line', 'value')]
)
def update_text_field(line_number):
if line_number != None:
stops = stop_explorer.ordered_served_stations(line_number)
stops_array = f"The train line {line_number} passes the stations: {', '.join(stops)}"
return html.P(stops_array)
else:
return None
'''We decided to keep the lines with only one station on it in the selection, since the SBB data clearly
corresponds to this and there may still be a use for knowing the station name of a line that serves ony
one station.'''
if __name__ == '__main__':
app.run_server(debug=True)