fix: wildfire data parsing + dashboard cascade failure protection
Population exposure was showing 0 because exposure.py parsed wildfire
data using wrong keys ("regions" instead of "fires_by_region", "detections"
instead of "top_clusters"). Now correctly matches NASA FIRMS response format.
Dashboard updateAll() now wraps each map/UI update in try/catch to prevent
a single failed layer from blocking all subsequent layer renders.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
de2cbeaa1a
commit
2d1c95389a
@@ -117,17 +117,17 @@ async def fetch_population_exposure(
|
|||||||
"detail": f"M{eq.get('magnitude', '?')} {eq.get('place', '')}",
|
"detail": f"M{eq.get('magnitude', '?')} {eq.get('place', '')}",
|
||||||
})
|
})
|
||||||
|
|
||||||
# Wildfires
|
# Wildfires (fires_by_region is a dict keyed by region name)
|
||||||
for region_data in results.get("wildfire", {}).get("regions", []):
|
for region_name, region_data in results.get("wildfire", {}).get("fires_by_region", {}).items():
|
||||||
for fire in region_data.get("detections", []):
|
for cluster in region_data.get("top_clusters", []):
|
||||||
lat = fire.get("latitude") or fire.get("lat")
|
lat = cluster.get("lat")
|
||||||
lon = fire.get("longitude") or fire.get("lon")
|
lon = cluster.get("lon")
|
||||||
if lat is not None and lon is not None:
|
if lat is not None and lon is not None:
|
||||||
events.append({
|
events.append({
|
||||||
"lat": float(lat),
|
"lat": float(lat),
|
||||||
"lon": float(lon),
|
"lon": float(lon),
|
||||||
"type": "wildfire",
|
"type": "wildfire",
|
||||||
"detail": f"FRP {fire.get('frp', '?')} in {region_data.get('region', '?')}",
|
"detail": f"FRP {cluster.get('max_frp', '?')} ({cluster.get('fire_count', '?')} fires) in {region_name}",
|
||||||
})
|
})
|
||||||
|
|
||||||
# Conflict
|
# Conflict
|
||||||
|
|||||||
@@ -1887,30 +1887,35 @@ function updateTicker(data) {
|
|||||||
function updateAll(data) {
|
function updateAll(data) {
|
||||||
latestData = data;
|
latestData = data;
|
||||||
|
|
||||||
// Map layers
|
// Map layers (each wrapped to prevent cascade failures)
|
||||||
updateMapQuakes(data.earthquakes);
|
|
||||||
updateMapMilitary(data.military_flights);
|
|
||||||
var conflictData = (data.acled_events && !data.acled_events.error && data.acled_events.count > 0) ? data.acled_events
|
var conflictData = (data.acled_events && !data.acled_events.error && data.acled_events.count > 0) ? data.acled_events
|
||||||
: (data.ucdp_events && !data.ucdp_events.error && data.ucdp_events.count > 0) ? data.ucdp_events
|
: (data.ucdp_events && !data.ucdp_events.error && data.ucdp_events.count > 0) ? data.ucdp_events
|
||||||
: data.conflict_zones;
|
: data.conflict_zones;
|
||||||
updateMapConflict(conflictData);
|
var mapUpdates = [
|
||||||
updateMapFires(data.wildfires);
|
['quakes', function() { updateMapQuakes(data.earthquakes); }],
|
||||||
updateMapConvergence(data.signal_convergence);
|
['military', function() { updateMapMilitary(data.military_flights); }],
|
||||||
updateMapNuclear(data.nuclear_monitor);
|
['conflict', function() { updateMapConflict(conflictData); }],
|
||||||
updateMapInfra(data);
|
['fires', function() { updateMapFires(data.wildfires); }],
|
||||||
updateMapExposure(data.population_exposure);
|
['convergence', function() { updateMapConvergence(data.signal_convergence); }],
|
||||||
|
['nuclear', function() { updateMapNuclear(data.nuclear_monitor); }],
|
||||||
|
['infra', function() { updateMapInfra(data); }],
|
||||||
|
['exposure', function() { updateMapExposure(data.population_exposure); }]
|
||||||
|
];
|
||||||
|
mapUpdates.forEach(function(pair) {
|
||||||
|
try { pair[1](); } catch(e) { console.warn('updateAll: ' + pair[0] + ' failed:', e); }
|
||||||
|
});
|
||||||
|
|
||||||
// Alert banner
|
// Alert banner
|
||||||
updateAlertBanner(data.alert_digest);
|
try { updateAlertBanner(data.alert_digest); } catch(e) { console.warn('updateAll: alert_banner failed:', e); }
|
||||||
|
|
||||||
// HUD
|
// HUD
|
||||||
updateHudStats(data);
|
try { updateHudStats(data); } catch(e) { console.warn('updateAll: hud failed:', e); }
|
||||||
|
|
||||||
// Drawer
|
// Drawer
|
||||||
updateDrawer(data);
|
try { updateDrawer(data); } catch(e) { console.warn('updateAll: drawer failed:', e); }
|
||||||
|
|
||||||
// Ticker
|
// Ticker
|
||||||
updateTicker(data);
|
try { updateTicker(data); } catch(e) { console.warn('updateAll: ticker failed:', e); }
|
||||||
|
|
||||||
// Feed health
|
// Feed health
|
||||||
var feedKeys = Object.keys(data).filter(function(k) { return k !== 'source_health' && k !== 'cache_stats' && k !== 'timestamp'; });
|
var feedKeys = Object.keys(data).filter(function(k) { return k !== 'source_health' && k !== 'cache_stats' && k !== 'timestamp'; });
|
||||||
|
|||||||
Reference in New Issue
Block a user