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.
- sdg11-0.1.0/CHANGELOG.md +36 -0
- sdg11-0.1.0/CITATION.cff +21 -0
- sdg11-0.1.0/LICENSE +21 -0
- sdg11-0.1.0/MANIFEST.in +9 -0
- sdg11-0.1.0/PKG-INFO +332 -0
- sdg11-0.1.0/README.md +289 -0
- sdg11-0.1.0/examples/quickstart.py +24 -0
- sdg11-0.1.0/pyproject.toml +131 -0
- sdg11-0.1.0/setup.cfg +4 -0
- sdg11-0.1.0/src/sdg11/__init__.py +73 -0
- sdg11-0.1.0/src/sdg11/_result.py +117 -0
- sdg11-0.1.0/src/sdg11/air_quality.py +166 -0
- sdg11-0.1.0/src/sdg11/citations.py +160 -0
- sdg11-0.1.0/src/sdg11/cli.py +127 -0
- sdg11-0.1.0/src/sdg11/components.py +114 -0
- sdg11-0.1.0/src/sdg11/config.py +258 -0
- sdg11-0.1.0/src/sdg11/degurba.py +324 -0
- sdg11-0.1.0/src/sdg11/geometry.py +159 -0
- sdg11-0.1.0/src/sdg11/housing.py +265 -0
- sdg11-0.1.0/src/sdg11/io.py +267 -0
- sdg11-0.1.0/src/sdg11/land.py +192 -0
- sdg11-0.1.0/src/sdg11/network.py +159 -0
- sdg11-0.1.0/src/sdg11/open_space.py +227 -0
- sdg11-0.1.0/src/sdg11/py.typed +0 -0
- sdg11-0.1.0/src/sdg11/report.py +197 -0
- sdg11-0.1.0/src/sdg11/synthetic.py +168 -0
- sdg11-0.1.0/src/sdg11/transport.py +210 -0
- sdg11-0.1.0/src/sdg11.egg-info/PKG-INFO +332 -0
- sdg11-0.1.0/src/sdg11.egg-info/SOURCES.txt +42 -0
- sdg11-0.1.0/src/sdg11.egg-info/dependency_links.txt +1 -0
- sdg11-0.1.0/src/sdg11.egg-info/entry_points.txt +2 -0
- sdg11-0.1.0/src/sdg11.egg-info/requires.txt +18 -0
- sdg11-0.1.0/src/sdg11.egg-info/top_level.txt +1 -0
- sdg11-0.1.0/tests/test_air_quality.py +70 -0
- sdg11-0.1.0/tests/test_components.py +59 -0
- sdg11-0.1.0/tests/test_degurba.py +226 -0
- sdg11-0.1.0/tests/test_geometry_network.py +101 -0
- sdg11-0.1.0/tests/test_housing.py +99 -0
- sdg11-0.1.0/tests/test_io.py +171 -0
- sdg11-0.1.0/tests/test_land.py +92 -0
- sdg11-0.1.0/tests/test_open_space.py +99 -0
- sdg11-0.1.0/tests/test_readme.py +25 -0
- sdg11-0.1.0/tests/test_report_cli.py +266 -0
- sdg11-0.1.0/tests/test_transport.py +133 -0
sdg11-0.1.0/CHANGELOG.md
ADDED
|
@@ -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
|
sdg11-0.1.0/CITATION.cff
ADDED
|
@@ -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.
|
sdg11-0.1.0/MANIFEST.in
ADDED
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
|
+
[](https://pypi.org/project/sdg11/)
|
|
50
|
+
[](https://pypi.org/project/sdg11/)
|
|
51
|
+
[](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
|