|
import streamlit as st |
|
import pandas as pd |
|
import plotly.express as px |
|
import pydeck as pdk |
|
|
|
|
|
st.set_page_config(page_title="AI-Powered Air Quality Dashboard", layout="wide") |
|
|
|
|
|
st.markdown(""" |
|
<style> |
|
.card { |
|
background-color: #ffffff; |
|
padding: 20px; |
|
border-radius: 15px; |
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); |
|
margin-bottom: 20px; |
|
} |
|
.header { |
|
font-size: 26px; |
|
font-weight: bold; |
|
color: #333333; |
|
text-align: center; |
|
margin-top: 10px; |
|
margin-bottom: 20px; |
|
} |
|
.subheader { |
|
font-size: 20px; |
|
color: #555555; |
|
font-weight: 600; |
|
margin-top: 10px; |
|
margin-bottom: 15px; |
|
} |
|
.recommendation { |
|
background-color: #f0f9ff; |
|
padding: 15px; |
|
border-radius: 10px; |
|
border-left: 5px solid #007bff; |
|
color: #007bff; |
|
font-weight: bold; |
|
} |
|
</style> |
|
""", unsafe_allow_html=True) |
|
|
|
|
|
st.sidebar.header("Air Quality Monitoring") |
|
station_list = ["Louisville", "Lexington", "Richmond", "Elizabethtown"] |
|
selected_station = st.sidebar.selectbox("Select AQI Station", station_list) |
|
|
|
|
|
aqi_data = { |
|
"Louisville": {"AQI": 50, "Pollutant": "Carbon Monoxide", "CO_ppb": 572.21}, |
|
"Lexington": {"AQI": 150, "Pollutant": "Ozone", "O3_ppb": 70.00}, |
|
"Richmond": {"AQI": 400, "Pollutant": "PM2.5", "PM25_ug/m3": 180.00}, |
|
"Elizabethtown": {"AQI": 85, "Pollutant": "Sulfur Dioxide", "SO2_ppb": 15.00}, |
|
} |
|
|
|
|
|
st.markdown("<div class='header'>AI-Powered Air Quality Dashboard</div>", unsafe_allow_html=True) |
|
|
|
|
|
station_data = aqi_data[selected_station] |
|
|
|
|
|
col1, col2, col3 = st.columns(3) |
|
|
|
|
|
with col1: |
|
st.markdown("<div class='card'>", unsafe_allow_html=True) |
|
st.metric(label="Air Quality Index (AQI)", value=station_data["AQI"]) |
|
st.write(f"**Top Pollutant:** {station_data['Pollutant']}") |
|
st.write(f"**Concentration:** {station_data.get('CO_ppb', station_data.get('PM25_ug/m3', 'N/A'))} ppb/µg/m³") |
|
st.markdown("</div>", unsafe_allow_html=True) |
|
|
|
|
|
with col2: |
|
st.markdown("<div class='card'>", unsafe_allow_html=True) |
|
st.write("<div class='subheader'>AI Recommendation</div>", unsafe_allow_html=True) |
|
|
|
|
|
if station_data["AQI"] <= 50: |
|
recommendation = "The air quality is good. It's a great day to enjoy outdoor activities." |
|
elif station_data["AQI"] <= 100: |
|
recommendation = "The air quality is moderate. Sensitive groups may need to limit prolonged outdoor activities." |
|
elif station_data["AQI"] <= 150: |
|
recommendation = "Unhealthy for sensitive groups. Reduce outdoor exertion if you have heart or lung conditions." |
|
else: |
|
recommendation = "The air is hazardous. It's strongly recommended to stay indoors and use air purifiers." |
|
|
|
st.markdown(f"<div class='recommendation'>{recommendation}</div>", unsafe_allow_html=True) |
|
st.markdown("</div>", unsafe_allow_html=True) |
|
|
|
|
|
with col3: |
|
st.markdown("<div class='card'>", unsafe_allow_html=True) |
|
st.write("<div class='subheader'>Health Impact</div>", unsafe_allow_html=True) |
|
st.write(""" |
|
- **General Population:** No immediate danger at low AQI levels. |
|
- **Sensitive Groups:** Individuals with heart or lung conditions may experience symptoms at higher AQI. |
|
""") |
|
st.markdown("</div>", unsafe_allow_html=True) |
|
|
|
|
|
st.subheader("AQI Trends Over Time") |
|
trend_data = pd.DataFrame({ |
|
"Date": ["2023-01-01", "2023-01-02", "2023-01-03", "2023-01-04"], |
|
"AQI": [station_data["AQI"] - 20, station_data["AQI"], station_data["AQI"] + 30, station_data["AQI"] - 10] |
|
}) |
|
|
|
trend_chart = px.line(trend_data, x="Date", y="AQI", title=f"AQI Trend for {selected_station}") |
|
trend_chart.update_traces(line=dict(color="#007bff")) |
|
trend_chart.update_layout(plot_bgcolor="rgba(0,0,0,0)", paper_bgcolor="rgba(0,0,0,0)") |
|
st.plotly_chart(trend_chart, use_container_width=True) |
|
|
|
|
|
st.subheader("Air Quality Stations Map") |
|
map_data = pd.DataFrame( |
|
[ |
|
{"lat": 38.2527, "lon": -85.7585, "AQI": 50}, |
|
{"lat": 38.0406, "lon": -84.5037, "AQI": 150}, |
|
{"lat": 37.7479, "lon": -84.2947, "AQI": 400}, |
|
{"lat": 37.6939, "lon": -85.8591, "AQI": 85}, |
|
] |
|
) |
|
|
|
|
|
aqi_map = pdk.Deck( |
|
map_style="mapbox://styles/mapbox/light-v9", |
|
initial_view_state=pdk.ViewState( |
|
latitude=38.0, |
|
longitude=-85.5, |
|
zoom=7, |
|
pitch=50, |
|
), |
|
layers=[ |
|
pdk.Layer( |
|
"ScatterplotLayer", |
|
data=map_data, |
|
get_position="[lon, lat]", |
|
get_radius=5000, |
|
get_fill_color="[255-AQI, 100, AQI/2, 150]", |
|
pickable=True, |
|
) |
|
], |
|
) |
|
|
|
st.pydeck_chart(aqi_map) |
|
|
|
|
|
st.write("---") |
|
st.write("Learn more about air quality and its impact [here](https://www.epa.gov/air-quality-index).") |
|
|