GDACS global hazard dashboard¶
A 90-day snapshot of every GDACS hazard type worldwide: a faceted world map (one panel per hazard) coloured by alert level, plus a table of the current Red alerts.
GDACS is public — no credentials, no extra to install. download() returns a pyramids FeatureCollection (a geopandas.GeoDataFrame).
Setup¶
First the imports. matplotlib and pandas are used by the plotting and summary cells; earthlens provides the unified EarthLens entry point. We also create the output directory the backend writes into.
import datetime as dt
from pathlib import Path
import matplotlib.pyplot as plt
import pandas as pd
from earthlens import EarthLens
OUT_DIR = Path('gdacs_output')
OUT_DIR.mkdir(exist_ok=True)
The request window¶
We look back 90 days from today and list the six GDACS hazard codes we want, with friendly names for the map titles.
TODAY = dt.date.today()
START = (TODAY - dt.timedelta(days=90)).strftime('%Y-%m-%d')
END = TODAY.strftime('%Y-%m-%d')
HAZARDS = ['EQ', 'TC', 'FL', 'VO', 'WF', 'DR']
HAZARD_NAMES = {
'EQ': 'Earthquake',
'TC': 'Tropical cyclone',
'FL': 'Flood',
'VO': 'Volcano',
'WF': 'Wildfire',
'DR': 'Drought',
}
print('window:', START, 'to', END)
Pull every hazard for the window¶
A single request returns all six hazard types. We build the request first, then call download() on its own line so each step is easy to read and re-run. The call is wrapped so the notebook stays safe under nbval-lax when run offline.
alerts = None
try:
dashboard = EarthLens(
variables=HAZARDS,
data_source='gdacs',
start=START,
end=END,
aoi=[-180, -90, 180, 90],
alert_level=['Green', 'Orange', 'Red'],
path=str(OUT_DIR),
)
alerts = dashboard.download()
print(f'{len(alerts)} alerts')
print(alerts['hazard_type'].value_counts().to_dict())
except Exception as exc:
print(f'live GDACS query skipped (offline?): {type(exc).__name__}: {exc}')
Faceted world map — one panel per hazard¶
Each panel shows that hazard's alerts coloured by level (green / orange / red).
if alerts is not None and len(alerts):
colours = {'Green': 'green', 'Orange': 'orange', 'Red': 'red'}
fig, axes = plt.subplots(2, 3, figsize=(15, 7), sharex=True, sharey=True)
for ax, code in zip(axes.ravel(), HAZARDS):
subset = alerts[alerts['hazard_type'] == code]
ax.set_title(f'{HAZARD_NAMES[code]} ({len(subset)})')
ax.set_xlim(-180, 180)
ax.set_ylim(-90, 90)
if len(subset):
subset.plot(
ax=ax,
color=subset['alert_level'].map(colours).fillna('grey'),
markersize=18,
alpha=0.6,
)
fig.suptitle(f'GDACS alerts by hazard, {START} to {END}')
fig.tight_layout()
plt.show()
The current Red alerts¶
Red is GDACS's highest impact level. These are the alerts most likely to need a coordinated response.
if alerts is not None and len(alerts):
red = alerts[alerts['alert_level'] == 'Red'].sort_values(
'from_date', ascending=False
)
print(f'{len(red)} Red alerts in the window')
cols = ['from_date', 'hazard_type', 'name', 'country', 'alert_score', 'glide']
display(red[cols].head(20))
Alert-level breakdown per hazard¶
A compact cross-tab of how many alerts of each level each hazard produced.
if alerts is not None and len(alerts):
crosstab = pd.crosstab(alerts['hazard_type'], alerts['alert_level'])
for level in ['Green', 'Orange', 'Red']:
if level not in crosstab.columns:
crosstab[level] = 0
display(crosstab[['Green', 'Orange', 'Red']])