euler314 commited on
Commit
e6b6548
·
verified ·
1 Parent(s): fcd1f06

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +132 -7
app.py CHANGED
@@ -33,7 +33,7 @@ DATA_PATH = args.data_path
33
 
34
  ONI_DATA_PATH = os.path.join(DATA_PATH, 'oni_data.csv')
35
  TYPHOON_DATA_PATH = os.path.join(DATA_PATH, 'processed_typhoon_data.csv')
36
- LOCAL_iBtrace_PATH = os.path.join(DATA_PATH, 'ibtracs.ALL.list.v04r01.csv')
37
  iBtrace_uri = 'https://www.ncei.noaa.gov/data/international-best-track-archive-for-climate-stewardship-ibtracs/v04r01/access/csv/ibtracs.ALL.list.v04r01.csv'
38
  CACHE_FILE = 'ibtracs_cache.pkl'
39
  CACHE_EXPIRY_DAYS = 1
@@ -325,6 +325,83 @@ def generate_main_analysis(start_year, start_month, end_year, end_month, enso_ph
325
 
326
  return tracks_fig, wind_scatter, pressure_scatter, regression_fig, slopes_text
327
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
328
  # Video animation function with fixed sidebar and wind radius visualization
329
  def categorize_typhoon_by_standard(wind_speed, standard):
330
  if standard == 'taiwan':
@@ -523,6 +600,21 @@ def generate_track_video(year, basin, typhoon, standard):
523
 
524
  return temp_file.name
525
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
526
  # Logistic regression functions
527
  def perform_wind_regression(start_year, start_month, end_year, end_month):
528
  start_date = datetime(start_year, start_month, 1)
@@ -916,6 +1008,45 @@ def update_route_clusters(start_year, start_month, end_year, end_month, enso_val
916
  cluster_info_text = "\n".join(cluster_info_lines)
917
  return fig_tsne, fig_routes, fig_stats, cluster_info_text
918
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
919
  # Gradio Interface
920
  with gr.Blocks(title="Typhoon Analysis Dashboard") as demo:
921
  gr.Markdown("# Typhoon Analysis Dashboard")
@@ -949,7 +1080,6 @@ 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
- # 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,7 +1098,6 @@ with gr.Blocks(title="Typhoon Analysis Dashboard") as demo:
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,7 +1116,6 @@ with gr.Blocks(title="Typhoon Analysis Dashboard") as demo:
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,7 +1135,6 @@ with gr.Blocks(title="Typhoon Analysis Dashboard") as demo:
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],
@@ -1058,8 +1185,6 @@ with gr.Blocks(title="Typhoon Analysis Dashboard") as demo:
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
 
 
33
 
34
  ONI_DATA_PATH = os.path.join(DATA_PATH, 'oni_data.csv')
35
  TYPHOON_DATA_PATH = os.path.join(DATA_PATH, 'processed_typhoon_data.csv')
36
+ LOCAL_iBtrace_PATH = os.path.join(DATA_PATH, 'ibtracs.WP.list.v04r01.csv')
37
  iBtrace_uri = 'https://www.ncei.noaa.gov/data/international-best-track-archive-for-climate-stewardship-ibtracs/v04r01/access/csv/ibtracs.ALL.list.v04r01.csv'
38
  CACHE_FILE = 'ibtracs_cache.pkl'
39
  CACHE_EXPIRY_DAYS = 1
 
325
 
326
  return tracks_fig, wind_scatter, pressure_scatter, regression_fig, slopes_text
327
 
328
+ # Get full tracks function for Track Visualization tab
329
+ def get_full_tracks(start_year, start_month, end_year, end_month, enso_phase, typhoon_search):
330
+ start_date = datetime(start_year, start_month, 1)
331
+ end_date = datetime(end_year, end_month, 28)
332
+ filtered_data = merged_data[
333
+ (merged_data['ISO_TIME'] >= start_date) &
334
+ (merged_data['ISO_TIME'] <= end_date)
335
+ ]
336
+ filtered_data['ENSO_Phase'] = filtered_data['ONI'].apply(classify_enso_phases)
337
+ if enso_phase != 'all':
338
+ filtered_data = filtered_data[filtered_data['ENSO_Phase'] == enso_phase.capitalize()]
339
+ unique_storms = filtered_data['SID'].unique()
340
+ count = len(unique_storms)
341
+ fig = go.Figure()
342
+ for sid in unique_storms:
343
+ storm_data = typhoon_data[typhoon_data['SID'] == sid]
344
+ name = storm_data['NAME'].iloc[0] if not pd.isna(storm_data['NAME'].iloc[0]) else "Unnamed"
345
+ storm_oni = filtered_data[filtered_data['SID'] == sid]['ONI'].iloc[0]
346
+ color = 'red' if storm_oni >= 0.5 else ('blue' if storm_oni <= -0.5 else 'green')
347
+ fig.add_trace(go.Scattergeo(
348
+ lon=storm_data['LON'], lat=storm_data['LAT'], mode='lines',
349
+ name=f"{name} ({storm_data['SEASON'].iloc[0]})",
350
+ line=dict(width=1.5, color=color),
351
+ hoverinfo="name"
352
+ ))
353
+ if typhoon_search:
354
+ search_mask = typhoon_data['NAME'].str.contains(typhoon_search, case=False, na=False)
355
+ if search_mask.any():
356
+ for sid in typhoon_data[search_mask]['SID'].unique():
357
+ storm_data = typhoon_data[typhoon_data['SID'] == sid]
358
+ fig.add_trace(go.Scattergeo(
359
+ lon=storm_data['LON'], lat=storm_data['LAT'], mode='lines+markers',
360
+ name=f"MATCHED: {storm_data['NAME'].iloc[0]} ({storm_data['SEASON'].iloc[0]})",
361
+ line=dict(width=3, color='yellow'),
362
+ marker=dict(size=5),
363
+ hoverinfo="name"
364
+ ))
365
+ fig.update_layout(
366
+ title=f"Typhoon Tracks ({start_year}-{start_month} to {end_year}-{end_month})",
367
+ geo=dict(
368
+ projection_type='natural earth',
369
+ showland=True,
370
+ showcoastlines=True,
371
+ landcolor='rgb(243, 243, 243)',
372
+ countrycolor='rgb(204, 204, 204)',
373
+ coastlinecolor='rgb(204, 204, 204)',
374
+ center=dict(lon=140, lat=20),
375
+ projection_scale=3
376
+ ),
377
+ legend_title="Typhoons by ENSO Phase",
378
+ showlegend=True,
379
+ height=700
380
+ )
381
+ fig.add_annotation(
382
+ x=0.02, y=0.98, xref="paper", yref="paper",
383
+ text="Red: El Niño, Blue: La Niña, Green: Neutral",
384
+ showarrow=False, align="left",
385
+ bgcolor="rgba(255,255,255,0.8)"
386
+ )
387
+ return fig, f"Total typhoons displayed: {count}"
388
+
389
+ # Analysis functions for Wind, Pressure, and Longitude tabs
390
+ def get_wind_analysis(start_year, start_month, end_year, end_month, enso_phase, typhoon_search):
391
+ results = generate_main_analysis(start_year, start_month, end_year, end_month, enso_phase, typhoon_search)
392
+ regression = perform_wind_regression(start_year, start_month, end_year, end_month)
393
+ return results[1], regression
394
+
395
+ def get_pressure_analysis(start_year, start_month, end_year, end_month, enso_phase, typhoon_search):
396
+ results = generate_main_analysis(start_year, start_month, end_year, end_month, enso_phase, typhoon_search)
397
+ regression = perform_pressure_regression(start_year, start_month, end_year, end_month)
398
+ return results[2], regression
399
+
400
+ def get_longitude_analysis(start_year, start_month, end_year, end_month, enso_phase, typhoon_search):
401
+ results = generate_main_analysis(start_year, start_month, end_year, end_month, enso_phase, typhoon_search)
402
+ regression = perform_longitude_regression(start_year, start_month, end_year, end_month)
403
+ return results[3], results[4], regression
404
+
405
  # Video animation function with fixed sidebar and wind radius visualization
406
  def categorize_typhoon_by_standard(wind_speed, standard):
407
  if standard == 'taiwan':
 
600
 
601
  return temp_file.name
602
 
603
+ def simplified_track_video(year, basin, typhoon, standard):
604
+ if not typhoon:
605
+ return None
606
+
607
+ # Extract storm ID from the dropdown selection
608
+ typhoon_id = typhoon.split('(')[-1].strip(')')
609
+
610
+ # Extract basin code from the basin selection
611
+ basin_code = "All"
612
+ if basin != "All Basins":
613
+ basin_code = basin.split(' - ')[0]
614
+
615
+ # Generate the animation
616
+ return generate_track_video(year, basin_code, typhoon, standard)
617
+
618
  # Logistic regression functions
619
  def perform_wind_regression(start_year, start_month, end_year, end_month):
620
  start_date = datetime(start_year, start_month, 1)
 
1008
  cluster_info_text = "\n".join(cluster_info_lines)
1009
  return fig_tsne, fig_routes, fig_stats, cluster_info_text
1010
 
1011
+ # Define the basin to prefix mapping
1012
+ basin_to_prefix = {
1013
+ "All Basins": None,
1014
+ "NA - North Atlantic": "AL",
1015
+ "EP - Eastern North Pacific": "EP",
1016
+ "WP - Western North Pacific": "WP",
1017
+ "NI - North Indian": ["IO", "BB", "AS"], # Multiple prefixes for North Indian
1018
+ "SI - South Indian": "SI",
1019
+ "SP - Southern Pacific": "SP",
1020
+ "SA - South Atlantic": "SL"
1021
+ }
1022
+
1023
+ # Update typhoon options function for animation tab
1024
+ def update_typhoon_options(year, basin):
1025
+ try:
1026
+ season = ibtracs.get_season(int(year))
1027
+ storm_summary = season.summary()
1028
+
1029
+ # Get the prefix for filtering
1030
+ prefix = basin_to_prefix.get(basin)
1031
+
1032
+ # Get all storms for the year
1033
+ options = []
1034
+ for i in range(len(storm_summary)):
1035
+ try:
1036
+ name = storm_summary['name'][i] if not pd.isna(storm_summary['name'][i]) else "Unnamed"
1037
+ storm_id = storm_summary['id'][i]
1038
+
1039
+ # Filter by basin if a specific basin is selected
1040
+ 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)):
1041
+ options.append(f"{name} ({storm_id})")
1042
+ except Exception:
1043
+ continue
1044
+
1045
+ return gr.update(choices=options, value=options[0] if options else None)
1046
+ except Exception as e:
1047
+ print(f"Error updating typhoon options: {e}")
1048
+ return gr.update(choices=[], value=None)
1049
+
1050
  # Gradio Interface
