momepy - cityseer

Last update

October 15, 2024

from future import annotations

import geopandas as gpd from osmnx import features

from cityseer.tools import io, graphs from cityseer.metrics import networks, layers

This example uses the momepy bubenec.gpkg GeoPandas GeoDataFrame as an example. Please download this file and place it in a locally accessible file. Update the filepaths in the next code block accordingly.

from pathlib import Path

import geopandas as gpd
from cityseer.tools import io, graphs
from cityseer.metrics import networks, layers
from osmnx import features

repo_path = Path.cwd()
if str(repo_path).endswith("examples"):
    repo_path = Path.cwd() / ".."
if not str(repo_path.resolve()).endswith("cityseer-examples"):
    raise ValueError(
        "Please check your notebook working directory relative to your project and data paths."
    )

bubenec_path = Path(repo_path / "temp/bubenec.gpkg")
print("data path:", bubenec_path)
print("path exists:", bubenec_path.exists())

df_streets: gpd.GeoDataFrame = gpd.read_file(bubenec_path, layer="streets")  # type: ignore
nx_momepy = io.nx_from_generic_geopandas(df_streets)
data path: /Users/gareth/dev/benchmark-urbanism/cityseer-examples/examples/../temp/bubenec.gpkg
path exists: True
100%|██████████| 35/35 [00:00<00:00, 1769.83it/s]
INFO:cityseer.tools.graphs:Merging parallel edges within buffer of 1.
100%|██████████| 35/35 [00:00<00:00, 47187.61it/s]

At this point the input GeoPandas file has been converted to a networkX MultiGraph with geom attributes for the edges. This graph can now be fed to cityseer graph module methods if wanted. For running optimised network centrality or landuse accessibilities, use the io.network_structure_from_nx method to prepare the necessary structures.

nodes_gdf, edges_gdf, network_structure = io.network_structure_from_nx(
    nx_momepy, crs=df_streets.crs.to_epsg()
)
INFO:cityseer.tools.io:Preparing node and edge arrays from networkX graph.
100%|██████████| 29/29 [00:00<00:00, 14449.37it/s]
100%|██████████| 29/29 [00:00<00:00, 2098.13it/s]

The following block downloads some OSM data which will be used for demonstrating some landuse accessibility methods.

