Spaces:
Sleeping
Sleeping
| """Wave front propagation map visualization""" | |
| import streamlit as st | |
| import numpy as np | |
| import matplotlib.pyplot as plt | |
| from matplotlib.patches import Circle | |
| import plotly.graph_objects as go | |
| from typing import Optional, Tuple | |
| def create_synthetic_bathymetry(size: int = 100) -> Tuple[np.ndarray, np.ndarray, np.ndarray]: | |
| """Create synthetic bathymetry for demonstration""" | |
| x = np.linspace(-500, 500, size) | |
| y = np.linspace(-500, 500, size) | |
| X, Y = np.meshgrid(x, y) | |
| # Simple continental shelf profile | |
| r = np.sqrt(X**2 + Y**2) | |
| depth = -5000 + 0.1 * r # Depth increases with distance | |
| depth = np.clip(depth, -6000, 0) | |
| return X, Y, depth | |
| def create_wave_front(r: np.ndarray, t: float, speed: float = 0.5) -> np.ndarray: | |
| """Create synthetic wave front""" | |
| return 5 * np.exp(-(r - 300 - speed * t)**2 / 5000) | |
| def display_wave_front_map(zone: str = "global", | |
| show_bathymetry: bool = True, | |
| show_front: bool = True, | |
| time_step: int = 0): | |
| """Display interactive wave front map""" | |
| # Create data | |
| X, Y, depth = create_synthetic_bathymetry() | |
| r = np.sqrt(X**2 + Y**2) | |
| wave = create_wave_front(r, time_step) | |
| # Create figure | |
| fig, ax = plt.subplots(figsize=(12, 8)) | |
| if show_bathymetry: | |
| contour = ax.contourf(X, Y, depth, levels=20, cmap='Blues_r', alpha=0.6) | |
| plt.colorbar(contour, ax=ax, label='Depth (m)') | |
| if show_front: | |
| front_contour = ax.contour(X, Y, wave, levels=[2, 4, 6], | |
| colors='red', linewidths=2) | |
| ax.clabel(front_contour, inline=True, fontsize=10) | |
| # Mark shoreline | |
| ax.axhline(y=0, color='brown', linestyle='-', linewidth=2, label='Shoreline') | |
| # Add coast | |
| coast_x = np.linspace(-500, 500, 100) | |
| coast_y = 50 * np.exp(-coast_x**2 / 50000) | |
| ax.fill_between(coast_x, 0, coast_y, color='green', alpha=0.3, label='Land') | |
| # Labels and formatting | |
| ax.set_xlabel('Distance (km)', fontsize=12) | |
| ax.set_ylabel('Distance (km)', fontsize=12) | |
| ax.set_title(f'Tsunami Wave Front Propagation - {zone}', fontsize=14) | |
| ax.grid(True, alpha=0.3) | |
| ax.legend() | |
| # Set limits | |
| ax.set_xlim(-500, 500) | |
| ax.set_ylim(-500, 200) | |
| # Add scale bar | |
| ax.plot([-400, -300], [-450, -450], 'k-', linewidth=3) | |
| ax.text(-350, -470, '100 km', ha='center') | |
| return fig | |
| def display_interactive_map(): | |
| """Display interactive map with Plotly""" | |
| # Create data | |
| x = np.linspace(-500, 500, 100) | |
| y = np.linspace(-500, 200, 70) | |
| X, Y = np.meshgrid(x, y) | |
| # Bathymetry | |
| r = np.sqrt(X**2 + Y**2) | |
| depth = -5000 + 0.1 * r | |
| depth = np.clip(depth, -6000, 0) | |
| # Wave front | |
| wave = 5 * np.exp(-(r - 300)**2 / 5000) | |
| # Create figure | |
| fig = go.Figure() | |
| # Add bathymetry heatmap | |
| fig.add_trace(go.Contour( | |
| z=depth, | |
| x=x, y=y, | |
| colorscale='Blues', | |
| showscale=True, | |
| colorbar=dict(title="Depth (m)"), | |
| name="Bathymetry" | |
| )) | |
| # Add wave front contours | |
| fig.add_trace(go.Contour( | |
| z=wave, | |
| x=x, y=y, | |
| contours=dict( | |
| coloring='none', | |
| showlabels=True, | |
| labelfont=dict(size=12, color='red') | |
| ), | |
| line=dict(color='red', width=2), | |
| showscale=False, | |
| name="Wave Front" | |
| )) | |
| # Add shoreline | |
| fig.add_shape( | |
| type="line", | |
| x0=-500, y0=0, x1=500, y1=0, | |
| line=dict(color="brown", width=3, dash="solid"), | |
| name="Shoreline" | |
| ) | |
| # Update layout | |
| fig.update_layout( | |
| title="Tsunami Wave Front - Interactive Map", | |
| xaxis_title="Distance (km)", | |
| yaxis_title="Distance (km)", | |
| width=800, | |
| height=600, | |
| hovermode='closest' | |
| ) | |
| return fig | |
| def get_front_properties(wcc: float = 1.31, | |
| hfsi: float = 0.63, | |
| distance: float = 180) -> dict: | |
| """Get wave front properties""" | |
| # Calculate ETA based on distance and speed | |
| speed = 200 # m/s approximate | |
| eta_minutes = distance * 1000 / speed / 60 | |
| return { | |
| "celerity": wcc, | |
| "stability": hfsi, | |
| "distance_to_shore_km": distance, | |
| "eta_minutes": eta_minutes, | |
| "status": "ALERT" if hfsi < 0.6 else "MONITOR", | |
| "front_width_km": 50, | |
| "amplification_factor": 2.5 | |
| } | |
| def display_front_properties_panel(properties: dict): | |
| """Display wave front properties panel""" | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| st.metric("Celerity (WCC)", f"{properties['celerity']:.2f}") | |
| st.metric("Distance to Shore", f"{properties['distance_to_shore_km']} km") | |
| st.metric("Front Width", f"{properties['front_width_km']} km") | |
| with col2: | |
| st.metric("Stability (HFSI)", f"{properties['stability']:.2f}") | |
| st.metric("ETA to Landfall", f"{properties['eta_minutes']:.0f} min") | |
| st.metric("Amplification", f"{properties['amplification_factor']:.1f}x") | |
| # Status indicator | |
| if properties['stability'] < 0.4: | |
| st.error("⚠️ CRITICAL: Breaking imminent") | |
| elif properties['stability'] < 0.6: | |
| st.warning("⚠️ ALERT: Front unstable") | |
| elif properties['stability'] < 0.8: | |
| st.info("ℹ️ MONITOR: Weakly unstable") | |
| else: | |
| st.success("✅ SAFE: Stable front") | |