Saving via GeoPandas

Last update

October 15, 2024

Generate a network

Tip

For more details on downloading for a boundary, see this example.

Assume we have the following network.

import osmnx as ox
from cityseer.tools import io, plot

bounds_gdf = ox.geocode_to_gdf(
    "R1536593",  # OSM relation ID
    by_osmid=True,
)
bounds_gdf = bounds_gdf.to_crs(3035)  # projected CRS
bounds_geom = bounds_gdf.union_all().simplify(500)
G_nx = io.osm_graph_from_poly(
    bounds_geom,
    poly_crs_code=3035,  # set to your CRS
    to_crs_code=3035,  # output CRS
    simplify=False,  # set to True for automatic simplification
)
plot.plot_nx(G_nx, plot_geoms=True)
INFO:cityseer.tools.io:Converting networkX graph from EPSG code 4326 to EPSG code 3035.
INFO:cityseer.tools.io:Processing node x, y coordinates.
  0%|          | 0/18052 [00:00<?, ?it/s]100%|██████████| 18052/18052 [00:00<00:00, 686221.08it/s]
INFO:cityseer.tools.io:Processing edge geom coordinates, if present.
  0%|          | 0/19745 [00:00<?, ?it/s]100%|██████████| 19745/19745 [00:00<00:00, 1416757.03it/s]
INFO:cityseer.tools.graphs:Generating interpolated edge geometries.
  0%|          | 0/19745 [00:00<?, ?it/s] 56%|█████▌    | 11003/19745 [00:00<00:00, 110021.97it/s]100%|██████████| 19745/19745 [00:00<00:00, 108997.23it/s]
INFO:cityseer.tools.graphs:Removing filler nodes.
  0%|          | 0/18052 [00:00<?, ?it/s]  6%|▌         | 994/18052 [00:00<00:01, 9911.44it/s] 12%|█▏        | 2159/18052 [00:00<00:01, 10902.39it/s] 18%|█▊        | 3321/18052 [00:00<00:01, 11194.64it/s] 25%|██▌       | 4563/18052 [00:00<00:01, 11663.64it/s] 33%|███▎      | 5902/18052 [00:00<00:00, 12270.56it/s] 40%|███▉      | 7189/18052 [00:00<00:00, 12463.58it/s] 47%|████▋     | 8436/18052 [00:00<00:00, 12459.81it/s] 54%|█████▍    | 9736/18052 [00:00<00:00, 12585.45it/s] 62%|██████▏   | 11102/18052 [00:00<00:00, 12911.15it/s] 69%|██████▊   | 12394/18052 [00:01<00:00, 12909.79it/s] 76%|███████▌  | 13686/18052 [00:01<00:00, 12559.57it/s] 83%|████████▎ | 14944/18052 [00:01<00:00, 12417.87it/s] 90%|█████████ | 16329/18052 [00:01<00:00, 12840.57it/s] 98%|█████████▊| 17616/18052 [00:01<00:00, 12770.29it/s]100%|██████████| 18052/18052 [00:01<00:00, 12455.77it/s]
INFO:cityseer.tools.graphs:Ironing edges.
  0%|          | 0/6961 [00:00<?, ?it/s]  8%|▊         | 587/6961 [00:00<00:01, 5862.50it/s] 17%|█▋        | 1189/6961 [00:00<00:00, 5947.04it/s] 27%|██▋       | 1845/6961 [00:00<00:00, 6224.10it/s] 36%|███▌      | 2489/6961 [00:00<00:00, 6305.25it/s] 45%|████▌     | 3137/6961 [00:00<00:00, 6363.99it/s] 54%|█████▍    | 3774/6961 [00:00<00:00, 6348.27it/s] 63%|██████▎   | 4420/6961 [00:00<00:00, 6383.97it/s] 73%|███████▎  | 5059/6961 [00:00<00:00, 6306.64it/s] 82%|████████▏ | 5702/6961 [00:00<00:00, 6343.92it/s] 91%|█████████ | 6337/6961 [00:01<00:00, 6279.97it/s]100%|██████████| 6961/6961 [00:01<00:00, 6291.37it/s]
INFO:cityseer.tools.graphs:Merging parallel edges within buffer of 1.
  0%|          | 0/6961 [00:00<?, ?it/s]100%|██████████| 6961/6961 [00:00<00:00, 201654.52it/s]
INFO:cityseer.tools.plot:Preparing graph nodes
INFO:cityseer.tools.plot:Preparing graph edges
  0%|          | 0/6954 [00:00<?, ?it/s] 35%|███▌      | 2453/6954 [00:00<00:00, 24519.09it/s] 71%|███████   | 4905/6954 [00:00<00:00, 14898.79it/s] 95%|█████████▍| 6603/6954 [00:00<00:00, 12087.91it/s]100%|██████████| 6954/6954 [00:00<00:00, 12741.10it/s]