1051
  with gr.Blocks(title="Typhoon Analysis Dashboard") as demo:
1052
  gr.Markdown("# Typhoon Analysis Dashboard")
 
1080
  tracks_plot = gr.Plot(label="Typhoon Tracks", elem_id="tracks_plot")
1081
  typhoon_count = gr.Textbox(label="Number of Typhoons Displayed")
1082
 
 
1083
  analyze_btn.click(
1084
  fn=get_full_tracks,
1085
  inputs=[start_year, start_month, end_year, end_month, enso_phase, typhoon_search],
 
1098
  wind_scatter = gr.Plot(label="Wind Speed vs ONI")
1099
  wind_regression_results = gr.Textbox(label="Wind Regression Results")
1100
 
 
1101
  wind_analyze_btn.click(
1102
  fn=get_wind_analysis,
1103
  inputs=[wind_start_year, wind_start_month, wind_end_year, wind_end_month, wind_enso_phase, wind_typhoon_search],
 
1116
  pressure_scatter = gr.Plot(label="Pressure vs ONI")
1117
  pressure_regression_results = gr.Textbox(label="Pressure Regression Results")
1118
 
 
1119
  pressure_analyze_btn.click(
1120
  fn=get_pressure_analysis,
1121
  inputs=[pressure_start_year, pressure_start_month, pressure_end_year, pressure_end_month, pressure_enso_phase, pressure_typhoon_search],
 
1135
  slopes_text = gr.Textbox(label="Regression Slopes")
1136
  lon_regression_results = gr.Textbox(label="Longitude Regression Results")
1137
 
 
1138
  lon_analyze_btn.click(
1139
  fn=get_longitude_analysis,
1140
  inputs=[lon_start_year, lon_start_month, lon_end_year, lon_end_month, lon_enso_phase, lon_typhoon_search],
 
1185
  Different agencies use different wind speed averaging periods: USA (1-min), JTWC (1-min), JMA (10-min), IMD (3-min).
1186
  """)
1187
 
 
 
1188
  year_dropdown.change(fn=update_typhoon_options, inputs=[year_dropdown, basin_dropdown], outputs=typhoon_dropdown)
1189
  basin_dropdown.change(fn=update_typhoon_options, inputs=[year_dropdown, basin_dropdown], outputs=typhoon_dropdown)
1190