Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ jobs:
run: pip install pylint

- name: Lint Source Code
run: pylint -d E0401 superblockify/
run: pylint -d E0401,R0917 superblockify/
# ignore import-errors first, analyze later with tests in anaconda environment

- name: Lint Tests
run: pylint -d E0401 -d R0801 tests/
run: pylint -d E0401,R0801,R0917 tests/
# also ignore code repetition in tests
1 change: 1 addition & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ jobs:

name: ${{ matrix.submodule.name }} (${{ matrix.python-version }} on ${{ matrix.os }})
runs-on: ${{ matrix.os }}
timeout-minutes: 60
defaults:
run:
shell: bash -el {0}
Expand Down
9 changes: 9 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@
Changelog
*********

Version 1.0.1 (2024-12-04)
**************************

* 🧹 Lint: Reconfigured linting settings.
* 🐛 Fixes: Removed unused Haversine distance function and adapted to `osmnx` API changes.
* 🛠️ Update: Updated `test.yml` for artifacts v4.4.0 breaking change.
* 📝 Documentation: Various updates including changelog, badge links,
mobile optimization, GitHub handles, installation instructions, `CITATION.cff`, and `paper.md`.

Version 1.0.0 (2024-08-12)
**************************

Expand Down
5 changes: 3 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#
import os
import sys
from datetime import datetime

sys.path.insert(0, os.path.abspath(".."))

Expand All @@ -22,9 +23,9 @@
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information

project = "superblockify"
copyright = "2023-2024, superblockify developers"
copyright = f"2023-{datetime.now().year}, superblockify developers"
author = "superblockify developers"
release = "1.0.0"
release = "1.0.1"

# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
Expand Down
16 changes: 12 additions & 4 deletions docs/guide/30_population_density.myst
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ from rasterstats import zonal_stats
## 1. Area Boundary

```{code-cell} ipython3
bogota_gdf = ox.geocode_to_gdf('Bogotá, Colombia')
bogota_gdf = ox.geocode_to_gdf('Bogotá, Capital District, RAP (Especial) Central, Colombia')
# Project to UTM, so we can treat it as flat Cartesian coordinates (meters)
bogota_gdf = ox.project_gdf(bogota_gdf)
bogota_gdf = ox.projection.project_gdf(bogota_gdf)
print(f"The area of Bogotá is {round(bogota_gdf.area[0] / 10 ** 6, 2)} km²")
bogota_gdf.explore()
```
Expand Down Expand Up @@ -405,7 +405,9 @@ One such example is the city of Jönköping in Sweden, it falls on two tiles.

