Developer reference

This is the complete developer reference for the GrowBikeNet package. If you are looking for an introduction to GrowBikeNet, read the Getting started guide.

growbikenet.growbikenet

growbikenet.growbikenet.growbikenet(city_query, ordering='betweenness', seed_point_type='auto', seed_point_grid_spacing='auto', seed_point_linking='auto', existing_network_spacing=None, export_data=True, city_id=None, export_plots=False, import_files={}, seed_point_tags=None)[source]

Creates a list of urban street network edges ordered by an ordering method.

The edges form a subnetwork of a city’s street network, interpreted as a growing bicycle network following [1]. By default, growth is from scratch, but the existing bicycle network can also be used as a starting point [2].

Parameters:
city_querystr

Search string for the city that the analysis should be performed on. This is the query used to fetch the data from nominatim. Overruled for data fetching if city_boundary or growable_network is set.

ordering{‘betweenness’, ‘closeness’, ‘random’}, default ‘betweenness’

Method used to order the edges.

seed_point_type{‘auto’, ‘grid_square’, ‘grid_triangle’, ‘rail’, ‘school’, ‘park’, ‘file’, ‘tags’}, default ‘auto’
  • ‘auto’ selects ‘grid_square’ or ‘grid_triangle’ automatically depending on the street network’s orientation entropy, see [3].

  • ‘grid_square’ creates a square grid.

  • ‘grid_triangle’ creates a triangle grid. In this case, seed_point_linking must not be set to ‘quadrangulate’.

  • ‘rail’, uses railway stations and halts.

  • ‘school’ uses kindergartens, schools, colleges, and universities.

  • ‘park’ uses parks, gardens, nature reserves, and public bathing places.

  • ‘file’ imports seed_point. In this case, the name of the seed points in the exported file name is controlled via settings.seed_point_type_name.

  • ‘tags’ uses geocodable seed_point_tags, see [4].

seed_point_grid_spacing‘auto’ or int, default ‘auto’

If seed_point_type is set to ‘grid_square’ or ‘grid_triangle’, this is the spacing between seed points, in meters. Auto-values for seed_point_type.

  • ‘grid_square’ with seed_point_linking ‘triangulate_delaunay’: 1707

  • ‘grid_square’ with seed_point_linking ‘quadrangulate’: 1000

  • ‘grid_triangle’: 1154

  • otherwise: 1707

These values ensure that any point in the city is always within 500m of the network (under perfect conditions). For the explanation of case 1707 see [1].

seed_point_linking{‘auto’, ‘triangulate_delaunay’, ‘quadrangulate’}, default ‘auto’

The algorithm for linking up the seed points into an unrouted, abstract network.

  • ‘auto’ selects ‘triangulate_delaunay’ or ‘quadrangulate’ automatically depending on the street network’s orientation entropy, see [3].

  • ‘triangulate_delaunay’ uses Delaunay triangulation.

  • ‘quadrangulate’ uses quadrangulation, which only works for seed_point_type ‘grid_square’ and existing_network_spacing None. Useful for grid-like street networks like Manhattan or Barcelona.

existing_network_spacingNone or ‘auto’ or int, default None

Spacing between seed points, in meters, only on the existing bicycle network. If set to None, the existing network is ignored. existing_network_spacing is recommended to be smaller than seed_point_grid_spacing, ideally around 50%, to ensure that the existing bicycle network is built first. Option ‘auto’ sets existing_network_spacing to 50% of the seed_point_grid_spacing. Independent of existing_network_spacing, all bicycle components shorter than constants.EXISTING_NETWORK_MINIMUM_COMPONENT_LENGTH are ignored.

export_databool, default True

If set to True, data is saved to a file. The filename is [slug]-growbikenet-[ordering]-from_scratch|from_bikenw-[seed_point_type].[settings.export_file_format], depending on the respective parameters, and where [slug] is a string id made out of city_query (or city_id if set).

city_idNone or str, default None

If set, the slugified city_id is used in the filename of the data export. For example, a city_id “Athens” will slugify into “athens” in filenames. If set to None, the slugified city_query is used in the filename of the data export. It is useful to set a city_id for cities where the city_query is not the city name, for example to set for a city_query “Municipality of Athens” the city_id to “Athens”.

export_plotsbool, default False

If set to True, plots are saved to files, overwriting existing ones.

import_files: dict, default {}

