euler314 commited on
Commit
55508d2
·
verified ·
1 Parent(s): 55b0661

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +122 -60
app.py CHANGED
@@ -678,15 +678,11 @@ class TyphoonAnalyzer:
678
 
679
  def create_typhoon_animation(self, year, typhoon_id):
680
  """Create animated visualization of typhoon path"""
681
- storm_data = self.typhoon_data[self.typhoon_data['SID'] == typhoon_id]
682
- storm_data = storm_data.sort_values('ISO_TIME')
683
-
684
- fig = go.Figure()
685
-
686
- # Base map settings
687
- fig.update_layout(
688
- title=f"Typhoon Path Animation - {storm_data['NAME'].iloc[0]} ({year})",
689
- showlegend=True,
690
  geo=dict(
691
  projection_type='mercator',
692
  showland=True,
@@ -702,61 +698,127 @@ class TyphoonAnalyzer:
702
  )
703
  )
704
 
705
- # Create animation frames
706
- frames = []
707
- for i in range(len(storm_data)):
708
- frame = go.Frame(
709
- data=[
710
- go.Scattergeo(
711
- lon=storm_data['LON'].iloc[:i+1],
712
- lat=storm_data['LAT'].iloc[:i+1],
713
- mode='lines+markers',
714
- line=dict(width=2, color='red'),
715
- marker=dict(size=8, color='red'),
716
- name='Path'
717
- )
718
- ],
719
- name=f'frame{i}'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
720
  )
721
- frames.append(frame)
722
 
723
- fig.frames = frames
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
724
 
725
- # Add animation controls
726
- fig.update_layout(
727
- updatemenus=[{
728
- 'buttons': [
729
- {
730
- 'args': [None, {'frame': {'duration': 100, 'redraw': True},
731
- 'fromcurrent': True}],
732
- 'label': 'Play',
733
- 'method': 'animate'
734
- },
735
- {
736
- 'args': [[None], {'frame': {'duration': 0, 'redraw': True},
737
- 'mode': 'immediate',
738
- 'transition': {'duration': 0}}],
739
- 'label': 'Pause',
740
- 'method': 'animate'
741
- }
742
- ],
743
- 'type': 'buttons',
744
- 'showactive': False,
745
- 'x': 0.1,
746
- 'y': 0,
747
- 'xanchor': 'right',
748
- 'yanchor': 'top'
749
- }]
750
- )
751
 
752
- info_text = f"""
753
- ### Typhoon Information
754
- - Name: {storm_data['NAME'].iloc[0]}
755
- - Start Date: {storm_data['ISO_TIME'].iloc[0]:%Y-%m-%d %H:%M}
756
- - End Date: {storm_data['ISO_TIME'].iloc[-1]:%Y-%m-%d %H:%M}
757
- - Maximum Wind Speed: {storm_data['USA_WIND'].max():.1f} kt
758
- - Minimum Pressure: {storm_data['WMO_PRES'].min():.1f} hPa
759
- """
 
 
 
 
 
 
 
 
 
 
 
760
 
761
  return fig, info_text
762
  def create_pressure_analysis(self, data):
 
678
 
679
  def create_typhoon_animation(self, year, typhoon_id):
680
  """Create animated visualization of typhoon path"""
681
+ # Create default empty figure
682
+ empty_fig = go.Figure()
683
+ empty_fig.update_layout(
684
+ title="No Data Available",
685
+ showlegend=False,
 
 
 
 
686
  geo=dict(
687
  projection_type='mercator',
688
  showland=True,
 
698
  )
699
  )
700
 
701
+ # Input validation
702
+ if not typhoon_id:
703
+ return empty_fig, "Please select a typhoon"
704
+
705
+ # Get storm data
706
+ try:
707
+ storm_data = self.typhoon_data[self.typhoon_data['SID'] == typhoon_id]
708
+ if len(storm_data) == 0:
709
+ return empty_fig, "No data available for selected typhoon"
710
+
711
+ storm_data = storm_data.sort_values('ISO_TIME')
712
+
713
+ # Get the name safely
714
+ storm_name = storm_data['NAME'].values[0] if len(storm_data) > 0 else "Unknown"
715
+
716
+ fig = go.Figure()
717
+
718
+ # Base map settings
719
+ fig.update_layout(
720
+ title=f"Typhoon Path Animation - {storm_name}",
721
+ showlegend=True,
722
+ geo=dict(
723
+ projection_type='mercator',
724
+ showland=True,
725
+ showcoastlines=True,
726
+ landcolor='rgb(243, 243, 243)',
727
+ countrycolor='rgb(204, 204, 204)',
728
+ coastlinecolor='rgb(214, 214, 214)',
729
+ showocean=True,
730
+ oceancolor='rgb(230, 250, 255)',
731
+ lataxis=dict(range=[0, 50]),
732
+ lonaxis=dict(range=[100, 180]),
733
+ center=dict(lat=20, lon=140)
734
+ )
735
  )
 
