import gradio as gr
import folium
import requests
import json
from datetime import datetime, timedelta
class RadarToggleApp:
def __init__(self):
# Canadian radar configuration
self.canada_wms_url = "https://geo.weather.gc.ca/geomet"
self.canada_layers = {
"Rain Radar (1km)": "RADAR_1KM_RRAI",
"Snow Radar (1km)": "RADAR_1KM_RSNO",
"Composite Radar": "RADAR_1KM_RDBR",
"24h Rain": "RDPA.24F_PR",
"6h Rain": "RDPA.6F_PR"
}
# American CONUS radar configuration
self.conus_wms_url = "https://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r.cgi"
self.conus_layers = {
"Base Reflectivity": "nexrad-n0r-900913",
"Storm Relative Motion": "nexrad-n1r-900913",
"Composite Reflectivity": "nexrad-ncr-900913",
"Echo Tops": "nexrad-net-900913"
}
# Map bounds
self.north_america_bounds = {
"center": [50.0, -100.0], # Center of North America
"southwest": [25.0, -140.0],
"northeast": [70.0, -50.0]
}
def create_radar_map(self, radar_system="Canada", layer_selection="Rain Radar (1km)", opacity=0.7):
"""Create a Folium map with radar overlay based on selected system."""
try:
# Create base map centered on North America
m = folium.Map(
location=self.north_america_bounds["center"],
zoom_start=4,
tiles="OpenStreetMap"
)
if radar_system == "Canada":
# Canadian radar system
wms_url = self.canada_wms_url
layer_name = self.canada_layers.get(layer_selection, "RADAR_1KM_RRAI")
system_name = "Canadian Radar"
attribution = 'ECCC'
# Add Canadian radar overlay
wms_layer = folium.raster_layers.WmsTileLayer(
url=wms_url,
layers=layer_name,
version="1.3.0",
transparent=True,
format="image/png",
name=f"{system_name} - {layer_selection}",
overlay=True,
control=True,
opacity=opacity,
attr=attribution
)
else: # CONUS American radar
# American CONUS radar system
wms_url = self.conus_wms_url
layer_name = self.conus_layers.get(layer_selection, "nexrad-n0r-900913")
system_name = "CONUS American Radar"
attribution = 'Iowa State University'
# Add American radar overlay
wms_layer = folium.raster_layers.WmsTileLayer(
url=wms_url,
layers=layer_name,
version="1.1.1",
transparent=True,
format="image/png",
name=f"{system_name} - {layer_selection}",
overlay=True,
control=True,
opacity=opacity,
attr=attribution
)
wms_layer.add_to(m)
# Add layer control
folium.LayerControl().add_to(m)
# Add info panel
info_html = f"""
{system_name}
Layer: {layer_selection}
Opacity: {opacity:.1f}
Coverage: {"Canada & Northern US" if radar_system == "Canada" else "Continental US"}
{"Environment Canada MSC GeoMet" if radar_system == "Canada" else "NEXRAD via Iowa State Mesonet"}
"""
m.get_root().html.add_child(folium.Element(info_html))
# Add major cities for reference
if radar_system == "Canada":
cities = [
{"name": "Toronto", "coords": [43.6532, -79.3832]},
{"name": "Vancouver", "coords": [49.2827, -123.1207]},
{"name": "Montreal", "coords": [45.5017, -73.5673]},
{"name": "Calgary", "coords": [51.0447, -114.0719]},
{"name": "Ottawa", "coords": [45.4215, -75.6972]},
{"name": "Winnipeg", "coords": [49.8951, -97.1384]}
]
marker_color = "red"
else:
cities = [
{"name": "New York", "coords": [40.7128, -74.0060]},
{"name": "Los Angeles", "coords": [34.0522, -118.2437]},
{"name": "Chicago", "coords": [41.8781, -87.6298]},
{"name": "Houston", "coords": [29.7604, -95.3698]},
{"name": "Miami", "coords": [25.7617, -80.1918]},
{"name": "Seattle", "coords": [47.6062, -122.3321]}
]
marker_color = "blue"
for city in cities:
folium.Marker(
location=city["coords"],
popup=folium.Popup(city["name"], parse_html=True),
tooltip=city["name"],
icon=folium.Icon(color=marker_color, icon="info-sign")
).add_to(m)
return m
except Exception as e:
# Create error map
error_map = folium.Map(
location=self.north_america_bounds["center"],
zoom_start=4
)
error_html = f"""
Error Loading Radar Data
Error: {str(e)}
System: {radar_system}
Layer: {layer_selection}
"""
error_map.get_root().html.add_child(folium.Element(error_html))
return error_map
# Initialize the app
app = RadarToggleApp()
def update_radar_map(radar_system, layer_selection, opacity):
"""Update the radar map based on user selections."""
radar_map = app.create_radar_map(radar_system, layer_selection, opacity)
return radar_map._repr_html_()
def get_available_layers(radar_system):
"""Get available layers for the selected radar system."""
if radar_system == "Canada":
return gr.Dropdown(choices=list(app.canada_layers.keys()), value="Rain Radar (1km)")
else:
return gr.Dropdown(choices=list(app.conus_layers.keys()), value="Base Reflectivity")
# Create Gradio interface
with gr.Blocks(title="North America Radar Toggle", theme=gr.themes.Soft()) as interface:
gr.Markdown("# 🌦️ North America Radar Toggle")
gr.Markdown("Switch between Canadian and American CONUS radar systems")
with gr.Row():
with gr.Column(scale=1):
gr.Markdown("## Radar Controls")
# Radar system selector
radar_system = gr.Radio(
choices=["Canada", "CONUS American"],
value="Canada",
label="Radar System",
info="Choose between Canadian or American radar"
)
# Layer selector (will update based on radar system)
layer_dropdown = gr.Dropdown(
choices=list(app.canada_layers.keys()),
value="Rain Radar (1km)",
label="Radar Layer",
info="Choose the type of radar data to display"
)
# Opacity slider
opacity_slider = gr.Slider(
minimum=0.1,
maximum=1.0,
value=0.7,
step=0.1,
label="Radar Opacity",
info="Adjust transparency of radar overlay"
)
# Update button
update_btn = gr.Button("Update Radar Map", variant="primary")
gr.Markdown("---")
with gr.Accordion("System Information", open=False):
gr.Markdown("""
## Canadian Radar System
- **Source**: Environment Canada MSC GeoMet
- **Coverage**: Canada and Northern US
- **Update**: Every 10 minutes
- **Layers**: Rain, Snow, Composite, Precipitation
## CONUS American Radar System
- **Source**: NEXRAD via Iowa State Mesonet
- **Coverage**: Continental United States
- **Update**: Real-time
- **Layers**: Base Reflectivity, Storm Motion, Composite
""")
with gr.Column(scale=6):
radar_map = gr.HTML(
value=app.create_radar_map()._repr_html_(),
label="North America Radar Map"
)
# Event handlers
def update_layer_choices(system):
"""Update available layers when radar system changes."""
if system == "Canada":
return gr.Dropdown(choices=list(app.canada_layers.keys()), value="Rain Radar (1km)")
else:
return gr.Dropdown(choices=list(app.conus_layers.keys()), value="Base Reflectivity")
# Update layer dropdown when radar system changes
radar_system.change(
fn=update_layer_choices,
inputs=[radar_system],
outputs=[layer_dropdown]
)
# Update map when any control changes
update_btn.click(
fn=update_radar_map,
inputs=[radar_system, layer_dropdown, opacity_slider],
outputs=[radar_map]
)
radar_system.change(
fn=update_radar_map,
inputs=[radar_system, layer_dropdown, opacity_slider],
outputs=[radar_map]
)
layer_dropdown.change(
fn=update_radar_map,
inputs=[radar_system, layer_dropdown, opacity_slider],
outputs=[radar_map]
)
opacity_slider.change(
fn=update_radar_map,
inputs=[radar_system, layer_dropdown, opacity_slider],
outputs=[radar_map]
)
# Launch the app
if __name__ == "__main__":
interface.launch(
server_name="0.0.0.0",
server_port=7861,
share=True,
debug=True
)