The following key:value entries can be set:

  • ‘city_boundary’None or str, default None

    If not set to None, the study area is selected from the (Multi)Polygon provided in the city_boundary shape or gpkg file, ideally in unprojected latitude-longitude degrees (EPSG:4326), but EPSG:3857 also works. For example, ‘./tests/test_data/copenhagen_city_boundary.shp’.

  • ‘growable_network’None or str, default None

    If not set to None, the growable street network is loaded from this file. Must be a gpkg file in unprojected CRS EPSG:4326 with layers nodes and edges, with the structure that an undirected OSMnx street network g has after saved via ox.io.save_graph_geopackage(). For example:

    >>> g = ox.graph_from_place("Barcelona", network_type='drive')
    >>> g = nx.MultiGraph(ox.convert.to_digraph(g))
    >>> ox.io.save_graph_geopackage(g, 'Barcelona_streets.gpkg')
    

    To download a growable network that also includes existing bicycle infrastructure, as growbikenet does by default, replace the first line in the above example by this line:

    >>> g = ox.graph_from_place("Barcelona", custom_filter=gbn.constants.GROWABLE_NETWORK_CUSTOM_FILTER)
    
  • ‘bike_network’None or str, default None

    If not set to None, the existing bike network is loaded from this file. Must be a gpkg file in unprojected CRS EPSG:4326 with layers nodes and edges, with the structure that an undirected OSMnx bike network has after saved via ox.io.save_graph_geopackage().

  • ‘seed_points’None or str, default None

    If not set to None, the seed points is loaded from this file. Must be a gpkg file in unprojected CRS EPSG:4326 containing only point objects. For example, ‘./tests/test_data/oelde_seed_points.shp’. seed_point_type must be set to ‘file’. The name of the seed points in the exported file name is controlled via settings.seed_point_type_name.

  • ‘point_data’None or str, default None

    If not set to None, an additional data set of points will be loaded from this file, representing point events like traffic crashes or citizen feedback to improve bike infrastructure. Must be a gpkg file in unprojected CRS EPSG:4326 containing only point objects, optionally with an int num column that encodes the number of point events. The data set is used to re-prioritize the ordering of the network links, controlled with settings.import_data_impact and settings.import_data_trip_point_balance, following [2].

  • ‘trip_data’None or str, default None

    If not set to None, an additional data set of trips will be loaded from this file, representing trip events for prioritizing bike infrastructure growth. Must be a csv file in unprojected CRS EPSG:4326 containing the following fields: o_lat, o_lon, d_lat, d_lon. Optionally there can be an int num field that encodes the number of trips between each origin and destination. The data set is used to re-prioritize the ordering of the network links, controlled with settings.import_data_impact and settings.import_data_trip_point_balance, following [2].

seed_point_tagsNone or dict[str, bool or str or list[str]], default None

If not None, must be a geocodable seed_point_tags, see [4], and seed_point_type must be set to ‘tags’. For example, seed_point_tags={'railway': ['station', 'halt']} retrieves exactly the same as seed_point_type='rail'.

Returns:
edges_orderedgeopandas.geodataframe.GeoDataFrame

Geodataframe of all edges in street network ordered by the ordering method.

Notes

The original paper [1] uses minimum weight triangulation, but Delaunay triangulation is implemented much faster and in practice gives identical results. Triangulation and metrics (betweenness, closeness) are calculated for the unrouted, abstract network for which egde lengths are taken from the routed network.

References

[1] (1,2,3)
  1. Szell, S. Mimar, T. Perlman, G. Ghoshal, R. Sinatra, Growing urban bicycle networks, Scientific Reports 12, 6765 (2022)

[2] (1,2,3)
  1. Folco, L. Gauvin, M. Tizzoni, M. Szell, Data-driven micromobility network planning for demand and safety, Environment and planning B: Urban analytics and city science 50(8), 2087-2102 (2023)

[3] (1,2)
  1. Boeing, Urban spatial order: Street network orientation, configuration, and entropy, Applied Network Science 4, 67 (2019)

Examples

Minimum working example: Grow a bicycle network from scratch in Lyon.

>>> edges_ordered = gbn.growbikenet("Lyon")

Grow a bicycle network from scratch in Copenhagen, providing a study area polygon to include also Frederiksberg and Amager.

>>> edges_ordered = gbn.growbikenet("Copenhagen", import_files={'city_boundary':'./tests/test_data/copenhagen_city_boundary.shp'}) 

Expand the existing bicycle network of Lyon, connecting all educational institutions.

>>> edges_ordered = gbn.growbikenet("Lyon", seed_point_type='school', existing_network_spacing='auto') 

Grow a bicycle network in Oelde from scratch, working offline by importing the street network and custom seed points from file.

>>> edges_ordered = gbn.growbikenet("Oelde", seed_point_type='file', import_files={'growable_network':'./tests/test_data/oelde_growable_network.gpkg', 'seed_points':'./tests/test_data/oelde_seed_points.gpkg'})

growbikenet.constants

Global constants for growbikenet that can be tweaked during development, but should not be changed later by the user. Especially technical or internal constants start with an underscore.

PBI_CUSTOM_FILTERlist[str]

Custom filter for protected bicycle infrastructure (pbi).

EXISTING_NETWORK_MINIMUM_COMPONENT_LENGTHint, default 100

Minimum length a bike network component needs to have for seed points to snap, in meters.

GRID_SPACING_TRIANGULATEint, default 1707

Grid spacing in meters for grid triangulation that ensures that any point in the city is always within buffer distance b=500m of the network (if seed points snap perfectly).

GRID_SPACING_QUADRANGULATEint, default 1000

Grid spacing in meters for quadrangulation that ensures that any point in the city is always within buffer distance b=500m of the network (if seed points snap perfectly).

GRID_SPACING_TRIANGLEint, default 1154

Grid spacing in meters for triangle grid that ensures that any point in the city is always within buffer distance b=500m of the network (if seed points snap perfectly).

GROWABLE_NETWORK_CUSTOM_FILTERlist[str] or None

Custom filter for all infrastructure elements that are considered as growable by growbikenet. By default, growbikenet uses a custom filter to retrieve the combined drive and pbi (protected bicycle infrastructure) network. To only consider the drive network, set GROWABLE_NETWORK_CUSTOM_FILTER to None and GROWABLE_NETWORK_TYPE to ‘drive’. However, doing so can lead to issues: https://github.com/BikeNetKit/GrowBikeNet/issues/255.

GROWABLE_NETWORK_TYPE{‘drive’, ‘all’, ‘all_public’, ‘bike’, ‘drive_service’, ‘walk’}, default ‘drive’

