Note

This page was generated from usage_03_existing_bike_network.ipynb.

Usage | 3. Existing bike network

This notebook explains how growbikenet can extend an existing bike network.

Parameters covered: existing_network_spacing

We start every Usage notebook with the standard way of importing growbikenet:

[1]:
import growbikenet as gbn

Adding seed points on the existing bike network

So far growbikenet was executed with the default parameter setting existing_network_spacing=None, which instructed growbikenet to ignore existing bicycle infrastructure. This works for most cities, as existing infrastructure is usually negligible and one might as well just start from scratch. However, there are some cities with an already existing substantial network which would be useful to incorporate into the growth process. By calling growbikenet with the parameter existing_network_spacing='auto' or with a positive integer, it will do exactly that.

In this case, the process of generating seed points is amended beforehand:

  • Consider all network components of the existing bike network that have a minimum length. This ensures that tiny, insignificant pieces are ignored.

  • On these components, choose a random first seed point.

  • Choose the closest seed point on the components that is at least existing_network_spacing meters away. The 'auto' option automatically chooses a recommended distance, at 50% of the seed_point_grid_spacing.

  • Proceed with the previous step until no more seed points can be placed on the components.

  • Now generate all the other seed points as usual, but do not consider seed points that are too close to already existing seed points.

Let us run growbikenet on Athens with the existing_network_spacing='auto' option and observe the results:

[2]:
edges_ranked = gbn.growbikenet("Municipality of Athens",
                               existing_network_spacing='auto',)
==============================================
RUNNING GROWBIKENET FOR CITY: Municipality of Athens
betweenness_centrality | auto | from existing bike network
----------------------------------------------╮
Downloading OSM data   : 100%|████████████████| 2/2 [08:34<00:00, 257.06s/network]
Creating seed points   : 100%|████████████████| 4/4 [00:00<00:00,  5.08step/s]
Triangulation          : 100%|████████████████| 1/1 [00:00<00:00, 695.11step/s]
Routing                : 100%|████████████████| 3/3 [00:00<00:00,  8.21step/s]
Computing edge metrics : 100%|████████████████| 2/2 [00:00<00:00, 151.15step/s]
Removing edge overlaps : 100%|████████████████| 81/81 [00:00<00:00, 364.36edge/s]
Exporting data         : 100%|████████████████| 1/1 [00:00<00:00, 16.89step/s]
----------------------------------------------╯
Data exported to ./results/
----------------------------------------------
FINISHED IN 0:08:36
==============================================

The existing bike network is saved as multilinestring into the first row of the resulting geodataframe with several entries being None:

[3]:
edges_ranked.head()
[3]:
betweenness_centrality geometry source target rank length length_cumulative
0 None MULTILINESTRING ((2641105 4575914, 2641098 457... None None None 11439 11439
1 0.146237 LINESTRING (2641080 4580897, 2641058 4580773, ... 358482734.0 358483920.0 0 1877 13316
2 0.144086 LINESTRING (2642456 4578854, 2642506 4578807, ... 370604212.0 363931220.0 1 1911 15228
3 0.133333 LINESTRING (2640253 4576932, 2640235 4576962, ... 250663738.0 1172304125.0 2 863 16091
4 0.111828 LINESTRING (2640761 4579200, 2640757 4579141, ... 358483920.0 250663738.0 3 1823 17914

To visualize the outcome, we plot first the existing bike network (first row) in blue, then the grown network (all other rows) in green. To add layer control in the top right of the map, we import folium:

[4]:
import folium
viz = edges_ranked.iloc[:1].explore(tiles="CartoDB Positron",
                     style_kwds={"weight": 2, "color": "#9999cc"},
                        name="Existing bike network")
viz = edges_ranked.iloc[1:].explore(m=viz,
                     style_kwds={"weight": 3, "color": "#096a51"},
                        name="Grown bike network")
folium.LayerControl().add_to(viz)
viz
[4]:
Make this Notebook Trusted to load map: File -> Trust Notebook

Note how the short existing pieces in the northeast are ignored, but the other big enough components are incorporated into the growth process.

Comparing with growth from scratch

Let us add the outcome from growth from scratch (without the existing network) in orange to see the difference:

[5]:
edges_ranked_from_scratch = gbn.growbikenet("Municipality of Athens")
==============================================
RUNNING GROWBIKENET FOR CITY: Municipality of Athens
betweenness_centrality | auto | from scratch
----------------------------------------------╮
Downloading OSM data   : 100%|████████████████| 1/1 [00:06<00:00,  6.40s/network]
Creating seed points   : 100%|████████████████| 3/3 [00:00<00:00,  4.39step/s]
Triangulation          : 100%|████████████████| 1/1 [00:00<00:00, 1084.36step/s]
Routing                : 100%|████████████████| 3/3 [00:00<00:00,  9.58step/s]
Computing edge metrics : 100%|████████████████| 2/2 [00:00<00:00, 317.49step/s]
Removing edge overlaps : 100%|████████████████| 59/59 [00:00<00:00, 516.24edge/s]
Exporting data         : 100%|████████████████| 1/1 [00:00<00:00, 31.53step/s]
----------------------------------------------╯
Data exported to ./results/
----------------------------------------------
FINISHED IN 0:00:08
==============================================

[6]:
viz = edges_ranked.iloc[:1].explore(tiles="CartoDB Positron",
                     style_kwds={"weight": 2, "color": "#9999cc"},
                        name="Existing bike network")
viz = edges_ranked_from_scratch.explore(m=viz,
                     style_kwds={"weight": 3, "color": "#f19730"},
                        name="Grown bike network (from scratch)")
viz = edges_ranked.iloc[1:].explore(m=viz,
                     style_kwds={"weight": 3, "color": "#096a51"},
                        name="Grown bike network (with existing network)")
folium.LayerControl().add_to(viz)
viz
[6]:
Make this Notebook Trusted to load map: File -> Trust Notebook

In general, the network which accounts for existing infrastructure will be longer than the one grown from scratch, in this case

[7]:
int((edges_ranked.iloc[-1].length_cumulative-
    edges_ranked.iloc[0].length_cumulative)/1000)
[7]:
132

kilometers compared to

[8]:
int((edges_ranked_from_scratch.iloc[-1].length_cumulative)/1000)
[8]:
120

kilometers, as seed points are generated more densely.