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_name, crs_projected='3857', ranking='betweenness_centrality', seed_point_type='auto', seed_point_grid_spacing='auto', seed_point_delta='auto', seed_point_linking='auto', existing_network_spacing=None, export_data=True, export_file_format='geojson', export_data_slug=None, export_plots=False, allow_edge_overlaps=False, city_boundary_file=None, street_network_file=None, seed_point_file=None, seed_point_tags=None)[source]¶
Creates a list of urban street network edges ordered by a ranking 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[Raf425b00f903-2]_. 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.
- Parameters:
- city_namestr
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_file or street_network_file is set.
- crs_projectedstr, default ‘3857’
EPSG code of the coordinate reference system that is used to project osm data. Default is ‘3857’ (WGS 84 / Pseudo-Mercator). If this web mercator projection is not needed, then for Europe ‘3035’ (LAEA) and globally ‘54035’ (Equal Earth) is better.
- rankingstr, default ‘betweenness_centrality’
Method used to rank edges. Must be ‘betweenness_centrality’ (default), ‘closeness_centrality’, or ‘random’.
- seed_point_typestr (‘auto’ | ‘grid_square’ | ‘grid_triangle’ | ‘rail’ | ‘school’ | ‘park’ | ‘file’ | ‘tags’), default ‘auto’
If set to ‘auto’, selects ‘grid_square’ or ‘grid_triangle’ automatically depending on the street network’s orientation entropy, see [3]. If set to ‘grid_square’, creates a square grid. If set to ‘grid_triangle’, creates a triangle grid. In this case, seed_point_linking must not be set to ‘quadrangulate’. If set to ‘rail’, uses railway stations and halts. If set to ‘school’, uses kindergartens, schools, colleges, and universities. If set to ‘park’, uses parks, gardens, nature reserves, and public bathing places. If set to ‘file’, imports seed_point_file. If set to ‘tags’, uses geocodable seed_point_tags, see [4].
- seed_point_grid_spacing‘auto’ | 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-value for seed_point_type ‘grid_square’ with seed_point_linking ‘triangulate_delaunay’: 1707 Auto-value for seed_point_type ‘grid_square’ with seed_point_linking ‘quadrangulate’: 1000 Auto-value for seed_point_type ‘grid_triangle’: 1154 Auto-value otherwise: 1707 These values ensure that any point in the city is always within 500m of the network (under perfect conditions). For case 1707, see [1].
- seed_point_delta‘auto’ | int, default ‘auto’
Maximum distance between raw seed points and osm nodes for snapping, in meters. Auto-value is round(seed_point_grid_spacing/4).
- seed_point_linkingstr (‘auto’ | ‘triangulate_delaunay’ | ‘quadrangulate’), default ‘auto’
The algorithm for linking up the seed points into an unrouted, abstract network. If set to ‘auto’, selects ‘triangulate_delaunay’ or ‘quadrangulate’ automatically depending on the street network’s orientation entropy, see [3]. If set to ‘triangulate_delaunay’, uses Delaunay triangulation. If set to ‘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_spacingint, default None
Spacing between seed points, in meters, only on the existing bicycle network. If not set to a positive integer, the existing network is ignored. existing_network_spacing is recommended to be smaller than seed_point_grid_spacing, ideally around 25%, to ensure that the existing bicycle network is built first.
- export_databool, default True
If set to True, data is saved to a file. The filename is [slug]-[ranking]-[seed_point_type].[export_file_format], where slug is a string id made out of city_name.
- export_file_formatstr (‘geojson’ | ‘gpkg’), default ‘geojson’
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_data_slugstr | None, 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_plotsbool, default False
If set to True, plots are saved to files, overwriting existing ones.
- 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.
- city_boundary_filestr | None, default None
If not set to None, the study area will be selected from the (Multi)Polygon provided in the city_boundary_file shape file, ideally in unprojected latitude-longitude degrees (EPSG:4326), but EPSG:3857 also works. For example, “./tests/test_data/copenhagen.shp”. city_boundary_file and street_network_file cannot both be set.
- street_network_filestr | None, default None
If not set to None, the street network will be 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 saved its undirected version via ox.io.save_graph_geopackage(). For example: >>> g = ox.graph_from_place(“Barcelona”, network_type=’drive’) >>> ox.io.save_graph_geopackage(g.to_undirected(), “Barcelona_streets.gpkg”). city_boundary_file and street_network_file cannot both be set.
- seed_point_filestr | None, default None
If not set to None, the seed points will be 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’.
- seed_point_tagsNone | dict[str, bool | str | 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”]} will retrieve exactly the same as seed_point_type=’rail’.
- Returns:
- edges_rankedgeopandas.geodataframe.GeoDataFrame
ordered geodataframe of all edges in street network
References
[1] (1,2,3)Szell, S. Mimar, T. Perlman, G. Ghoshal, R. Sinatra, “Growing urban bicycle networks”, Scientific Reports 12, 6765 (2022)
[2]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)
Examples
Minimum working example: Grow a bicycle network from scratch in Lyon.
>>> edges_ranked = growbikenet("Lyon")
Grow a bicycle network from scratch in Copenhagen, providing a study area polygon to include also Frederiksberg and Amager.
>>> edges_ranked = growbikenet("Copenhagen", city_boundary_file="./tests/test_data/copenhagen.shp")
Expand the existing bicycle network of Lyon, connecting all educational institutions.
>>> edges_ranked = growbikenet("Lyon", seed_point_type='school', existing_network_spacing=500)
Grow a bicycle network in Oelde from scratch, working offline by importing the street network and custom seed points from file.
>>> edges_ranked = growbikenet("Oelde", street_network_file="./tests/test_data/oelde_streets.gpkg", seed_point_type='file', seed_point_file="./tests/test_data/oelde_seed_points.gpkg")
growbikenet.functions¶
Utility functions for growbikenet.
- 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:
- df: pandas.DataFrame
Dataframe with information about edges
- edges: geopandas.geodataframe.GeoDataFrame
The street network, in a projected coordinate reference system
- g_undir: networkx.graph undirected
graph to use for routing
- Returns:
- df: pandas.DataFrame
Dataframe with added path nodes and path edges
- 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:
- n: int
Number of bins
- bearings: pandas.Series
Series of bearings
- Returns:
- bearings_merged: numpy.ndarray, dtype=int
The frequencies of the new merged bearings
- growbikenet.functions.create_delaunay_edges(nodes_gdf)[source]¶
Create df with edges that are part of Delaunay triangulation
Note that 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.
- Parameters:
- nodes_gdf: geopandas.geodataframe.GeoDataFrame
seed points with osmid and corresponding point geometry
- Returns:
- dfpandas.DataFrame
DataFrame with Edge pairs and singled out source and target nodes
References
[1]Szell, S. Mimar, T. Perlman, G. Ghoshal, R. Sinatra, “Growing urban bicycle networks”, Scientific Reports 12, 6765 (2022)
- growbikenet.functions.create_gdf_with_geoms(df, edges)[source]¶
Merge path geometries and create geodataframe
- Parameters:
- df: pandas.DataFrame
Dataframe with path nodes and path edges
- edges: geopandas.GeoDataFrame
The street network, in a projected coordinate reference system
- 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:
- A: networkx.graph
Graph created from triangulation edge list
- method: str
Method used to rank edges. Must be ‘betweenness_centrality’ (default), ‘closeness_centrality’, or ‘random’.
- 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_name, crs_projected, 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 gdfs and projects using crs_projected.
- Parameters:
- city_namestr
Name of the city that the analysis should be performed on. Overruled (for data fetching) if city_boundary_file or street_network_file is set.
- crs_projectedstr
Coordinate reference system that is used to project osm data.
- network_type{‘all’, ‘all_public’, ‘bike’, ‘drive’, ‘drive_service’, ‘walk’}
What type of street network to retrieve if custom_filter is None.
- custom_filter(str | list[str] | 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_geometry(shapely Polygon | shapely MultiPolygon | None), default None
If not set to None, the study area will be 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.filter_seed_points(seed_points_snapped, seed_point_delta)[source]¶
Remove seed_points that are further than delta away from an actual osm node
- Parameters:
- seed_points_snapped: geopandas.geodataframe.GeoDataFrame
seed_points with additional information about geometries of osm nodes that seed nodes were snapped to
- seed_point_delta: int
maximum distance a seed_point may be removed from an actual osm node
- Returns:
- seed_points_snapped: geopandas.geodataframe.GeoDataFrame
seed_points within delta away from an actual osm node, only columns are osmid and the associated osm geometry
- 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_gdf: geopandas.geodataframe.GeoDataFrame
The street network, in a projected coordinate reference system
- nodelist: list
A list of nodes that make up source and targets of edges
- Returns:
- edgelist_final: list
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_exnw: geopandas.geodataframe.GeoDataFrame
Nodes of the existing bicycle network, in a projected coordinate reference system.
- existing_network_spacing: int
Distance between seed points, in meters.
- Returns
- ——-
- seed_points_exnw: geopandas.geodataframe.GeoDataFrame
Seed points, already part of the network, in the same projected coordinate reference system 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:
- edges: geopandas.geodataframe.GeoDataFrame
The street network, in a projected coordinate reference system
- seed_point_spacing: int
Distance between seed points, in meters
- principal_bearing: float
Principal bearing (most common bearing of streets)
- seed_point_type: str (‘grid_square’ | ‘grid_triangle’)
- Returns:
- seed_points: geopandas.geodataframe.GeoDataFrame
Seed points, rotated by principal bearing, to be snapped to the street network, in the same projected coordinate reference system as edges
- seed_network: networkx 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_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 coordinate reference system must be geographical, not projected.
- Returns:
- principal_bearing: float
The principal bearing, precise to 5 degrees.
- growbikenet.functions.get_tags_seed_points(city_name, crs_projected, tags, city_boundary_geometry=None)[source]¶
Get tags seed points for a city
- Parameters:
- city_namestr
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.
- crs_projectedstr
Coordinate reference system that is used to project osm data. Default is ‘3857’ (WGS 84 / Pseudo-Mercator). If this web mercator projection is not needed, then for Europe ‘3035’ (LAEA) and globally ‘54035’ (Equal Earth) is better.
- tagsNone | dict[str, bool | str | 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_geometry(shapely Polygon | shapely MultiPolygon | None), default None
If not set to None, the study area will be selected from this geometry.
- Returns:
- seed_points: geopandas.geodataframe.GeoDataFrame
Seed points, rotated by principal bearing, to be snapped to the street network, in the same projected coordinate reference system as edges
References
- growbikenet.functions.import_network(street_network_file, crs_projected)[source]¶
Import and project a street network from gpkg file
- Parameters:
- street_network_filestr
The street network will be 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 saved its undirected version via ox.io.save_graph_geopackage(). For example: >>> g = ox.graph_from_place(“Barcelona”, network_type=’drive’) >>> ox.io.save_graph_geopackage(g.to_undirected(), “Barcelona_streets.gpkg”)
- crs_projectedstr
Coordinate reference system that is used to project osm data.
- 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
- 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, crs_projected)[source]¶
Get nodes and projected edges from networkX graph
- Parameters:
- Gnetworkx.classes.multigraph.MultiGraph
networkX graph, undirected
- crs_projectedstr
Coordinate reference system that is used to project osm data.
- 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]
Whether phi is weighted or unweighted does not matter much, but for the purpose of growing bike networks, weighted seems more appropriate. Note that the values here are lower than in the paper [1] for unknown reasons, also with the unweighted version.
- Parameters:
- g_undirnetworkx.classes.multigraph.MultiGraph
networkX street network, undirected, weighted with “length”
- Returns:
- phifloat
Weighted orientation order
References
- growbikenet.functions.prepare_nodes_edges(nodes, edges, crs_projected)[source]¶
Project and prepare nodes and edges for further use
- Parameters:
- nodesgeopandas.geodataframe.GeoDataFrame
OSM nodes, unprojected
- edgesgeopandas.geodataframe.GeoDataFrame
OSM edges, unprojected
- crs_projectedstr
Coordinate reference system that is used to project osm data.
- Returns:
- nodesgeopandas.geodataframe.GeoDataFrame
OSM nodes, projected, osmid is index
- edgesgeopandas.geodataframe.GeoDataFrame
OSM edges, projected
- growbikenet.functions.prepare_seed_points(seed_points, crs_projected)[source]¶
Project and prepare seed points for further use
- Parameters:
- seed_points: geopandas.geodataframe.GeoDataFrame
Unprojected seed points
- crs_projectedstr
Coordinate reference system that is used to project the seed points.
- Returns:
- seed_points: geopandas.geodataframe.GeoDataFrame
Projected and prepared seed points.
- growbikenet.functions.rank_df(df, method)[source]¶
Rank dataframe by specified method
- Parameters:
- df: pandas.DataFrame
Dataframe with source and target information for each edge, as well as edge attributes as columns
- method: str
Method used to rank edges. Must be ‘betweenness_centrality’ (default), ‘closeness_centrality’, or ‘random’.
- growbikenet.functions.remove_edge_overlaps(edges_in)[source]¶
In the grown network, remove edge overlaps stepwise
- Parameters:
- edges_in: geopandas.geodataframe.GeoDataFrame
The grown bike network, in a projected coordinate reference system
- Returns:
- edges_out: geopandas.geodataframe.GeoDataFrame
The grown bike network without edge overlaps, in a projected coordinate reference system
- growbikenet.functions.resolve_auto_parameters(seed_point_type, seed_point_grid_spacing, seed_point_delta, seed_point_linking, existing_network_spacing, phi, PHI_LIMITS)[source]¶
Resolve auto parameters and parameter inconsistencies
- Parameters:
- seed_point_* and existing_network_spacing from growbikenet.growbikenet()
- Additionally:
- phifloat
Weighted orientation order
- PHI_LIMITSlist
Limits for phi between seed point type categories
- Returns:
- seed_point_* and existing_network_spacing from growbikenet.growbikenet()
- 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:
- x: float
The bearing to reverse
- Returns:
- x_rev: float
The reversed bearing
- growbikenet.functions.slugify(s)[source]¶
Slugify a string
Source: 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
- growbikenet.functions.snap_seed_points(seed_points, nodes)[source]¶
Snap generated seed_points to actual osm nodes
- Parameters:
- seed_points: geopandas.geodataframe.GeoDataFrame
Seed points that were created within city area, to be snapped to actual osm nodes
- nodes: geopandas.geodataframe.GeoDataFrame
actual osm nodes, downloaded from osmnx
- Returns:
- seed_points_snapped: geopandas.geodataframe.GeoDataFrame
seed_points with additional information about geometries of osm nodes that seed nodes were snapped to
- growbikenet.functions.update_seed_points_with_existing_bike_network(seed_points_snapped, nodes_exnw, existing_network_spacing, crs_projected)[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
- existing_network_spacingint
Positive integer denoting spacing between seed points, in meters, only on the existing bicycle network.
- crs_projectedstr
Coordinate reference system that is used to project osm data.
- Returns:
- seed_points_snappedgeopandas.geodataframe.GeoDataFrame
Snapped seed points incorporating both street grid and existing bike network
- growbikenet.functions.update_with_existing_bike_network(city_name, crs_projected, g_undir, 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) and merges it to a given street network graph g_undir.
- Parameters:
- city_namestr
Name of the city that the analysis should be performed on. Overruled (for data fetching) if city_boundary_geometry is set.
- crs_projectedstr
Coordinate reference system that is used to project osm data.
- g_undirnetworkx.classes.multigraph.MultiGraph
Street network networkX graph, undirected
- city_boundary_geometry(shapely Polygon | shapely MultiPolygon | None), default None
If not set to None, the study area will be 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.validate_parameters(city_name, crs_projected, ranking, seed_point_type, seed_point_grid_spacing, seed_point_delta, seed_point_linking, existing_network_spacing, export_data, export_file_format, export_data_slug, export_plots, allow_edge_overlaps, city_boundary_file, street_network_file, seed_point_file, seed_point_tags, PRESET_TAGS)[source]¶
Check if user parameter input is valid. If not, raise an exception or warning
- Parameters:
- Same as growbikenet.growbikenet()
- Additionally:
- PRESET_TAGSdict
Dictionary of preset seed point tags.
- Returns:
- True