What type of street network to retrieve for the growable network if GROWABLE_NETWORK_CUSTOM_FILTER is None.

REORDERbool, default True

Decision whether ordering should be reordered after edge removal, as edge removal can leave gaps.

_CRS_CALCULATIONSstr, default ‘auto’

EPSG code of the coordinate reference system that is used to project OSM data for calculations. This has to be a distance-preserving projected CRS, so ‘3857’ (WGS 84 / Pseudo-Mercator) would be wrong! Option ‘auto’ selects the best UTM via estimate_utm_crs(). Note that the CRS for plotting is unrelated - it is instead set in settings.viz[‘crs’].

_PRESET_TAGSdict

Pre-defined tags to select tags as seed points

_PHI_LIMITSlist[float], default [0.02, 0.08]

Two orientation order limits between street networks with: 1) negligible grid elements, 2) some grid elements, 3) grid. We aimed to use the tercile limits from the paper [1] (Fig 2), but the values here are lower for unknown reasons, also with the unweighted version. Also, it was aimed to have Barcelona in the grid category. For these reasons, the limits were lowered.

_SEED_POINT_SNAP_DISTANCE_FACTORfloat, default 0.25

Factor to multiply seed_point_grid_spacing with, to determine auto value of seed_point_snap_distance.

_EXISTING_NETWORK_SPACING_FACTORfloat, default 0.5

Factor to multiply seed_point_grid_spacing with, to determine auto value of existing_network_spacing.

_BUFFER_SEED_POINTS_EXNW_FACTORfloat, default 0.5

Factor to multiply existing_network_spacing with, to determine which previously determined seed points (grid or rail) to drop that are too close to the extra existing network points.

_BEARING_BINSint, default 72

Number of bins to determine bearing. e.g. 72 will create 5 degrees bins.

_ROUTING_PENALTYdict, default {0: 1.5, 1: 1}

Factor to multiply length of non-pbi/pbi for routing, to avoid routing through parallel streets when slightly longer pbi is available. By default, non-pbi counts as 50% longer than pbi.

_PROGRESS_BAR_LENGTHint, default 23

Character length of tqdm progress bars.

_PROGRESS_BAR_DESC_LENGTHint, default 23

Character length of tqdm progress bar descriptions. This is the space given to text like “Importing network data “, which is at the maximum of 23 characters.

References

[1]
  1. Boeing, Urban spatial order: Street network orientation, configuration, and entropy, Applied Network Science 4, 67 (2019)

growbikenet.functions

Utility functions for growbikenet.

growbikenet.functions._acquire_network(import_files, existing_network_spacing, city_query)[source]

Import or download networks, prepare them, and create boundary.

growbikenet.functions._angulate_seed_points(seed_point_linking, seed_points_snapped_filtered, seed_network)[source]

Triangulate or quadrangulate seed points or seed point network.

growbikenet.functions._compute_edge_metrics(ordering, B, metric_weight)[source]

Compute edge metrics.

growbikenet.functions._count_and_merge(n, bearings)[source]

Double, then merge bins to avoid edge effects.

Make twice as many bins as desired, then merge them in pairs. Prevents bin-edge effects around common values like 0° and 90°. Adapted from: https://github.com/gboeing/osmnx-examples/blob/v0.11/notebooks/17-street-network-orientations.ipynb

Parameters:
nint

Number of bins.

bearingspandas.Series

Series of bearings.

Returns:
bearings_mergednumpy.ndarray, dtype=int

The frequencies of the new merged bearings.

growbikenet.functions._create_delaunay_edges(nodes_gdf)[source]

Create dataframe with edges that are part of Delaunay triangulation.

Parameters:
nodes_gdfgeopandas.geodataframe.GeoDataFrame

Seed points with osmid and corresponding point geometry.

Returns:
dfpandas.DataFrame

Dataframe with edge pairs and singled out source and target nodes.

Notes

The original paper [1] uses minimum weight triangulation, but Delaunay triangulation is much faster due to the Delaunay() scipy function and gives in most cases identical results. Triangulation and metrics (betweenness, closeness) are calculated for the abstract network for which egde lengths are taken from the routed network.

References

[1]
  1. Szell, S. Mimar, T. Perlman, G. Ghoshal, R. Sinatra, Growing urban bicycle networks, Scientific Reports 12, 6765 (2022)

growbikenet.functions._create_seed_points(existing_network_spacing, seed_point_type, g_undir, edges, nodes, seed_point_grid_spacing, import_files, city_query, seed_point_tags, city_boundary_geometry)[source]

Create seed points.

growbikenet.functions._get_correct_edgetuples(edge_gdf, nodelist)[source]

Map a node list (from nx.shortest_paths()) to the correct set of edge tuples that can be used for indexing the edge geodataframe.

Parameters:
edge_gdfgeopandas.geodataframe.GeoDataFrame

The street network, in a projected CRS.

nodelistlist

A list of nodes that make up source and targets of edges.

Returns:
edgelist_finallist

List of edge tuples that can be used for indexing the edge geodataframe.

growbikenet.functions._get_existing_network_seed_points(nodes_exnw, existing_network_spacing)[source]

Get seed points on an existing bicycle network.

Start with the first (arbitrary) node from nodes_exnw. Then, for each node: Delete all other nodes closer than existing_network_spacing, proceed with the closest of the remaining nodes. Finish once all nodes are found or deleted.

Parameters:
nodes_exnwgeopandas.geodataframe.GeoDataFrame

Nodes of the existing bicycle network, in a projected CRS.

