From cab47965b3194aa64953d52aba84f194a27d5ddb Mon Sep 17 00:00:00 2001 From: Michael Szell Date: Wed, 29 Apr 2026 15:25:54 +0200 Subject: [PATCH 1/5] Add geojson default data export --- growbikenet/growbikenet.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/growbikenet/growbikenet.py b/growbikenet/growbikenet.py index 1b3b772..5cc10fc 100644 --- a/growbikenet/growbikenet.py +++ b/growbikenet/growbikenet.py @@ -33,6 +33,7 @@ def growbikenet( existing_network_spacing=None, export_data=True, export_data_slug=None, + export_file_format="geojson", export_plots=False, export_video=False, ): @@ -59,8 +60,10 @@ def growbikenet( Spacing between seed points, in meters, only on the existing bicycle network. If not set to a positive integer, the existing network is ignored. export_data : bool, optional, default True If set to True, data will be saved to a file. The filename is [slug]-[ranking]-[seed_point_type].gpkg, where slug is a string id made out of city_name - export_data_slug : string, optional, default None - If not set to None, it will be slugified and used as the slug in the filename of the data export + export_data_slug : stri, optional, default None + If not set to None, the city_name will be slugified and used as the slug in the filename of the data export + export_file_format : str, optional, default "geojson" + File format for the data export, relevant if export_data set to True. Default "geojson", also possible "gpkg". export_plots : bool, optional, default False If set to True, plots will be saved to a file export_video : bool, optional, default False @@ -116,6 +119,8 @@ def growbikenet( raise ValueError( "export_data_slug must contain at least one non-special character" ) + if export_file_format != "geojson" and export_file_format != "gpkg": + raise ValueError("export_file_format must be 'geojson' or 'gpkg'") if type(export_plots) is not bool: raise TypeError("export_plots must be a boolean") if type(export_video) is not bool: @@ -225,14 +230,17 @@ def growbikenet( else: city_string = export_data_slug export_data_filename = ( - slugify(city_string) + "-" + ranking + "-" + seed_point_type + ".gpkg" + slugify(city_string) + "-" + ranking + "-" + seed_point_type + "." + export_file_format ) # Save to file if export_data: ### save data print("Saving data..") - a_edges.to_file("./results/"+export_data_filename, driver="GPKG") + if export_file_format == "geojson": + a_edges.to_file("./results/"+export_data_filename, driver="GeoJSON") + elif export_file_format == "gpkg": + a_edges.to_file("./results/"+export_data_filename, driver="GPKG") if export_plots or export_video: ### Visualize From cfdcafec7fd68ec96f44677e8c7da627dc0c3a26 Mon Sep 17 00:00:00 2001 From: Michael Szell Date: Wed, 29 Apr 2026 16:16:45 +0200 Subject: [PATCH 2/5] Export seed points --- examples/mwe.py | 3 ++- growbikenet/growbikenet.py | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/mwe.py b/examples/mwe.py index 4b0e073..42058f7 100644 --- a/examples/mwe.py +++ b/examples/mwe.py @@ -3,10 +3,11 @@ import growbikenet as gbn a_edges = gbn.growbikenet( - city_name="Turin", + city_name="Bath", proj_crs="3857", ranking="betweenness_centrality", existing_network_spacing=600, + export_file_format="gpkg", export_data=True, export_plots=False, export_video=False, diff --git a/growbikenet/growbikenet.py b/growbikenet/growbikenet.py index 5cc10fc..630a7ba 100644 --- a/growbikenet/growbikenet.py +++ b/growbikenet/growbikenet.py @@ -237,10 +237,13 @@ def growbikenet( if export_data: ### save data print("Saving data..") + seed_points_snapped.drop(["osmid"], axis=1, inplace=True) if export_file_format == "geojson": a_edges.to_file("./results/"+export_data_filename, driver="GeoJSON") + seed_points_snapped.to_file("./results/"+slugify(city_string)+"-"+seed_point_type+".geojson", driver="GeoJSON") elif export_file_format == "gpkg": - a_edges.to_file("./results/"+export_data_filename, driver="GPKG") + a_edges.to_file("./results/"+export_data_filename, driver="GPKG", layer="Bike network") + seed_points_snapped.to_file("./results/"+export_data_filename, driver="GPKG", layer="Seed points", append=True) if export_plots or export_video: ### Visualize From 871836e95c0c859a7a8cd7561d4da7103b5195a5 Mon Sep 17 00:00:00 2001 From: Michael Szell Date: Wed, 29 Apr 2026 16:17:14 +0200 Subject: [PATCH 3/5] Fix seed point creation --- growbikenet/functions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/growbikenet/functions.py b/growbikenet/functions.py index bf1c841..e600d14 100644 --- a/growbikenet/functions.py +++ b/growbikenet/functions.py @@ -263,7 +263,7 @@ def update_seed_points_with_existing_bike_network(seed_points_snapped, nodes_exn # Bring back to original form (geometry and osmid columns, osmid index) # This is a bit of a mess but it works. Simplify it in the future. seed_points_snapped.loc[seed_points_snapped['osmid_1'].isnull(), 'osmid_1'] = seed_points_snapped['osmid_2'] # _1 comes from one side, _2 from the other. One has NaNs, the other too. https://stackoverflow.com/a/60132614 - seed_points_snapped.drop(["y","x","street_count", "highway", "railway", "osmid_2"], axis=1, inplace=True) + seed_points_snapped = seed_points_snapped[['osmid_1','geometry']] seed_points_snapped.rename(columns={"osmid_1": "osmid"}, inplace=True) seed_points_snapped.set_index("osmid", drop=False, inplace=True) return seed_points_snapped From 7a28f6c41d51b304d1f5589ff30bb8b94d827da5 Mon Sep 17 00:00:00 2001 From: Michael Szell Date: Wed, 29 Apr 2026 18:07:29 +0200 Subject: [PATCH 4/5] Export city boundary, round coordinates --- growbikenet/growbikenet.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/growbikenet/growbikenet.py b/growbikenet/growbikenet.py index 630a7ba..dd7f072 100644 --- a/growbikenet/growbikenet.py +++ b/growbikenet/growbikenet.py @@ -238,12 +238,21 @@ def growbikenet( ### save data print("Saving data..") seed_points_snapped.drop(["osmid"], axis=1, inplace=True) + city_boundary = ox.geocoder.geocode_to_gdf(city_name) + city_boundary.to_crs(epsg=proj_crs, inplace=True) + # We have meter precision, so rounding to integers is fine. Better would be to + # change dtypes to int, but this does not seem possible without manual looping. + city_boundary.geometry = city_boundary.geometry.set_precision(grid_size=1) + seed_points_snapped.geometry = seed_points_snapped.geometry.set_precision(grid_size=1) + a_edges.geometry = a_edges.geometry.set_precision(grid_size=1) if export_file_format == "geojson": a_edges.to_file("./results/"+export_data_filename, driver="GeoJSON") seed_points_snapped.to_file("./results/"+slugify(city_string)+"-"+seed_point_type+".geojson", driver="GeoJSON") + city_boundary.to_file("./results/"+slugify(city_string)+"-city_boundary.geojson", driver="GeoJSON") elif export_file_format == "gpkg": a_edges.to_file("./results/"+export_data_filename, driver="GPKG", layer="Bike network") seed_points_snapped.to_file("./results/"+export_data_filename, driver="GPKG", layer="Seed points", append=True) + city_boundary.to_file("./results/"+export_data_filename, driver="GPKG", layer="City boundary", append=True) if export_plots or export_video: ### Visualize From 51fd0c2a711f8ec104ee104f398f4a45c00c2b52 Mon Sep 17 00:00:00 2001 From: Michael Szell Date: Wed, 29 Apr 2026 18:13:28 +0200 Subject: [PATCH 5/5] Update export_file_format docstring --- growbikenet/growbikenet.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/growbikenet/growbikenet.py b/growbikenet/growbikenet.py index dd7f072..d2305d5 100644 --- a/growbikenet/growbikenet.py +++ b/growbikenet/growbikenet.py @@ -63,7 +63,7 @@ def growbikenet( export_data_slug : stri, optional, default None If not set to None, the city_name will be slugified and used as the slug in the filename of the data export export_file_format : str, optional, default "geojson" - File format for the data export, relevant if export_data set to True. Default "geojson", also possible "gpkg". + File format for the data export, relevant if export_data set to True. Default "geojson", also possible "gpkg". If exporting as geojson, generates extra files for seed points and city boundary. If exporting as gkpg, these are added all in one file as extra layers. export_plots : bool, optional, default False If set to True, plots will be saved to a file export_video : bool, optional, default False