Spaces:
Sleeping
Sleeping
Commit
·
aec6e07
1
Parent(s):
302cd89
added line scores tiles
Browse files- app/app.py +224 -177
- app/data_processing/get_station_coverage.py +1 -1
app/app.py
CHANGED
@@ -61,6 +61,7 @@ with ui.sidebar(open="open"):
|
|
61 |
ui.input_action_button("reset", "Reset zoom")
|
62 |
|
63 |
with ui.layout_columns(col_widths=[8, 4]):
|
|
|
64 |
with ui.card(full_screen=True):
|
65 |
ui.card_header("Capital area")
|
66 |
|
@@ -69,179 +70,215 @@ with ui.layout_columns(col_widths=[8, 4]):
|
|
69 |
def map():
|
70 |
return Map(
|
71 |
basemap=basemaps.CartoDB.Positron)
|
|
|
|
|
|
|
|
|
|
|
72 |
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
with ui.
|
77 |
-
with ui.
|
78 |
-
"
|
79 |
@render.text
|
80 |
-
def
|
81 |
-
|
82 |
-
|
|
|
83 |
|
84 |
-
|
85 |
-
def contribution_pie_chart():
|
86 |
-
print("Generating pie chart of contributions")
|
87 |
-
|
88 |
-
# Get score components
|
89 |
-
score = scores()
|
90 |
-
age_contribution = score["age_score"]
|
91 |
-
income_contribution = score["income_score"]
|
92 |
-
density_contribution = score["density_score"]
|
93 |
-
|
94 |
-
# Data for the pie chart
|
95 |
-
contributions = [age_contribution, income_contribution, density_contribution]
|
96 |
-
labels = ["Age", "Income", "Density"]
|
97 |
-
colors = ["#FD4D86", "#36DEC2", "#704CB0"] # Custom colors for the segments
|
98 |
-
|
99 |
-
# Create a Matplotlib figure
|
100 |
-
fig, ax = plt.subplots(figsize=(6, 6))
|
101 |
-
|
102 |
-
# Create the pie chart
|
103 |
-
ax.pie(
|
104 |
-
contributions,
|
105 |
-
labels=labels,
|
106 |
-
autopct='%1.1f%%',
|
107 |
-
startangle=90,
|
108 |
-
colors=colors,
|
109 |
-
textprops={'fontsize': 12}
|
110 |
-
)
|
111 |
-
|
112 |
-
# Add a title
|
113 |
-
ax.set_title("Score Contributions", fontsize=16)
|
114 |
-
|
115 |
-
# Return the figure for rendering in Shiny
|
116 |
-
return fig
|
117 |
-
|
118 |
-
with ui.nav_panel("Income"):
|
119 |
-
"Income Score"
|
120 |
@render.text
|
121 |
-
def
|
122 |
-
|
123 |
-
return f"{round(float(score["income_score"]), 2)}"
|
124 |
-
@render.plot(alt="A chart of income distribution.")
|
125 |
-
def income_plot():
|
126 |
-
print("Generating income distribution bar chart")
|
127 |
-
|
128 |
-
# Get selected stop coordinates
|
129 |
-
x, y = stop.get()
|
130 |
-
station_coord = (y, x)
|
131 |
-
|
132 |
-
# Fetch income distribution data from the Data_provider instance
|
133 |
-
income_data = initBackend.get_station_score(station_coord, radius=input.rad())['income_data'] # Assume this returns a dictionary
|
134 |
-
|
135 |
-
# Example structure: {1: 150, 2: 200, 3: 180, ...}
|
136 |
-
income_brackets = list(income_data.keys())
|
137 |
-
populations = list(income_data.values())
|
138 |
-
|
139 |
-
# Create a Matplotlib figure
|
140 |
-
fig, ax = plt.subplots(figsize=(8, 4))
|
141 |
-
|
142 |
-
# Create the bar chart
|
143 |
-
ax.bar(income_brackets, populations, color='#36DEC2')
|
144 |
-
|
145 |
-
# Customize the plot
|
146 |
-
ax.set_title("Population by Income Bracket")
|
147 |
-
ax.set_xlabel("Income Bracket")
|
148 |
-
ax.set_ylabel("Population")
|
149 |
-
ax.set_xticks(income_brackets)
|
150 |
-
ax.set_xticklabels(income_brackets, rotation=45, ha="right")
|
151 |
-
|
152 |
-
# Return the figure for rendering in Shiny
|
153 |
-
return fig
|
154 |
|
155 |
-
|
156 |
-
|
157 |
-
"Age Score"
|
158 |
@render.text
|
159 |
-
def
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
def age_plot():
|
165 |
-
print("Generating age distribution bar chart")
|
166 |
-
|
167 |
-
# Get selected stop coordinates
|
168 |
-
x, y = stop.get()
|
169 |
-
station_coord = (y, x)
|
170 |
-
|
171 |
-
# Fetch age distribution data from the Data_provider instance
|
172 |
-
age_data = initBackend.get_station_score(station_coord, radius=input.rad())['age_data'] # Assume this returns a dictionary
|
173 |
-
|
174 |
-
# Example structure: {'0-4 ára': 120, '5-9 ára': 140, ...}
|
175 |
-
age_brackets = list(age_data.keys())
|
176 |
-
populations = list(age_data.values())
|
177 |
-
|
178 |
-
# Create a Matplotlib figure
|
179 |
-
fig, ax = plt.subplots(figsize=(8, 4))
|
180 |
-
|
181 |
-
# Create the bar chart with custom colors
|
182 |
-
ax.bar(age_brackets, populations, color='#FD4D86')
|
183 |
-
|
184 |
-
# Customize the plot
|
185 |
-
ax.set_title("Population by Age Bracket", fontsize=14)
|
186 |
-
ax.set_xlabel("Age Bracket", fontsize=12)
|
187 |
-
ax.set_ylabel("Population", fontsize=12)
|
188 |
-
ax.set_xticks(range(len(age_brackets)))
|
189 |
-
ax.set_xticklabels(age_brackets, rotation=45, ha="right", fontsize=10)
|
190 |
-
|
191 |
-
# Return the figure for rendering in Shiny
|
192 |
-
return fig
|
193 |
-
|
194 |
-
with ui.nav_panel("Density"):
|
195 |
-
"Density"
|
196 |
@render.text
|
197 |
-
def
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
w_age=input.w_age()
|
218 |
-
)['small_area_contributions']
|
219 |
-
|
220 |
-
# Extract density scores for each small area
|
221 |
-
area_ids = [area_id for area_id in small_area_contributions.keys()]
|
222 |
-
density_scores = [area_data['density_score'] for area_data in small_area_contributions.values()]
|
223 |
|
224 |
-
# Create a Matplotlib figure
|
225 |
-
fig, ax = plt.subplots(figsize=(8, 4))
|
226 |
|
227 |
-
|
228 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
229 |
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
236 |
|
237 |
-
# Return the figure for rendering in Shiny
|
238 |
-
return fig
|
239 |
|
240 |
-
with ui.nav_panel("The Line"):
|
241 |
-
"The Total Score For Lines"
|
242 |
-
@render.text
|
243 |
-
def line():
|
244 |
-
return lineScore()
|
245 |
|
246 |
|
247 |
|
@@ -324,27 +361,37 @@ def scores():
|
|
324 |
score = initBackend.get_station_score(station_coord=(y, x), w_density=input.w_density(), w_income=input.w_income(), w_age=input. w_age(), radius=input.rad())
|
325 |
return score
|
326 |
|
327 |
-
|
328 |
@reactive.calc
|
329 |
def lineScore():
|
|
|
330 |
listOfStops = generateStops(input.year())
|
331 |
listOflines = {}
|
|
|
|
|
332 |
for stop, color in listOfStops:
|
333 |
x, y = stop
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
339 |
|
340 |
-
|
|
|
341 |
for key, val in listOflines.items():
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
|
|
|
61 |
ui.input_action_button("reset", "Reset zoom")
|
62 |
|
63 |
with ui.layout_columns(col_widths=[8, 4]):
|
64 |
+
|
65 |
with ui.card(full_screen=True):
|
66 |
ui.card_header("Capital area")
|
67 |
|
|
|
70 |
def map():
|
71 |
return Map(
|
72 |
basemap=basemaps.CartoDB.Positron)
|
73 |
+
|
74 |
+
|
75 |
+
|
76 |
+
|
77 |
+
|
78 |
|
79 |
+
|
80 |
+
|
81 |
+
with ui.layout_column_wrap(width="450px"):
|
82 |
+
with ui.layout_columns(col_widths=(6, 6)):
|
83 |
+
with ui.value_box(theme="bg-gradient-red-yellow"):
|
84 |
+
"Red line"
|
85 |
@render.text
|
86 |
+
def render_line_score():
|
87 |
+
return str(lineScore().get("red", 0))
|
88 |
+
|
89 |
+
with ui.value_box(theme="bg-gradient-blue-cyan"):
|
90 |
|
91 |
+
"Blue line"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
92 |
@render.text
|
93 |
+
def render_line_score1():
|
94 |
+
return str(lineScore().get("blue", 0))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
95 |
|
96 |
+
with ui.value_box(theme="bg-gradient-orange-yellow"):
|
97 |
+
"Orange line"
|
|
|
98 |
@render.text
|
99 |
+
def render_line_score2():
|
100 |
+
return str(lineScore().get("orange", 0))
|
101 |
+
|
102 |
+
with ui.value_box(theme="bg-gradient-indigo-purple"):
|
103 |
+
"Purple line"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
@render.text
|
105 |
+
def render_line_score3():
|
106 |
+
return str(lineScore().get("purple", 0))
|
107 |
+
|
108 |
+
with ui.value_box(theme="bg-gradient-green-teal"):
|
109 |
+
"Green line"
|
110 |
+
@render.text
|
111 |
+
def render_line_score4():
|
112 |
+
return str(lineScore().get("green", 0))
|
113 |
+
|
114 |
+
with ui.value_box():
|
115 |
+
"Total score"
|
116 |
+
@render.text
|
117 |
+
def render_line_score5():
|
118 |
+
return str(sum(lineScore().get(color, 0) for color in ["red", "blue", "orange", "purple", "green"]))
|
119 |
+
|
120 |
+
|
121 |
+
with ui.card(min_height="600px"):
|
122 |
+
ui.card_header("Stop Data")
|
123 |
+
with ui.navset_pill(id="tab"):
|
124 |
+
with ui.nav_panel("Score Contributions"):
|
|
|
|
|
|
|
|
|
|
|
|
|
125 |
|
|
|
|
|
126 |
|
127 |
+
@render.plot(alt="A pie chart of score contributions from age, income, and density.")
|
128 |
+
def contribution_pie_chart():
|
129 |
+
print("Generating pie chart of contributions")
|
130 |
+
|
131 |
+
# Get score components
|
132 |
+
score = scores()
|
133 |
+
age_contribution = score["age_score"]
|
134 |
+
income_contribution = score["income_score"]
|
135 |
+
density_contribution = score["density_score"]
|
136 |
+
|
137 |
+
# Data for the pie chart
|
138 |
+
contributions = [age_contribution, income_contribution, density_contribution]
|
139 |
+
labels = ["Age", "Income", "Density"]
|
140 |
+
colors = ["#FD4D86", "#36DEC2", "#704CB0"] # Custom colors for the segments
|
141 |
+
|
142 |
+
# Create a Matplotlib figure
|
143 |
+
fig, ax = plt.subplots(figsize=(6, 6))
|
144 |
+
|
145 |
+
# Create the pie chart
|
146 |
+
ax.pie(
|
147 |
+
contributions,
|
148 |
+
labels=labels,
|
149 |
+
autopct='%1.1f%%',
|
150 |
+
startangle=90,
|
151 |
+
colors=colors,
|
152 |
+
textprops={'fontsize': 12}
|
153 |
+
)
|
154 |
+
|
155 |
+
# Add a title
|
156 |
+
ax.set_title("Score Contributions", fontsize=16)
|
157 |
+
|
158 |
+
# Return the figure for rendering in Shiny
|
159 |
+
return fig
|
160 |
+
|
161 |
+
with ui.nav_panel("Income"):
|
162 |
+
"Income Score"
|
163 |
+
@render.text
|
164 |
+
def incomeScore():
|
165 |
+
score = scores()
|
166 |
+
return score["income_score"]
|
167 |
+
@render.plot(alt="A chart of income distribution.")
|
168 |
+
def income_plot():
|
169 |
+
print("Generating income distribution bar chart")
|
170 |
+
|
171 |
+
# Get selected stop coordinates
|
172 |
+
x, y = stop.get()
|
173 |
+
station_coord = (y, x)
|
174 |
+
|
175 |
+
# Fetch income distribution data from the Data_provider instance
|
176 |
+
income_data = initBackend.get_station_score(station_coord, radius=input.rad())['income_data'] # Assume this returns a dictionary
|
177 |
+
|
178 |
+
# Example structure: {1: 150, 2: 200, 3: 180, ...}
|
179 |
+
income_brackets = list(income_data.keys())
|
180 |
+
populations = list(income_data.values())
|
181 |
+
|
182 |
+
# Create a Matplotlib figure
|
183 |
+
fig, ax = plt.subplots(figsize=(8, 4))
|
184 |
+
|
185 |
+
# Create the bar chart
|
186 |
+
ax.bar(income_brackets, populations, color='#36DEC2')
|
187 |
+
|
188 |
+
# Customize the plot
|
189 |
+
ax.set_title("Population by Income Bracket")
|
190 |
+
ax.set_xlabel("Income Bracket")
|
191 |
+
ax.set_ylabel("Population")
|
192 |
+
ax.set_xticks(income_brackets)
|
193 |
+
ax.set_xticklabels(income_brackets, rotation=45, ha="right")
|
194 |
+
|
195 |
+
# Return the figure for rendering in Shiny
|
196 |
+
return fig
|
197 |
+
|
198 |
+
|
199 |
+
with ui.nav_panel("Age"):
|
200 |
+
"Age Score"
|
201 |
+
@render.text
|
202 |
+
def ageScore():
|
203 |
+
score = scores()
|
204 |
+
return score["age_score"]
|
205 |
+
@render.plot(alt="A bar chart of age distribution.")
|
206 |
+
def age_plot():
|
207 |
+
print("Generating age distribution bar chart")
|
208 |
+
|
209 |
+
# Get selected stop coordinates
|
210 |
+
x, y = stop.get()
|
211 |
+
station_coord = (y, x)
|
212 |
+
|
213 |
+
# Fetch age distribution data from the Data_provider instance
|
214 |
+
age_data = initBackend.get_station_score(station_coord, radius=input.rad())['age_data'] # Assume this returns a dictionary
|
215 |
+
|
216 |
+
# Example structure: {'0-4 ára': 120, '5-9 ára': 140, ...}
|
217 |
+
age_brackets = list(age_data.keys())
|
218 |
+
populations = list(age_data.values())
|
219 |
+
|
220 |
+
# Create a Matplotlib figure
|
221 |
+
fig, ax = plt.subplots(figsize=(8, 4))
|
222 |
+
|
223 |
+
# Create the bar chart with custom colors
|
224 |
+
ax.bar(age_brackets, populations, color='#FD4D86')
|
225 |
+
|
226 |
+
# Customize the plot
|
227 |
+
ax.set_title("Population by Age Bracket", fontsize=14)
|
228 |
+
ax.set_xlabel("Age Bracket", fontsize=12)
|
229 |
+
ax.set_ylabel("Population", fontsize=12)
|
230 |
+
ax.set_xticks(range(len(age_brackets)))
|
231 |
+
ax.set_xticklabels(age_brackets, rotation=45, ha="right", fontsize=10)
|
232 |
+
|
233 |
+
# Return the figure for rendering in Shiny
|
234 |
+
return fig
|
235 |
|
236 |
+
with ui.nav_panel("Density"):
|
237 |
+
"Density"
|
238 |
+
@render.text
|
239 |
+
def sensityScoer():
|
240 |
+
score = scores()
|
241 |
+
return float(score["density_score"] * 1000000)
|
242 |
+
|
243 |
+
|
244 |
+
@render.plot(alt="A bar chart of density scores for all areas within the radius.")
|
245 |
+
def density_plot():
|
246 |
+
print("Generating density score bar chart")
|
247 |
+
|
248 |
+
# Get selected stop coordinates
|
249 |
+
x, y = stop.get()
|
250 |
+
station_coord = (y, x)
|
251 |
+
|
252 |
+
# Fetch small area contributions from the Data_provider instance
|
253 |
+
small_area_contributions = initBackend.get_station_score(
|
254 |
+
station_coord,
|
255 |
+
radius=input.rad(),
|
256 |
+
w_density=input.w_density(),
|
257 |
+
w_income=input.w_income(),
|
258 |
+
w_age=input.w_age()
|
259 |
+
)['small_area_contributions']
|
260 |
+
|
261 |
+
# Extract density scores for each small area
|
262 |
+
area_ids = [area_id for area_id in small_area_contributions.keys()]
|
263 |
+
density_scores = [area_data['density_score'] for area_data in small_area_contributions.values()]
|
264 |
+
|
265 |
+
# Create a Matplotlib figure
|
266 |
+
fig, ax = plt.subplots(figsize=(8, 4))
|
267 |
+
|
268 |
+
# Create the bar chart
|
269 |
+
ax.bar(area_ids, density_scores, color='#704CB0')
|
270 |
+
|
271 |
+
# Customize the plot
|
272 |
+
ax.set_title("Density Scores of Small Areas", fontsize=14)
|
273 |
+
ax.set_xlabel("Small Area ID", fontsize=12)
|
274 |
+
ax.set_ylabel("Density Score", fontsize=12)
|
275 |
+
ax.set_xticks(range(len(area_ids)))
|
276 |
+
ax.set_xticklabels(area_ids, rotation=45, ha="right", fontsize=10)
|
277 |
+
|
278 |
+
# Return the figure for rendering in Shiny
|
279 |
+
return fig
|
280 |
|
|
|
|
|
281 |
|
|
|
|
|
|
|
|
|
|
|
282 |
|
283 |
|
284 |
|
|
|
361 |
score = initBackend.get_station_score(station_coord=(y, x), w_density=input.w_density(), w_income=input.w_income(), w_age=input. w_age(), radius=input.rad())
|
362 |
return score
|
363 |
|
|
|
364 |
@reactive.calc
|
365 |
def lineScore():
|
366 |
+
# Generate stops based on the input year
|
367 |
listOfStops = generateStops(input.year())
|
368 |
listOflines = {}
|
369 |
+
|
370 |
+
# Handle stops with single and multiple colors
|
371 |
for stop, color in listOfStops:
|
372 |
x, y = stop
|
373 |
+
# If the color is a list (multiple colors), iterate through it
|
374 |
+
if isinstance(color, list):
|
375 |
+
for single_color in color:
|
376 |
+
if single_color not in listOflines:
|
377 |
+
listOflines[single_color] = []
|
378 |
+
listOflines[single_color].append((y, x))
|
379 |
+
else:
|
380 |
+
# If it's a single color, process it normally
|
381 |
+
if color not in listOflines:
|
382 |
+
listOflines[color] = []
|
383 |
+
listOflines[color].append((y, x))
|
384 |
|
385 |
+
# Calculate scores for each line
|
386 |
+
lines = {}
|
387 |
for key, val in listOflines.items():
|
388 |
+
score = initBackend.line_score(
|
389 |
+
val,
|
390 |
+
w_density=input.w_density(),
|
391 |
+
w_income=input.w_income(),
|
392 |
+
w_age=input.w_age(),
|
393 |
+
radius=input.rad()
|
394 |
+
)
|
395 |
+
lines[key] = score["final_score"]
|
396 |
+
|
397 |
+
return lines
|
app/data_processing/get_station_coverage.py
CHANGED
@@ -35,7 +35,7 @@ def get_station_coverage(
|
|
35 |
|
36 |
# Validate and fix invalid geometries
|
37 |
if not geometry.is_valid:
|
38 |
-
print(f"Invalid geometry detected for Area ID: {area['id']}. Attempting to fix.")
|
39 |
geometry = make_valid(geometry)
|
40 |
|
41 |
# Simplify geometry to avoid potential issues with highly complex polygons
|
|
|
35 |
|
36 |
# Validate and fix invalid geometries
|
37 |
if not geometry.is_valid:
|
38 |
+
# print(f"Invalid geometry detected for Area ID: {area['id']}. Attempting to fix.")
|
39 |
geometry = make_valid(geometry)
|
40 |
|
41 |
# Simplify geometry to avoid potential issues with highly complex polygons
|