existing_network_spacingint

Distance between seed points, in meters.

Returns
——-
seed_points_exnwgeopandas.geodataframe.GeoDataFrame

Seed points, already part of the network, in the same projected CRS as edges.

growbikenet.functions._get_grid_seed_points(edges, seed_point_spacing, principal_bearing, seed_point_type='grid_square')[source]

Get grid seed points for street network, rotated by principal bearing.

Adapted from: https://github.com/gboeing/osmnx-examples/blob/v0.11/notebooks/17-street-network-orientations.ipynb

Parameters:
edgesgeopandas.geodataframe.GeoDataFrame

The street network, in a projected coordinate reference system.

seed_point_spacingint

Distance between seed points, in meters.

principal_bearingfloat

Principal bearing (most common bearing of streets).

seed_point_type{‘grid_square’, ‘grid_triangle’}, default ‘grid_square’

Type of seed points.

Returns:
seed_points: geopandas.geodataframe.GeoDataFrame

Seed points, rotated by principal bearing, to be snapped to the street network, in the same projected CRS as edges.

seed_networknetworkx graph

If seed_point_type is ‘grid_square’, quadrangulated network of the seed_points, where node ids are the seed_points. If seed_point_type is ‘grid_triangle’, empty network because the seed points will be triangulated.

growbikenet.functions._get_tags_seed_points(city_query, tags, city_boundary_geometry=None)[source]

Get tags seed points for a city

Parameters:
city_querystr

Name of the city that the analysis should be performed on. This is the query string used to fetch the data from nominatim. Overruled (for data fetching) if city_boundary_geometry is set.

tagsNone or dict[str, bool or str or list[str]], default None

Geocodable tags, see [3]. For example, tags={“railway”: [“station”, “halt”]} will retrieve exactly the same as seed_point_type=’rail’.

city_boundary_geometryNone or shapely Polygon or shapely MultiPolygon,
default None

If not set to None, the study area is selected from this geometry.

Returns:
seed_points: geopandas.geodataframe.GeoDataFrame

Seed points, rotated by the principal bearing, to be snapped to the street network, in the same projected CRS as the edges.

References

growbikenet.functions._get_weighted_distances(B, num_types)[source]

Get weighted distances by edge attribute num_types.

Parameters:
Bnetworkx.classes.multigraph.MultiGraph

The routed, grown bicycle network graph, where edges have the attribute num_types. The numerical attribute “distance” must exist for all edges.

num_typesstr

Name of the attribute to weight the distances.

Returns:
dist_weighted_by_types_dictdict

Dictionary where keys are the edges (tuples of node ids), and values are the weighted distances following [1].

Notes

The calculation follows [1], only without +1 in the numerator and with a small epsilon to prevent division by zero.

References

[1] (1,2)
  1. Folco, L. Gauvin, M. Tizzoni, M. Szell, Data-driven micromobility network planning for demand and safety, Environment and planning B: Urban analytics and city science 50(8), 2087-2102 (2023)

growbikenet.functions._import_data_files(import_files)[source]

Import data files.

growbikenet.functions._order_df(df, method)[source]

Order dataframe by specified method.

Parameters:
dfpandas.DataFrame

Dataframe with source and target information for each edge, as well as edge attributes as columns.

method{‘betweenness’, ‘closeness’, ‘random’}

Method used to order the edges.

Returns:
df: pandas.DataFrame

Dataframe sorted by specified ordering method.

growbikenet.functions._postprocess_edges(existing_network_spacing, edges_exnw, edges_ordered)[source]

Postprocess edges: Add bike net on top, remove overlaps, add length metrics, reorder, reproject.

growbikenet.functions._prepare_export(export_data, export_plots, city_id, city_query, existing_network_spacing, seed_point_type, ordering)[source]

Prepare export: Create folder and filename for exported data

growbikenet.functions._prepare_seed_points(seed_points)[source]

Project and prepare seed points for further use.

Preparation consists of filtering for Point geometries and setting the CRS.

Parameters:
seed_pointsgeopandas.geodataframe.GeoDataFrame

Unprojected seed points.

Returns:
seed_pointsgeopandas.geodataframe.GeoDataFrame

Projected and prepared seed points.

Print footer.

growbikenet.functions._print_header(city_query, ordering, seed_point_type, existing_network_spacing)[source]

Print header.

growbikenet.functions._remove_edge_overlaps(edges_in)[source]

In the grown network, remove edge overlaps stepwise.

Parameters:
edges_ingeopandas.geodataframe.GeoDataFrame

The grown bike network, in a projected CRS.

Returns:
edges_outgeopandas.geodataframe.GeoDataFrame

The grown bike network without edge overlaps, in a projected CRS.

growbikenet.functions._reroute(edges_ordered, edges, g_undir, grown_bikenet_edges_abstract)[source]

Reroute all edges, set pbi iteratively.

The point of rerouting is to go through all abstract edges one by one in their determined ordering. In each step, reroute with pbi penalties, and then set the routed path to pbi. That way newly routed paths assume that all previously routed paths are already pbi, and go more likely through those previous paths, preventing “nile delta” artefacts to some extent, and making the resulting grown network shorter / more effective.

Parameters:
edges_orderedgeopandas.geodataframe.GeoDataFrame

Geodataframe of all edges in street network ordered by the ordering method, in projected CRS constants._CRS_CALCULATIONS.

edgesgeopandas.geodataframe.GeoDataFrame

Edges of the growable network, in projected CRS constants._CRS_CALCULATIONS.

