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.
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)
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]
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]
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