Convert to GeoPandas

You can now convert the network to a geopandas GeoDataFrame.

# convert to a LineString GeoDataFrame
edges_gdf = io.geopandas_from_nx(G_nx, crs=3035)
edges_gdf.head()
INFO:cityseer.tools.io:Preparing node and edge arrays from networkX graph.
geom names routes highways start_nd_key end_nd_key edge_idx
0 LINESTRING (3686135.767 2665023.326, 3686194.5... [rue francoise dolto, rue de gireugne] [] [tertiary] 448239596 10746741880 0
1 LINESTRING (3686215.164 2665464.119, 3686216.1... [rue de gireugne] [] [tertiary] 10746741880 1969279930 0
2 LINESTRING (3686586.641 2665354.037, 3686435.5... [] [] [track] 10746741880 10746741876 0
3 LINESTRING (3683478.127 2667452.761, 3683515.2... [rue de chatellerault] [d 925] [secondary] 1563458310 1527199968 0
4 LINESTRING (3683926.884 2667717.073, 3683959.4... [rue de chatellerault] [d 925] [secondary] 1527199968 9328420068 0

Save

It is then possible to save the GeoDataFrame. Create a temp folder or update your path accordingly:

from pathlib import Path

# create the directory if necessary
Path.mkdir(Path("temp"), exist_ok=True)
edges_gdf.to_file("temp/output_file.gpkg")
INFO:pyogrio._io:Created 6,954 records

The GPKG file can now be explored or modified in GIS software such as QGIS.

Reload

To reload, you can read the LineString file with geopandas.

import geopandas as gpd

in_edges_gdf = gpd.read_file("temp/output_file.gpkg")
in_edges_gdf.head()
names routes highways start_nd_key end_nd_key edge_idx geometry
0 ['rue francoise dolto', 'rue de gireugne'] [] ['tertiary'] 448239596 10746741880 0 LINESTRING (3686135.767 2665023.326, 3686194.5...
1 ['rue de gireugne'] [] ['tertiary'] 10746741880 1969279930 0 LINESTRING (3686215.164 2665464.119, 3686216.1...
2 [] [] ['track'] 10746741880 10746741876 0 LINESTRING (3686586.641 2665354.037, 3686435.5...
3 ['rue de chatellerault'] ['d 925'] ['secondary'] 1563458310 1527199968 0 LINESTRING (3683478.127 2667452.761, 3683515.2...
4 ['rue de chatellerault'] ['d 925'] ['secondary'] 1527199968 9328420068 0 LINESTRING (3683926.884 2667717.073, 3683959.4...

Convert back to nx

Then use cityseer to convert the LineString GeoDataFrame back into a networkx graph.

in_G_nx = io.nx_from_generic_geopandas(in_edges_gdf)
plot.plot_nx(in_G_nx, plot_geoms=True)
  0%|          | 0/6954 [00:00<?, ?it/s] 10%|█         | 718/6954 [00:00<00:00, 7177.83it/s] 21%|██        | 1451/6954 [00:00<00:00, 7264.64it/s] 31%|███▏      | 2178/6954 [00:00<00:00, 7180.70it/s] 42%|████▏     | 2921/6954 [00:00<00:00, 7275.64it/s] 53%|█████▎    | 3667/6954 [00:00<00:00, 7338.23it/s] 63%|██████▎   | 4401/6954 [00:00<00:00, 5005.25it/s] 74%|███████▍  | 5131/6954 [00:00<00:00, 5565.32it/s] 85%|████████▍ | 5881/6954 [00:00<00:00, 6070.57it/s] 95%|█████████▌| 6615/6954 [00:01<00:00, 6414.58it/s]100%|██████████| 6954/6954 [00:01<00:00, 6394.35it/s]
INFO:cityseer.tools.graphs:Merging parallel edges within buffer of 1.
  0%|          | 0/6952 [00:00<?, ?it/s]100%|██████████| 6952/6952 [00:00<00:00, 173975.41it/s]
INFO:cityseer.tools.plot:Preparing graph nodes
INFO:cityseer.tools.plot:Preparing graph edges
  0%|          | 0/6952 [00:00<?, ?it/s] 32%|███▏      | 2250/6952 [00:00<00:00, 22481.15it/s] 65%|██████▍   | 4499/6952 [00:00<00:00, 14818.86it/s] 88%|████████▊ | 6129/6952 [00:00<00:00, 11416.97it/s]100%|██████████| 6952/6952 [00:00<00:00, 11516.06it/s]