g_undirnetworkx.classes.multigraph.MultiGraph

NetworkX graph of growable network, undirected.

grown_bikenet_edges_abstractpandas.DataFrame

Dataframe of abstract edges.

Returns:
edges_reorderedgeopandas.geodataframe.GeoDataFrame

Geodataframe of all edges in street network ordered by the ordering method, and reordered to account for pbi dynamically, in projected CRS constants._CRS_CALCULATIONS. If settings.reroute is set to False, returns the input edges_ordered.

growbikenet.functions._reset_auto_settings(setting_was_auto)[source]

Reset settings and constants to auto.

growbikenet.functions._resolve_auto_parameters(seed_point_type, seed_point_grid_spacing, seed_point_linking, existing_network_spacing, phi, import_files)[source]

Resolve auto parameters their inconsistencies, and settings.

Parameters:
Several parameters from `growbikenet.growbikenet()`.
Additionally:
phifloat

Weighted orientation order.

Returns:
Several parameters from growbikenet.growbikenet().
growbikenet.functions._resolve_crs_calculations(gdf)[source]

Resolve constants._CRS_CALCULATIONS = ‘auto’

Parameters:
gdfgeopandas.geodataframe.GeoDataFrame

A geodataframe from which to estimate the UTM CRS

growbikenet.functions._reverse_bearing(x)[source]

Reverse bearing.

Adapted from: https://github.com/gboeing/osmnx-examples/blob/v0.11/notebooks/17-street-network-orientations.ipynb

Parameters:
xfloat

The bearing to reverse.

Returns:
x_revfloat

The reversed bearing.

growbikenet.functions._route(g_undir, edges, grown_bikenet_edges_abstract, seed_points_snapped_filtered, num_data_files, point_data, trip_data)[source]

Weigh edges, route, make graph object, add point and trip data.

growbikenet.functions._snap_filter_seed_points(progress_bar, seed_points, seed_network, nodes, seed_point_linking, existing_network_spacing, nodes_exnw_filtered)[source]

Snap and filter seed points.

growbikenet.functions._update_seed_points_with_existing_bike_network(seed_points_snapped, nodes_exnw, existing_network_spacing)[source]

Update seed points with existing bike network.

Updates given snapped seed points by incorporating seed points from an existing bike network.

Parameters:
seed_points_snappedgeopandas.geodataframe.GeoDataFrame

Snapped seed points on the street network, constructed with seed_point_grid_spacing.

nodes_exnwgeopandas.geodataframe.GeoDataFrame

Nodes of the existing bike network, after shortest components below constants.EXISTING_NETWORK_MINIMUM_COMPONENT_LENGTH have been filtered out.

existing_network_spacingint

Positive integer denoting spacing between seed points, in meters, only on the existing bicycle network.

Returns:
seed_points_snappedgeopandas.geodataframe.GeoDataFrame

Snapped seed points incorporating both street grid and existing bike network.

growbikenet.functions._validate_parameters(city_query, ordering, seed_point_type, seed_point_grid_spacing, seed_point_linking, existing_network_spacing, export_data, city_id, export_plots, import_files, seed_point_tags)[source]

Check if user parameter input is valid. If not, raise an exception or warning.

Parameters:
Same as `growbikenet.growbikenet()`
Additionally:
constants._PRESET_TAGSdict

Dictionary of preset seed point tags.

Returns:
True
growbikenet.functions._validate_settings()[source]

Check if user settings input is valid. If not, raise an exception or warning.

Returns:
setting_was_autodict

Dictionary remembering which setting or constant was set to auto, so it can be reset to auto in the end.

growbikenet.functions.add_path_to_df(df, edges, g_undir)[source]

Map each unrouted edge to a merged geometry of corresponding OSMnx edges (routed on g_undir).

Parameters:
dfpandas.DataFrame

Dataframe with information about edges.

edgesgeopandas.geodataframe.GeoDataFrame

The street network, in a projected CRS.

g_undirnetworkx.graph undirected

Graph to use for routing.

Returns:
dfpandas.DataFrame

Dataframe with added path nodes and path edges.

growbikenet.functions.add_point_data_to_net(points, edges, matching_distance=500)[source]

Match point data to network edges.

Parameters:
pointsgeopandas.geodataframe.GeoDataFrame

A geodataframe of unprojected point geometries, optional having a column num containing an integer. This could be (number of) point events like crashes or citizen feedback to improve bike infrastructure. If a num column is not provided, assumes 1 per point.

edgesgeopandas.geodataframe.GeoDataFrame

A geodataframe of projected spatial network edges. This is the routed network of seed points.

matching_distanceint, default settings.import_point_data_snap_distance

Matching distance in meters. Set via settings.import_point_data_snap_distance.

Returns:
edges_with_datageopandas.geodataframe.GeoDataFrame

The same spatial network edges, but with a new int column num_points populated with the summed up num values of all points, matched to the closest links if within matching_distance.

growbikenet.functions.add_trip_data_to_net(trips, A, matching_distance=500)[source]

Match trip data to network edges.

First, match origin and destination points given in trips to the nodes. Only consider trips where both origins and nodes are matched within matching_distance. Then, for each trip, find the shortest path over the edges from matched origin node to matched destination node, and add 1 (or optionally num if column provided in trips) to the affected edges.

Parameters:
tripspandas DataFrame

A dataframe of unprojected origin-destination coordinates (columns: o_lat, o_lon, d_lat, d_lon), with each row encoding a trip, in unprojected CRS EPSG:4326. Optional with a column num containing an integer. This could be (number of) trip events. If num column is not provided, assumes 1 per trip.

