cwadayi commited on
Commit
6becbe6
·
verified ·
1 Parent(s): 8a77572

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. 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
- # --- Data Preparation ---
47
- # Convert data types
48
- df['originTime'] = pd.to_datetime(df['originTime'])
49
- df['magnitudeValue'] = pd.to_numeric(df['magnitudeValue'])
50
- df['depth'] = pd.to_numeric(df['depth'])
51
-
52
- # --- Interactive Map Display ---
53
- st.header("Earthquake Epicenter Map")
54
- st.markdown("Each circle represents an earthquake epicenter. Updates for the same event are grouped. Hover to see all affected areas.")
55
-
56
- # To show one point per earthquake, we find the most significant report (highest magnitude) for each unique origin time.
57
- map_df = df.sort_values('magnitudeValue', ascending=False).drop_duplicates(subset='originTime').copy()
58
-
59
- # For the hover text, we group all locations for each unique origin time.
60
- table_df_for_hover = df.explode('locationDesc')
61
- hover_areas = table_df_for_hover.groupby('originTime')['locationDesc'].apply(lambda x: ', '.join(set(x))).reset_index(name="Affected Areas")
62
- map_df = pd.merge(map_df, hover_areas, on='originTime')
63
-
64
- fig = px.scatter_mapbox(
65
- map_df,
66
- lat="epicenterLat",
67
- lon="epicenterLon",
68
- size="magnitudeValue",
69
- color="depth",
70
- color_continuous_scale=px.colors.sequential.OrRd,
71
- size_max=25,
72
- zoom=6.5,
73
- center={"lat": 23.9, "lon": 121.5},
74
- mapbox_style="open-street-map",
75
- hover_name="originTime",
76
- hover_data={
77
- "Affected Areas": True,
78
- "magnitudeValue": ':.1f',
79
- "depth": True,
80
- "epicenterLat": False,
81
- "epicenterLon": False
82
- },
83
- labels={"depth": "Depth (km)", "magnitudeValue": "Magnitude"}
84
- )
85
- fig.update_layout(
86
- margin={"r": 0, "t": 40, "l": 0, "b": 0},
87
- legend_title_text='Magnitude'
88
- )
89
- st.plotly_chart(fig, use_container_width=True)
90
-
91
- # --- Detailed Table Display (MODIFIED SECTION) ---
92
- st.header("Detailed Alarm Reports")
93
- st.markdown("This table shows all alarm reports, including updates. Areas for each report are listed together.")
94
-
95
- # Create a new column by joining the list of areas into a single string.
96
- df['Alarm Areas'] = df['locationDesc'].apply(lambda areas: ', '.join(areas))
97
-
98
- # Select and rename the requested columns for a clean display.
99
- display_df = df[[
100
- "originTime",
101
- "identifier",
102
- "msgType",
103
- "msgNo",
104
- "magnitudeValue",
105
- "depth",
106
- "epicenterLat",
107
- "epicenterLon",
108
- "Alarm Areas" # Use the new joined column
109
- ]].rename(columns={
110
- "originTime": "Origin Time",
111
- "identifier": "Report ID",
112
- "msgType": "Message Type",
113
- "msgNo": "Message No.",
114
- "magnitudeValue": "Magnitude",
115
- "depth": "Depth (km)",
116
- "epicenterLat": "Latitude",
117
- "epicenterLon": "Longitude",
118
- "Alarm Areas": "Alarm Areas"
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
+ )