Skip to content

A city with no waste figure of its own generates waste at its country's default rate - #79

Open
HughRunyan wants to merge 2 commits into
mainfrom
defaulted-cities-generate-waste-at-the-default-rate
Open

HughRunyan wants to merge 2 commits into
mainfrom
defaulted-cities-generate-waste-at-the-default-rate

Conversation

@HughRunyan

Copy link
Copy Markdown
Collaborator

Summary

When a cities-table row has no tonnage, City.load_andre_params sizes the city's waste as the IPCC per-capita default × the city's population. That population is the one for the row's population year, so the mass already describes the population year. The loader labelled it 2019 anyway, then ran the adjustment that moves a surveyed tonnage from its survey year to the population year. That moved the mass a second time, so every defaulted city got default × P(population year) / P(2019), or the compounded equivalent for a big city on its own UN rates.

With this PR, the default takes the population year as its year, so the adjustment leaves it alone.

Bug report

Environment: SWEET_python main at d5c592e, City.load_andre_params, non-backfill branch (SWEET_python/city_params.py, the default block and the "difference in reporting years" adjustment below it). WasteMAP's cities-table build (backend/scripts/make_cities_table.py) reaches this code. That build publishes the map's city figures and the table the City DST reads.

Reproduction:

  1. Build a cities-query row for Kuwait City: population 2,779,000 in 2015, country Kuwait, its own UN rates of 5.74% and 1.34% a year, no MSW tonnage. _row in tests/test_default_waste_per_capita.py does this.
  2. Run City("Kuwait City").load_andre_params(row).

Expected: waste_per_capita is Kuwait's default: 3.05 t/yr, or 8.356 kg/person/day. The waste mass is 8.356 × 2,779,000 × 365 / 1000 = 8,475,950 t/yr.

Actual: 7.923 kg/person/day and 8,036,460 t/yr, which is the default × 1.0134⁻⁴. The June 2026 cities table publishes exactly this for Kuwait City (7.92 kg/person/day, 8,036,459.98 t/yr).