A: networkx.graph

Graph created from triangulation edge list.

matching_distanceint, default settings.import_trip_data_snap_distance

Matching distance in meters. Set via settings.import_trip_data_snap_distance.

Returns:
graph_with_datanetworkx.graph

The same graph created from triangulation edges list, but with a new edge attribute ‘num_trips’ populated with the summed up num values of all trips where both origins and destinations could be matched to the closest network nodes within matching_distance.

growbikenet.functions.bike_infra_mapping_gdf(g, edges_gdf)[source]

add binary edge attribute pbi to edges_gdf

Parameters:
gnetworkx.MultiDiGraph

simplified graph representing the street network, with added binary edge attribute “pbi”

edges_gdf: geopandas.GeoDataFrame

edges representing the street network

Returns:
edges_gdf: geopandas.GeoDataFrame

edges representing the street network with added binary attribute “pbi”

growbikenet.functions.create_gdf_with_geoms(df, edges)[source]

Merge path geometries and create geodataframe.

Parameters:
dfpandas.DataFrame

Dataframe with path nodes and path edges.

edgesgeopandas.GeoDataFrame

The street network, in a projected CRS.

Returns:
gdf: geopandas.GeoDataFrame

Projected GeoDataFrame with path nodes and path edges and merged geometries.

growbikenet.functions.df_from_graph(A, method)[source]

Create a dataframe from an input graph.

Parameters:
Anetworkx.graph

Graph created from triangulation edge list.

method{‘betweenness’, ‘closeness’, ‘random’}

Method used to order the edges.

Returns:
df: pandas.DataFrame

Dataframe with source and target information for each edge, as well as edge attributes as columns.

growbikenet.functions.download_network(city_query, network_type='drive', custom_filter=None, retain_all=True, city_boundary_geometry=None)[source]

Download and prepare a street network from OSM via OSMnx.

Downloads a network with a given network_type and custom_filter using ox.graph_from_place(). Then, stores the undirected OSM data in geodataframes and projects using constants._CRS_CALCULATIONS.

Parameters:
city_querystr

Name of the city that the analysis should be performed on. Overruled (for data fetching) if city_boundary or growable_network is set.

network_type{‘drive’, ‘all’, ‘all_public’, ‘bike’, ‘drive_service’, ‘walk’}, default ‘drive’

What type of street network to retrieve if custom_filter is None.

custom_filterNone or str or list[str], default None

A custom ways filter to be used instead of the network_type presets.

retain_allbool, default True

If True, return the entire graph even if it is not connected, useful for disconnected bicycle networks. If False, retain only the largest weakly connected component, useful for road networks.

city_boundary_geometryNone or shapely.Polygon or shapely.MultiPolygon,
default None

If not set to None, the study area is selected from this geometry.

Returns:
nodesgeopandas.geodataframe.GeoDataFrame

Extracted OSM nodes, projected.

edgesgeopandas.geodataframe.GeoDataFrame

Extracted OSM edges, projected.

g_undirnetworkx.classes.multigraph.MultiGraph

Extracted networkX graph, undirected.

growbikenet.functions.export_data_to_file(export_data, seed_points_snapped_filtered, city_boundary_exists, city_boundary_gdf, existing_network_spacing, edges_ordered, export_strings)[source]

Export data.

growbikenet.functions.export_plots_to_file(export_plots, ordering, edges_ordered, seed_points_snapped_filtered, existing_network_spacing)[source]

Export plots.

growbikenet.functions.filter_network_by_component_length(g_undir)[source]

Filter a network to remove too short components.

The application is that g_undir is all the components of the existing bicycle network, but we do not snap seed points to components shorter than constants.EXISTING_NETWORK_MINIMUM_COMPONENT_LENGTH. So we create a new set of nodes where the nodes from the too small components are removed.

Parameters:
g_undirnetworkx.classes.multigraph.MultiGraph

Street network networkX graph, undirected.

Returns:
nodes_filteredgeopandas.geodataframe.GeoDataFrame

Filtered OSM nodes of the street network, projected.

edges_filteredgeopandas.geodataframe.GeoDataFrame

Filtered OSM edges of the street network, projected.

g_undir_filterednetworkx.classes.multigraph.MultiGraph

Filtered street networkX graph, undirected.

growbikenet.functions.filter_points_distant_from_osm_nodes(points_snapped, snap_distance='auto')[source]

Remove points that are further than the snap distance away from an actual OSM node.

Parameters:
points_snappedgeopandas.geodataframe.GeoDataFrame

Points with additional information about geometries of OSM nodes that seed nodes were snapped to.

snap_distanceint

Maximum distance between raw seed points and OSM nodes for snapping, in meters.

Returns:
points_snapped_filteredgeopandas.geodataframe.GeoDataFrame

points within snap distance away from an actual OSM node; only columns are osmid and the associated OSM geometry.

growbikenet.functions.get_principal_bearing(G)[source]

Determine the most common (principal) bearing, for the best grid orientation.

Adapted from: https://github.com/gboeing/osmnx-examples/blob/v0.11/notebooks/17-street-network-orientations.ipynb The bearing is determined from edges weighted by length.

Parameters:
Gnetworkx MultiGraph (undirected)

The graph from which to determine the principal bearing. Its CRS must be geographical, not projected.

Returns:
principal_bearingfloat

The principal bearing, precise to 5 degrees.

growbikenet.functions.import_network(growable_network)[source]

Import and project a street network from gpkg file.

Parameters:
growable_networkstr

The street network is loaded from this file. Must be a gpkg file in unprojected CRS EPSG:4326 with layers nodes and edges, with the structure that a OSMnx street network g has after saving its undirected version via ox.io.save_graph_geopackage(). For example:

>>> g = ox.graph_from_place("Barcelona", network_type='drive')
>>> g = nx.MultiGraph(ox.convert.to_digraph(g))
>>> ox.io.save_graph_geopackage(g, "Barcelona_streets.gpkg")
import_pathstr, default settings.import_path

Path to import files.

Returns:
nodesgeopandas.geodataframe.GeoDataFrame

Extracted OSM nodes, projected.

edgesgeopandas.geodataframe.GeoDataFrame

Extracted OSM edges, projected.

g_undirnetworkx.classes.multigraph.MultiGraph

Extracted networkX graph, undirected.

city_boundary_gdfgeopandas.geodataframe.GeoDataFrame

Convex hull of the street network.

Notes

For all edges between a pair of nodes u and v there must be one edge with key 0.

growbikenet.functions.initialize_progress_bar(desc_string, total=1, unit='step')[source]

Initialize tqdm progress bar.

growbikenet.functions.map_edges_to_bike_infrastructure(g)[source]

map if edges in graph have bike infrastructure as specified in config.py

Parameters:
g :networkx.MultiDiGraph

simplified graph representing the street network

Returns:
gnetworkx.MultiDiGraph

simplified graph representing the street network, with added binary edge attribute “pbi”

growbikenet.functions.node_to_edge_attributes(values_nodes, edges)[source]

Map node to edge attributes.

Creates edge attributes by taking the average values of adjacent node attributes.

Parameters:
values_nodesdict

Keys: node ids, Values: Node attributes (for example a scalar).

edgesnetworkx.classes.reportviews.EdgeView

A view of edge attributes of a networkx graph. Could also be a list of tuples of node ids.

Returns:
values_edges: dict

Keys: tuples of node ids, Values: Edge attributes

growbikenet.functions.nx_to_nodes_edges(G)[source]

Get nodes and projected edges from networkX graph.

Parameters:
Gnetworkx.classes.multigraph.MultiGraph

NetworkX graph, undirected.

Returns:
nodesgeopandas.geodataframe.GeoDataFrame

Extracted OSM nodes, projected, osmid is index.

edgesgeopandas.geodataframe.GeoDataFrame

Extracted OSM edges, projected.

growbikenet.functions.orientation_order(g_undir)[source]

Calculate a graph’s weighted orientation order phi, see [1].

Parameters:
g_undirnetworkx.classes.multigraph.MultiGraph

networkX street network, undirected, weighted with “length”.

Returns:
phifloat

Weighted orientation order.

Notes

Whether phi is weighted or unweighted does not matter much, but for the purpose of growing bike networks, weighted seems more appropriate. Also, the values here are lower than in the paper [1] for unknown reasons, also with the unweighted version.

References

[1] (1,2)
  1. Boeing, Urban spatial order: Street network orientation, configuration, and entropy, Applied Network Science 4, 67 (2019)

growbikenet.functions.prepare_nodes_edges(nodes, edges)[source]

Project and prepare nodes and edges for further use.

Parameters:
nodesgeopandas.geodataframe.GeoDataFrame

OSM nodes, unprojected.

edgesgeopandas.geodataframe.GeoDataFrame

OSM edges, unprojected.

crs_calculationsstr, default constants._CRS_CALCULATIONS

EPSG code of the CRS that is used to project OSM data for calculations.

Returns:
nodesgeopandas.geodataframe.GeoDataFrame

OSM nodes, projected, osmid is index

edgesgeopandas.geodataframe.GeoDataFrame

OSM edges, projected

Notes

For all edges between a pair of nodes u and v there must be one edge with key 0.

growbikenet.functions.set_path_to_pbi(source, target, edges, g)[source]

Map an unrouted edge to a merged geometry of corresponding OSMnx edges (routed on g), and set g’s edges pbi to 1.

Parameters:
edgesgeopandas.geodataframe.GeoDataFrame

The street network, in a projected CRS.

gnetworkx.graph undirected

Graph to use for routing.

Returns:
gnetworkx.graph undirected

Graph to use for routing, with edges set to pbi=1.

growbikenet.functions.slugify(s)[source]

Slugify a string.

Adapted from: https://github.com/Chalarangelo/30-seconds-of-code/blob/master/content/snippets/python/s/slugify.md

Parameters:
sstr

String to slufigy.

Returns:
sstr

Slugified string.

Notes

A clean global solution would be using unidecode, but we do not want extra dependencies for this. We assume European city names in latin alphabet, some special letters like Hungarian ő already mapped.

growbikenet.functions.snap_points_to_osm_nodes(points, nodes)[source]

Snap points to OSM nodes.

Parameters:
pointsgeopandas.geodataframe.GeoDataFrame

Points that were created within city area, to be snapped to actual OSM nodes.

nodesgeopandas.geodataframe.GeoDataFrame

Actual OSM nodes, downloaded from osmnx.

Returns:
points_snappedgeopandas.geodataframe.GeoDataFrame

Points with additional information about geometries of OSM nodes that nodes were snapped to.

growbikenet.functions.update_with_existing_bike_network(city_query, g_undir, import_files, city_boundary_geometry=None)[source]

Update street network with existing bike network.

Downloads a network of protected bike infrastructure from OSM (retaining all connected components) or imports it from a local file and merges it to a given street network graph g_undir.

Parameters:
city_querystr

Name of the city that the analysis should be performed on. Overruled (for data fetching) if city_boundary_geometry is set.

g_undirnetworkx.classes.multigraph.MultiGraph

Street network networkX graph, undirected

import_filesdict

Dictionary containing the key “bike_network” and value None or a string with the path of a bicycle network to import. Must be a gpkg file in unprojected CRS EPSG:4326 with layers nodes and edges, with the structure that an undirected OSMnx bike network has after saved via ox.io.save_graph_geopackage().

city_boundary_geometryNone or shapely.Polygon or shapely.MultiPolygon,
default None

If not set to None, the study area is selected from this geometry.

Returns:
nodesgeopandas.geodataframe.GeoDataFrame

Updated OSM nodes of the street network, projected.

edgesgeopandas.geodataframe.GeoDataFrame

Updated OSM edges of the street network, projected.

g_undirnetworkx.classes.multigraph.MultiGraph

Updated street networkX graph, undirected.

nodes_exnwgeopandas.geodataframe.GeoDataFrame

OSM nodes of the corresponding bike network, projected.

edges_exnwgeopandas.geodataframe.GeoDataFrame

OSM edges of the corresponding bike network, projected.

growbikenet.functions.weigh_edges(G, penalty)[source]

adds weight parameter to all edges in G, which is calculated by multiplying the length of the edge with the corresponding penalty value

Parameters:
G: networkx.Graph

undirected simple graph representing the street network

penalty: dictionary

dictionary of penalty values, dependent on if edge has bike infrastructure or not

Returns:
G: networkx.Graph

undirected simple graph representing the street network with weighted edges

growbikenet.settings

Global settings for growbikenet that can be configured by the user.

allow_edge_overlapsbool, default False

If set to False, removes edge overlaps in consecutive growth stages and deletes growth stages that do not add anything new.

crs_resultstr, default ‘4326’

EPSG code of the coordinate reference system for the resulting geodataframe and exported data. If ‘4326’ (WGS84) and export_file_format is set to ‘geojson’, data is exported via the RFC7946 standard.

export_pathdict(str)

Paths to results and plots folders to save data and plots.

export_file_format{‘gpkg’, ‘geojson’}, default ‘gpkg’

File format for the data export, relevant if export_data is set to True. If exporting as geojson, generates extra files for seed points, city boundary, and existing bicycle network (if relevant). If exporting as gkpg, these are added all in one file as extra layers.

import_data_impactfloat, default 9

Impact of imported trip or point data on results. Must be non-negative.

import_data_trip_point_balancefloat, default 0.5

Impact of imported trip data versus point data on results. Must be between 0 and 1, where 0 means no trip impact and full point impact, 1 means full trip impact and no point impact, and 0.5 means balanced impact of both. If only the trip data is imported, this variable is treated as 1; if only the point data is imported, this variable is treated as 0 - meaning in such a case the data impact is controlled only by settings.import_data_impact.

import_pathstr

Path to import files (as defined in growbikenet’s import_files parameter).

import_point_data_snap_distanceint, default 500

Maximum distance between point data and network links for snapping, in meters.

import_trip_data_snap_distanceint, default 500

Maximum distance between trip data and network links for snapping, in meters.

random_seedint, default 43

Random number generator seed for reproducibility

reroutebool, default True

Decide whether to add a rerouting step, which takes extra computations but removes unrealistic artefacts.

seed_point_snap_distance‘auto’ or int, default ‘auto’

Maximum distance between raw seed points and osm nodes for snapping, in meters. Auto-value is ceil(seed_point_grid_spacing`* `constants._SEED_POINT_SNAP_DISTANCE_FACTOR). If integer, must be positive. The default values for seed_point_grid_spacing of 1000/1154/1707 are: 250/289/427

seed_point_type_namestr, default ‘file’

The name of the seed points in the exported file name, when seed_point_type is set to ‘file’.

silentbool, default False

If set to True, suppresses all user feedback. Useful for batch exports.

vizdict

Dictionary of visualization settings:

  • ‘bike_to_grow’dict

    Dictionary of properties for the bicycle network to grow but not yet grown.

  • ‘bike_grown’dict

    Dictionary of properties for the bicycle network grown.

  • ‘bike_existing’dict

    Dictionary of properties for the existing bicycle network.

  • ‘seed_point’dict

    Dictionary of properties for the seed points. Set ‘markersize’ to 0 to hide them.

  • ‘crs’str, default ‘auto’

    The CRS used for plotting. Option ‘auto’ sets a local azimuthal projection centered on the network. Otherwise, for Europe ‘3035’ (LAEA) and globally ‘54035’ (Equal Earth) or ‘54030’ (Robinson) also produce good results.

growbikenet.visualization

Visualization functions for growbikenet.

growbikenet.visualization.generate_plots(edges_ordered, nodes, ordering, with_existing_bike_network)[source]

Plot frames of a growing bicycle network .

Results are png files saved into settings.export_path[‘plots’].

Parameters:
edges_orderedgeopandas.geodataframe.GeoDataFrame

Ordered geodataframe of all edges in street network, representing a growing bicycle network.

nodesgeopandas.geodataframe.GeoDataFrame

Set of seed points snapped to the street network, representing the growing bicycle network nodes.

orderingstr

Method used to order edges.

with_existing_bike_networkbool

Boolean deciding whether the plot is with or without existing bike network.

Returns:
figslist

List of figure handles.