tsunami / src /tsuwave /dashboard /wave_front_map.py
Gitdeeper4's picture
رفع جميع ملفات TSU-WAVE مع YAML
12834b7
"""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")