Evidence: on main, the new tests give 13 failed and 1 passed. Each failing value equals the default × P(population year) / P(2019) to the last digit:

  • Eldoret: 0.30137 × 0.69536 (Kenya's population, 2005 over 2019) = 0.20956
  • Kadoma City: 0.52055 × 1.05191 (Zimbabwe's, 2022 over 2019) = 0.54757

The test that passes on both is the control: a surveyed tonnage still moves from its survey year to the population year.

The fix

In the default branch, year_of_data_msw = int(year_of_data_pop) replaces 2019. The adjustment below then leaves the mass alone. A surveyed tonnage moves exactly as before.

City.import_basics, the legacy SINIR loader, had the same rule and gets the same one-line fix. Only model_city_via_sites reaches it, and nothing calls that.

Effect

In WasteMAP's June 2026 cities table, 39 of 5,962 cities have "Defaults Used: Waste Mass". SWEET's emissions are linear in waste mass, so each city's CH4 changes by the same ratio as its waste, in every year. I checked this: for all 39 cities, the CH4 ratio equals the mass ratio to within 1e-15 in both 2025 and 2050.

  • Waste and CH4: from −7.9% (Abeokuta, population year 2022) to +53.9% (Kano, 2006). 30 cities rise and 9 fall.
  • 2025 total for the 39: 394.9 kt CH4 as published becomes about 421.5 kt (+26.6 kt, +6.7%).
  • Published year: "Year of Data Collection (MSW)" becomes the population year (2005–2022) instead of 2019. The map build appends that year to the three "Data Source" labels, and the API returns it as waste_mass_year.
  • When: nothing moves until the cities table is rebuilt, because the map and the City DST read the published table. Climate TRACE doesn't call load_andre_params (no matches on CT main).
Per-city before/after (39 cities)
City ISO3 Pop. year Growth kg/person/day: June table main this PR Waste & CH4 2025 CH4, June table (t) ≈ Δ 2025 (t)
Melbourne AUS 2015 own UN rates 1.585 1.585 1.671 +5.4% 92,209 +5,004
Kuwait City KWT 2015 own UN rates 7.923 7.923 8.356 +5.5% 75,239 +4,115
Hamburg DEU 2015 own UN rates 1.638 1.638 1.644 +0.4% 47,651 +172
Tel Aviv ISR 2010 own UN rates 1.480 1.480 1.699 +14.7% 42,647 +6,288
Zurich CHE 2015 own UN rates 1.883 1.883 1.945 +3.3% 39,503 +1,296
Tbilisi GEO 2015 own UN rates 1.682 1.682 1.699 +1.0% 27,612 +266
Jerusalem ISR 2010 own UN rates 1.502 1.502 1.699 +13.1% 10,320 +1,355
Kano NGA 2006 own UN rates 0.356 0.356 0.548 +53.9% 8,565 +4,613
Bloemfontein ZAF 2011 country series 1.768 1.782 2.000 +12.2% 6,621 +809
Eindhoven NLD 2017 country series 1.546 1.543 1.562 +1.2% 5,596 +69
Burgas BGR 2016 country series 1.510 1.540 1.507 -2.1% 3,939 -85
Manama BHR 2015 own UN rates 1.007 1.007 1.096 +8.8% 3,204 +282
Namangan UZB 2015 own UN rates 0.883 0.883 0.932 +5.5% 2,934 +160
Ruse BGR 2016 country series 1.515 1.540 1.507 -2.1% 2,826 -61
Apia WSM 2016 country series 3.379 3.365 3.466 +3.0% 2,814 +84
Debrecen HUN 2017 country series 1.095 1.098 1.096 -0.2% 2,809 -6
Ilorin NGA 2015 own UN rates 0.480 0.480 0.548 +14.1% 2,686 +378
Turku FIN 2015 country series 1.266 1.277 1.288 +0.8% 2,360 +20
Blantyre MWI 2010 own UN rates 0.337 0.337 0.493 +46.2% 2,146 +991
Moroni COM 2015 country series 1.877 2.048 2.219 +8.3% 1,970 +164
Abeokuta NGA 2022 own UN rates 0.595 0.595 0.548 -7.9% 1,680 -132
Nyagatare RWA 2016 own UN rates 0.471 0.471 0.521 +10.6% 1,253 +133
Kostanay KAZ 2014 country series 0.925 0.864 0.932 +7.8% 968 +76
Nouakchott MRT 2015 country series 0.427 0.438 0.493 +12.7% 769 +98
Oulu FIN 2015 country series 1.266 1.277 1.288 +0.8% 749 +6
Douglas IMN 2014 country series 1.564 1.619 1.616 -0.2% 748 -1
Tartumaa EST 2016 country series 0.844 0.844 0.849 +0.7% 742 +5
Labe GIN 2014 country series 0.440 0.434 0.493 +13.6% 685 +93
Halaba Kulito ETH 2016 country series 0.266 0.278 0.301 +8.5% 595 +50
Limbe CMR 2005 country series 0.488 0.514 0.767 +49.4% 447 +221
Liepaja LVA 2017 country series 0.873 0.890 0.877 -1.5% 413 -6
Perth AUS 2013 country series 1.559 1.522 1.671 +9.8% 382 +37
Riihimaki FIN 2015 country series 1.261 1.277 1.288 +0.8% 373 +3
Eldoret KEN 2005 country series 0.173 0.210 0.301 +43.8% 309 +135
Ramallah PSE 2017 country series 1.013 0.995 1.041 +4.6% 308 +14
Kadoma City ZWE 2022 country series 0.574 0.548 0.521 -4.9% 279 -14
Masvingo City ZWE 2022 country series 0.574 0.548 0.521 -4.9% 277 -14
Paralimni CYP 2017 country series 1.773 1.842 1.890 +2.6% 149 +4
Funafuti TUV 2014 country series 3.299 3.571 3.466 -2.9% 124 -4
All 39 +6.7% 394,902 +26,620

How the columns were computed:

  • main and this PR: I ran load_andre_params on each city's published population, population year, country and own UN rates. Those are the only inputs that decide a defaulted city's mass.
  • Check against the June table: on main, this reproduces the June table's mass to within 6e-8 for the 14 cities on their own rates. The 25 cities on their country's series differ, because WasteMAP's tools grow waste with the country's UN population, year by year #71 changed their growth after the table was built.
  • ≈ Δ 2025: this PR's ratio applied to the June figure. It is exact for the first group and approximate for the second.

Needs your input: which year these 39 rows publish

The arithmetic doesn't depend on this choice: a per-capita rate × population gives the same mass whatever year the rate is said to describe. The label matters downstream. year_of_data_msw is published as "Year of Data Collection (MSW)" and appended to all three "Data Source" labels. The API also returns it as waste_mass_year, the year the ADST prefill anchors the city's tonnage on.

  1. Population year (implemented, and my recommendation). It is the only label under which the published tonnage and its year agree, so waste_mass_year becomes correct for these rows. The catch: 21 of the 39 carry their own composition, and its label would show the population year, which isn't that data's year either. Today it shows 2019.
  2. 2010. This is the year the IPCC per-capita defaults describe (2019 Refinement Vol. 5 Ch. 2, Table 2.1 footnote 3; the country rows are Table 2A.1's 2010 column). The provenance is honest, but the API would pair a population-year tonnage with 2010. The ADST prefill would then anchor it up to 12 years off, which is the same kind of error this PR fixes.
  3. Keep 2019. No label changes. It has the same API mismatch, and 2019 is the year of the IPCC report, not of its data.
  4. The row's own survey year. Honest for the composition and diversion labels, but the tonnage has the same API mismatch.

Options 2–4 need the label kept separately from the year the adjustment uses. That is a one-line follow-up.

Not in this PR

Acceptance criteria

  • A city with no tonnage gets exactly its country's per-capita default (else its region's), whatever its population year and growth path.
  • A defaulted city is modelled exactly like a city that reports the default rate for its population year: emissions are identical in every year.
  • A surveyed tonnage still moves from its survey year to the population year.
  • import_basics follows the same rule.
  • Per-city before/after for the 39 cities.
  • Hugh confirms the published year: the population year as implemented, or another option.

Definition of Done

  • Acceptance criteria met
  • Tests and checks pass (pytest -m "not integration": 286 passed locally)
  • Changelog updated
  • Reviewed and merged

Test plan

  • tests/test_default_waste_per_capita.py (14 tests): 13 fail on main, and all 14 pass on this branch.
  • Full suite: 286 passed locally (Python 3.13). CI runs 3.12.

🤖 Generated with Claude Code

When a cities-table row has no generated or collected tonnage,
load_andre_params sizes the city's waste as the IPCC per-capita default
times the city's population. That population is the population year's, so
the mass already describes the population year. The loader labelled it
2019, and the adjustment that moves a surveyed tonnage from its survey year
to the population year then moved it again: the city got
default x P(population year) / P(2019). Kuwait City published 7.92
kg/person/day against Kuwait's 8.36.

The default branch now takes the population year as its year, so the
adjustment leaves it alone; a surveyed tonnage is still moved. The legacy
SINIR loader, import_basics, had the same rule and gets the same fix.

The 39 defaulted cities in WasteMAP's June 2026 table change by -7.9% to
+53.9% (mass and CH4 alike), and publish their population year as
"Year of Data Collection (MSW)" instead of 2019.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@HughRunyan HughRunyan added bug Something isn't working model-output-change Changes model OUTPUT values (expected progress, not breaking); results differ from prior runs test Adds or modifies tests labels Oct 9, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working model-output-change Changes model OUTPUT values (expected progress, not breaking); results differ from prior runs test Adds or modifies tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant