Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -949,66 +949,7 @@ with gr.Blocks(title="Typhoon Analysis Dashboard") as demo:
|
|
949 |
tracks_plot = gr.Plot(label="Typhoon Tracks", elem_id="tracks_plot")
|
950 |
typhoon_count = gr.Textbox(label="Number of Typhoons Displayed")
|
951 |
|
952 |
-
|
953 |
-
start_date = datetime(start_year, start_month, 1)
|
954 |
-
end_date = datetime(end_year, end_month, 28)
|
955 |
-
filtered_data = merged_data[
|
956 |
-
(merged_data['ISO_TIME'] >= start_date) &
|
957 |
-
(merged_data['ISO_TIME'] <= end_date)
|
958 |
-
]
|
959 |
-
filtered_data['ENSO_Phase'] = filtered_data['ONI'].apply(classify_enso_phases)
|
960 |
-
if enso_phase != 'all':
|
961 |
-
filtered_data = filtered_data[filtered_data['ENSO_Phase'] == enso_phase.capitalize()]
|
962 |
-
unique_storms = filtered_data['SID'].unique()
|
963 |
-
count = len(unique_storms)
|
964 |
-
fig = go.Figure()
|
965 |
-
for sid in unique_storms:
|
966 |
-
storm_data = typhoon_data[typhoon_data['SID'] == sid]
|
967 |
-
name = storm_data['NAME'].iloc[0] if not pd.isna(storm_data['NAME'].iloc[0]) else "Unnamed"
|
968 |
-
storm_oni = filtered_data[filtered_data['SID'] == sid]['ONI'].iloc[0]
|
969 |
-
color = 'red' if storm_oni >= 0.5 else ('blue' if storm_oni <= -0.5 else 'green')
|
970 |
-
fig.add_trace(go.Scattergeo(
|
971 |
-
lon=storm_data['LON'], lat=storm_data['LAT'], mode='lines',
|
972 |
-
name=f"{name} ({storm_data['SEASON'].iloc[0]})",
|
973 |
-
line=dict(width=1.5, color=color),
|
974 |
-
hoverinfo="name"
|
975 |
-
))
|
976 |
-
if typhoon_search:
|
977 |
-
search_mask = typhoon_data['NAME'].str.contains(typhoon_search, case=False, na=False)
|
978 |
-
if search_mask.any():
|
979 |
-
for sid in typhoon_data[search_mask]['SID'].unique():
|
980 |
-
storm_data = typhoon_data[typhoon_data['SID'] == sid]
|
981 |
-
fig.add_trace(go.Scattergeo(
|
982 |
-
lon=storm_data['LON'], lat=storm_data['LAT'], mode='lines+markers',
|
983 |
-
name=f"MATCHED: {storm_data['NAME'].iloc[0]} ({storm_data['SEASON'].iloc[0]})",
|
984 |
-
line=dict(width=3, color='yellow'),
|
985 |
-
marker=dict(size=5),
|
986 |
-
hoverinfo="name"
|
987 |
-
))
|
988 |
-
fig.update_layout(
|
989 |
-
title=f"Typhoon Tracks ({start_year}-{start_month} to {end_year}-{end_month})",
|
990 |
-
geo=dict(
|
991 |
-
projection_type='natural earth',
|
992 |
-
showland=True,
|
993 |
-
showcoastlines=True,
|
994 |
-
landcolor='rgb(243, 243, 243)',
|
995 |
-
countrycolor='rgb(204, 204, 204)',
|
996 |
-
coastlinecolor='rgb(204, 204, 204)',
|
997 |
-
center=dict(lon=140, lat=20),
|
998 |
-
projection_scale=3
|
999 |
-
),
|
1000 |
-
legend_title="Typhoons by ENSO Phase",
|
1001 |
-
showlegend=True,
|
1002 |
-
height=700
|
1003 |
-
)
|
1004 |
-
fig.add_annotation(
|
1005 |
-
x=0.02, y=0.98, xref="paper", yref="paper",
|
1006 |
-
text="Red: El Niño, Blue: La Niña, Green: Neutral",
|
1007 |
-
showarrow=False, align="left",
|
1008 |
-
bgcolor="rgba(255,255,255,0.8)"
|
1009 |
-
)
|
1010 |
-
return fig, f"Total typhoons displayed: {count}"
|
1011 |
-
|
1012 |
analyze_btn.click(
|
1013 |
fn=get_full_tracks,
|
1014 |
inputs=[start_year, start_month, end_year, end_month, enso_phase, typhoon_search],
|
@@ -1027,11 +968,7 @@ with gr.Blocks(title="Typhoon Analysis Dashboard") as demo:
|
|
1027 |
wind_scatter = gr.Plot(label="Wind Speed vs ONI")
|
1028 |
wind_regression_results = gr.Textbox(label="Wind Regression Results")
|
1029 |
|
1030 |
-
|
1031 |
-
results = generate_main_analysis(start_year, start_month, end_year, end_month, enso_phase, typhoon_search)
|
1032 |
-
regression = perform_wind_regression(start_year, start_month, end_year, end_month)
|
1033 |
-
return results[1], regression
|
1034 |
-
|
1035 |
wind_analyze_btn.click(
|
1036 |
fn=get_wind_analysis,
|
1037 |
inputs=[wind_start_year, wind_start_month, wind_end_year, wind_end_month, wind_enso_phase, wind_typhoon_search],
|
@@ -1050,11 +987,7 @@ with gr.Blocks(title="Typhoon Analysis Dashboard") as demo:
|
|
1050 |
pressure_scatter = gr.Plot(label="Pressure vs ONI")
|
1051 |
pressure_regression_results = gr.Textbox(label="Pressure Regression Results")
|
1052 |
|
1053 |
-
|
1054 |
-
results = generate_main_analysis(start_year, start_month, end_year, end_month, enso_phase, typhoon_search)
|
1055 |
-
regression = perform_pressure_regression(start_year, start_month, end_year, end_month)
|
1056 |
-
return results[2], regression
|
1057 |
-
|
1058 |
pressure_analyze_btn.click(
|
1059 |
fn=get_pressure_analysis,
|
1060 |
inputs=[pressure_start_year, pressure_start_month, pressure_end_year, pressure_end_month, pressure_enso_phase, pressure_typhoon_search],
|
@@ -1074,11 +1007,7 @@ with gr.Blocks(title="Typhoon Analysis Dashboard") as demo:
|
|
1074 |
slopes_text = gr.Textbox(label="Regression Slopes")
|
1075 |
lon_regression_results = gr.Textbox(label="Longitude Regression Results")
|
1076 |
|
1077 |
-
|
1078 |
-
results = generate_main_analysis(start_year, start_month, end_year, end_month, enso_phase, typhoon_search)
|
1079 |
-
regression = perform_longitude_regression(start_year, start_month, end_year, end_month)
|
1080 |
-
return results[3], results[4], regression
|
1081 |
-
|
1082 |
lon_analyze_btn.click(
|
1083 |
fn=get_longitude_analysis,
|
1084 |
inputs=[lon_start_year, lon_start_month, lon_end_year, lon_end_month, lon_enso_phase, lon_typhoon_search],
|
@@ -1102,11 +1031,16 @@ with gr.Blocks(title="Typhoon Analysis Dashboard") as demo:
|
|
1102 |
],
|
1103 |
value="WP - Western North Pacific"
|
1104 |
)
|
|
|
|
|
1105 |
typhoon_dropdown = gr.Dropdown(label="Tropical Cyclone")
|
1106 |
standard_dropdown = gr.Dropdown(label="Classification Standard", choices=['atlantic', 'taiwan'], value='atlantic')
|
1107 |
|
1108 |
animate_btn = gr.Button("Generate Animation")
|
1109 |
-
|
|
|
|
|
|
|
1110 |
animation_info = gr.Markdown("""
|
1111 |
### Animation Instructions
|
1112 |
1. Select a year and basin from the dropdowns
|
@@ -1124,61 +1058,16 @@ with gr.Blocks(title="Typhoon Analysis Dashboard") as demo:
|
|
1124 |
Different agencies use different wind speed averaging periods: USA (1-min), JTWC (1-min), JMA (10-min), IMD (3-min).
|
1125 |
""")
|
1126 |
|
1127 |
-
#
|
1128 |
-
basin_to_prefix = {
|
1129 |
-
"All Basins": None,
|
1130 |
-
"NA - North Atlantic": "AL",
|
1131 |
-
"EP - Eastern North Pacific": "EP",
|
1132 |
-
"WP - Western North Pacific": "WP",
|
1133 |
-
"NI - North Indian": ["IO", "BB", "AS"], # Multiple prefixes for North Indian
|
1134 |
-
"SI - South Indian": "SI",
|
1135 |
-
"SP - Southern Pacific": "SP",
|
1136 |
-
"SA - South Atlantic": "SL"
|
1137 |
-
}
|
1138 |
-
|
1139 |
-
def update_typhoon_options(year, basin):
|
1140 |
-
try:
|
1141 |
-
season = ibtracs.get_season(int(year))
|
1142 |
-
storm_summary = season.summary()
|
1143 |
-
|
1144 |
-
# Get the prefix for filtering
|
1145 |
-
prefix = basin_to_prefix.get(basin)
|
1146 |
-
|
1147 |
-
# Get all storms for the year
|
1148 |
-
options = []
|
1149 |
-
for i in range(len(storm_summary)):
|
1150 |
-
try:
|
1151 |
-
name = storm_summary['name'][i] if not pd.isna(storm_summary['name'][i]) else "Unnamed"
|
1152 |
-
storm_id = storm_summary['id'][i]
|
1153 |
-
|
1154 |
-
# Filter by basin if a specific basin is selected
|
1155 |
-
if prefix is None or (isinstance(prefix, list) and any(storm_id.startswith(p) for p in prefix)) or (not isinstance(prefix, list) and storm_id.startswith(prefix)):
|
1156 |
-
options.append(f"{name} ({storm_id})")
|
1157 |
-
except:
|
1158 |
-
continue
|
1159 |
-
|
1160 |
-
return gr.update(choices=options, value=options[0] if options else None)
|
1161 |
-
except Exception as e:
|
1162 |
-
print(f"Error updating typhoon options: {e}")
|
1163 |
-
return gr.update(choices=[], value=None)
|
1164 |
|
1165 |
year_dropdown.change(fn=update_typhoon_options, inputs=[year_dropdown, basin_dropdown], outputs=typhoon_dropdown)
|
1166 |
basin_dropdown.change(fn=update_typhoon_options, inputs=[year_dropdown, basin_dropdown], outputs=typhoon_dropdown)
|
1167 |
|
1168 |
-
|
1169 |
-
|
1170 |
-
|
1171 |
-
|
1172 |
-
|
1173 |
-
typhoon_id = typhoon.split('(')[-1].strip(')')
|
1174 |
-
|
1175 |
-
# Extract basin code from the basin selection
|
1176 |
-
basin_code = "All"
|
1177 |
-
if basin != "All Basins":
|
1178 |
-
basin_code = basin.split(' - ')[0]
|
1179 |
-
|
1180 |
-
# Generate the animation
|
1181 |
-
return generate_track_video(year, basin_code, typhoon, standard)
|
1182 |
|
1183 |
with gr.Tab("TSNE Cluster"):
|
1184 |
with gr.Row():
|
|
|
949 |
tracks_plot = gr.Plot(label="Typhoon Tracks", elem_id="tracks_plot")
|
950 |
typhoon_count = gr.Textbox(label="Number of Typhoons Displayed")
|
951 |
|
952 |
+
# Function definitions remain the same
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
953 |
analyze_btn.click(
|
954 |
fn=get_full_tracks,
|
955 |
inputs=[start_year, start_month, end_year, end_month, enso_phase, typhoon_search],
|
|
|
968 |
wind_scatter = gr.Plot(label="Wind Speed vs ONI")
|
969 |
wind_regression_results = gr.Textbox(label="Wind Regression Results")
|
970 |
|
971 |
+
# Function definitions remain the same
|
|
|
|
|
|
|
|
|
972 |
wind_analyze_btn.click(
|
973 |
fn=get_wind_analysis,
|
974 |
inputs=[wind_start_year, wind_start_month, wind_end_year, wind_end_month, wind_enso_phase, wind_typhoon_search],
|
|
|
987 |
pressure_scatter = gr.Plot(label="Pressure vs ONI")
|
988 |
pressure_regression_results = gr.Textbox(label="Pressure Regression Results")
|
989 |
|
990 |
+
# Function definitions remain the same
|
|
|
|
|
|
|
|
|
991 |
pressure_analyze_btn.click(
|
992 |
fn=get_pressure_analysis,
|
993 |
inputs=[pressure_start_year, pressure_start_month, pressure_end_year, pressure_end_month, pressure_enso_phase, pressure_typhoon_search],
|
|
|
1007 |
slopes_text = gr.Textbox(label="Regression Slopes")
|
1008 |
lon_regression_results = gr.Textbox(label="Longitude Regression Results")
|
1009 |
|
1010 |
+
# Function definitions remain the same
|
|
|
|
|
|
|
|
|
1011 |
lon_analyze_btn.click(
|
1012 |
fn=get_longitude_analysis,
|
1013 |
inputs=[lon_start_year, lon_start_month, lon_end_year, lon_end_month, lon_enso_phase, lon_typhoon_search],
|
|
|
1031 |
],
|
1032 |
value="WP - Western North Pacific"
|
1033 |
)
|
1034 |
+
|
1035 |
+
with gr.Row():
|
1036 |
typhoon_dropdown = gr.Dropdown(label="Tropical Cyclone")
|
1037 |
standard_dropdown = gr.Dropdown(label="Classification Standard", choices=['atlantic', 'taiwan'], value='atlantic')
|
1038 |
|
1039 |
animate_btn = gr.Button("Generate Animation")
|
1040 |
+
|
1041 |
+
# Use format="mp4" to indicate we expect MP4 video, and no source parameter to avoid upload/webcam UI
|
1042 |
+
path_video = gr.Video(label="Tropical Cyclone Path Animation", format="mp4", interactive=False, elem_id="path_video")
|
1043 |
+
|
1044 |
animation_info = gr.Markdown("""
|
1045 |
### Animation Instructions
|
1046 |
1. Select a year and basin from the dropdowns
|
|
|
1058 |
Different agencies use different wind speed averaging periods: USA (1-min), JTWC (1-min), JMA (10-min), IMD (3-min).
|
1059 |
""")
|
1060 |
|
1061 |
+
# Basin to prefix mapping and functions remain the same
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1062 |
|
1063 |
year_dropdown.change(fn=update_typhoon_options, inputs=[year_dropdown, basin_dropdown], outputs=typhoon_dropdown)
|
1064 |
basin_dropdown.change(fn=update_typhoon_options, inputs=[year_dropdown, basin_dropdown], outputs=typhoon_dropdown)
|
1065 |
|
1066 |
+
animate_btn.click(
|
1067 |
+
fn=simplified_track_video,
|
1068 |
+
inputs=[year_dropdown, basin_dropdown, typhoon_dropdown, standard_dropdown],
|
1069 |
+
outputs=path_video
|
1070 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1071 |
|
1072 |
with gr.Tab("TSNE Cluster"):
|
1073 |
with gr.Row():
|