736
 
737
+ # Create animation frames
738
+ frames = []
739
+ for i in range(len(storm_data)):
740
+ frame = go.Frame(
741
+ data=[
742
+ go.Scattergeo(
743
+ lon=storm_data['LON'].values[:i+1],
744
+ lat=storm_data['LAT'].values[:i+1],
745
+ mode='lines+markers',
746
+ line=dict(width=2, color='red'),
747
+ marker=dict(size=8, color='red'),
748
+ name='Path',
749
+ hovertemplate=(
750
+ f"Time: {pd.to_datetime(storm_data['ISO_TIME'].values[i]).strftime('%Y-%m-%d %H:%M')}<br>" +
751
+ f"Wind: {storm_data['USA_WIND'].values[i]:.1f} kt<br>" +
752
+ f"Pressure: {storm_data['WMO_PRES'].values[i]:.1f} hPa<br>" +
753
+ f"Lat: {storm_data['LAT'].values[i]:.2f}°N<br>" +
754
+ f"Lon: {storm_data['LON'].values[i]:.2f}°E"
755
+ )
756
+ )
757
+ ],
758
+ name=f'frame{i}'
759
+ )
760
+ frames.append(frame)
761
+
762
+ fig.frames = frames
763
+
764
+ # Add animation controls
765
+ fig.update_layout(
766
+ updatemenus=[{
767
+ 'buttons': [
768
+ {
769
+ 'args': [None, {'frame': {'duration': 100, 'redraw': True},
770
+ 'fromcurrent': True}],
771
+ 'label': 'Play',
772
+ 'method': 'animate'
773
+ },
774
+ {
775
+ 'args': [[None], {'frame': {'duration': 0, 'redraw': True},
776
+ 'mode': 'immediate',
777
+ 'transition': {'duration': 0}}],
778
+ 'label': 'Pause',
779
+ 'method': 'animate'
780
+ }
781
+ ],
782
+ 'type': 'buttons',
783
+ 'showactive': False,
784
+ 'x': 0.1,
785
+ 'y': 0,
786
+ 'xanchor': 'right',
787
+ 'yanchor': 'top'
788
+ }]
789
+ )
790
 
791
+ # Add initial data
792
+ fig.add_trace(
793
+ go.Scattergeo(
794
+ lon=[storm_data['LON'].values[0]],
795
+ lat=[storm_data['LAT'].values[0]],
796
+ mode='markers',
797
+ marker=dict(size=8, color='red'),
798
+ name='Start Point',
799
+ showlegend=True
800
+ )
801
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
802
 
803
+ start_time = pd.to_datetime(storm_data['ISO_TIME'].values[0])
804
+ end_time = pd.to_datetime(storm_data['ISO_TIME'].values[-1])
805
+ duration = (end_time - start_time).total_seconds() / 3600
806
+
807
+ info_text = f"""
808
+ ### Typhoon Information
809
+ - Name: {storm_name}
810
+ - Start Date: {start_time.strftime('%Y-%m-%d %H:%M')}
811
+ - End Date: {end_time.strftime('%Y-%m-%d %H:%M')}
812
+ - Maximum Wind Speed: {storm_data['USA_WIND'].max():.1f} kt
813
+ - Minimum Pressure: {storm_data['WMO_PRES'].min():.1f} hPa
814
+ - Duration: {duration:.1f} hours
815
+ """
816
+
817
+ return fig, info_text
818
+
819
+ except Exception as e:
820
+ print(f"Error in create_typhoon_animation: {str(e)}")
821
+ return empty_fig, f"Error processing typhoon data: {str(e)}"
822
 
823
  return fig, info_text
824
  def create_pressure_analysis(self, data):