Usage | 2. Network growth

This notebook explains how GrowBikeNet orders the edges and why this is important.

Parameters covered: ordering

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

import growbikenet as gbn

Ordering of edges

GrowBikeNet not only creates a potential bicycle network, but also an ordering of the edges. The ordering is important, as it provides an ordering, informing a city which edges to implement first to arrive at a functional network early. The ordering metric is controlled by the parameter ordering which is by default set to 'betweenness'. Other options are 'closeness' and 'random'.

Here we work with Paris, France. We are going to generate all different orderings (saved in the dictionary edges_ordered_all) and visualize them interactively in the end.

edges_ordered_all = {}

Betweenness centrality

Betweenness centrality is a network centrality measure approximating flow. By ordering edges like this, the first built edge is the one with highest expected flow of cyclists. As was shown in the research on which GrowBikeNet is based, this is a much better ordering than random, and in most cases also better than ordering by closeness centrality.

edges_ordered = gbn.growbikenet("Paris",
    ordering="betweenness",)
edges_ordered_all["betweenness"] = edges_ordered

The content of the output edges_ordered shows several columns:

edges_ordered.head()
betweenness geometry source target ordering length length_cumulative
0 0.116956 LINESTRING (2.31973 48.84587, 2.31935 48.84565... 25255896 24972212 0 1319 1319
1 0.108434 LINESTRING (2.3043 48.84363, 2.30456 48.84325,... 25255896 260015405 1 1276 2595
2 0.104614 LINESTRING (2.3352 48.87521, 2.3352 48.87516, ... 94164238 94173781 2 1361 3957
3 0.090215 LINESTRING (2.35176 48.84957, 2.35187 48.84956... 25034466 26401904 3 1198 5155
4 0.088451 LINESTRING (2.33485 48.84911, 2.33484 48.84919... 25254925 24972212 4 1197 6353

They are:

  • betweenness: The metric to order edges by.

  • geometry: The geometries of the edges connecting source and target seed points, in the coordinate references system (crs) given by the setting settings.crs_result. These geometries are typically a mix between linestrings and multilinestrings.

  • source, target: The OSM IDs of source and target seed points. These are nodes that can be looked up on OSM, for example for OSM ID 298719867: https://www.openstreetmap.org/node/298719867

  • ordering: The ordering of the edges by betweenness centrality. These are increasing integers, but not necessarily consecutive, due to potentially empty pieces in-between that are removed due to edge overlaps, see end of this notebook.

  • length: Length of the current edge, rounded to whole meters.

  • length_cumulative: Cumulative length of current and all previous edges, rounded to whole meters.

Closeness centrality

Ranking by closeness centrality means growing from the center.

edges_ordered = gbn.growbikenet("Paris",
    ordering="closeness",)
edges_ordered_all["closeness"] = edges_ordered

Random

GrowBikeNet can also showcase suboptimal random growth.

edges_ordered = gbn.growbikenet("Paris",
    ordering="random",)
edges_ordered_all["random"] = edges_ordered

Visualization

Below the three different growths are visualized together interactively. Use the slider and buttons to see the different growth patterns:

Note

This interactive widget does not work in the online docs, but it works when you run the notebook yourself.

Hide code cell source

import ipywidgets as widgets
import matplotlib.pyplot as plt

step = widgets.IntSlider(
    value=4, min=0, max=max(edges_ordered["ordering"]), step=1, description="Growth step:", layout=widgets.Layout(width='500px')
)
ordering = widgets.ToggleButtons(
    options=['betweenness', 'closeness', 'random'],
    description='Ranking:',
)
def update_map(step=step, ordering=ordering):
    fig, ax = plt.subplots(figsize=(8, 6))
    edges_ordered_all[ordering][edges_ordered_all[ordering]["ordering"] <= step].plot(
        linewidth=3,
        color="#096a51",
        ax=ax,
    )
    ax.set_title(f"Paris bike net growth, growth step {step}", fontsize=12)
    ax.set_ylim(edges_ordered.total_bounds[1], edges_ordered.total_bounds[3])
    ax.set_xlim(edges_ordered.total_bounds[0], edges_ordered.total_bounds[2])
    plt.axis('off')
    plt.show()

widgets.interactive(update_map, step=step, ordering=ordering)