Summary
Create interactive visualizations for pattern exploration, including publication-quality maps, time series plots, and a Streamlit dashboard for real-time pattern analysis.
Parent Issue: #1
Depends On: Phase 4 (Extreme Event Analysis)
Objectives
- Generate publication-quality EOF pattern maps with Cartopy
- Create time series visualizations with phase shading
- Build interactive Streamlit dashboard
- Produce Jupyter notebook for exploration
System Context
src/visualization/
├── maps.py # Cartopy-based pattern maps
├── timeseries.py # Index time series plots
└── dashboard.py # Streamlit interactive app
Files to Create/Modify
| File |
Action |
Description |
src/visualization/maps.py |
Create |
EOF pattern maps with coastlines |
src/visualization/timeseries.py |
Create |
Time series with phase highlighting |
src/visualization/dashboard.py |
Create |
Streamlit interactive dashboard |
notebooks/exploration.ipynb |
Create |
Analysis notebook |
Implementation Checklist
Pattern Maps
Time Series Plots
Interactive Dashboard
Notebook
Code Snippets
EOF Pattern Map
# src/visualization/maps.py
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import numpy as np
def plot_eof_pattern(
pattern: np.ndarray,
lat: np.ndarray,
lon: np.ndarray,
title: str = "EOF Pattern",
variance_explained: float = None,
output_path: str = None
) -> plt.Figure:
"""Plot EOF spatial pattern with coastlines.
Args:
pattern: 2D array (lat, lon)
lat: Latitude coordinates
lon: Longitude coordinates
title: Plot title
variance_explained: Optional variance explained percentage
output_path: Optional path to save figure
Returns:
matplotlib Figure object
"""
fig, ax = plt.subplots(
figsize=(12, 8),
subplot_kw={"projection": ccrs.PlateCarree()}
)
# Set up map features
ax.add_feature(cfeature.LAND, facecolor="lightgray")
ax.add_feature(cfeature.COASTLINE, linewidth=0.5)
ax.add_feature(cfeature.BORDERS, linewidth=0.3, linestyle=":")
ax.gridlines(draw_labels=True, alpha=0.3)
# Plot pattern
vmax = np.abs(pattern).max()
im = ax.contourf(
lon, lat, pattern,
levels=np.linspace(-vmax, vmax, 21),
cmap="RdBu_r",
transform=ccrs.PlateCarree(),
extend="both"
)
# Colorbar
cbar = plt.colorbar(im, ax=ax, orientation="horizontal", pad=0.05)
cbar.set_label("Standardized Anomaly")
# Title
if variance_explained:
title = f"{title} ({variance_explained:.1f}% variance)"
ax.set_title(title, fontsize=14, fontweight="bold")
if output_path:
fig.savefig(output_path, dpi=150, bbox_inches="tight")
return fig
Time Series with Phase Shading
# src/visualization/timeseries.py
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import pandas as pd
import numpy as np
def plot_index_timeseries(
index: pd.Series,
title: str = "Climate Index",
threshold: float = 0.5,
output_path: str = None
) -> plt.Figure:
"""Plot climate index time series with phase shading.
Args:
index: Time series with datetime index
title: Plot title
threshold: Threshold for phase classification
output_path: Optional path to save figure
Returns:
matplotlib Figure object
"""
fig, ax = plt.subplots(figsize=(14, 5))
# Plot index
ax.plot(index.index, index.values, "k-", linewidth=0.8, label="Monthly")
# Add running mean
rolling = index.rolling(12, center=True).mean()
ax.plot(rolling.index, rolling.values, "b-", linewidth=2, label="12-month mean")
# Shade positive phases
ax.fill_between(
index.index, index.values, threshold,
where=index.values > threshold,
alpha=0.3, color="red", label="Positive phase"
)
# Shade negative phases
ax.fill_between(
index.index, index.values, -threshold,
where=index.values < -threshold,
alpha=0.3, color="blue", label="Negative phase"
)
# Zero line
ax.axhline(0, color="gray", linestyle="--", linewidth=0.5)
# Formatting
ax.set_xlabel("Date")
ax.set_ylabel("Index Value")
ax.set_title(title, fontsize=14, fontweight="bold")
ax.legend(loc="upper right")
ax.xaxis.set_major_locator(mdates.YearLocator(10))
ax.xaxis.set_major_formatter(mdates.DateFormatter("%Y"))
if output_path:
fig.savefig(output_path, dpi=150, bbox_inches="tight")
return fig
Streamlit Dashboard
# src/visualization/dashboard.py
import streamlit as st
import pandas as pd
import numpy as np
# Page config
st.set_page_config(
page_title="Climate Pattern Explorer",
layout="wide"
)
st.title("Climate Pattern Recognition Dashboard")
# Sidebar controls
st.sidebar.header("Settings")
pattern_type = st.sidebar.selectbox(
"Select Teleconnection",
["NAO", "AO", "ONI", "PDO"]
)
date_range = st.sidebar.date_input(
"Date Range",
value=(pd.Timestamp("2000-01-01"), pd.Timestamp("2023-12-31"))
)
# Main content
col1, col2 = st.columns(2)
with col1:
st.subheader(f"{pattern_type} Spatial Pattern")
# Load and display pattern map
# st.pyplot(fig)
with col2:
st.subheader(f"{pattern_type} Time Series")
# Load and display time series
# st.line_chart(data)
# Correlation matrix
st.subheader("Index Correlations")
# st.dataframe(corr_matrix)
# Footer
st.markdown("---")
st.markdown("Data sources: ERA5, NOAA PSL")
Verification
# Generate pattern maps
python -c "
from src.visualization.maps import plot_eof_pattern
from src.features.eof import EOFAnalyzer
# ... generate and plot pattern
"
# Launch dashboard
streamlit run src/visualization/dashboard.py
# Run notebook
jupyter notebook notebooks/exploration.ipynb
Technical Challenges
| Challenge |
Mitigation |
| Cartopy installation |
Use conda environment |
| Projection performance |
Cache transformed coordinates |
| Streamlit data size |
Load summaries, not raw data |
| Color scale selection |
Use diverging for anomalies |
Definition of Done
Summary
Create interactive visualizations for pattern exploration, including publication-quality maps, time series plots, and a Streamlit dashboard for real-time pattern analysis.
Parent Issue: #1
Depends On: Phase 4 (Extreme Event Analysis)
Objectives
System Context
Files to Create/Modify
src/visualization/maps.pysrc/visualization/timeseries.pysrc/visualization/dashboard.pynotebooks/exploration.ipynbImplementation Checklist
Pattern Maps
Time Series Plots
Interactive Dashboard
Notebook
Code Snippets
EOF Pattern Map
Time Series with Phase Shading
Streamlit Dashboard
Verification
Technical Challenges
Definition of Done
figures/directory