nodes_gdf.head()
ns_node_idx x y live weight geom
x1603585.6-y6464428.8 0 1603585.6 6464428.8 True 1 POINT (1603585.6 6464428.8)
x1603413.2-y6464228.7 1 1603413.2 6464228.7 True 1 POINT (1603413.2 6464228.7)
x1603268.5-y6464060.8 2 1603268.5 6464060.8 True 1 POINT (1603268.5 6464060.8)
x1603363.6-y6464031.9 3 1603363.6 6464031.9 True 1 POINT (1603363.6 6464031.9)
x1603607.3-y6464181.9 4 1603607.3 6464181.9 True 1 POINT (1603607.3 6464181.9)
edges_gdf.head(3)
ns_edge_idx start_ns_node_idx end_ns_node_idx edge_idx nx_start_node_key nx_end_node_key length angle_sum imp_factor in_bearing out_bearing total_bearing geom
x1603585.6-y6464428.8-x1603413.2-y6464228.7 0 0 1 0 x1603585.6-y6464428.8 x1603413.2-y6464228.7 264.124535 0.000000 1 -130.747175 -130.747175 -130.747175 LINESTRING (1603585.6 6464428.8, 1603413.2 646...
x1603585.6-y6464428.8-x1603561.7-y6464494.5 1 0 8 0 x1603585.6-y6464428.8 x1603561.7-y6464494.5 70.026746 8.479425 1 111.540976 103.061551 109.990108 LINESTRING (1603561.7 6464494.5, 1603564.6 646...
x1603585.6-y6464428.8-x1603650.5-y6464368.6 2 0 6 0 x1603585.6-y6464428.8 x1603650.5-y6464368.6 88.999005 19.087196 1 -42.077527 -55.684912 -42.848413 LINESTRING (1603585.6 6464428.8, 1603603.1 646...
data_gdf = features.features_from_point(
    (50.1029248, 14.4029967), tags={"amenity": ["pub", "restaurant"]}, dist=400
)
data_gdf.to_crs(3857, inplace=True)
data_gdf = data_gdf.loc["node"]
data_gdf = data_gdf.reset_index(level=0, drop=True)
data_gdf.index = data_gdf.index.astype(str)
data_gdf = data_gdf[["amenity", "geometry"]]
print(data_gdf.head())
      amenity                         geometry
0  restaurant  POINT (1602992.986 6463522.177)
1  restaurant  POINT (1602903.753 6463784.958)
2  restaurant  POINT (1603489.527 6463552.391)
3  restaurant  POINT (1602809.665 6464167.222)
4  restaurant   POINT (1603027.863 6464060.66)
# compute metrics
nodes_gdf = networks.node_centrality_shortest(
    network_structure, nodes_gdf, [250, 500, 1000]
)
nodes_gdf, data_gdf = layers.compute_accessibilities(
    data_gdf,
    landuse_column_label="amenity",
    accessibility_keys=["restaurant"],
    nodes_gdf=nodes_gdf,
    network_structure=network_structure,
    distances=[100, 200, 400],
)
nodes_gdf.head()
INFO:cityseer.metrics.networks:Computing shortest path node centrality.
100%|██████████| 29/29 [00:01<00:00, 28.82it/s]
INFO:cityseer.metrics.layers:Computing land-use accessibility for: restaurant
100%|██████████| 29/29 [00:01<00:00, 28.90it/s]
ns_node_idx x y live weight geom cc_beta_250 cc_beta_500 cc_beta_1000 cc_cycles_250 ... cc_betweenness_beta_250 cc_betweenness_beta_500 cc_betweenness_beta_1000 cc_restaurant_100_nw cc_restaurant_100_wt cc_restaurant_200_nw cc_restaurant_200_wt cc_restaurant_400_nw cc_restaurant_400_wt cc_restaurant_nearest_max_400
x1603585.6-y6464428.8 0 1603585.6 6464428.8 True 1 POINT (1603585.6 6464428.8) 0.716430 2.049671 4.991226 0.0 ... 0.104906 1.055928 6.453668 0.0 0.000000 0.0 0.000000 1.0 0.043196 314.199646
x1603413.2-y6464228.7 1 1603413.2 6464228.7 True 1 POINT (1603413.2 6464228.7) 0.121621 1.310057 5.305830 0.0 ... 0.000000 0.089919 5.085167 1.0 0.134929 1.0 0.367327 2.0 0.660115 50.075100
x1603268.5-y6464060.8 2 1603268.5 6464060.8 True 1 POINT (1603268.5 6464060.8) 0.434258 1.921060 5.837248 0.0 ... 0.036046 0.693404 4.368770 1.0 0.309082 1.0 0.555951 5.0 0.895088 29.353716
x1603363.6-y6464031.9 3 1603363.6 6464031.9 True 1 POINT (1603363.6 6464031.9) 0.390539 1.849684 6.035850 1.0 ... 0.000000 0.676799 6.885900 0.0 0.000000 1.0 0.075555 2.0 0.354505 129.144821
x1603607.3-y6464181.9 4 1603607.3 6464181.9 True 1 POINT (1603607.3 6464181.9) 0.284575 1.452098 4.887502 1.0 ... 0.000000 0.263222 3.326343 0.0 0.000000 0.0 0.000000 1.0 0.082238 249.814056

5 rows × 37 columns

# if using dual network
nx_dual = graphs.nx_to_dual(nx_momepy)
nodes_gdf_dual, _edges_gdf_dual, network_structure_dual = io.network_structure_from_nx(
    nx_dual, df_streets.crs.to_epsg()
)
nodes_gdf_dual = networks.node_centrality_simplest(
    network_structure_dual, nodes_gdf_dual, [500]
)
nodes_gdf_dual.head()
INFO:cityseer.tools.graphs:Converting graph to dual.
INFO:cityseer.tools.graphs:Preparing dual nodes
100%|██████████| 35/35 [00:00<00:00, 8260.22it/s]
INFO:cityseer.tools.graphs:Preparing dual edges (splitting and welding geoms)
100%|██████████| 35/35 [00:00<00:00, 411.48it/s]
INFO:cityseer.tools.io:Preparing node and edge arrays from networkX graph.
100%|██████████| 35/35 [00:00<00:00, 26374.53it/s]
100%|██████████| 35/35 [00:00<00:00, 1860.40it/s]
INFO:cityseer.metrics.networks:Computing simplest path node centrality.
100%|██████████| 35/35 [00:01<00:00, 34.90it/s]
ns_node_idx x y live weight primal_edge primal_edge_node_a primal_edge_node_b primal_edge_idx dual_node cc_density_500_ang cc_harmonic_500_ang cc_hillier_500_ang cc_farness_500_ang cc_betweenness_500_ang
x1603413.2-y6464228.7_x1603585.6-y6464428.8_k0 0 1.603499e+06 6.464329e+06 True 1 LINESTRING (1603585.6 6464428.8, 1603413.2 646... x1603585.6-y6464428.8 x1603413.2-y6464228.7 0 POINT (1603499.4 6464328.75) 18.0 11.510646 10.932516 29.636362 10.0
x1603561.7-y6464494.5_x1603585.6-y6464428.8_k0 1 1.603573e+06 6.464461e+06 True 1 LINESTRING (1603561.7 6464494.5, 1603564.6 646... x1603585.6-y6464428.8 x1603561.7-y6464494.5 0 POINT (1603572.744261 6464461.367872) 13.0 8.309587 7.957019 21.239109 11.0
x1603585.6-y6464428.8_x1603650.5-y6464368.6_k0 2 1.603619e+06 6.464400e+06 True 1 LINESTRING (1603585.6 6464428.8, 1603603.1 646... x1603585.6-y6464428.8 x1603650.5-y6464368.6 0 POINT (1603619.281722 6464399.737661) 13.0 8.325413 8.047424 21.000507 16.0
x1603413.2-y6464228.7_x1603607.3-y6464181.9_k0 3 1.603510e+06 6.464204e+06 True 1 LINESTRING (1603607.3 6464181.9, 1603592.9 646... x1603413.2-y6464228.7 x1603607.3-y6464181.9 0 POINT (1603510.08598 6464204.473294) 21.0 13.297271 12.853871 34.308731 10.0
x1603363.6-y6464031.9_x1603413.2-y6464228.7_k0 4 1.603388e+06 6.464130e+06 True 1 LINESTRING (1603363.6 6464031.9, 1603376.5 646... x1603413.2-y6464228.7 x1603363.6-y6464031.9 0 POINT (1603388.006614 6464130.397742) 24.0 15.824812 15.012451 38.368153 9.0