CoolFace
Apppublic

idiouf/African-Conservation-Human-Development-Observatory

sourceHugging Facecc-by-4.0updated 20d agoView on Hugging Face
0likes
App README

Conservation & Human Development in Africa

Where Africa's protected areas sit, what human conditions surround them, and whether the two move together.

The framing comes from *Li et al. (2024), The synergy between protected area effectiveness and economic growth, Current Biology 34. Across 10,143 protected areas worldwide the authors sort each park into one of four relationships with its neighbouring communities — synergy (47.7%), economy impaired (42.9%), conservation impaired (4.8%) and retreat* (4.6%) — and find that the strongest predictors of synergy are socioeconomic, not environmental: the country's HDI, income around the park, travel time to cities, road density in the 0–10 km buffer, and the size of the park.

This dashboard follows that thread for Africa: it maps the estate, puts the human conditions next to it, and lets you look at how conservation cover and human development have co-moved since 1990.

What is in it

PageWhat it answers
OverviewWhere the protected areas are, on a choropleth of the human development indicator you pick
Protected areasFilter and search the estate; a profile for any single park with its country context
Human conditionsEducation, health, income, demography and dependency, country by country
RelationshipsThe Li et al. 2×2 applied to African countries, plus a park-level scatter once you upload effectiveness scores
TrajectoriesIndicator paths 1990–2024, with UN projections drawn separately to 2100
Data & methodLive connector status, per-series coverage, the full indicator registry, and a detailed account of every computation and what each analysis supports

Deploying to a Hugging Face Space

  1. 1.Create a Space with SDK = Docker. Either the Blank or the Streamlit template works — the Dockerfile below replaces whatever the template generates.
  2. 2.Upload every file in this folder to the repo root. There are no subfolders: the theme that would normally live in .streamlit/config.toml is passed as flags in the Dockerfile, and downloads are cached to /tmp.
  3. 3.Optionally add unpopulation_data.csv — the same UN WPP 2024 extract the Africa Population Atlas uses. Without it the dashboard still runs; the demography and dependency indicators simply stay switched off.
  4. 4.Wait for the first build. On first load the app downloads its data and caches it to /tmp; that pass takes a minute or two, later loads are instant.

Making cold starts instant (recommended)

A free Space sleeps and restarts cold, losing /tmp, so every wake-up repeats the download. Run this once on a machine with normal internet and commit what it writes:

bash
python prefetch.py     # writes cache_protected_areas.parquet, cache_indicators_*.parquet, …

The app prefers those snapshots over the network and never expires them, so the Space paints immediately. Re-run and re-commit whenever you want fresher data; the Data & method page always shows how old the snapshot is.

The files

FileRole
app.pyThe Streamlit dashboard: six pages, bilingual, mobile-first
sources.pyData connectors, disk caching and the status each one reports
analysis.pyThe Li et al. typology, spatial joins, association measure and derived measures
methods.pyThe detailed Data, methods and analyses text, in both languages
DockerfileBuild for the Space; also carries the light and dark palettes
requirements.txtPinned dependencies
selftest.pyRuns every connector and prints what answered
prefetch.pyDownloads everything once and writes a cache_* snapshot to commit
record_demo.py, narration.mdRecords a 3-minute guided tour as demo.mp4, with voice-over text
make_fixtures.py, test_app.py, fixture_*Offline test doubles and the 37-check suite. Safe to delete from the Space; keep them if you want to re-run the tests.

Theme

Both palettes ship, so light and dark both render correctly — native widgets, data grids and pop-overs included — and the reader can switch at any time from ⋮ → Settings → Appearance. The dashboard opens dark by default.

Streamlit has no API for choosing which palette a first-time reader gets: with two palettes it simply follows the browser. CONSERVATION_HD_THEME=dark closes that gap — app.py writes the reader's preference key once, on a first visit only. It treats Streamlit's own eagerly-written "System" value as no choice made; an explicit Light or Dark is the reader's and is never overwritten. Set the variable to auto to follow the browser instead, or to light to open light.

One trap worth knowing: adding a single top-level --theme.<key> flag collapses the two palettes into one fixed custom theme and the switch disappears. --theme.base is likewise ignored once per-mode keys are present.

