import streamlit as st
import pandas as pd
import geopandas as gpd
def get_distance(row):
distance = (row["dx"] - row["sx"])**2 + (row["dy"] - row["sy"])**2
distance = distance**0.5
return distance
## Title and description
st.title('2SFCA')
st.markdown('This app calculates the 2-Step Floating Catchment Area (2SFCA) accessibility score for a given supply and demand dataset.')
## Upload data and preprocess the data
cols = st.columns(2)
supply = cols[0].file_uploader('Upload supply data', type=['csv', 'xlsx','zip', 'geojson', 'gpkg'])
# upload target data
demand = cols[1].file_uploader('Upload demand data', type=['csv', 'xlsx', 'zip', 'geojson','gpkg'])
if supply and demand:
# read supply data
if supply.name.endswith('.csv'):
supply_data = pd.read_csv(supply)
elif supply.name.endswith('.xlsx'):
supply_data = pd.read_excel(supply)
elif supply.name.endswith('.zip'):
supply_data = gpd.read_file(f'zip://{supply.name}')
elif supply.name.endswith('.geojson'):
supply_data = gpd.read_file(supply)
elif supply.name.endswith('.gpkg'):
supply_data = gpd.read_file(supply)
# read demand data
if demand.name.endswith('.csv'):
demand_data = pd.read_csv(demand)
elif demand.name.endswith('.xlsx'):
demand_data = pd.read_excel(demand)
elif demand.name.endswith('.zip'):
demand_data = gpd.read_file(f'zip://{demand.name}')
elif demand.name.endswith('.geojson'):
demand_data = gpd.read_file(demand)
elif demand.name.endswith('.gpkg'):
demand_data = gpd.read_file(demand)
## preview the data
cols[0].write(supply_data.head())
cols[1].write(demand_data.head())
# plot supply data
supply_data["lat"] = supply_data.geometry.y
supply_data["lon"] = supply_data.geometry.x
demand_data["lat"] = demand_data.geometry.y
demand_data["lon"] = demand_data.geometry.x
import matplotlib.pyplot as plt
fig0 , ax0 = plt.subplots(figsize=(8, 6))
supply_data.plot(ax=ax0, color='red')
cols[0].pyplot(fig0)
fig1 , ax1 = plt.subplots(figsize=(8, 6))
demand_data.plot(ax=ax1, color='blue')
cols[1].pyplot(fig1)
## 2sfca parameters
s_va = cols[0].selectbox(
"Supply Variable",
supply_data.columns)
d_va = cols[1].selectbox(
"Demand Variable",
demand_data.columns)
radius = cols[0].slider('Select Service radius', min_value=0, max_value=100000, value=32180, step=1000)
buffer_radius = supply_data.buffer(radius)
fig_b , ax_b = plt.subplots(figsize=(8, 6))
buffer_radius.plot(ax=ax_b)
cols[1].pyplot(fig_b)
# buffer_radius.plot()
## Run 2sfca
if st.button('Run'):
# calculate distance matrix
supply_data["sx"],supply_data["sy"] = supply_data.geometry.x,supply_data.geometry.y
supply_data["sid"] = supply_data.index
demand_data["dx"],demand_data["dy"] = demand_data.geometry.x,demand_data.geometry.y
demand_data["did"] = demand_data.index
joint_data = demand_data.merge(supply_data,how="cross")
joint_data["distance"] = joint_data.apply(get_distance,axis=1)
distance_matrix = joint_data.pivot_table(index="did",columns="sid",values="distance")
d_matrix = distance_matrix.values
## calculate access score
import aceso
model = aceso.TwoStepFCA(radius=radius)
demand_data['access_score'] = model.calculate_accessibility_scores(
distance_matrix=d_matrix,
demand_array=demand_data[d_va].values,
supply_array = supply_data[s_va].values
)
# plot access score
st.write(demand_data.head())
# plot access score
fig_c = plt.figure()
ax = plt.gca()
demand_data.plot(column='access_score', legend=True, ax=ax)
st.pyplot(fig_c)
# download access score
demand_data.to_csv('access_score.csv', index=False)
st.download_button(label='Download access score', data='access_score.csv', file_name='access_score.csv', mime='text/csv')