Spaces:
Sleeping
Sleeping
Update src/streamlit_app.py
Browse files- src/streamlit_app.py +100 -83
src/streamlit_app.py
CHANGED
|
@@ -40,89 +40,106 @@ if st.button("Refresh Data"):
|
|
| 40 |
|
| 41 |
df = fetch_cwa_alarms()
|
| 42 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
if df.empty:
|
| 44 |
st.warning("No alarm data is currently available or the API could not be reached.")
|
| 45 |
else:
|
| 46 |
-
# ---
|
| 47 |
-
#
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
map_df,
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
"
|
| 80 |
-
"
|
| 81 |
-
"
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
st.dataframe(
|
| 122 |
-
display_df.sort_values(by=["Origin Time", "Message No."], ascending=[False, True]),
|
| 123 |
-
use_container_width=True,
|
| 124 |
-
hide_index=True,
|
| 125 |
-
column_config={
|
| 126 |
-
"Origin Time": st.column_config.DatetimeColumn(format="YYYY-MM-DD HH:mm:ss")
|
| 127 |
-
}
|
| 128 |
-
)
|
|
|
|
| 40 |
|
| 41 |
df = fetch_cwa_alarms()
|
| 42 |
|
| 43 |
+
# --- Sidebar for Filters ---
|
| 44 |
+
with st.sidebar:
|
| 45 |
+
st.header("🔍 Filter Options")
|
| 46 |
+
if not df.empty:
|
| 47 |
+
# Get unique values for filter controls
|
| 48 |
+
msg_types = sorted(df['msgType'].unique())
|
| 49 |
+
msg_numbers = sorted(df['msgNo'].unique())
|
| 50 |
+
|
| 51 |
+
# Create user controls
|
| 52 |
+
selected_types = st.multiselect(
|
| 53 |
+
'Message Type(s)',
|
| 54 |
+
options=msg_types,
|
| 55 |
+
default=msg_types,
|
| 56 |
+
help="Filter reports by their type (e.g., Alert, Update)."
|
| 57 |
+
)
|
| 58 |
+
selected_numbers = st.multiselect(
|
| 59 |
+
'Message Number(s)',
|
| 60 |
+
options=msg_numbers,
|
| 61 |
+
default=msg_numbers,
|
| 62 |
+
help="Filter reports by their sequence number. '1' is the initial alert."
|
| 63 |
+
)
|
| 64 |
+
else:
|
| 65 |
+
st.info("Waiting for data to load filters...")
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
# --- Main Content Area ---
|
| 69 |
if df.empty:
|
| 70 |
st.warning("No alarm data is currently available or the API could not be reached.")
|
| 71 |
else:
|
| 72 |
+
# --- Apply Filters ---
|
| 73 |
+
# Filter the DataFrame based on user selections in the sidebar
|
| 74 |
+
filtered_df = df[
|
| 75 |
+
df['msgType'].isin(selected_types) &
|
| 76 |
+
df['msgNo'].isin(selected_numbers)
|
| 77 |
+
]
|
| 78 |
+
|
| 79 |
+
if filtered_df.empty:
|
| 80 |
+
st.warning("No data matches your current filter settings. Please adjust the filters in the sidebar.")
|
| 81 |
+
else:
|
| 82 |
+
# Prepare data using the filtered DataFrame
|
| 83 |
+
filtered_df['originTime'] = pd.to_datetime(filtered_df['originTime'])
|
| 84 |
+
filtered_df['magnitudeValue'] = pd.to_numeric(filtered_df['magnitudeValue'])
|
| 85 |
+
filtered_df['depth'] = pd.to_numeric(filtered_df['depth'])
|
| 86 |
+
|
| 87 |
+
# --- Interactive Map Display ---
|
| 88 |
+
st.header("Earthquake Epicenter Map")
|
| 89 |
+
st.markdown("Each circle represents an earthquake epicenter. The map updates based on your filters.")
|
| 90 |
+
|
| 91 |
+
map_df = filtered_df.sort_values('magnitudeValue', ascending=False).drop_duplicates(subset='originTime').copy()
|
| 92 |
+
table_df_for_hover = filtered_df.explode('locationDesc')
|
| 93 |
+
hover_areas = table_df_for_hover.groupby('originTime')['locationDesc'].apply(lambda x: ', '.join(set(x))).reset_index(name="Affected Areas")
|
| 94 |
+
map_df = pd.merge(map_df, hover_areas, on='originTime')
|
| 95 |
+
|
| 96 |
+
fig = px.scatter_mapbox(
|
| 97 |
+
map_df,
|
| 98 |
+
lat="epicenterLat",
|
| 99 |
+
lon="epicenterLon",
|
| 100 |
+
size="magnitudeValue",
|
| 101 |
+
color="depth",
|
| 102 |
+
color_continuous_scale=px.colors.sequential.OrRd,
|
| 103 |
+
size_max=25,
|
| 104 |
+
zoom=6.5,
|
| 105 |
+
center={"lat": 23.9, "lon": 121.5},
|
| 106 |
+
mapbox_style="open-street-map",
|
| 107 |
+
hover_name="originTime",
|
| 108 |
+
hover_data={
|
| 109 |
+
"Affected Areas": True,
|
| 110 |
+
"magnitudeValue": ':.1f',
|
| 111 |
+
"depth": True,
|
| 112 |
+
"epicenterLat": False,
|
| 113 |
+
"epicenterLon": False
|
| 114 |
+
},
|
| 115 |
+
labels={"depth": "Depth (km)", "magnitudeValue": "Magnitude"}
|
| 116 |
+
)
|
| 117 |
+
fig.update_layout(
|
| 118 |
+
margin={"r": 0, "t": 40, "l": 0, "b": 0},
|
| 119 |
+
legend_title_text='Magnitude'
|
| 120 |
+
)
|
| 121 |
+
st.plotly_chart(fig, use_container_width=True)
|
| 122 |
+
|
| 123 |
+
# --- Detailed Table Display ---
|
| 124 |
+
st.header("Detailed Alarm Reports")
|
| 125 |
+
st.markdown("This table shows all alarm reports matching your filters.")
|
| 126 |
+
|
| 127 |
+
filtered_df['Alarm Areas'] = filtered_df['locationDesc'].apply(lambda areas: ', '.join(areas))
|
| 128 |
+
|
| 129 |
+
display_df = filtered_df[[
|
| 130 |
+
"originTime", "identifier", "msgType", "msgNo", "magnitudeValue",
|
| 131 |
+
"depth", "epicenterLat", "epicenterLon", "Alarm Areas"
|
| 132 |
+
]].rename(columns={
|
| 133 |
+
"originTime": "Origin Time", "identifier": "Report ID", "msgType": "Message Type",
|
| 134 |
+
"msgNo": "Message No.", "magnitudeValue": "Magnitude", "depth": "Depth (km)",
|
| 135 |
+
"epicenterLat": "Latitude", "epicenterLon": "Longitude", "Alarm Areas": "Alarm Areas"
|
| 136 |
+
})
|
| 137 |
+
|
| 138 |
+
st.dataframe(
|
| 139 |
+
display_df.sort_values(by=["Origin Time", "Message No."], ascending=[False, True]),
|
| 140 |
+
use_container_width=True,
|
| 141 |
+
hide_index=True,
|
| 142 |
+
column_config={
|
| 143 |
+
"Origin Time": st.column_config.DatetimeColumn(format="YYYY-MM-DD HH:mm:ss")
|
| 144 |
+
}
|
| 145 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|