You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Delivered by the polycell work on branch edu/polycell-spatial-support (@eduaguilera) — the consumer-side half of #460. Do not start.
The "decision needed" in this issue is settled: polycell_id, not majority-fraction overwrite. Majority-fraction is centroid assignment under another name — it re-creates the very failure this issue opens with (a polity smaller than a cell gets nothing), just with a different tie-break. The polycell costs +6.3% rows (68,527 vs 64,438), which buys the guarantee that aggregating polycells to a polity changes no absolute value and no quantity crosses a border it does not belong to.
Corollary, and a separate acceptance criterion: that guarantee only holds if every allocation is keyed on the polycell, never computed on the cell and apportioned afterwards. Computing from cell-average drivers and splitting after the fact hands a neighbour a share of whatever the cell produced.
Measurements from that work: the centroid pin is genuinely one polity per cell (58,791 rows = 58,791 unique cells, no share column, so .normalize_country_grid() defaults cell_area_frac = 1). The two grids disagree in both directions — 5,651 cells in the fractional grid and not the centroid one, and 4 cells the other way ((-75.75, 22.25) a/c 12, (98.25, 11.25) a/c 28, (131.75, -4.75) a/c 101, (-80.75, -33.75) a/c 40) which are carbon-path rows today, so a naive switch silently deletes them. Small polities are worse than "zero cells": French Polynesia 18 polycells, Kiribati 9, Micronesia 4, Maldives 1, all with zero LUH2 terrestrial area, so each draws a full cell and over-counts land by roughly 13×, 34×, 18× and 10×.
This will expose polygon-quality problems underneath it — MDV-1800-2025 measures 24.4 km² against an official 300 km², MCO-1800-2025 19.7 km² against 2.08 km². Those belong upstream in whep-polities, not here.
Two wiring traps for whoever touches it: landfrac is already an alias for cell_area_frac in .normalize_country_grid(), so a land-fraction column under that name is silently reinterpreted as a polity share with no warning and no failing test; and inst/scripts/run_spatialize.R:255-258 and :396-403 conditionally re-attach the centroid grid on (lon, lat), which becomes many-to-many under a fractional or polycell grid and will not warn because the next join already declares relationship = "many-to-many".
Original text follows for the record.
Problem prepare_spatialize_all.R builds TWO grids from the same shapefile: prepare_country_grid()
(Section 1) does single-centroid terra::rasterize() — one area_code per 0.5° cell, winner-take-
all at borders — and this is what build_gridded_landuse()/build_gridded_livestock() actually
consume via the spatialize-country-grid pin. build_cell_polity_fraction() (Section 1b) does the
geometrically correct thing (6x finer, per-cell fractional coverage) but that output is saved
separately as cell_polity_fraction and only read by build_cell_polity() (#460's target) —
never plumbed into the crop/livestock engine. The engine already has first-class support for
exactly this fractional input (cell_area_frac in .normalize_country_grid(), exercised by tests/testthat/test_spatialize.R:564 and test_spatialize_livestock.R:383), so this is a wiring
gap, not a missing feature. Small polities whose land area is smaller than a 0.5° cell and whose
polygon never contains a cell centroid get ZERO cells and their entire harvested-area/livestock
total is unallocated.
Evidence
inst/scripts/prepare_spatialize_all.R:887-933 (prepare_country_grid, centroid), :945-1027 (build_cell_polity_fraction, fractional, unused by the engine).
R/spatialize_compartments.R:3-34 (.normalize_country_grid already treats polity_frac as an
alias for cell_area_frac).
.load_landuse_inputs()/.load_livestock_inputs() (R/run_spatialize.R:472-597) read spatialize-country-grid (centroid), not cell_polity_fraction.
Target state
Feed build_gridded_landuse()/build_gridded_livestock() the fractional table (or a table
unioning it with polycell_id/cell_id per compartment) as country_grid — a data-wiring change
in R/run_spatialize.R and the pin-build step, not an engine change.
Acceptance criteria
Small polities previously invisible to .warn_unallocated_crops()/.warn_unallocated_livestock()
now receive nonzero cells.
Total spatialized area/heads per country diffed against pre-change output; document any material
shifts.
Depends on: none. Decision needed: whether to add polycell_id (multiple compartment rows
per fractional cell, more correct) vs. overwrite with the majority-fraction polity (simpler, no
row-count change).
Important
Delivered by the polycell work on branch
edu/polycell-spatial-support(@eduaguilera) — the consumer-side half of #460. Do not start.The "decision needed" in this issue is settled:
polycell_id, not majority-fraction overwrite. Majority-fraction is centroid assignment under another name — it re-creates the very failure this issue opens with (a polity smaller than a cell gets nothing), just with a different tie-break. The polycell costs +6.3% rows (68,527 vs 64,438), which buys the guarantee that aggregating polycells to a polity changes no absolute value and no quantity crosses a border it does not belong to.Corollary, and a separate acceptance criterion: that guarantee only holds if every allocation is keyed on the polycell, never computed on the cell and apportioned afterwards. Computing from cell-average drivers and splitting after the fact hands a neighbour a share of whatever the cell produced.
Measurements from that work: the centroid pin is genuinely one polity per cell (58,791 rows = 58,791 unique cells, no share column, so
.normalize_country_grid()defaultscell_area_frac = 1). The two grids disagree in both directions — 5,651 cells in the fractional grid and not the centroid one, and 4 cells the other way ((-75.75, 22.25)a/c 12,(98.25, 11.25)a/c 28,(131.75, -4.75)a/c 101,(-80.75, -33.75)a/c 40) which are carbon-path rows today, so a naive switch silently deletes them. Small polities are worse than "zero cells": French Polynesia 18 polycells, Kiribati 9, Micronesia 4, Maldives 1, all with zero LUH2 terrestrial area, so each draws a full cell and over-counts land by roughly 13×, 34×, 18× and 10×.This will expose polygon-quality problems underneath it —
MDV-1800-2025measures 24.4 km² against an official 300 km²,MCO-1800-202519.7 km² against 2.08 km². Those belong upstream inwhep-polities, not here.Two wiring traps for whoever touches it:
landfracis already an alias forcell_area_fracin.normalize_country_grid(), so a land-fraction column under that name is silently reinterpreted as a polity share with no warning and no failing test; andinst/scripts/run_spatialize.R:255-258and:396-403conditionally re-attach the centroid grid on(lon, lat), which becomes many-to-many under a fractional or polycell grid and will not warn because the next join already declaresrelationship = "many-to-many".Original text follows for the record.
Problem
prepare_spatialize_all.Rbuilds TWO grids from the same shapefile:prepare_country_grid()(Section 1) does single-centroid
terra::rasterize()— onearea_codeper 0.5° cell, winner-take-all at borders — and this is what
build_gridded_landuse()/build_gridded_livestock()actuallyconsume via the
spatialize-country-gridpin.build_cell_polity_fraction()(Section 1b) does thegeometrically correct thing (6x finer, per-cell fractional coverage) but that output is saved
separately as
cell_polity_fractionand only read bybuild_cell_polity()(#460's target) —never plumbed into the crop/livestock engine. The engine already has first-class support for
exactly this fractional input (
cell_area_fracin.normalize_country_grid(), exercised bytests/testthat/test_spatialize.R:564andtest_spatialize_livestock.R:383), so this is a wiringgap, not a missing feature. Small polities whose land area is smaller than a 0.5° cell and whose
polygon never contains a cell centroid get ZERO cells and their entire harvested-area/livestock
total is unallocated.
Evidence
inst/scripts/prepare_spatialize_all.R:887-933(prepare_country_grid, centroid),:945-1027(build_cell_polity_fraction, fractional, unused by the engine).R/spatialize_compartments.R:3-34(.normalize_country_gridalready treatspolity_fracas analias for
cell_area_frac)..load_landuse_inputs()/.load_livestock_inputs()(R/run_spatialize.R:472-597) readspatialize-country-grid(centroid), notcell_polity_fraction.Target state
Feed
build_gridded_landuse()/build_gridded_livestock()the fractional table (or a tableunioning it with
polycell_id/cell_idper compartment) ascountry_grid— a data-wiring changein
R/run_spatialize.Rand the pin-build step, not an engine change.Acceptance criteria
.warn_unallocated_crops()/.warn_unallocated_livestock()now receive nonzero cells.
shifts.
Depends on: none. Decision needed: whether to add
polycell_id(multiple compartment rowsper fractional cell, more correct) vs. overwrite with the majority-fraction polity (simpler, no
row-count change).
Moves published values: yes. Port from #382: no.
Part of the polity migration epic #458.