bash
pip install -r requirements.txt
CONSERVATION_HD_THEME=dark streamlit run app.py \
  --theme.light.backgroundColor="#F2F6FA" --theme.light.secondaryBackgroundColor="#FFFFFF" \
  --theme.light.textColor="#0F2439"       --theme.light.primaryColor="#1668CE" \
  --theme.dark.backgroundColor="#070F1A"  --theme.dark.secondaryBackgroundColor="#0D1E30" \
  --theme.dark.textColor="#F2F7FC"        --theme.dark.primaryColor="#4A9BFF"

To re-run the offline test suite:

bash
python make_fixtures.py   # regenerate the test doubles
python test_app.py        # 37 checks: analysis layer + every page in both languages

Optional configuration (Settings → Variables and secrets)

VariableEffect
PROTECTED_PLANET_TOKENUse the authoritative WDPA from Protected Planet instead of Wikidata
UN_WPP_CSVPath to the WPP extract if it is not at the repo root
SHDI_CSV_URLDirect link (or local path) to the Global Data Lab SHDI csv, to move from country averages to subnational regions
CONSERVATION_HD_CACHEWhere to cache downloads (default: a conservation_hd_cache folder in the system temp directory)
CONSERVATION_HD_CACHE_TTLCache lifetime in seconds (default 7 days)
CONSERVATION_HD_THEMEWhich palette a first-time reader opens in: dark (default), light, or auto to follow their browser. Readers can always switch afterwards.

Checking the connectors

Docker Spaces have no terminal unless Dev Mode is enabled, so the live check is inside the app: open Data & method. The table at the top lists every source with its state, row count and, when something fails, the exact error.

Locally, python selftest.py prints the same table.

Rules the dashboard keeps

  1. 1.Provenance is never inferred. Every indicator carries its source and every selector prints it, so a World Bank series and a UN series are never confused.
  2. 2.Projections never enter an analysis. WPP 2024 runs to 2100; everything after 2024 is a median-variant projection, filtered out of the typology, the change calculations, the map and the park profiles. Projections appear only on Trajectories, drawn dashed behind a marked line.
  3. 3.One variant only. Only the WPP median variant is read; high, low and probabilistic variants are dropped at load time.
  4. 4.The reference is stated, not hidden. Li et al. compare each park with matched counterfactual sites. That cannot be reconstructed from open country series, so the 2×2 here uses the African median change over the selected period. It is a descriptive benchmark, not a causal estimate, and the app says so on every view that uses it. Because a median split fixes each margin at 50/50, the four quadrant shares are near-arithmetic and are not comparable in level with the paper's; the page therefore also reports the association between the two axes (phi and an odds ratio), which is the part the split does not force.
  5. 5.Missing is missing. A failed connector disables its features and reports why. Nothing is filled in with modelled or invented numbers.

Adding Canopy PACE scores

The sidebar takes a CSV with at least a name column and a score column; pa_id (WDPA or Wikidata id) and iso3 are used first when present. Matching is by id, then by normalised name within a country, then by name; the app reports how many rows matched and lists the ones that did not, so a half-join is never silent. Once scores are loaded, the Relationships page gains a park-level scatter of effectiveness against any human development indicator.

Known limits

  • The pressure index is built from national population density, child dependency, rural share and how clustered the protected areas are. It is a screening proxy — which parks sit in busier settings — not a count of people within 10 km of a boundary. That number needs gridded population (WorldPop, GHSL, or a modelled surface) clipped to a buffer around each boundary polygon. It is the clearest next step.
  • Country averages hide the subnational variation the question is about. Switching on SHDI_CSV_URL is the single highest-value change.
  • Wikidata's coverage of protected areas is uneven between countries. A Protected Planet token replaces it with WDPA.
  • No nightlight or land-cover-change series is used, so this describes conditions and co-movement, not the causal park effect Li et al. estimate.

Citation

Li, B.V., Wu, S., Pimm, S.L. & Cui, J. (2024). The synergy between protected area effectiveness and economic growth. Current Biology 34, 1–14. <https://doi.org/10.1016/j.cub.2024.05.044>

United Nations, Department of Economic and Social Affairs, Population Division (2024). World Population Prospects 2024.

Dashboard: Diouf, I. (2026). Conservation & Human Development in Africa.


Dr. Ibrahima Diouf — UCAD–ESP/LPAO-SF · Université de Labé–FST

Site · Hugging Face · ORCID · LinkedIn · Google Scholar