```{code-cell} ipython3
:tags: [hide-input]
def get_population(place_gdf, pop_raster_files, resample_factor=1, place_name=None):
def get_population(
place_gdf, pop_raster_files, resample_factor=1, place_name=None, low_cutoff=0
):
"""Get the population for a place.

Parameters
Expand All @@ -419,6 +421,8 @@ def get_population(place_gdf, pop_raster_files, resample_factor=1, place_name=No
up-scaling.
place_name : str, optional
Name of the place. The default is None.
low_cutoff : float, optional
The least considered value for the population. The default is 0.

Returns
-------
Expand All @@ -427,7 +431,8 @@ def get_population(place_gdf, pop_raster_files, resample_factor=1, place_name=No
"""
fig, axe = plt.subplots(figsize=(6, 6))
pop_sum = 0
for pop_raster_file in pop_raster_files if isinstance(pop_raster_files, list) else [pop_raster_files]:
for pop_raster_file in pop_raster_files if isinstance(pop_raster_files, list) else [
pop_raster_files]:
# Window of place, buffered by 100m
with rasterio.open(pop_raster_file) as src:
window = src.window(*place_gdf.buffer(100).total_bounds)
Expand All @@ -442,6 +447,9 @@ def get_population(place_gdf, pop_raster_files, resample_factor=1, place_name=No
pop_raster = pop_raster / resample_factor ** 2 # Correct for resampling
# Set masked values to 0
pop_raster = pop_raster.filled(0)
# Cut off low values
pop_raster[pop_raster < low_cutoff] = 0

# Get population
zs_place = zonal_stats(place_gdf_raster_crs, pop_raster, affine=affine,
stats="sum", nodata=0)
Expand Down
8 changes: 4 additions & 4 deletions docs/guide/31_tessellation.myst
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ that might come to one's mind is the convex hull of the linestrings.

```{code-cell} ipython3
# From subgraph_edges we want to get a hull that encloses all edges
convex_hull = subgraph_edges.unary_union.convex_hull
convex_hull = subgraph_edges.union_all().convex_hull
# Make gdf from convex hull with the same crs as the subgraph
convex_hull_gdf = gpd.GeoDataFrame(
geometry=[convex_hull], crs=subgraph_edges.crs
Expand Down Expand Up @@ -102,7 +102,7 @@ from numpy import linspace
def plot_concave_hull(ax, subgraph_edges, ratio=0.4, allow_holes=False,
color="crimson"):
concave_hull = shp.concave_hull(
subgraph_edges.unary_union,
subgraph_edges.union_all(),
ratio=ratio,
allow_holes=allow_holes,
)
Expand Down Expand Up @@ -186,7 +186,7 @@ each other, we'll buffer using a flat cap style.
Does work well with small buffer values."""
edges = ox.graph_to_gdfs(subgraph, nodes=False, edges=True)
# First buffer with flat cap style to avoid self-intersections
polygon = shp.Polygon(edges.unary_union.buffer(2 * buffer, cap_style='flat')
polygon = shp.Polygon(edges.union_all().buffer(2 * buffer, cap_style='flat')
.exterior)
# Simplify the polygon to remove small artifacts of flat cap style at curved edges
# polygon = polygon.simplify(buffer*2, preserve_topology=True)
Expand Down Expand Up @@ -335,7 +335,7 @@ geometries. Then we can also split up the hull into points and add them to the p
array.

```{code-cell} ipython3
hull = shp.Polygon(edges.unary_union.buffer(100).exterior)
hull = shp.Polygon(edges.union_all().buffer(100).exterior)
# interpolate points along the hull - double the distance
hull_points = shp.line_interpolate_point(
hull.boundary,
Expand Down
4 changes: 2 additions & 2 deletions docs/guide/32_edge_population.myst
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,11 @@ For that, we take the union of all road cells and get the bounding box of it. Wh
looking at the union, the _skewness_ of our projection is visible.

```{code-cell} ipython3
lc_road_cells.unary_union
lc_road_cells.union_all()
```

```{code-cell} ipython3
lc_bbox = lc_road_cells.unary_union.bounds
lc_bbox = lc_road_cells.union_all().bounds
lc_ghsl = get_ghsl(lc_bbox)
```

Expand Down
16 changes: 12 additions & 4 deletions examples/06-population-density.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,9 @@
},
"outputs": [],
"source": [
"bogota_gdf = ox.geocode_to_gdf('Bogotá, Colombia')\n",
"bogota_gdf = ox.geocode_to_gdf('Bogotá, Capital District, RAP (Especial) Central, Colombia')\n",
"# Project to UTM, so we can treat it as flat Cartesian coordinates (meters)\n",
"bogota_gdf = ox.project_gdf(bogota_gdf)\n",
"bogota_gdf = ox.projection.project_gdf(bogota_gdf)\n",
"print(f\"The area of Bogotá is {round(bogota_gdf.area[0] / 10 ** 6, 2)} km²\")\n",
"bogota_gdf.explore()"
]
Expand Down Expand Up @@ -681,7 +681,9 @@
},
"outputs": [],
"source": [
"def get_population(place_gdf, pop_raster_files, resample_factor=1, place_name=None):\n",
"def get_population(\n",
" place_gdf, pop_raster_files, resample_factor=1, place_name=None, low_cutoff=0\n",
"):\n",
" \"\"\"Get the population for a place.\n",
"\n",
" Parameters\n",
Expand All @@ -695,6 +697,8 @@
" up-scaling.\n",
" place_name : str, optional\n",
" Name of the place. The default is None.\n",
" low_cutoff : float, optional\n",
" The least considered value for the population. The default is 0.\n",
"\n",
" Returns\n",
" -------\n",
Expand All @@ -703,7 +707,8 @@
" \"\"\"\n",
" fig, axe = plt.subplots(figsize=(6, 6))\n",
" pop_sum = 0\n",
" for pop_raster_file in pop_raster_files if isinstance(pop_raster_files, list) else [pop_raster_files]:\n",
" for pop_raster_file in pop_raster_files if isinstance(pop_raster_files, list) else [\n",
" pop_raster_files]:\n",
" # Window of place, buffered by 100m\n",
" with rasterio.open(pop_raster_file) as src:\n",
" window = src.window(*place_gdf.buffer(100).total_bounds)\n",
Expand All @@ -718,6 +723,9 @@
" pop_raster = pop_raster / resample_factor ** 2 # Correct for resampling\n",
" # Set masked values to 0\n",
" pop_raster = pop_raster.filled(0)\n",
" # Cut off low values\n",
" pop_raster[pop_raster < low_cutoff] = 0\n",
"\n",
" # Get population\n",
" zs_place = zonal_stats(place_gdf_raster_crs, pop_raster, affine=affine,\n",
" stats=\"sum\", nodata=0)\n",
Expand Down
20 changes: 10 additions & 10 deletions examples/07-superblock-boundary.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@
"outputs": [],
"source": [
"# From subgraph_edges we want to get a hull that encloses all edges\n",
"convex_hull = subgraph_edges.unary_union.convex_hull\n",
"convex_hull = subgraph_edges.union_all().convex_hull\n",
"# Make gdf from convex hull with the same crs as the subgraph\n",
"convex_hull_gdf = gpd.GeoDataFrame(\n",
" geometry=[convex_hull], crs=subgraph_edges.crs\n",
Expand Down Expand Up @@ -163,7 +163,7 @@
"outputs": [],
"source": [
"# Shapely MultiLineString geometry\n",
"subgraph_edges.explode().unary_union.boundary\n"
"subgraph_edges.explode().union_all().boundary\n"
]
},
{
Expand All @@ -179,7 +179,7 @@
"source": [
"# Concave hull of the edges\n",
"shp.concave_hull(\n",
" subgraph_edges.unary_union,\n",
" subgraph_edges.union_all(),\n",
" ratio=0.4,\n",
" allow_holes=True,\n",
")"
Expand All @@ -199,7 +199,7 @@
"def plot_concave_hull(ax, subgraph_edges, ratio=0.4, allow_holes=False,\n",
" color=\"crimson\"):\n",
" concave_hull = shp.concave_hull(\n",
" subgraph_edges.unary_union,\n",
" subgraph_edges.union_all(),\n",
" ratio=ratio,\n",
" allow_holes=allow_holes,\n",
" )\n",
Expand Down Expand Up @@ -281,7 +281,7 @@
"source": [
"def border_from_subgraph(subgraph, buffer=2):\n",
" edges = ox.graph_to_gdfs(subgraph, nodes=False, edges=True)\n",
" return edges.unary_union.buffer(buffer, cap_style='flat').buffer(-buffer / 2)"
" return edges.union_all().buffer(buffer, cap_style='flat').buffer(-buffer / 2)"
]
},
{
Expand Down Expand Up @@ -341,7 +341,7 @@
" Does work well with small buffer values.\"\"\"\n",
" edges = ox.graph_to_gdfs(subgraph, nodes=False, edges=True)\n",
" # First buffer with flat cap style to avoid self-intersections\n",
" polygon = shp.Polygon(edges.unary_union.buffer(2 * buffer, cap_style='flat')\n",
" polygon = shp.Polygon(edges.union_all().buffer(2 * buffer, cap_style='flat')\n",
" .exterior)\n",
" # Simplify the polygon to remove small artifacts of flat cap style at curved edges\n",
" # polygon = polygon.simplify(buffer*2, preserve_topology=True)\n",
Expand Down Expand Up @@ -378,7 +378,7 @@
" Works better with larger buffer values.\"\"\"\n",
" edges = ox.graph_to_gdfs(subgraph, nodes=False, edges=True)\n",
" # First buffer with flat cap style to avoid self-intersections\n",
" lin_ring = edges.unary_union.buffer(buffer, cap_style='flat').exterior\n",
" lin_ring = edges.union_all().buffer(buffer, cap_style='flat').exterior\n",
" # Smoothen the linear ring, taking the midpoints of the edges\n",
" lin_ring = shp.LinearRing(\n",
" [shp.Point((x1 + x2) / 2, (y1 + y2) / 2) for (x1, y1), (x2, y2) in zip(\n",
Expand Down Expand Up @@ -543,7 +543,7 @@
" primary_barriers=gpd.GeoDataFrame(\n",
" geometry=part.graph.graph[\"boundary\"].difference(\n",
" gpd.GeoSeries(edges_sparsified.buffer(5)\n",
" .unary_union)),\n",
" .union_all())),\n",
" crs=part.graph.graph[\"boundary_crs\"]\n",
" ),\n",
" limit= #mm.buffered_limit(borders, 1).convex_hull,\n",
Expand Down Expand Up @@ -818,7 +818,7 @@
" part.graph.nodes[node][\"cell\"] = node_poly_gdf.loc[node, \"geometry\"]\n",
"# For each partition create boundary as union of cells\n",
"for p, p_order in zip(part.partitions, part.get_partition_nodes()):\n",
" p[\"boundary\"] = shp.unary_union(\n",
" p[\"boundary\"] = shp.union_all()(\n",
" [part.graph.nodes[node][\"cell\"] for node in p_order[\"nodes\"]])"
]
},
Expand Down Expand Up @@ -990,7 +990,7 @@
"source": [
"# get hull from the graph boundary\n",
"# hull = part.graph.graph[\"boundary\"]\n",
"hull = shp.Polygon(edges.unary_union.buffer(100).exterior)\n",
"hull = shp.Polygon(edges.union_all().buffer(100).exterior)\n",
"hull"
]
},
Expand Down
2 changes: 1 addition & 1 deletion superblockify/_version.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""superblockify package version."""

__version__ = "1.0.0"
__version__ = "1.0.1"
4 changes: 2 additions & 2 deletions superblockify/cities.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,11 @@ place_lists:
- 1572779
pop_GHSL2023: 328740.3926395578
Liechtenstein:
query: Liechtenstein, Europe
query: Liechtenstein
country: LI
region: EU
nominatim link:
- https://nominatim.openstreetmap.org/ui/search.html?q=Liechtenstein,+Europe
- https://nominatim.openstreetmap.org/ui/search.html?q=Liechtenstein
OSM relation:
- https://www.openstreetmap.org/relation/1155955
osm_id:
Expand Down
Loading