Skip to content

Decision needed: GAUL country coding — Kosovo/disputed territories + who owns the GAUL↔VIEWS crosswalk #123

Description

@Polichinel

Ask

We need someone working on this repo to do a deep dive and land a decision (not necessarily code yet) on two connected questions about country coding in the platform's GAUL era:

  1. How should disputed / non-VIEWS territories be coded — Kosovo first among them? GAUL 2024 (FAO's coding) folds Kosovo into Serbia, so any consumer that colours or labels cells by gaul0_code/iso3_code will render Kosovo territory as "Serbia". Is that the platform's intended presentation? If not, what is — a declared override table, a platform-owned coding layer on top of GAUL, something else?
  2. Who owns the GAUL↔VIEWS-country crosswalk long-term? Today there is no bridge between GAUL codes and VIEWS country_id anywhere in the factory; views-reporting has built a makeshift, script-only one for its own needs (details below). If a general solution belongs anywhere, it is probably in the data layer, not in a reporting repo.

Full context (from views-reporting's global-PGM work, 2026-07-20/21)

The first real global PGM ensemble report (views-reporting epic views-platform/views-reporting#230) surfaced this: the models now consume the datafactory (global, 64,818 land cells, country identity = gaul0_code), while viewser's pg_metadata queryset is still Africa+ME-bounded (verified 2026-07-20: 13,110 cells × 852 months; the pgm loa has no global rows). The factory's own grid_to_country_month adapter groups by gaul0_code — GAUL is the factory-era country identity, and no GAUL↔VIEWS crosswalk exists in the factory.

To label global maps, views-reporting built an explicitly interim crosswalk (decision recorded on views-platform/views-reporting#231, PR views-platform/views-reporting#238, risk register entry C-211): GAUL iso3_code → VIEWS isoabcountry_id, built from the harvested data/raw/gaul_admin/ parquets (gaul0_code, gaul0_name, iso3_code; full 259,200-cell grid).

Measured facts from that crosswalk (all reproducible from the harvest + VIEWS country table):

  • 66,205 of 259,200 grid cells resolve to a VIEWS country; coverage of the 64,818-cell forecast land region is 99.5%.
  • Grid-wide, 29,373 GAUL-coded land cells have no VIEWS country: Antarctica (ATA) 25,444, Greenland (GRL) 3,038, then the disputed set — Western Sahara (ESH) 101, Jammu & Kashmir (xJK) 75, Arunachal Pradesh (xAP) 23, Aksai Chin (xAC) 11, Hala'ib (xHT) 8, Abyei (xAB), Ilemi (xIT), and assorted small territories. (GAUL's x-prefixed codes mark disputed areas.)
  • Kosovo concretely: GAUL has no Kosovo unit at gaul0 level — its territory is coded SRB. The 10 Kosovo-region cells (gids 190482, 190483, 191201–191204, 191921–191924) therefore map to VIEWS Serbia (country_id 233). VIEWS's Kosovo entity (country_id 232, the platform's only null-isoab country) receives zero cells. This is silent by construction: the cells carry a valid code, so no "unmatched" accounting flags them.
  • ~157 Africa+ME border cells differ between GAUL 2024 and the old viewser assignment (e.g. GAUL puts the Aouzou strip in Chad, viewser had Libya; similar bands on Algeria/Morocco/Tunisia, Turkey/Syria, Somalia/Ethiopia borders).
  • VIEWS isoab is not unique over history (retired states share codes with successors: DEU, ETH, IDN, SAU, SDN, SRB, SUN, TZA, YEM, YUG, ZAF) — any ISO-keyed bridge must resolve duplicates to the currently-active entity; the reporting script does this by most-recent observation.

The makeshift solution in views-reporting (and the ask attached to it)

views-reporting/scripts/build_entity_metadata.py (functions read_gaul_cells, active_country_by_isoab, crosswalk_priogrid) freezes the crosswalk into a bundled parquet (priogrid_id → country_id) that reporting's renderers consume offline. It is a dev-time script, deliberately not shipped in the wheel — nobody can import it, and it is not intended as platform infrastructure. It exists solely so global forecast maps have country labels while the real decision is pending.

If a more general solution manifests here (a factory-owned crosswalk, a platform coding layer, a GAUL-with-overrides standard, anything) — please open an issue in views-platform/views-reporting so reporting can retire the makeshift script and re-source its bundle. The reporting side is architected so this is a build-script-only swap (runtime accessors depend only on the bundle schema), so switching costs are low once a decision lands.

What a resolution could look like (non-binding sketch, from the reporting-side investigation)

  • Kosovo/disputed policy: either (a) accept GAUL's coding as-is and declare it platform-wide, or (b) maintain a small, versioned override table (cell → platform country) applied on top of the harvest — ~10 cells for Kosovo; the x-coded disputed territories would need an explicit stance either way.
  • Crosswalk ownership: a small importable module (factory-side or a shared package) exposing GAUL↔VIEWS mapping with the duplicate-isoab resolution made explicit — so consumers (reporting, postprocessing, CM adapters) agree on cell→country instead of re-deriving it independently.

A cross-repo copy of this issue is being filed in the sibling repo (views-datafactory ↔ views-postprocessing) — coordinate as one decision, not two.

Filed from the views-reporting global-PGM epic; questions → Simon (@Polichinl) or the reporting repo's #231/#230 threads.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions