sdg11 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. sdg11-0.1.0/CHANGELOG.md +36 -0
  2. sdg11-0.1.0/CITATION.cff +21 -0
  3. sdg11-0.1.0/LICENSE +21 -0
  4. sdg11-0.1.0/MANIFEST.in +9 -0
  5. sdg11-0.1.0/PKG-INFO +332 -0
  6. sdg11-0.1.0/README.md +289 -0
  7. sdg11-0.1.0/examples/quickstart.py +24 -0
  8. sdg11-0.1.0/pyproject.toml +131 -0
  9. sdg11-0.1.0/setup.cfg +4 -0
  10. sdg11-0.1.0/src/sdg11/__init__.py +73 -0
  11. sdg11-0.1.0/src/sdg11/_result.py +117 -0
  12. sdg11-0.1.0/src/sdg11/air_quality.py +166 -0
  13. sdg11-0.1.0/src/sdg11/citations.py +160 -0
  14. sdg11-0.1.0/src/sdg11/cli.py +127 -0
  15. sdg11-0.1.0/src/sdg11/components.py +114 -0
  16. sdg11-0.1.0/src/sdg11/config.py +258 -0
  17. sdg11-0.1.0/src/sdg11/degurba.py +324 -0
  18. sdg11-0.1.0/src/sdg11/geometry.py +159 -0
  19. sdg11-0.1.0/src/sdg11/housing.py +265 -0
  20. sdg11-0.1.0/src/sdg11/io.py +267 -0
  21. sdg11-0.1.0/src/sdg11/land.py +192 -0
  22. sdg11-0.1.0/src/sdg11/network.py +159 -0
  23. sdg11-0.1.0/src/sdg11/open_space.py +227 -0
  24. sdg11-0.1.0/src/sdg11/py.typed +0 -0
  25. sdg11-0.1.0/src/sdg11/report.py +197 -0
  26. sdg11-0.1.0/src/sdg11/synthetic.py +168 -0
  27. sdg11-0.1.0/src/sdg11/transport.py +210 -0
  28. sdg11-0.1.0/src/sdg11.egg-info/PKG-INFO +332 -0
  29. sdg11-0.1.0/src/sdg11.egg-info/SOURCES.txt +42 -0
  30. sdg11-0.1.0/src/sdg11.egg-info/dependency_links.txt +1 -0
  31. sdg11-0.1.0/src/sdg11.egg-info/entry_points.txt +2 -0
  32. sdg11-0.1.0/src/sdg11.egg-info/requires.txt +18 -0
  33. sdg11-0.1.0/src/sdg11.egg-info/top_level.txt +1 -0
  34. sdg11-0.1.0/tests/test_air_quality.py +70 -0
  35. sdg11-0.1.0/tests/test_components.py +59 -0
  36. sdg11-0.1.0/tests/test_degurba.py +226 -0
  37. sdg11-0.1.0/tests/test_geometry_network.py +101 -0
  38. sdg11-0.1.0/tests/test_housing.py +99 -0
  39. sdg11-0.1.0/tests/test_io.py +171 -0
  40. sdg11-0.1.0/tests/test_land.py +92 -0
  41. sdg11-0.1.0/tests/test_open_space.py +99 -0
  42. sdg11-0.1.0/tests/test_readme.py +25 -0
  43. sdg11-0.1.0/tests/test_report_cli.py +266 -0
  44. sdg11-0.1.0/tests/test_transport.py +133 -0
@@ -0,0 +1,36 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this
6
+ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.1.0] - 2026-11-08
11
+ ### Added
12
+ - **SDG 11.1.1** `slum_proportion`: population share in slum households from household
13
+ tables (five UN-Habitat deprivations, overcrowding derived from persons per room, survey
14
+ weights, urban filter, optional affordability criterion for inadequate housing).
15
+ - **SDG 11.2.1** `public_transport_access`: 500 m / 1 000 m walking thresholds to low- and
16
+ high-capacity public transport, along a street network (`WalkNetwork`) or with a Euclidean
17
+ fallback; disaggregation by population group and optional service-frequency filter.
18
+ - **SDG 11.3.1** `land_consumption` and `land_consumption_from_grids`: LCRPGR with the land
19
+ consumption rate, population growth rate, built-up area per capita and an interpretation.
20
+ - **SDG 11.6.2** `population_weighted_concentration`: population-weighted annual mean PM2.5 /
21
+ PM10 with exceedance of the 2021 WHO guideline and interim targets; `annual_mean` with a
22
+ data-completeness check and `assign_nearest_station`.
23
+ - **SDG 11.7.1** `open_space_share`, `average_open_space_share` and `open_space_access`
24
+ (share of population within 400 m of open public space).
25
+ - **Degree of Urbanisation** `classify_degurba`: level-1 grid classification (urban centre,
26
+ urban cluster, rural) with 4-/8-connectivity, the optional built-up criterion, majority-rule
27
+ smoothing and gap filling. Connected components use SciPy when available and a pure-NumPy
28
+ union-find fallback otherwise.
29
+ - `IndicatorResult` / `DegurbaResult` with components, metadata, citations and reporting notes;
30
+ `report()` producing JSON and Markdown.
31
+ - I/O for GeoJSON, CSV, `.npy`, ESRI ASCII grids and (with the `geo` extra) GeoTIFF.
32
+ - CLI: `sdg11 degurba`, `sdg11 report config.toml`, `sdg11 demo`, `sdg11 citations`.
33
+ - Synthetic example city (`sdg11.synthetic.write_synthetic_city`).
34
+
35
+ [Unreleased]: https://github.com/YusufEminoglu/sdg11_sdk/compare/v0.1.0...HEAD
36
+ [0.1.0]: https://github.com/YusufEminoglu/sdg11_sdk/releases/tag/v0.1.0
@@ -0,0 +1,21 @@
1
+ cff-version: 1.2.0
2
+ message: "If you use this software, please cite it as below."
3
+ authors:
4
+ - family-names: "Eminoğlu"
5
+ given-names: "Yusuf"
6
+ email: "yusufeminoglu@gmail.com"
7
+ orcid: "https://orcid.org/0009-0005-6000-2934"
8
+ title: "sdg11: UN SDG 11 urban indicators and the Degree of Urbanisation from open data"
9
+ version: "0.1.0"
10
+ date-released: "2026-11-08"
11
+ license: "MIT"
12
+ repository-code: "https://github.com/YusufEminoglu/sdg11_sdk"
13
+ url: "https://pypi.org/project/sdg11/"
14
+ abstract: "Open-source Python toolkit computing SDG 11 urban indicators (11.1.1, 11.2.1, 11.3.1, 11.6.2, 11.7.1) and the Degree of Urbanisation level-1 grid classification following the published UN-Habitat, WHO and EU/UN-Habitat methodologies. Not an official UN product."
15
+ keywords:
16
+ - SDG 11
17
+ - UN-Habitat
18
+ - urban indicators
19
+ - Degree of Urbanisation
20
+ - public transport access
21
+ - land consumption
sdg11-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Yusuf Eminoğlu
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,9 @@
1
+ include LICENSE
2
+ include README.md
3
+ include CHANGELOG.md
4
+ include CITATION.cff
5
+ include pyproject.toml
6
+ include src/sdg11/py.typed
7
+ recursive-include src/sdg11 *.py
8
+ recursive-include tests *.py
9
+ recursive-include examples *.py
sdg11-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,332 @@
1
+ Metadata-Version: 2.4
2
+ Name: sdg11
3
+ Version: 0.1.0
4
+ Summary: UN SDG 11 urban indicators (11.1.1, 11.2.1, 11.3.1, 11.6.2, 11.7.1) and the Degree of Urbanisation from open data, following the UN-Habitat metadata.
5
+ Author-email: Yusuf Eminoğlu <yusufeminoglu@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/YusufEminoglu/sdg11_sdk
8
+ Project-URL: Repository, https://github.com/YusufEminoglu/sdg11_sdk
9
+ Project-URL: Issues, https://github.com/YusufEminoglu/sdg11_sdk/issues
10
+ Project-URL: Changelog, https://github.com/YusufEminoglu/sdg11_sdk/blob/main/CHANGELOG.md
11
+ Keywords: sdg,sdg11,sustainable-development-goals,un-habitat,urban-indicators,degree-of-urbanisation,degurba,public-transport-access,land-consumption,lcrpgr,open-space,air-quality,pm2.5,slums,gis,urban-planning
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Operating System :: OS Independent
20
+ Classifier: Topic :: Scientific/Engineering :: GIS
21
+ Classifier: Topic :: Sociology
22
+ Classifier: Intended Audience :: Science/Research
23
+ Classifier: Intended Audience :: Developers
24
+ Classifier: Intended Audience :: End Users/Desktop
25
+ Classifier: Typing :: Typed
26
+ Requires-Python: >=3.9
27
+ Description-Content-Type: text/markdown
28
+ License-File: LICENSE
29
+ Requires-Dist: numpy>=1.20.0
30
+ Requires-Dist: tomli>=1.1.0; python_version < "3.11"
31
+ Provides-Extra: fast
32
+ Requires-Dist: scipy>=1.7.0; extra == "fast"
33
+ Provides-Extra: geo
34
+ Requires-Dist: scipy>=1.7.0; extra == "geo"
35
+ Requires-Dist: rasterio>=1.3.0; extra == "geo"
36
+ Requires-Dist: geopandas>=0.12.0; extra == "geo"
37
+ Provides-Extra: dev
38
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
39
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
40
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
41
+ Requires-Dist: mypy>=1.0.0; extra == "dev"
42
+ Dynamic: license-file
43
+
44
+ # sdg11
45
+
46
+ **Compute UN Sustainable Development Goal 11 urban indicators from open data, following the
47
+ published UN-Habitat / WHO methodology.**
48
+
49
+ [![PyPI](https://img.shields.io/pypi/v/sdg11.svg)](https://pypi.org/project/sdg11/)
50
+ [![Python](https://img.shields.io/pypi/pyversions/sdg11.svg)](https://pypi.org/project/sdg11/)
51
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/YusufEminoglu/sdg11_sdk/blob/main/LICENSE)
52
+
53
+ `sdg11` is a small, dependency-light toolkit for city governments, NGOs, voluntary local
54
+ review (VLR) teams and researchers who need transparent, reproducible SDG 11 numbers from data
55
+ they already have: population points or grids, transit stops, street centrelines, park
56
+ polygons, built-up areas, air-quality grids and household surveys.
57
+
58
+ - Pure Python + NumPy. SciPy is used when installed (faster connected components and nearest
59
+ neighbours) with a pure-NumPy fallback that gives identical results.
60
+ - Every indicator returns an `IndicatorResult` with the value, its components, the method
61
+ version, parameters, citations and a short **how to report** note.
62
+ - `sdg11.report(...)` bundles results into **JSON** and a **Markdown table**.
63
+ - Command line: `sdg11 degurba grid.tif`, `sdg11 report config.toml`, `sdg11 demo DIR`.
64
+
65
+ > **Not an official UN product.** `sdg11` is an independent open-source implementation of
66
+ > publicly documented methods. It is not produced, endorsed or validated by the United Nations,
67
+ > UN-Habitat, WHO or the European Commission. Official SDG values are reported by national
68
+ > statistical systems; check results against the current metadata before official use.
69
+
70
+ ## Installation
71
+
72
+ ```bash
73
+ pip install sdg11 # NumPy only
74
+ pip install "sdg11[fast]" # + SciPy (faster labelling and nearest-neighbour search)
75
+ pip install "sdg11[geo]" # + SciPy, rasterio (GeoTIFF I/O) and geopandas
76
+ ```
77
+
78
+ Python 3.9 or newer.
79
+
80
+ ## Indicators
81
+
82
+ | Code | Indicator (paraphrased from the official metadata) | Function | Value |
83
+ |---|---|---|---|
84
+ | 11.1.1 | Proportion of the urban population living in slums, informal settlements or inadequate housing. A *slum household* lacks one or more of: improved water, improved sanitation, sufficient living area (no more than 3 persons per habitable room), durable housing, secure tenure. *Inadequate housing* adds affordability. [1] | `slum_proportion` | % of population |
85
+ | 11.2.1 | Proportion of the population with convenient access to public transport: living within 500 m walking distance of a low-capacity stop (bus, tram...) or 1 000 m of a high-capacity station (rail, metro, ferry), by sex, age and disability. [2] | `public_transport_access` | % of population |
86
+ | 11.3.1 | Ratio of land consumption rate to population growth rate (LCRPGR): `LCR = ln(Urb_t2/Urb_t1)/y`, `PGR = ln(Pop_t2/Pop_t1)/y`, `LCRPGR = LCR/PGR`, with built-up area per capita as a companion metric. [3] | `land_consumption`, `land_consumption_from_grids` | ratio |
87
+ | 11.6.2 | Annual mean levels of fine particulate matter (PM2.5 and PM10) in cities, population weighted: `sum(P_i C_i) / sum(P_i)`, compared with the 2021 WHO guideline and interim targets. [4, 5] | `population_weighted_concentration` | ug/m3 |
88
+ | 11.7.1 | Average share of the built-up area of cities that is open space for public use (streets + open public spaces), and the share of the population within 400 m walking distance of an open public space. [6] | `open_space_share`, `average_open_space_share`, `open_space_access` | % |
89
+ | DEGURBA | Degree of Urbanisation, level 1 grid classification: urban centres, urban clusters and rural grid cells from a 1 km2 population grid. [7, 8, 9] | `classify_degurba` | class grid |
90
+
91
+ ### Degree of Urbanisation (level 1) as implemented
92
+
93
+ Following chapter 2 of *Applying the Degree of Urbanisation* (2021 manual) [7]:
94
+
95
+ | Class | Cell criterion | Contiguity | Cluster criterion | Post-processing |
96
+ |---|---|---|---|---|
97
+ | Urban centre (3) | density >= 1 500 inh/km2, or built-up share >= 50 % (optional) | 4-connectivity (no diagonals) | population >= 50 000 | majority rule (a cell with >= 5 of its 8 neighbours in the centre joins it, iterated until stable) and filling of enclosed gaps < 15 km2 |
98
+ | Urban cluster (2) | density >= 300 inh/km2 | 8-connectivity (diagonals included) | population >= 5 000 | urban centres are part of their cluster but keep class 3 |
99
+ | Rural grid cell (1) | all other valid cells | | | |
100
+ | No data (0) | NaN or negative population | | | never added to a centre; a hole containing no-data cells is not filled |
101
+
102
+ All thresholds are keyword arguments, so national variants and sensitivity tests are one call
103
+ away. The classification of *spatial units* (cities, towns and semi-dense areas, rural areas)
104
+ and level 2 are not implemented yet.
105
+
106
+ ## Quick start
107
+
108
+ All coordinates must be in a **projected CRS in metres** (UTM, a national grid...). WGS84
109
+ GeoJSON can be converted with `sdg11.project_lonlat` or the `lonlat_origin` config key.
110
+
111
+ ### 11.2.1 public transport (hand-checkable)
112
+
113
+ ```python
114
+ import sdg11
115
+
116
+ stops = [[0, 0], [10_000, 0]]
117
+ modes = ["bus", "metro"] # low / high capacity
118
+ homes = [[499, 0], [-501, 0], [10_000, 999], [10_000, -1_001]]
119
+ people = [1, 2, 4, 8]
120
+
121
+ r = sdg11.public_transport_access(homes, people, stops, modes)
122
+ print(r) # SDG 11.2.1 ...: 33.33 % (1 + 4 of 15 residents)
123
+ print(r.components["population_served_by_high_capacity"]) # 4.0
124
+ ```
125
+
126
+ Walking distances along a street network:
127
+
128
+ ```python
129
+ net = sdg11.WalkNetwork.from_lines([[[0, 0], [0, 300], [400, 300], [400, 0]]])
130
+ r = sdg11.public_transport_access([[400, 0]], [10], [[0, 0]], ["bus"], network=net)
131
+ r.value # 0.0 -> 400 m as the crow flies, but 1 000 m along the street
132
+ ```
133
+
134
+ Disaggregate with `groups={"female": [...], "age_65_plus": [...], "disability": [...]}` and
135
+ filter stops by service frequency with `stop_departures_per_hour=` and
136
+ `min_departures_per_hour=3` (a 20-minute headway).
137
+
138
+ ### 11.3.1 land consumption
139
+
140
+ ```python
141
+ r = sdg11.land_consumption(
142
+ urban_area_t1_km2=100, urban_area_t2_km2=121,
143
+ population_t1=1_000_000, population_t2=1_100_000,
144
+ year_t1=2015, year_t2=2025,
145
+ )
146
+ r.value # 2.0 (ln 1.21 = 2 ln 1.1)
147
+ r.components["built_up_area_per_capita_t2_m2"] # 110.0
148
+ r.components["interpretation"] # 'Built-up area grew faster than population: ...'
149
+ ```
150
+
151
+ `land_consumption_from_grids(built_up_t1, built_up_t2, pop_t1, pop_t2, 2015, 2025,
152
+ cell_area_km2=0.01, extent=urban_centre_mask)` does the same from boolean masks or 0-1
153
+ built-up shares (e.g. GHS-BUILT), keeping a fixed city extent for both dates.
154
+
155
+ ### 11.6.2 air quality
156
+
157
+ ```python
158
+ r = sdg11.population_weighted_concentration([10, 20, 40], [1, 1, 2], pollutant="PM2.5")
159
+ r.value # 27.5 ug/m3
160
+ r.components["who_2021_exceedance"]["IT-1"]["share_above_pct"] # 50.0
161
+ ```
162
+
163
+ Concentrations can be a model grid aligned with the population grid, or monitor annual means
164
+ assigned with `assign_nearest_station(...)`. `annual_mean(daily, expected_count=365)` applies
165
+ the usual 75 % data-completeness check.
166
+
167
+ ### 11.7.1 open public space
168
+
169
+ ```python
170
+ city_a = sdg11.open_space_share(built_up_area_km2=10, open_public_space_area_km2=1.5,
171
+ street_area_km2=2.5, city="A") # 40 %
172
+ city_b = sdg11.open_space_share(30, 3.0, 3.0, city="B") # 20 %
173
+ sdg11.average_open_space_share([city_a, city_b]).value # 30.0
174
+
175
+ park = [[[0, 0], [100, 0], [100, 100], [0, 100], [0, 0]]] # [exterior, holes...]
176
+ sdg11.open_space_access([[500, 50], [501, 50]], [1, 1], [park]).value # 50.0 (400 m vs 401 m)
177
+ ```
178
+
179
+ ### 11.1.1 housing
180
+
181
+ ```python
182
+ households = {
183
+ "persons": [4, 2, 6, 3, 5],
184
+ "rooms": [2, 1, 1, 3, 2], # > 3 persons per room = overcrowded
185
+ "improved_water": [1, 1, 0, 1, 1],
186
+ "improved_sanitation": ["yes", "yes", "no", "yes", "no"],
187
+ "durable_housing": [1, 1, 1, 1, 1],
188
+ "secure_tenure": [1, 1, 1, 0, 1],
189
+ }
190
+ sdg11.slum_proportion(households).value # 70.0 (6 + 3 + 5 of 20 people)
191
+ ```
192
+
193
+ Flags mean *has the condition*. Survey weights (`weight=`), an urban filter (`urban=`) and the
194
+ affordability criterion (`housing_cost=`, `income=`, 30 % threshold) are supported; missing
195
+ deprivation columns are reported as not assessed (the result is then a lower bound).
196
+
197
+ ### Degree of Urbanisation
198
+
199
+ ```python
200
+ import numpy as np
201
+ grid = np.zeros((7, 7)); grid[2:5, 2:5] = 6000 # 9 km2, 54 000 people
202
+ res = sdg11.classify_degurba(grid, cell_area_km2=1.0)
203
+ res.classes # 3 inside the block, 1 elsewhere
204
+ print(res.summary_table())
205
+ ```
206
+
207
+ ### Batch report
208
+
209
+ ```python
210
+ rep = sdg11.report([r, city_a, res], title="SDG 11 - My City", city="My City", year=2025)
211
+ print(rep.to_markdown())
212
+ rep.save(json_path="sdg11.json", markdown_path="sdg11.md")
213
+ ```
214
+
215
+ ## Command line
216
+
217
+ ```bash
218
+ sdg11 demo ./demo # write a synthetic city dataset + config.toml
219
+ sdg11 report ./demo/config.toml --json report.json --markdown report.md
220
+ sdg11 degurba population_1km.tif --out degurba.tif --json degurba.json
221
+ sdg11 citations
222
+ ```
223
+
224
+ `sdg11 degurba` reads GeoTIFF (with the `geo` extra), ESRI ASCII grids (`.asc`), `.npy` and
225
+ `.csv`. The cell area is taken from the raster (projected CRS in metres, e.g. Mollweide for
226
+ GHS-POP) or set with `--cell-area-km2`.
227
+
228
+ ### Configuration file
229
+
230
+ ```toml
231
+ title = "SDG 11 - Example City"
232
+ city = "Example City"
233
+ year = 2025
234
+ # lonlat_origin = [28.97, 41.01] # project WGS84 GeoJSON inputs to local metres
235
+
236
+ [degurba]
237
+ population_grid = "population_1km.tif"
238
+
239
+ ["11.1.1"]
240
+ households = "households.csv" # column names as in slum_proportion(); override e.g. water = "h2o"
241
+
242
+ ["11.2.1"]
243
+ population = "population_points.geojson" # Point features
244
+ population_field = "pop"
245
+ groups = ["female", "male"] # optional properties for disaggregation
246
+ stops = "stops.geojson"
247
+ capacity_field = "mode" # "low"/"high" or bus, tram, metro, rail, ferry...
248
+ network = "streets.geojson" # optional LineStrings; Euclidean otherwise
249
+ network_max_segment_m = 50
250
+ departures_field = "departures_per_hour" # optional
251
+ min_departures_per_hour = 3 # optional
252
+
253
+ ["11.3.1"]
254
+ built_up_area_t1_km2 = 82.0 # or built_up_grid_t1 / built_up_grid_t2 + cell_area_km2
255
+ built_up_area_t2_km2 = 96.5
256
+ population_t1 = 640000 # numbers or grid paths
257
+ population_t2 = 700000
258
+ year_t1 = 2015
259
+ year_t2 = 2025
260
+
261
+ ["11.6.2"]
262
+ pollutant = "PM2.5"
263
+ concentration_grid = "pm25.tif" # aligned with population_grid
264
+ population_grid = "population_100m.tif"
265
+ # or: population = "...geojson", stations = "...geojson", value_field = "annual_mean"
266
+
267
+ ["11.7.1"]
268
+ built_up_area_km2 = 96.5
269
+ street_area_km2 = 18.0 # or streets = "street_polygons.geojson"
270
+ open_spaces = "open_spaces.geojson" # Polygons; area used when open_public_space_area_km2 is absent
271
+ population = "population_points.geojson" # enables the 400 m access measure
272
+ population_field = "pop"
273
+ network = "streets.geojson"
274
+ ```
275
+
276
+ Relative paths are resolved against the configuration file. Run `sdg11 demo DIR` for a
277
+ complete working example.
278
+
279
+ ## Limitations
280
+
281
+ - **Inputs define quality.** The indicators are only as good as the population, stop,
282
+ street, open-space and built-up data supplied; OpenStreetMap completeness varies widely.
283
+ - **City extent.** UN-Habitat recommends computing city indicators over the urban centre (or
284
+ urban extent) delineated with the Degree of Urbanisation. `sdg11` computes over whatever
285
+ points or cells you pass; use `classify_degurba` to define the extent first.
286
+ - **Euclidean fallback** overstates access compared with network walking distances; the
287
+ method used is recorded in every result and a warning is raised.
288
+ - **Network snapping** is to the nearest network node; use `max_segment_m` to densify long
289
+ street segments. Crossing lines without a shared vertex are not connected.
290
+ - **Projected coordinates** are assumed (metres). `project_lonlat` is a local equirectangular
291
+ projection, adequate within roughly 20 km of the origin.
292
+ - **Open space for public use** requires knowing which spaces are publicly accessible;
293
+ `sdg11` does not judge accessibility, ownership or quality of spaces.
294
+ - **11.1.1** relies on household-survey definitions of "improved" water and sanitation, durable
295
+ housing and secure tenure, which differ between surveys; the five deprivations are used as
296
+ coded in your data.
297
+ - **DEGURBA** level 2 and the classification of spatial units are not yet implemented. The
298
+ thresholds are defined for 1 km2 cells; other resolutions trigger a warning.
299
+ - Methodologies are revised; check the current metadata on the
300
+ [UN SDG metadata repository](https://unstats.un.org/sdgs/metadata/).
301
+
302
+ ## References
303
+
304
+ 1. UN-Habitat. SDG indicator metadata 11.1.1. https://unstats.un.org/sdgs/metadata/files/Metadata-11-01-01.pdf
305
+ 2. UN-Habitat. SDG indicator metadata 11.2.1. https://unstats.un.org/sdgs/metadata/files/Metadata-11-02-01.pdf
306
+ 3. UN-Habitat. SDG indicator metadata 11.3.1. https://unstats.un.org/sdgs/metadata/files/Metadata-11-03-01.pdf
307
+ 4. World Health Organization. SDG indicator metadata 11.6.2. https://unstats.un.org/sdgs/metadata/files/Metadata-11-06-02.pdf
308
+ 5. World Health Organization (2021). *WHO global air quality guidelines: particulate matter (PM2.5 and PM10), ozone, nitrogen dioxide, sulfur dioxide and carbon monoxide.* Geneva.
309
+ 6. UN-Habitat. SDG indicator metadata 11.7.1. https://unstats.un.org/sdgs/metadata/files/Metadata-11-07-01.pdf
310
+ 7. European Commission, FAO, ILO, OECD, UN-Habitat and World Bank (2021). *Applying the Degree of Urbanisation: A methodological manual to define cities, towns and rural areas for international comparisons.* 2021 edition. Publications Office of the European Union, Luxembourg.
311
+ 8. Dijkstra, L. et al. (2021). Applying the Degree of Urbanisation to the globe: A new harmonised definition reveals a different picture of global urbanisation. *Journal of Urban Economics* 125, 103312. https://doi.org/10.1016/j.jue.2020.103312
312
+ 9. United Nations Statistical Commission (2020). Endorsement of the Degree of Urbanisation at its 51st session.
313
+
314
+ `sdg11 citations` prints the same list; every result carries its own citations in
315
+ `result.metadata["citations"]`.
316
+
317
+ ## Development
318
+
319
+ ```bash
320
+ pip install -e ".[dev,geo]"
321
+ python -m pytest --cov=sdg11
322
+ python -m ruff check . && python -m ruff format --check src tests
323
+ python -m mypy src
324
+ ```
325
+
326
+ ## Citing
327
+
328
+ See [CITATION.cff](https://github.com/YusufEminoglu/sdg11_sdk/blob/main/CITATION.cff).
329
+
330
+ ## License
331
+
332
+ MIT (c) Yusuf Eminoğlu