ChristophS
commited on
Commit
•
9b34089
1
Parent(s):
1e3c92b
reanming fronent filter
Browse files- DataModel.py +2 -6
- Visualization.py +20 -16
- app.py +6 -9
DataModel.py
CHANGED
@@ -35,8 +35,7 @@ class DataModel:
|
|
35 |
st.error('Error while data loading')
|
36 |
st.stop()
|
37 |
# extrect feature variables from returned request json
|
38 |
-
|
39 |
-
return directs, feature, kpis, gdf
|
40 |
|
41 |
def __waiting_for_calculation(self, node_id, extension_radius):
|
42 |
"""
|
@@ -67,8 +66,7 @@ class DataModel:
|
|
67 |
:return req: response data from endpoint
|
68 |
"""
|
69 |
url = self.base_url + f'/task_status/{node_id}/{extension_radius}/NodeTimeLoss'
|
70 |
-
|
71 |
-
return req
|
72 |
|
73 |
def __extract_backend_data(self, response):
|
74 |
"""
|
@@ -93,8 +91,6 @@ class DataModel:
|
|
93 |
'Standing2LossRatio':pd.read_json(json_data['feature']['Standing2LossRatio']),
|
94 |
'TimeLoss':pd.read_json(json_data['feature']['TimeLoss']),
|
95 |
'StandingTime':pd.read_json(json_data['feature']['StandingTime'])}
|
96 |
-
# extract and process rush hour feature saved in a dataframe with traveling directions
|
97 |
-
#time = json_data['time']
|
98 |
# extract main KPIs of the node for displaying in the dashboard
|
99 |
kpis = json_data['kpis']
|
100 |
# extract GeoDataFrame with node geometry and extended node geometry
|
|
|
35 |
st.error('Error while data loading')
|
36 |
st.stop()
|
37 |
# extrect feature variables from returned request json
|
38 |
+
return _self.__extract_backend_data(response)
|
|
|
39 |
|
40 |
def __waiting_for_calculation(self, node_id, extension_radius):
|
41 |
"""
|
|
|
66 |
:return req: response data from endpoint
|
67 |
"""
|
68 |
url = self.base_url + f'/task_status/{node_id}/{extension_radius}/NodeTimeLoss'
|
69 |
+
return requests.get(url, headers={'X-API-KEY':st.secrets['api_key']})
|
|
|
70 |
|
71 |
def __extract_backend_data(self, response):
|
72 |
"""
|
|
|
91 |
'Standing2LossRatio':pd.read_json(json_data['feature']['Standing2LossRatio']),
|
92 |
'TimeLoss':pd.read_json(json_data['feature']['TimeLoss']),
|
93 |
'StandingTime':pd.read_json(json_data['feature']['StandingTime'])}
|
|
|
|
|
94 |
# extract main KPIs of the node for displaying in the dashboard
|
95 |
kpis = json_data['kpis']
|
96 |
# extract GeoDataFrame with node geometry and extended node geometry
|
Visualization.py
CHANGED
@@ -4,7 +4,6 @@ import streamlit as st
|
|
4 |
import numpy as np
|
5 |
import pandas as pd
|
6 |
import matplotlib as mpl
|
7 |
-
import ast
|
8 |
import bezier
|
9 |
|
10 |
class Visualization:
|
@@ -25,12 +24,16 @@ class Visualization:
|
|
25 |
|
26 |
def get_final_result(self, timeloss):
|
27 |
"""
|
|
|
|
|
|
|
|
|
28 |
"""
|
29 |
final = -1
|
30 |
for idx in range(1, len(self.bounds)):
|
31 |
if self.bounds[idx-1] < timeloss <=self.bounds[idx]:
|
32 |
-
|
33 |
-
|
34 |
return self.final_result[final]
|
35 |
|
36 |
def create_folium_map(self, gdf):
|
@@ -65,6 +68,11 @@ class Visualization:
|
|
65 |
return figures, results, min_loss
|
66 |
|
67 |
def get_min_relavent_direction_loss(self, results):
|
|
|
|
|
|
|
|
|
|
|
68 |
total_rides = sum([df[df['Richtung']=='Gesamt']['Fahrten'].sum() for df in results])
|
69 |
min_rides = self.min_ride_percentage*total_rides
|
70 |
loss_class = []
|
@@ -89,15 +97,14 @@ class Visualization:
|
|
89 |
:param df_time: datafrme with the aggregated rushhour feature of the travel direction
|
90 |
"""
|
91 |
# initialise dataframes for displaying feature in dataframe format
|
92 |
-
df_result = pd.DataFrame(index=range(len(directs)+1),columns=['Richtung', '
|
93 |
# define maplotlib figure and axes objects for direction plots
|
94 |
fig_loss, axs_loss = plt.subplots(1,3, figsize=(8,4), gridspec_kw={'width_ratios':[1, 1, 0.15]})
|
95 |
# setup input angle and transform data into the radians and the projection onto the unit circle
|
96 |
angle_in = directs[current_key]['value']
|
97 |
origin = (180+angle_in)%360
|
98 |
rad_origin = np.deg2rad(origin)
|
99 |
-
x_origin = np.cos(rad_origin)
|
100 |
-
y_origin = np.sin(rad_origin)
|
101 |
# initialise tracking parameter for total time quality feature estimation of the travel directions
|
102 |
total_loss = 0
|
103 |
total_rides = 0
|
@@ -120,7 +127,7 @@ class Visualization:
|
|
120 |
# save aggregated time quality data in dataframe
|
121 |
df_result.at[i, 'Richtung'] = f"{directs[dkey_out]['name']}"
|
122 |
df_result.at[i, 'Zeitverlust'] = np.round(timeloss,2)
|
123 |
-
df_result.at[i, '
|
124 |
df_result.at[i, 'Fahrten'] = rides
|
125 |
df_result.at[i, 'Ratio'] = np.round(ratio,2)
|
126 |
total_loss += rides*timeloss
|
@@ -171,7 +178,7 @@ class Visualization:
|
|
171 |
axs_loss[a].axis('off')
|
172 |
# set plot titles
|
173 |
axs_loss[0].set_title(f'Zeitverlust')
|
174 |
-
axs_loss[1].set_title(f'
|
175 |
# drop not used columns from dataframe
|
176 |
df_result.dropna(inplace=True)
|
177 |
# calculate mean resulting feature of all directions for time quality feature
|
@@ -179,7 +186,7 @@ class Visualization:
|
|
179 |
df_result.at[i+1, 'Fahrten'] = total_rides
|
180 |
if total_rides >0:
|
181 |
df_result.at[i+1, 'Zeitverlust'] = np.round(total_loss/total_rides, 2)
|
182 |
-
df_result.at[i+1, '
|
183 |
df_result.at[i+1, 'Ratio'] = np.round(total_ratio/total_rides, 2)
|
184 |
else:
|
185 |
df_result.fillna(0, inplace=True)
|
@@ -207,9 +214,7 @@ class Visualization:
|
|
207 |
data.append(curve.evaluate(float(p)))
|
208 |
# reshape data
|
209 |
data = np.array(data).reshape(n,2)
|
210 |
-
|
211 |
-
y_out = data[:,1]
|
212 |
-
return x_out, y_out
|
213 |
|
214 |
def get_unit_circle_data(self, n=50):
|
215 |
"""
|
@@ -218,10 +223,9 @@ class Visualization:
|
|
218 |
:return x: x coordinates of the points on the unit circle
|
219 |
:return y: y coordinates of the poits on the unit cirlce
|
220 |
"""
|
221 |
-
alpha = np.linspace(0, np.pi
|
222 |
-
x =
|
223 |
-
|
224 |
-
return x,y
|
225 |
|
226 |
def get_metric_color(self, value):
|
227 |
"""
|
|
|
4 |
import numpy as np
|
5 |
import pandas as pd
|
6 |
import matplotlib as mpl
|
|
|
7 |
import bezier
|
8 |
|
9 |
class Visualization:
|
|
|
24 |
|
25 |
def get_final_result(self, timeloss):
|
26 |
"""
|
27 |
+
Function for calculating the time loss class in a range from
|
28 |
+
'A' very good to 'F' very bad
|
29 |
+
:param timeloss: worst relevant timeloss of node driving directions
|
30 |
+
:return: timeloss class
|
31 |
"""
|
32 |
final = -1
|
33 |
for idx in range(1, len(self.bounds)):
|
34 |
if self.bounds[idx-1] < timeloss <=self.bounds[idx]:
|
35 |
+
return self.final_result[idx-1]
|
36 |
+
|
37 |
return self.final_result[final]
|
38 |
|
39 |
def create_folium_map(self, gdf):
|
|
|
68 |
return figures, results, min_loss
|
69 |
|
70 |
def get_min_relavent_direction_loss(self, results):
|
71 |
+
"""
|
72 |
+
Method for calculating the timeloss of the worst relevant node path
|
73 |
+
:param results: dataframe with possible driving paths and timelosses
|
74 |
+
:return: timeloss
|
75 |
+
"""
|
76 |
total_rides = sum([df[df['Richtung']=='Gesamt']['Fahrten'].sum() for df in results])
|
77 |
min_rides = self.min_ride_percentage*total_rides
|
78 |
loss_class = []
|
|
|
97 |
:param df_time: datafrme with the aggregated rushhour feature of the travel direction
|
98 |
"""
|
99 |
# initialise dataframes for displaying feature in dataframe format
|
100 |
+
df_result = pd.DataFrame(index=range(len(directs)+1),columns=['Richtung', 'Standzeit', 'Zeitverlust', 'Ratio', 'Fahrten'])
|
101 |
# define maplotlib figure and axes objects for direction plots
|
102 |
fig_loss, axs_loss = plt.subplots(1,3, figsize=(8,4), gridspec_kw={'width_ratios':[1, 1, 0.15]})
|
103 |
# setup input angle and transform data into the radians and the projection onto the unit circle
|
104 |
angle_in = directs[current_key]['value']
|
105 |
origin = (180+angle_in)%360
|
106 |
rad_origin = np.deg2rad(origin)
|
107 |
+
x_origin, y_origin = np.cos(rad_origin), np.sin(rad_origin)
|
|
|
108 |
# initialise tracking parameter for total time quality feature estimation of the travel directions
|
109 |
total_loss = 0
|
110 |
total_rides = 0
|
|
|
127 |
# save aggregated time quality data in dataframe
|
128 |
df_result.at[i, 'Richtung'] = f"{directs[dkey_out]['name']}"
|
129 |
df_result.at[i, 'Zeitverlust'] = np.round(timeloss,2)
|
130 |
+
df_result.at[i, 'Standzeit'] = np.round(waiting,2)
|
131 |
df_result.at[i, 'Fahrten'] = rides
|
132 |
df_result.at[i, 'Ratio'] = np.round(ratio,2)
|
133 |
total_loss += rides*timeloss
|
|
|
178 |
axs_loss[a].axis('off')
|
179 |
# set plot titles
|
180 |
axs_loss[0].set_title(f'Zeitverlust')
|
181 |
+
axs_loss[1].set_title(f'Standzeit')
|
182 |
# drop not used columns from dataframe
|
183 |
df_result.dropna(inplace=True)
|
184 |
# calculate mean resulting feature of all directions for time quality feature
|
|
|
186 |
df_result.at[i+1, 'Fahrten'] = total_rides
|
187 |
if total_rides >0:
|
188 |
df_result.at[i+1, 'Zeitverlust'] = np.round(total_loss/total_rides, 2)
|
189 |
+
df_result.at[i+1, 'Standzeit'] = np.round(total_waiting/total_rides, 2)
|
190 |
df_result.at[i+1, 'Ratio'] = np.round(total_ratio/total_rides, 2)
|
191 |
else:
|
192 |
df_result.fillna(0, inplace=True)
|
|
|
214 |
data.append(curve.evaluate(float(p)))
|
215 |
# reshape data
|
216 |
data = np.array(data).reshape(n,2)
|
217 |
+
return data[:,0], data[:,1]
|
|
|
|
|
218 |
|
219 |
def get_unit_circle_data(self, n=50):
|
220 |
"""
|
|
|
223 |
:return x: x coordinates of the points on the unit circle
|
224 |
:return y: y coordinates of the poits on the unit cirlce
|
225 |
"""
|
226 |
+
alpha = np.linspace(0, 2*np.pi, n, endpoint=True)
|
227 |
+
# return x and y coordinates in polor coordinate system with radius = 1
|
228 |
+
return np.cos(alpha), np.sin(alpha)
|
|
|
229 |
|
230 |
def get_metric_color(self, value):
|
231 |
"""
|
app.py
CHANGED
@@ -1,5 +1,4 @@
|
|
1 |
import streamlit as st
|
2 |
-
import numpy as np
|
3 |
from streamlit_folium import st_folium
|
4 |
from DataModel import DataModel
|
5 |
from Visualization import Visualization
|
@@ -7,8 +6,6 @@ from Visualization import Visualization
|
|
7 |
def app_run(node_id=0):
|
8 |
# page configs
|
9 |
st.set_page_config(page_title='Zeitverluste an Knotenpunkten', layout='wide')
|
10 |
-
#st.write(st.__version__)
|
11 |
-
|
12 |
# handle empty query parameter
|
13 |
node = st.experimental_get_query_params()
|
14 |
if 'node_id' in node:
|
@@ -26,7 +23,7 @@ def app_run(node_id=0):
|
|
26 |
st.session_state['extension_radius'] = 30#[m]
|
27 |
|
28 |
# get data from backend
|
29 |
-
directs, feature,
|
30 |
# create images for direction and
|
31 |
with st.spinner('Grafiken werden erstellt ...'):
|
32 |
folium_map = visu.create_folium_map(gdf)
|
@@ -34,7 +31,7 @@ def app_run(node_id=0):
|
|
34 |
|
35 |
usable_rides = int(sum([df.tail(1)['Fahrten'] for df in results]))
|
36 |
mean_time_loss = float(sum([df.tail(1)['Fahrten']*df.tail(1)['Zeitverlust'] for df in results])/usable_rides)
|
37 |
-
mean_waiting_time = float(sum([df.tail(1)['Fahrten']*df.tail(1)['
|
38 |
# dsipaly time quality plots, time quality dataframes and rush hour data frames for each travel direction in a different tab
|
39 |
input_directions = [f"Richtung {directs[d]['name']}" for d in directs]
|
40 |
#
|
@@ -48,7 +45,7 @@ def app_run(node_id=0):
|
|
48 |
elem1.header(f":{color}[{visu.float2str(mean_time_loss)}s]")
|
49 |
#
|
50 |
elem2 = metric_cols[2].container()#border=True
|
51 |
-
elem2.markdown('Gesamte
|
52 |
color = visu.get_metric_color(mean_waiting_time)
|
53 |
elem2.header(f":{color}[{visu.float2str(mean_waiting_time)}s]")
|
54 |
#
|
@@ -56,7 +53,7 @@ def app_run(node_id=0):
|
|
56 |
elem3.markdown('Gesamtbewertung')
|
57 |
color = visu.get_metric_color(worst_relevant_loss['Zeitverlust'])
|
58 |
final_class = visu.get_final_result(worst_relevant_loss['Zeitverlust'])
|
59 |
-
indirection =input_directions[worst_relevant_loss['InDirection']]
|
60 |
elem3.header(f":{color}[{final_class}, {visu.float2str(worst_relevant_loss['Zeitverlust'])}s]")
|
61 |
elem3.text(f" Einfahrtsrichtung: {indirection[9:]} \n Ausfahrtsrichtung: {worst_relevant_loss['Richtung']}")
|
62 |
# define column layout
|
@@ -76,12 +73,12 @@ def app_run(node_id=0):
|
|
76 |
cols[0].dataframe(results[idx], hide_index=True, use_container_width=True)
|
77 |
|
78 |
def get_plot_helper_text():
|
79 |
-
return '''Darstellung der
|
80 |
Zeitliche Verluste werden entsprechend den Qualitätsklassen farblich visualisiert.
|
81 |
Zusätzlich erfolgt die Darstellung der Anzahl der Fahrten pro Fahrtrichtung durch die Breite der Linien. '''
|
82 |
|
83 |
def get_table_helper_text():
|
84 |
-
return '''Liste der durchschnittlichen
|
85 |
wobei die Richtungen den in der Abbildung dargestellten Fahrtrichtungen entsprechen.'''
|
86 |
|
87 |
if __name__ == '__main__':
|
|
|
1 |
import streamlit as st
|
|
|
2 |
from streamlit_folium import st_folium
|
3 |
from DataModel import DataModel
|
4 |
from Visualization import Visualization
|
|
|
6 |
def app_run(node_id=0):
|
7 |
# page configs
|
8 |
st.set_page_config(page_title='Zeitverluste an Knotenpunkten', layout='wide')
|
|
|
|
|
9 |
# handle empty query parameter
|
10 |
node = st.experimental_get_query_params()
|
11 |
if 'node_id' in node:
|
|
|
23 |
st.session_state['extension_radius'] = 30#[m]
|
24 |
|
25 |
# get data from backend
|
26 |
+
directs, feature, _, gdf = dm.get_data_of_node(st.session_state['node_id'],st.session_state['extension_radius'])
|
27 |
# create images for direction and
|
28 |
with st.spinner('Grafiken werden erstellt ...'):
|
29 |
folium_map = visu.create_folium_map(gdf)
|
|
|
31 |
|
32 |
usable_rides = int(sum([df.tail(1)['Fahrten'] for df in results]))
|
33 |
mean_time_loss = float(sum([df.tail(1)['Fahrten']*df.tail(1)['Zeitverlust'] for df in results])/usable_rides)
|
34 |
+
mean_waiting_time = float(sum([df.tail(1)['Fahrten']*df.tail(1)['Standzeit'] for df in results])/usable_rides)
|
35 |
# dsipaly time quality plots, time quality dataframes and rush hour data frames for each travel direction in a different tab
|
36 |
input_directions = [f"Richtung {directs[d]['name']}" for d in directs]
|
37 |
#
|
|
|
45 |
elem1.header(f":{color}[{visu.float2str(mean_time_loss)}s]")
|
46 |
#
|
47 |
elem2 = metric_cols[2].container()#border=True
|
48 |
+
elem2.markdown('Gesamte Standzeit')
|
49 |
color = visu.get_metric_color(mean_waiting_time)
|
50 |
elem2.header(f":{color}[{visu.float2str(mean_waiting_time)}s]")
|
51 |
#
|
|
|
53 |
elem3.markdown('Gesamtbewertung')
|
54 |
color = visu.get_metric_color(worst_relevant_loss['Zeitverlust'])
|
55 |
final_class = visu.get_final_result(worst_relevant_loss['Zeitverlust'])
|
56 |
+
indirection = input_directions[worst_relevant_loss['InDirection']]
|
57 |
elem3.header(f":{color}[{final_class}, {visu.float2str(worst_relevant_loss['Zeitverlust'])}s]")
|
58 |
elem3.text(f" Einfahrtsrichtung: {indirection[9:]} \n Ausfahrtsrichtung: {worst_relevant_loss['Richtung']}")
|
59 |
# define column layout
|
|
|
73 |
cols[0].dataframe(results[idx], hide_index=True, use_container_width=True)
|
74 |
|
75 |
def get_plot_helper_text():
|
76 |
+
return '''Darstellung der Stand- und Verlustzeiten an den Ein- und Ausfahrtswegen im Knotenpunkt.
|
77 |
Zeitliche Verluste werden entsprechend den Qualitätsklassen farblich visualisiert.
|
78 |
Zusätzlich erfolgt die Darstellung der Anzahl der Fahrten pro Fahrtrichtung durch die Breite der Linien. '''
|
79 |
|
80 |
def get_table_helper_text():
|
81 |
+
return '''Liste der durchschnittlichen Stand- und Verlustzeiten pro Fahrtrichtung,
|
82 |
wobei die Richtungen den in der Abbildung dargestellten Fahrtrichtungen entsprechen.'''
|
83 |
|
84 |
if __name__ == '__main__':
|