Spaces:
Runtime error
Runtime error
import pandas as pd | |
import plotly.graph_objects as go | |
import streamlit as st | |
import requests | |
from streamlit_folium import st_folium | |
import folium | |
import branca.colormap as cm | |
st.set_page_config(layout="wide", page_title="Air Quality Health Index Dashboard") | |
def fetch_data(url): | |
response = requests.get(url) | |
return response.json() | |
def get_color(aqhi): | |
if aqhi <= 3: | |
return '#006400' # Dark Green | |
elif aqhi <= 6: | |
return '#DAA520' # Goldenrod | |
elif aqhi <= 7: | |
return '#FF4500' # OrangeRed | |
elif aqhi <= 10: | |
return '#8B0000' # Dark Red | |
else: | |
return '#4B0082' # Indigo | |
current_url = "https://csdi.vercel.app/aqhi/data/?last=true" | |
hourly_url = "https://csdi.vercel.app/aqhi/data/" | |
messages_url = "https://csdi.vercel.app/aqhi/repo/" | |
current_data = fetch_data(current_url) | |
hourly_data = fetch_data(hourly_url) | |
messages_data = fetch_data(messages_url) | |
features_current = current_data['features'] | |
features_hourly = hourly_data['features'] | |
messages = messages_data['aqhi_report'] | |
forecasts = messages_data['aqhi_forecast'] | |
col1, col2, col3 = st.columns([1, 1.5, 1.3]) | |
with col1: | |
st.caption('The following is the past hour Air Quality Health Index from EDP, updated hourly.') | |
for message in messages: | |
if message['StationTypeEN'] == 'General Stations': | |
with st.expander(f"General Stations - {message['AQHIRiskEN']}", expanded=True): | |
st.metric("AQHI Range", message['AQHIRange']) | |
st.markdown(f"**Risk Level:** {message['AQHIRiskEN']}") | |
stations = [feature['properties']['name'] for feature in features_hourly] | |
selected_station = st.selectbox("Select Station", stations, key="station1") | |
preset_station = "Tai Po" | |
tai_po_index = stations.index(preset_station) if preset_station in stations else 0 | |
selected_station2 = st.selectbox("Select another station for comparison", stations, index=tai_po_index, | |
key="station2") | |
station_data2 = next( | |
feature for feature in features_hourly if feature['properties']['name'] == selected_station2) | |
station_df2 = pd.DataFrame(station_data2['properties']['feature']) | |
station_data = next(feature for feature in features_hourly if feature['properties']['name'] == selected_station) | |
station_df = pd.DataFrame(station_data['properties']['feature']) | |
station_df['aqhi'] = pd.to_numeric(station_df['aqhi'], errors='coerce') | |
fig_hist = go.Figure(data=[ | |
go.Bar( | |
x=station_df['DateTime'], | |
y=station_df['aqhi'], | |
marker=dict( | |
color=station_df['aqhi'].apply(get_color), | |
), | |
) | |
]) | |
fig_hist.update_layout( | |
title='AQHI Histogram', | |
xaxis_title='Time', | |
yaxis_title='AQHI', | |
bargap=0.2, | |
height=350 | |
) | |
st.plotly_chart(fig_hist) | |
with col2: | |
m = folium.Map(location=[22.3547, 114.1483], zoom_start=11, | |
tiles='https://landsd.azure-api.net/dev/osm/xyz/basemap/gs/WGS84/tile/{z}/{x}/{y}.png?key=f4d3e21d4fc14954a1d5930d4dde3809', | |
attr="Map infortmation from Lands Department") | |
folium.TileLayer( | |
tiles='https://mapapi.geodata.gov.hk/gs/api/v1.0.0/xyz/label/hk/en/wgs84/{z}/{x}/{y}.png', | |
attr="Map infortmation from Lands Department").add_to(m) | |
colormap = cm.LinearColormap(colors=['#006400', '#DAA520', '#FF4500', '#8B0000', '#4B0082'], | |
vmin=1, vmax=10) | |
m.add_child(colormap) | |
for feature in features_current: | |
coords = feature['geometry']['coordinates'] | |
name = feature['properties']['name'] | |
aqhi = int(feature['properties']['feature'][0]['aqhi']) | |
folium.CircleMarker( | |
location=[coords[1], coords[0]], | |
radius=10, | |
popup=f"{name}: AQHI {aqhi}", | |
color=get_color(aqhi), | |
fill=True, | |
fillColor=get_color(aqhi) | |
).add_to(m) | |
st_folium(m, use_container_width=True , height=750) | |
with col3: | |
for df in [station_df, station_df2]: | |
for col in ['aqhi', 'PM25', 'PM10', 'NO2']: | |
df[col] = pd.to_numeric(df[col], errors='coerce') | |
tab1, tab2, tab3, tab4 = st.tabs(["AQHI", "PM2.5", "PM10", "NO2"]) | |
with tab1: | |
fig_aqhi = go.Figure() | |
fig_aqhi.add_trace(go.Scatter(x=station_df['DateTime'], y=station_df['aqhi'], mode='lines+markers', name=selected_station)) | |
fig_aqhi.add_trace(go.Scatter(x=station_df2['DateTime'], y=station_df2['aqhi'], mode='lines+markers', name=selected_station2)) | |
fig_aqhi.update_layout(title='AQHI Comparison', xaxis_title='Time', yaxis_title='AQHI', legend_title='Stations', height =380) | |
st.plotly_chart(fig_aqhi) | |
with tab2: | |
fig_pm25 = go.Figure() | |
fig_pm25.add_trace(go.Scatter(x=station_df['DateTime'], y=station_df['PM25'], mode='lines+markers', name=selected_station)) | |
fig_pm25.add_trace(go.Scatter(x=station_df2['DateTime'], y=station_df2['PM25'], mode='lines+markers', name=selected_station2)) | |
fig_pm25.update_layout(title='PM2.5 Comparison', xaxis_title='Time', yaxis_title='PM2.5 (µg/m³)', legend_title='Stations', height =380) | |
st.plotly_chart(fig_pm25) | |
with tab3: | |
fig_pm10 = go.Figure() | |
fig_pm10.add_trace(go.Scatter(x=station_df['DateTime'], y=station_df['PM10'], mode='lines+markers', name=selected_station)) | |
fig_pm10.add_trace(go.Scatter(x=station_df2['DateTime'], y=station_df2['PM10'], mode='lines+markers', name=selected_station2)) | |
fig_pm10.update_layout(title='PM10 Comparison', xaxis_title='Time', yaxis_title='PM10 (µg/m³)', legend_title='Stations', height =380) | |
st.plotly_chart(fig_pm10) | |
with tab4: | |
fig_no2 = go.Figure() | |
fig_no2.add_trace(go.Scatter(x=station_df['DateTime'], y=station_df['NO2'], mode='lines+markers', name=selected_station)) | |
fig_no2.add_trace(go.Scatter(x=station_df2['DateTime'], y=station_df2['NO2'], mode='lines+markers', name=selected_station2)) | |
fig_no2.update_layout(title='NO2 Comparison', xaxis_title='Time', yaxis_title='NO2 (µg/m³)', legend_title='Stations', height =380) | |
st.plotly_chart(fig_no2) | |
st.caption('Current Difference') | |
col3_1, col3_2 = st.columns(2) | |
with col3_1: | |
st.metric(f"{selected_station} PM2.5", f"{station_df['PM25'].iloc[-1]:.1f}") | |
st.metric(f"{selected_station} PM10", f"{station_df['PM10'].iloc[-1]:.1f}") | |
st.metric(f"{selected_station} NO2", f"{station_df['NO2'].iloc[-1]:.1f}") | |
with col3_2: | |
st.metric(f"{selected_station2} PM2.5", f"{station_df2['PM25'].iloc[-1]:.1f}") | |
st.metric(f"{selected_station2} PM10", f"{station_df2['PM10'].iloc[-1]:.1f}") | |
st.metric(f"{selected_station2} NO2", f"{station_df2['NO2'].iloc[-1]:.1f}") | |
st.caption('The PM2.5, PM10 and NO2 are in µg/m³ unit.') |