Coverage Matrix¶
The library tracks data coverage and downstream-readiness as a ragged country × feature × wave tensor. Each cell gets a status tier — from "no source" through "builds with warnings" to "sanity-clean" — so you can answer two questions at a glance:
- Where is work still needed? (the red/amber cells)
- Which cells are safe to feed into downstream analysis? (
sane/blessed)
The grid below is rendered from the committed snapshot
(.coder/coverage/latest.csv); it reflects the last time the matrix was built.
The tier ladder¶
Each tier is derived from existing machinery — Wave.data_scheme (coverage),
the built table's t index (drops), and
diagnostics.is_this_feature_sane (readiness). Nothing
re-implements the sanity checks.
| Tier | Meaning |
|---|---|
n/a |
No per-wave readiness applies (a country-level-only feature like panel_ids, or a table with no t axis). |
absent |
The feature applies to the country, but its source is not declared for this wave. An expected gap, not a defect. |
declared |
Source present for the wave; readiness not assessed (a coverage-only run). |
dropped |
Source declared for the wave but the wave is missing/empty in the built table — a silent-drop hazard. |
broken |
The country-level build raised, or the whole feature is empty. |
builds |
The wave slice is non-empty but fails a sanity check (SanityReport.ok is False). |
sane |
The wave slice is non-empty and passes every sanity check (warnings allowed). |
blessed |
sane and listed in the git-tracked blessing file .coder/coverage/blessed.csv. |
The grid cell shows a worst-first glyph tally over a country's waves
(e.g. ⚠2 ✓5 –1 = 2 builds, 5 sane, 1 absent) and is coloured by the most
actionable tier present.
Generating / refreshing the matrix¶
make matrix # full readiness cube (heavy first run; cache-cheap after)
make matrix C="Uganda Malawi" # scope to countries (C=) / features (F=)
make matrix-coverage # coverage layer only — no builds, no data access
make matrix writes the committed journal .coder/coverage/latest.csv and a
self-contained HTML readout under bench/results/<date>/matrix.html.
Authoritative runs use a clean cache
Readiness is graded by building each feature. A warm cache reflects
whatever is cached, which can surface stale-cache hazards (e.g. a stale
script-path wave parquet reporting a feature broken). For a canonical
"ready from source" snapshot, build each country from a cleared cache
(lsms-library cache clear --country <C> first). The committed snapshot is
produced this way.
Publishing a refreshed snapshot¶
The page on this site is rendered from the committed latest.csv at docs-build
time, and the docs site only deploys on a push to master. So the full loop
to refresh what readers see is:
- Rebuild authoritatively — clear caches, then build. For the whole cube,
the per-country clean-cache builds parallelise well (one country per job);
for a spot refresh, scope with
C=: - Commit the journal (it is tracked despite the global
*.csvignore): - Land it on
mastervia the normaldevelopment → masterflow. That push triggersmkdocs build+ deploy (ci.ymldocsjob, gated tomaster), and the page re-renders from the new CSV — no data access needed in CI.
Automated refresh (opt-in, Savio)¶
The loop above can run unattended via two self-resubmitting Slurm jobs in
bin/ — used because Savio disables both scrontab and user crontab, so the
Slurm scheduler itself becomes the cron (each run sbatchs its own successor).
They are off until seeded:
# weekly warm/incremental refresh + monthly authoritative (clean-cache) reseed,
# each set to retire on COV_EXPIRES unless renewed:
sbatch --export=ALL,COV_EXPIRES=2026-12-25 bin/coverage_refresh.sbatch
sbatch --export=ALL,COV_EXPIRES=2026-12-25 bin/coverage_reseed.sbatch
Properties (see bin/coverage_lib.sh): builds in a dedicated clone (never
your checkout); change-gated (skips the build unless countries/** or the
matrix code changed); connectivity-gated (most-but-not-all nodes reach
GitHub — a bad node is skipped, never breaks the chain); pushes to development.
It tells you before it retires: ~21 days before COV_EXPIRES it opens a
GitHub issue (which emails you), and this page shows a freshness/expiry banner
that escalates as the date nears. Stop it anytime with
touch ~/.lsms_coverage_refresh.STOP; renew by re-seeding with a later
COV_EXPIRES. Check the schedule with squeue -u $USER (a pending future job).
Reading it from Python¶
import lsms_library as ll
ll.coverage() # the committed snapshot (last `make matrix`)
ll.coverage(refresh="coverage") # live coverage layer — config only, no builds
ll.coverage(refresh="readiness") # recompute the full cube in-process (heavy)
See the Coverage API reference for details.
Status snapshot¶
Coverage status
Last auto-refreshed 2026-06-26T04:59:51Z. Auto-refresh active; renewal due by 2026-12-26 (~182d).
35 countries × 39 features · 1849 cells · tiers — absent: 456 · dropped: 39 · broken: 8 · builds: 138 · sane: 1208.
| country \ feature | anthropometry | assets | cluster_features | community_cluster_xwalk | community_prices | consumption | crop_production | earnings | employment | enterprise_income | fct | food_acquired | food_coping | food_expenditures | food_prices | food_quantities | food_security | food_security_hfias | hhsize | household_characteristics | household_roster | housing | income | individual_education | interview_date | life_satisfaction | livestock | months_food_inadequate | nonfood_expenditures | nutrition | panel_ids | people_last7days | plot_features | plot_inputs | plot_labor | sample | shocks | subjective_well_being | updated_ids |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Albania | ✓1 –5 | ⚠2 ✓2 –2 | ✓6 | ✓6 | ✓3 –3 | ✓3 –3 | ✓3 –3 | ⚠2 ✓2 –2 | ⚠2 ✓4 | ✓1 –5 | ✓5 –1 | ||||||||||||||||||||||||||||
| Armenia | ✗1 | ✗1 | |||||||||||||||||||||||||||||||||||||
| Azerbaijan | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ||||||||||||||||||||||||||||||||
| Benin | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ||||||||||||||||||
| Burkina_Faso | ✓3 | ✓3 | ✓1 –2 | ✓3 | ✓1 –2 | ✓3 | ✓3 | ✓3 | ✓2 –1 | ✗!1 ✓2 | ✓3 | ✓3 | ✓3 | ✓2 –1 | ✓1 –2 | ✓1 –2 | ✓1 | ✓1 –2 | ✓2 –1 | ✓1 –2 | ✓1 –2 | ⚠2 ✓1 | ⚠1 ✓2 | ✓2 –1 | ✓1 | ||||||||||||||
| Cambodia | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | |||||||||||||||||||||||||||
| China | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | |||||||||||||||||||||||||||||||||
| CotedIvoire | ✓1 –4 | ⚠5 | ✓1 –4 | ✓1 –4 | ✗!4 ✓1 | ✓1 –4 | ✓1 –4 | ✓1 –4 | ✗!4 ✓1 | ⚠4 ✓1 | ✓1 –4 | ✓5 | ✓1 –4 | ✓1 –4 | ✓1 –4 | ✓1 –4 | ✓1 –4 | ✓1 –4 | ⚠1 ✓4 | ✓1 –4 | ✓1 –4 | ||||||||||||||||||
| Ethiopia | ✓5 | ✓5 | ⚠3 ✓2 | ✓5 | ✓5 | ✓5 | ✓3 –2 | ✓5 | ✓5 | ✓5 | ✓1 –4 | ✗!2 ✓3 | ⚠5 | ✓5 | ✓5 | ✓2 –3 | ✓5 | –5 | ✓1 | ✓5 | ⚠1 ✓4 | ✓5 | ✓5 | ✓5 | ✓5 | ✓1 | |||||||||||||
| EthiopiaRHS | ✓4 –4 | ✓1 –7 | ✓7 –1 | –8 | ✓2 –6 | ⚠1 ✓5 –2 | ✓5 –3 | ✓5 –3 | ✗!1 ✓4 –3 | ✓5 –3 | ✓1 –7 | ✓6 –2 | ✓6 –2 | ✓1 –7 | ✓3 –5 | ✓1 | ✓1 –7 | ✓8 | –1 | ||||||||||||||||||||
| GhanaLSS | ✗!3 ⚠3 ✓1 | ⚠2 ✓5 | ✓7 | ✓7 | ✓7 | ✓1 –6 | ✓7 | ⚠3 ✓4 | ✓5 –2 | ✓7 | ✓7 | ✓1 | ⚠2 ✓2 –3 | ⚠5 ✓2 | ✓1 | ||||||||||||||||||||||||
| GhanaSPS | ✓3 | ✓3 | ✓3 | ✓3 | |||||||||||||||||||||||||||||||||||
| Guatemala | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ||||||||||||||||||||||||||||
| Guinea-Bissau | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ||||||||||||||||||
| Guyana | –1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | |||||||||||||||||||||||||||||||
| India | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | |||||||||||||||||||||||||||||
| Iraq | ⚠1 ✓1 | ✓2 | ✓2 | ✓2 | ✓2 | ✓2 | ✓2 | ✓1 –1 | ✓2 | ✓1 –1 | |||||||||||||||||||||||||||||
| Kazakhstan | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | |||||||||||||||||||||||||||||||
| Kosovo | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ||||||||||||||||||||||||||||||
| Liberia | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | |||||||||||||||||||||||||||||
| Malawi | ✓4 –1 | ⚠2 ✓3 | ⚠2 ✓3 | ✓3 –2 | ✓4 –1 | ✓5 | ✓4 –1 | ✓5 | ✓5 | ✓5 | ⚠1 ✓2 –2 | ✓5 | ✓5 | ✓5 | ✓5 | ✓5 | ✓4 –1 | ✓4 –1 | ✓4 –1 | ⚠2 ✓2 –1 | ⚠2 ✓2 –1 | ✓4 –1 | ✓5 | ⚠1 ✓4 | ⚠1 ✓2 –2 | ||||||||||||||
| Mali | ✓2 –2 | ✓4 | ✓1 –3 | ⚠1 ✓1 –2 | ✓3 –1 | ✓1 –3 | ✓3 –1 | ✓3 –1 | ✓3 –1 | ✓2 –2 | ✗!1 ✓3 | ⚠1 ✓3 | ✓4 | ✓4 | ✓4 | ✓2 –2 | ✓1 | ✓2 –2 | ✓2 –2 | ✓2 –2 | ✓2 –2 | ⚠3 ✓1 | ✓4 | ✓2 –2 | ✓1 | ||||||||||||||
| Nepal | ✗3 | –3 | –3 | –3 | –3 | –3 | –3 | –3 | –3 | –3 | ✗3 | ||||||||||||||||||||||||||||
| Niger | ✓4 | ⚠2 ✓2 | ✓2 –2 | ⚠4 | ✓2 –2 | ✓2 –2 | ✓2 –2 | ✓2 –2 | ✓3 –1 | ✓4 | ✓4 | ✓4 | ✓4 | ✓2 –2 | ✓4 | ✓1 | ⚠2 ✓2 | ✓2 –2 | ✓4 | ✓4 | ⚠3 ✓1 | ⚠1 ✓3 | ✓2 –2 | ✓1 | |||||||||||||||
| Nigeria | –10 | ⚠2 ✓6 –2 | ⚠6 ✓2 –2 | ✗!5 ✓5 | –10 | ⚠6 ✓2 –2 | ✗!3 ✓3 –4 | ✓8 –2 | ✓8 –2 | ✓8 –2 | ✓10 | ⚠8 ✓2 | ✗!5 ✓5 | ✓10 | ✗!4 ✓4 –2 | –10 | ⚠8 –2 | –10 | ✗!5 ⚠5 | –10 | –10 | ✓10 | ✓8 –2 | ||||||||||||||||
| Pakistan | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | |||||||||||||||||||||||||||||||||
| Senegal | ✓2 | ✓2 | ✓1 –1 | ✓2 | ✓2 | ✓2 | ✓2 | ✓2 | ✓2 | ✓2 | ✓2 | ✓2 | ✓2 | ✓1 –1 | ✓1 | ✓1 –1 | ✓2 | ✓1 –1 | ✓1 –1 | ✓2 | ✓2 | ✓2 | ✓1 | ||||||||||||||||
| Serbia | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | |||||||||||||||||||||||||||
| Serbia and Montenegro | ✓2 | ✓2 | ✓2 | ✓2 | ⚠1 ✓1 | ||||||||||||||||||||||||||||||||||
| South Africa | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ||||||||||||||||||||||||||||||
| Tajikistan | ✓4 | ✓2 –2 | ✓4 | ✓4 | ⚠2 ✓1 –1 | ✓4 | ✓4 | ✓2 –2 | ✓1 –3 | ⚠2 ✓2 | |||||||||||||||||||||||||||||
| Tanzania | ⚠1 ✓5 | ✓1 –5 | ✓6 | ✓2 –4 | ✓2 –4 | ✓2 –4 | ✓6 | ✗!1 ✓5 | ✓6 | ✓6 | ✓6 | ✓6 | ✓6 | ✓6 | ✓6 | ✓6 | ✓6 | ✓2 –4 | ✓1 | ✓2 –4 | ✓2 –4 | ✓2 –4 | ✓2 –4 | ✓6 | ⚠5 ✓1 | ✓1 | |||||||||||||
| Timor-Leste | ✓2 | ✓2 | ✓2 | ✓2 | ✓2 | ✓2 | ✓2 | ✓1 –1 | ✓2 | ||||||||||||||||||||||||||||||
| Togo | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ✓1 | ||||||||||||||||||
| Uganda | ⚠2 ✓5 –1 | ✓8 | ⚠1 ✓7 | ⚠2 ✓5 –1 | ✓8 | ✓8 | ✓1 –8 | ✓8 | ✓8 | ✓8 | ✓8 | ✓8 | ✓8 | ⚠1 ✓7 | –8 | ✓8 | ✓8 | ✓7 –1 | ⚠1 ✓4 –3 | ⚠8 | –8 | ✓1 | ✓5 –3 | ⚠3 ✓5 | ✓7 –1 | ✓7 –1 | ✓8 | ⚠1 ✓7 | ✓1 |