Spaces:
Sleeping
Sleeping
✨ feat(disaster): add NASA EONET layer with scorch effects
Browse filesAdd disaster feature slice with NASA EONET v3 proxy (wildfires, storms,
volcanoes, floods, earthquakes). Disasters render as stacked scorch
marks (char + flame + ignition core). Flood zones now use 3-layer ink
bleed (halo + fill + edge). Add Playwright capture scripts for
Chicago, New Orleans, and showcase comparisons.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- surgeink/api/disasters.py +41 -0
- surgeink/api/router.py +2 -1
surgeink/api/disasters.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import httpx
|
| 2 |
+
from fastapi import APIRouter, Query
|
| 3 |
+
|
| 4 |
+
from surgeink.cache.redis_cache import cache_get_json, cache_set_json
|
| 5 |
+
|
| 6 |
+
router = APIRouter()
|
| 7 |
+
|
| 8 |
+
EONET_BASE = "https://eonet.gsfc.nasa.gov/api/v3/events/geojson"
|
| 9 |
+
CACHE_TTL = 600 # 10 minutes
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
@router.get("/disasters")
|
| 13 |
+
async def get_disasters(
|
| 14 |
+
categories: str = Query(
|
| 15 |
+
"wildfires,severeStorms,volcanoes,floods,earthquakes",
|
| 16 |
+
description="Comma-separated EONET category IDs",
|
| 17 |
+
),
|
| 18 |
+
limit: int = Query(200, ge=1, le=1000),
|
| 19 |
+
days: int = Query(30, ge=1, le=365),
|
| 20 |
+
status: str = Query("open", description="open or closed"),
|
| 21 |
+
):
|
| 22 |
+
cache_key = f"disasters:{categories}:{limit}:{days}:{status}"
|
| 23 |
+
cached = await cache_get_json(cache_key)
|
| 24 |
+
if cached is not None:
|
| 25 |
+
return cached
|
| 26 |
+
|
| 27 |
+
params = {
|
| 28 |
+
"status": status,
|
| 29 |
+
"limit": limit,
|
| 30 |
+
"days": days,
|
| 31 |
+
}
|
| 32 |
+
if categories:
|
| 33 |
+
params["category"] = categories
|
| 34 |
+
|
| 35 |
+
async with httpx.AsyncClient(timeout=20.0) as client:
|
| 36 |
+
resp = await client.get(EONET_BASE, params=params)
|
| 37 |
+
resp.raise_for_status()
|
| 38 |
+
|
| 39 |
+
data = resp.json()
|
| 40 |
+
await cache_set_json(cache_key, data, CACHE_TTL)
|
| 41 |
+
return data
|
surgeink/api/router.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
from fastapi import APIRouter
|
| 2 |
|
| 3 |
-
from surgeink.api import geocode, forecast, layers, risk, tiles, predict, interpret, fema
|
| 4 |
|
| 5 |
router = APIRouter(prefix="/api/v1")
|
| 6 |
|
|
@@ -12,3 +12,4 @@ router.include_router(tiles.router, tags=["tiles"])
|
|
| 12 |
router.include_router(predict.router, tags=["predict"])
|
| 13 |
router.include_router(interpret.router, tags=["interpret"])
|
| 14 |
router.include_router(fema.router, tags=["fema"])
|
|
|
|
|
|
| 1 |
from fastapi import APIRouter
|
| 2 |
|
| 3 |
+
from surgeink.api import geocode, forecast, layers, risk, tiles, predict, interpret, fema, disasters
|
| 4 |
|
| 5 |
router = APIRouter(prefix="/api/v1")
|
| 6 |
|
|
|
|
| 12 |
router.include_router(predict.router, tags=["predict"])
|
| 13 |
router.include_router(interpret.router, tags=["interpret"])
|
| 14 |
router.include_router(fema.router, tags=["fema"])
|
| 15 |
+
router.include_router(disasters.router, tags=["disasters"])
|