diff --git a/docs/source/getting_started.rst b/docs/source/getting_started.rst index 9b3d815..5d0876b 100644 --- a/docs/source/getting_started.rst +++ b/docs/source/getting_started.rst @@ -27,7 +27,7 @@ GrowBikeNet is built on top of `OSMnx`_ and `GeoPandas`_. It takes one mandatory * The edges which link the seed points are routed on the street network. * A metric is computed for all edges. By default this is betweenness centrality. * The edges are ordered by this metric, denoting the importance and order of links to build. -* Data is exported to a results folder, by default to geojson files, but gpkg is also possible. Exported files are the city boundary, the seed points, and the grown edges (and the existing bicycle network, if used). +* Data is exported to a results folder, by default to gpkg files, but geojson or shp is also possible. Exported files are the city boundary, the seed points, and the grown edges (and the existing bicycle network, if used). * Optional, plots are generated in the results folder for each edge. diff --git a/docs/source/reference_developer.rst b/docs/source/reference_developer.rst index 0f78c24..99352ee 100644 --- a/docs/source/reference_developer.rst +++ b/docs/source/reference_developer.rst @@ -3,12 +3,14 @@ Developer reference This is the complete developer reference for the GrowBikeNet package. If you are looking for an introduction to GrowBikeNet, read the :doc:`getting_started` guide. + growbikenet.growbikenet ----------------------- .. automodule:: growbikenet.growbikenet :members: + growbikenet.constants --------------------- @@ -16,6 +18,7 @@ growbikenet.constants :members: :private-members: + growbikenet.osm --------------- @@ -23,6 +26,7 @@ growbikenet.osm :members: :private-members: + growbikenet.utils ----------------- @@ -30,6 +34,7 @@ growbikenet.utils :members: :private-members: + growbikenet.settings -------------------- @@ -37,6 +42,7 @@ growbikenet.settings :members: :private-members: + growbikenet.visualization ------------------------- @@ -44,6 +50,7 @@ growbikenet.visualization :members: :private-members: + growbikenet._procedure ---------------------- diff --git a/docs/source/reference_user.rst b/docs/source/reference_user.rst index 9fe0592..a8596a9 100644 --- a/docs/source/reference_user.rst +++ b/docs/source/reference_user.rst @@ -5,6 +5,7 @@ This is the user reference for the GrowBikeNet package. If you are looking for a The standard way to import the GrowBikeNet package is via ``import growbikenet as gbn``. The main ``growbikenet()`` function below is then called via ``gbn.growbikenet()``, see the :doc:`mwe`. + growbikenet.growbikenet ----------------------- @@ -12,16 +13,18 @@ growbikenet.growbikenet :members: :no-index: -growbikenet.osm ---------------- - -.. automodule:: growbikenet.osm - :members: - :no-index: growbikenet.settings -------------------- .. automodule:: growbikenet.settings + :members: + :no-index: + + +growbikenet.osm +--------------- + +.. automodule:: growbikenet.osm :members: :no-index: \ No newline at end of file diff --git a/docs/source/usage_07_settings_and_constants.ipynb b/docs/source/usage_07_settings_and_constants.ipynb index 334e897..57f3ef7 100644 --- a/docs/source/usage_07_settings_and_constants.ipynb +++ b/docs/source/usage_07_settings_and_constants.ipynb @@ -28,39 +28,9 @@ "tags": [] }, "source": [ - "**Modules covered**: `settings`, `constants`" + "**Modules covered**: `settings`, `osm`, `constants`" ] }, - { - "cell_type": "markdown", - "id": "f1e75528-7274-443c-92d4-dec397fe9d85", - "metadata": { - "deletable": true, - "editable": true, - "slideshow": { - "slide_type": "" - }, - "tags": [] - }, - "source": [ - "We start every Usage notebook with the standard way of importing GrowBikeNet:" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "e85c6ba0-8415-4c88-a365-0a50375381b3", - "metadata": { - "deletable": true, - "editable": true, - "slideshow": { - "slide_type": "" - }, - "tags": [] - }, - "outputs": [], - "source": [] - }, { "cell_type": "markdown", "id": "7f8eb802-37cf-4ced-a402-daad2cdbafb6", @@ -93,146 +63,34 @@ }, { "cell_type": "markdown", - "id": "4888591b-d932-42cd-b870-47af5affbe36", - "metadata": { - "deletable": true, - "editable": true, - "slideshow": { - "slide_type": "" - }, - "tags": [] - }, - "source": [ - "### Results and data export" - ] - }, - { - "cell_type": "markdown", - "id": "d0a117da-fcef-4ee1-9a01-2a907be28884", - "metadata": { - "deletable": true, - "editable": true, - "slideshow": { - "slide_type": "" - }, - "tags": [] - }, - "source": [ - "- crs_result : str, default '4326' \n", - " EPSG code of the coordinate reference system for the resulting geodataframe\n", - " and exported data. If '4326' (WGS84) and `export_file_format` is set to \n", - " 'geojson', data is exported via the RFC7946 standard.\n", - " \n", - "- export_path : dict(str) \n", - " Paths to results and plots folders to save data and plots.\n", - " \n", - "- export_file_format : {'gpkg', 'geojson'}, default 'gpkg' \n", - " File format for the data export, relevant if `export_data` is set to True. \n", - " If exporting as geojson, generates extra files for seed points and city \n", - " boundary. If exporting as gkpg, these are added all in one file as extra \n", - " layers.\n", - "\n", - "- seed_point_type_name : str, default 'file' \n", - " The name of the seed points in the exported file name, when \n", - " `seed_point_type` is set to 'file'.\n", - "\n", - "- viz : dict \n", - " Dictionary of visualization settings:\n", - "\n", - " - 'bike_to_grow' : dict \n", - " Dictionary of properties for the bicycle network to grow but not yet grown.\n", - " - 'bike_grown' : dict \n", - " Dictionary of properties for the bicycle network grown.\n", - " - 'bike_existing' : dict \n", - " Dictionary of properties for the existing bicycle network.\n", - " - 'seed_point' : dict \n", - " Dictionary of properties for the seed points. Set 'markersize' to 0 to hide them.\n", - " - 'crs' : str, default 'auto' \n", - " 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." - ] - }, - { - "cell_type": "markdown", - "id": "fef72bae-4d8e-44cd-981b-0637e9117c6a", - "metadata": { - "deletable": true, - "editable": true, - "slideshow": { - "slide_type": "" - }, - "tags": [] - }, + "id": "c6c69652-e723-4e75-a434-0084a595d64e", + "metadata": {}, "source": [ - "### Data import" + "Find the settings here: https://docs.bikenetkit.org/GrowBikeNet/reference_user/#growbikenet-settings" ] }, { "cell_type": "markdown", - "id": "d4a8e561-9705-48dc-b96b-f8a35b320a70", - "metadata": { - "deletable": true, - "editable": true, - "slideshow": { - "slide_type": "" - }, - "tags": [] - }, + "id": "acc49eb8-c674-42b9-8caf-ca03c831ff3f", + "metadata": {}, "source": [ - "- import_data_impact : float, default 9 \n", - " Impact of imported trip or point data on results. Must be non-negative.\n", - " \n", - "- import_data_trip_point_balance : float, default 0.5 \n", - " Impact of imported trip data versus point data on results. Must be between \n", - " 0 and 1, where 0 means no trip impact and full point impact, 1 means full \n", - " trip impact and no point impact, and 0.5 means balanced impact of both. If \n", - " only the trip data is imported, this variable is treated as 1; if only the \n", - " point data is imported, this variable is treated as 0 - meaning in such a \n", - " case the data impact is controlled only by `settings.import_data_impact`.\n", - " \n", - "- import_path : str \n", - " Path to import files (as defined in `growbikenet`'s import_files parameter).\n", - "\n", - "- import_point_data_snap_distance : int, default 500 \n", - " Maximum distance between point data and network links for snapping, in \n", - " meters.\n", - "\n", - "- import_trip_data_snap_distance : int, default 500 \n", - " Maximum distance between trip data and network links for snapping, in \n", - " meters." + "## OSM" ] }, { "cell_type": "markdown", - "id": "282358d5-4adb-45b3-a959-bd20ecd12926", - "metadata": { - "deletable": true, - "editable": true, - "slideshow": { - "slide_type": "" - }, - "tags": [] - }, + "id": "fc8510d5-bc15-46c5-99b5-08e032ffb607", + "metadata": {}, "source": [ - "### Operation" + "These are global constants for GrowBikeNet related to OpenStreetMap (OSM), such as the definition of the bicycle network. These are meant for advanced users only who have a good understanding of OSM tags. To change an OSM constant `constantname` to `newconstantvalue`, do the following before running `gbn.growbikenet()`: `gbn.osm.constantname = newconstantvalue`. The correctness of constants is *not* checked automatically, so if you experience strange results or errors, double-check your set OSM constants." ] }, { "cell_type": "markdown", - "id": "4ca150c1-c944-4717-888a-fe5781d43d89", - "metadata": { - "deletable": true, - "editable": true, - "slideshow": { - "slide_type": "" - }, - "tags": [] - }, + "id": "818b3f23-6251-428f-a2a8-ae2e77b3bd98", + "metadata": {}, "source": [ - "- random_seed : int, default 43 \n", - " Random number generator seed for reproducibility\n", - "\n", - "- silent : bool, default False \n", - " If set to True, suppresses all user feedback. Useful for batch exports." + "Find the OSM constants here: https://docs.bikenetkit.org/GrowBikeNet/reference_user/#growbikenet-osm" ] }, { @@ -263,172 +121,15 @@ }, "source": [ "These are global constants for GrowBikeNet that can be tweaked during development, but \n", - "should not be changed later by the user. GrowBikeNet still makes them configurable, for maximal configurability. To change a constant `constantname` to `newconstantvalue`, do the following before running `gbn.growbikenet()`: `gbn.constants.constantname = newconstantvalue`. The correctness of constants is *not* checked automatically, so if you experience strange results or errors, double-check your set constants." + "should not be changed later by the user. The most technical or internal constants start with an underscore. GrowBikeNet still makes them configurable, for maximal configurability. To change a constant `constantname` to `newconstantvalue`, do the following before running `gbn.growbikenet()`: `gbn.constants.constantname = newconstantvalue`. The correctness of constants is *not* checked automatically, so if you experience strange results or errors, double-check your set constants." ] }, { "cell_type": "markdown", - "id": "0ea45ecd-1c57-413b-a575-3b517341025c", - "metadata": { - "deletable": true, - "editable": true, - "slideshow": { - "slide_type": "" - }, - "tags": [] - }, - "source": [ - "### Custom filters" - ] - }, - { - "cell_type": "markdown", - "id": "044cd68f-e0d6-459d-8e9f-afc4a377970f", - "metadata": { - "deletable": true, - "editable": true, - "slideshow": { - "slide_type": "" - }, - "tags": [] - }, - "source": [ - "- PBI_CUSTOM_FILTER : list[str] \n", - " Custom filter for protected bicycle infrastructure (pbi).\n", - "\n", - "- GROWABLE_NETWORK_CUSTOM_FILTER : list[str] or None \n", - " Custom filter for all infrastructure elements that are considered as \n", - " growable by `growbikenet`. By default, `growbikenet` uses a custom filter to \n", - " retrieve the combined drive and pbi (protected bicycle infrastructure) \n", - " network. To only consider the drive network, set \n", - " `GROWABLE_NETWORK_CUSTOM_FILTER` to None and `GROWABLE_NETWORK_TYPE` to \n", - " 'drive'. However, doing so can lead to issues: \n", - " https://github.com/BikeNetKit/GrowBikeNet/issues/255. \n", - "\n", - "- GROWABLE_NETWORK_TYPE : {'drive', 'all', 'all_public', 'bike', 'drive_service', 'walk'}, default 'drive' \n", - " What type of street network to retrieve for the growable network if `GROWABLE_NETWORK_CUSTOM_FILTER` is None." - ] - }, - { - "cell_type": "markdown", - "id": "51ef6afc-613b-4548-9cac-aa82e680c50f", - "metadata": { - "deletable": true, - "editable": true, - "slideshow": { - "slide_type": "" - }, - "tags": [] - }, - "source": [ - "### Operation" - ] - }, - { - "cell_type": "markdown", - "id": "616880a8-b2d9-4d63-852a-ae9ce49b1a48", - "metadata": { - "deletable": true, - "editable": true, - "slideshow": { - "slide_type": "" - }, - "tags": [] - }, - "source": [ - "- GRID_SPACING_TRIANGULATE : int, default 1707 \n", - " Grid spacing in meters for grid triangulation that ensures that any point \n", - " in the city is always within buffer distance b=500m of the network (if seed \n", - " points snap perfectly).\n", - " \n", - "- GRID_SPACING_QUADRANGULATE : int, default 1000 \n", - " Grid spacing in meters for quadrangulation that ensures that any point in \n", - " the city is always within buffer distance b=500m of the network (if seed \n", - " points snap perfectly).\n", - "\n", - "- GRID_SPACING_TRIANGLE : int, default 1154 \n", - " Grid spacing in meters for triangle grid that ensures that any point in the \n", - " city is always within buffer distance b=500m of the network (if seed points \n", - " snap perfectly).\n", - "\n", - "- REORDER : bool, default True \n", - " Decision whether ordering should be reordered after edge removal, as edge \n", - " removal can leave gaps." - ] - }, - { - "cell_type": "markdown", - "id": "728b093d-22f9-4d7a-ad1d-91a04761d41f", - "metadata": { - "deletable": true, - "editable": true, - "slideshow": { - "slide_type": "" - }, - "tags": [] - }, - "source": [ - "### Internal / Technical" - ] - }, - { - "cell_type": "markdown", - "id": "5fdb0eff-7f43-4adf-9406-4a041d5c5b18", - "metadata": { - "deletable": true, - "editable": true, - "slideshow": { - "slide_type": "" - }, - "tags": [] - }, - "source": [ - "The following are especially technical or internal constants. To signify this, they start with an underscore." - ] - }, - { - "cell_type": "markdown", - "id": "4566b03a-d9ef-4580-88a8-85934c356a4d", - "metadata": { - "deletable": true, - "editable": true, - "slideshow": { - "slide_type": "" - }, - "tags": [] - }, + "id": "c10525cc-24fd-4cc9-982c-29618aac0fb4", + "metadata": {}, "source": [ - "- _CRS_CALCULATIONS : str, default '3857' \n", - " EPSG code of the coordinate reference system that is used to project OSM \n", - " data for calculations. The default '3857' is WGS 84 / Pseudo-Mercator. Note \n", - " that the CRS for plotting is not set here, but in `settings.viz['crs']`.\n", - "\n", - "- _PRESET_TAGS : dict \n", - " Pre-defined tags to select tags as seed points\n", - "\n", - "- _PHI_LIMITS : list[float], default [0.02, 0.08] \n", - " Two orientation order limits between street networks with:\n", - " 1) negligible grid elements, 2) some grid elements, 3) grid.\n", - " We aimed to use the tercile limits from the paper [1]_ (Fig 2), but the \n", - " values here are lower for unknown reasons, also with the unweighted \n", - " version. Also, it was aimed to have Barcelona in the grid category. For \n", - " these reasons, the limits were lowered.\n", - "\n", - "- _SEED_POINT_SNAP_DISTANCE_FACTOR : float, default 0.25 \n", - " Factor to multiply `seed_point_grid_spacing` with, to determine auto value \n", - " of `seed_point_snap_distance`.\n", - "\n", - "- _EXISTING_NETWORK_SPACING_FACTOR : float, default 0.5 \n", - " Factor to multiply `seed_point_grid_spacing` with, to determine auto value \n", - " of `existing_network_spacing`.\n", - "\n", - "- _BUFFER_SEED_POINTS_EXNW_FACTOR : float, default 0.5 \n", - " Factor to multiply `existing_network_spacing` with, to determine which \n", - " previously determined seed points (grid or rail) to drop that are too close \n", - " to the extra existing network points.\n", - "\n", - "- _BEARING_BINS : int, default 72 \n", - " Number of bins to determine bearing. e.g. 72 will create 5 degrees bins." + "Find the constants here: https://docs.bikenetkit.org/GrowBikeNet/reference_developer/#module-growbikenet.constants" ] } ], @@ -448,7 +149,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.14.6" + "version": "3.14.8" }, "widgets": { "application/vnd.jupyter.widget-state+json": { diff --git a/examples/batchexport_onecity.py b/examples/batchexport_onecity.py index 9de195b..e46ffec 100644 --- a/examples/batchexport_onecity.py +++ b/examples/batchexport_onecity.py @@ -8,7 +8,7 @@ city_id : str, default None If set, the slugified city_id is used as the filename of the data export. For example, "Athens" will use "athens" in filenames. If set to None, the slugified city_query is used as the filename of the data export. It is useful to set city_id for cities where the city_query is not the city name, for example "Municipality of Athens" vs "Athens". export_file_format : str, default "geojson" - File format for the data export. 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. + File format for the data export. Default "geojson", also possible "gpkg" or "shp". If exporting as geojson or shp, generates extra files for seed points and city boundary. If exporting as gkpg, these are added all in one file as extra layers. city_boundary : (str | None), default None If not set to None, the study area will be 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 : str diff --git a/examples/development.py b/examples/development.py index 4d456d3..48c8d37 100644 --- a/examples/development.py +++ b/examples/development.py @@ -8,17 +8,19 @@ city_id = "badalona_es" -gbn.settings.import_data_impact = 9 -gbn.settings.import_data_trip_point_balance = 0.4 # alpha - gbn.growbikenet( - "Turin", - import_files={ - 'growable_network':"turin_growable_network.gpkg", - 'point_data':"turin_crashes.gpkg", - 'trip_data':"turin_trips.csv", - }, -) + "Oelde", + # existing_network_spacing='auto', + import_files={ + 'growable_network':"oelde_growable_network.gpkg", + # 'bike_network':"bike_networks/"+city_id+".gpkg", + 'seed_points':"oelde_seed_points.geojson" + }, + ) + +# 'growable_network':"growable_networks/"+city_id+".gpkg", +# 'bike_network':"bike_networks/"+city_id+".gpkg", +# 'seed_points':"rail_stations/"+city_id+".gpkg" # import osmnx as ox # import networkx as nx diff --git a/growbikenet/_procedure.py b/growbikenet/_procedure.py index 3be5096..d4b2bf8 100644 --- a/growbikenet/_procedure.py +++ b/growbikenet/_procedure.py @@ -71,8 +71,8 @@ def _gbn_validate_settings(): if type(constants._CRS_CALCULATIONS) is not str: raise TypeError("constants._CRS_CALCULATIONS must be a string") - if settings.export_file_format != "geojson" and settings.export_file_format != "gpkg": - raise ValueError("settings.export_file_format must be 'geojson' or 'gpkg'") + if settings.export_file_format not in ["geojson", "gpkg", "shp"]: + raise ValueError("settings.export_file_format must be 'geojson' or 'gpkg' or 'shp'") # To do: check export_path if type(settings.seed_point_snap_distance) is not int and settings.seed_point_snap_distance != 'auto': raise TypeError("settings.seed_point_snap_distance must be 'auto' or an integer") @@ -586,59 +586,6 @@ def _gbn_compute_edge_metrics(ordering, B, metric_weight): return edges_ordered -def import_network(growable_network): - """Import and project a street network from gpkg file. - - Parameters - ---------- - growable_network : str - 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_path : str, default `settings.import_path` - Path to import files. - - Returns - ------- - nodes : geopandas.geodataframe.GeoDataFrame - Extracted OSM nodes, projected. - edges : geopandas.geodataframe.GeoDataFrame - Extracted OSM edges, projected. - g_undir : networkx.classes.multigraph.MultiGraph - Extracted networkX graph, undirected. - city_boundary_gdf : geopandas.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. - """ - - nodes = gpd.read_file(settings.import_path+growable_network, layer='nodes') - edges = gpd.read_file(settings.import_path+growable_network, layer='edges') - - # Set indices as required by osmnx.convert.graph_from_gdfs - # See: https://osmnx.readthedocs.io/en/stable/user-reference.html#osmnx.utils_graph.graph_from_gdfs - nodes = nodes.set_index(['osmid']) - edges = edges.set_index(['u', 'v', 'key']) - - g = ox.convert.graph_from_gdfs(nodes, edges) - g_undir = g.to_undirected().copy() # convert to undirected (dropping OSMnx keys!) - - city_boundary_gdf = gpd.GeoDataFrame(gpd.GeoSeries(nodes.union_all().convex_hull), geometry=0, crs=nodes.crs) # We do this before the projection of nodes below - # To do: To be super-correct, the hull should be buffered by settings.seed_point_snap_distance (in degrees due to being unprojected) - - nodes, edges = prepare_nodes_edges(nodes, edges) - - return nodes, edges, g_undir, city_boundary_gdf - - def _gbn_postprocess_edges(existing_network_spacing, edges_exnw, edges_ordered): """Postprocess edges: Add bike net on top, remove overlaps, add length metrics, reorder, reproject. @@ -756,6 +703,28 @@ def _gbn_export_data_to_file(export_data, seed_points_snapped_filtered, city_bou seed_points_snapped_filtered.to_file(f, driver="GPKG", layer="Seed points") if city_boundary_exists: city_boundary_gdf.to_file(f, driver="GPKG", layer="City boundary") progress_bar.update(1) + elif settings.export_file_format == "shp": + progress_bar = initialize_progress_bar("Exporting data", 2+int(bool(existing_network_spacing))+int(city_boundary_exists), "file") + if existing_network_spacing: + existing_network = edges_ordered.iloc[[0]] + edges_ordered = edges_ordered.iloc[1:].astype({'source': int, 'target': int}) + existing_network.columns = [str(col)[:10] for col in existing_network.columns] + existing_network.to_file(settings.export_path['results']+export_strings['city_string']+"-growbikenet-existing_bike_network.shp") + progress_bar.update(1) + edges_ordered.columns = [str(col)[:10] for col in edges_ordered.columns] + edges_ordered.to_file(settings.export_path['results']+export_strings['export_data_filename']) + progress_bar.update(1) + else: + edges_ordered.columns = [str(col)[:10] for col in edges_ordered.columns] + edges_ordered.to_file(settings.export_path['results']+export_strings['export_data_filename']) + progress_bar.update(1) + seed_points_snapped_filtered.columns = [str(col)[:10] for col in seed_points_snapped_filtered.columns] + seed_points_snapped_filtered.to_file(settings.export_path['results']+export_strings['city_string']+"-growbikenet-seed_points-"+export_strings['seed_point_string']+"-"+export_strings['exnw_string']+".shp") + progress_bar.update(1) + if city_boundary_exists: + city_boundary_gdf.columns = [str(col)[:10] for col in city_boundary_gdf.columns] + city_boundary_gdf.to_file(settings.export_path['results']+export_strings['city_string']+"-growbikenet-city_boundary.shp") + progress_bar.update(1) progress_bar.close() diff --git a/growbikenet/constants.py b/growbikenet/constants.py index 28b3734..a749ec7 100644 --- a/growbikenet/constants.py +++ b/growbikenet/constants.py @@ -20,7 +20,6 @@ REORDER : bool, default True Decision whether ordering should be reordered after edge removal, as edge removal can leave gaps. - _CRS_CALCULATIONS : str, 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, @@ -57,20 +56,13 @@ _ROUTING_PENALTY : dict, 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. + default, non-pbi counts as 50% longer than pbi, reflected in the value 1.5. References ---------- .. [1] G. Boeing, `Urban spatial order: Street network orientation, configuration, and entropy`, Applied Network Science 4, 67 (2019) """ -# Populate ox.settings.useful_tags_way to make application of custom filter possible -import osmnx as ox - -for custom_tag in ["highway", "cycleway", "bicycle", "cycleway:right", "cycleway:left", "cycleway:both", "cyclestreet", "access", "area", "service", "motor_vehicle", "motorcar"]: # This list should contain all tags used in any custom filters - if custom_tag not in ox.settings.useful_tags_way: - ox.settings.useful_tags_way.extend(custom_tag) - EXISTING_NETWORK_MINIMUM_COMPONENT_LENGTH = 100 GRID_SPACING_TRIANGULATE = 1707 # a=2b/(2-sqrt(2)) @@ -99,4 +91,4 @@ _PROGRESS_BAR_LENGTH = 23 _PROGRESS_BAR_DESC_LENGTH = 23 -_ROUTING_PENALTY = {0: 1.5, 1: 1} \ No newline at end of file +_ROUTING_PENALTY = {0: 1.5, 1: 1} diff --git a/growbikenet/growbikenet.py b/growbikenet/growbikenet.py index 24f2784..37f54b6 100644 --- a/growbikenet/growbikenet.py +++ b/growbikenet/growbikenet.py @@ -102,13 +102,15 @@ def growbikenet( export_plots : bool, 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: + All imported files can be given as geojson, gpkg, or shp, unless noted + otherwise. 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'. + (Multi)Polygon provided in the city_boundary 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 @@ -131,18 +133,20 @@ def growbikenet( 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`. + be 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]_. + citizen feedback to improve bike infrastructure. Must be 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 diff --git a/growbikenet/osm.py b/growbikenet/osm.py index e18151e..3da4fe1 100644 --- a/growbikenet/osm.py +++ b/growbikenet/osm.py @@ -1,4 +1,5 @@ -"""Global constants for `growbikenet` related to OpenStreetMap (OSM). +"""Global constants for `growbikenet` related to OpenStreetMap (OSM). These are +meant for advanced users only who have a good understanding of OSM tags. GROWABLE_NETWORK_CUSTOM_FILTER : list[str] or None Custom filter for all infrastructure elements that are considered as @@ -18,10 +19,6 @@ Dictionary for protected bicycle infrastructure (pbi), with one sub-criterion. For example, highway~path AND bicycle~designated. Always adds a second criterion access!~private. -ROUTING_PENALTY : dict, 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. """ # Populate ox.settings.useful_tags_way to make application of custom filter possible @@ -67,12 +64,10 @@ 'cycleway:left': ['track','opposite_track'], 'cycleway:both': ['track','opposite_track'], } + PBI_DICT_SUB = { 'highway': [ ['path','pedestrian','footway'], {'bicycle': ['designated','yes','permissive']}, ] } - -ROUTING_PENALTY = {0: 1.5, 1: 1} - diff --git a/growbikenet/settings.py b/growbikenet/settings.py index d5beb46..4518882 100644 --- a/growbikenet/settings.py +++ b/growbikenet/settings.py @@ -9,10 +9,11 @@ 'geojson', data is exported via the RFC7946 standard. export_path : dict(str) Paths to results and plots folders to save data and plots. -export_file_format : {'gpkg', 'geojson'}, default 'gpkg' +export_file_format : {'gpkg', 'geojson', 'shp'}, 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. + If exporting as geojson or shp, 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_impact : float, default 9 Impact of imported trip or point data on results. Must be non-negative. import_data_trip_point_balance : float, default 0.5 @@ -23,7 +24,8 @@ 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_path : str - Path to import files (as defined in `growbikenet`'s import_files parameter). + Path to import files (as defined in `growbikenet`'s import_files + parameter). import_point_data_snap_distance : int, default 500 Maximum distance between point data and network links for snapping, in meters. @@ -33,14 +35,14 @@ random_seed : int, default 43 Random number generator seed for reproducibility reroute : bool, default True - Decide whether to add a rerouting step, which takes extra computations but removes unrealistic artefacts. + 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 + 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_name : str, default 'file' The name of the seed points in the exported file name, when `seed_point_type` is set to 'file'. @@ -100,4 +102,4 @@ }, 'dpi': 150, 'crs': 'auto', -} \ No newline at end of file +} diff --git a/tests/test_data/oelde-growbikenet-betweenness-file-from_scratch.geojson b/tests/test_data/oelde-growbikenet-betweenness-file-from_scratch.geojson new file mode 100644 index 0000000..120761a --- /dev/null +++ b/tests/test_data/oelde-growbikenet-betweenness-file-from_scratch.geojson @@ -0,0 +1,13 @@ +{ +"type": "FeatureCollection", +"name": "oelde-growbikenet-betweenness-file-from_scratch", +"features": [ +{"type":"Feature","properties":{"betweenness":0.2,"source":4732996149,"target":2600979593,"ordering":0,"length":1216,"length_cumulative":1216},"geometry":{"type":"LineString","coordinates":[[8.14293,51.8293063],[8.1429857,51.8291722],[8.1429874,51.8291676],[8.14309,51.8289198],[8.1431329,51.8288162],[8.1432245,51.8288307],[8.1432431,51.8287857],[8.1432816,51.8287037],[8.1433052,51.8286533],[8.1429874,51.8285996],[8.1429297,51.8285802],[8.1428978,51.8285621],[8.1428707,51.8285346],[8.1428731,51.8284941],[8.1429371,51.8282582],[8.1429789,51.8281362],[8.1430273,51.827904],[8.143082,51.8276422],[8.143088,51.8276135],[8.143123,51.8274455],[8.1431653,51.8272582],[8.1433397,51.8264863],[8.1433168,51.826445],[8.1432484,51.825883],[8.1433266,51.8256544],[8.1436802,51.8254999],[8.1438167,51.8254324],[8.143959,51.8250735],[8.144057,51.8245889],[8.1440611,51.8245647],[8.1441716,51.8239134],[8.1441746,51.8238698],[8.1441853,51.8237764],[8.1442185,51.8235563],[8.1443403,51.8231172],[8.1443524,51.8230774],[8.1444599,51.8227376],[8.1445436,51.822588],[8.1445701,51.8225406],[8.1447522,51.8222305],[8.1447222,51.8221996],[8.1449265,51.8217864],[8.1448262,51.8215593],[8.1446857,51.8212538],[8.1446368,51.8211475],[8.1446106,51.8210893],[8.1445888,51.821036],[8.1443438,51.8205445],[8.1442938,51.8204443],[8.1442286,51.8203136],[8.1441526,51.8201941],[8.1440339,51.8200515],[8.1439109,51.8199221],[8.1436505,51.8196959],[8.1434804,51.8195688],[8.1433287,51.8194435],[8.1430919,51.8192871],[8.1430047,51.819343]]}}, +{"type":"Feature","properties":{"betweenness":0.13333333333333333,"source":4732996149,"target":5416742037,"ordering":1,"length":935,"length_cumulative":2151},"geometry":{"type":"LineString","coordinates":[[8.14293,51.8293063],[8.1428862,51.8294102],[8.1428526,51.8294925],[8.1423958,51.8294178],[8.1423843,51.8294496],[8.1402038,51.8290908],[8.140151,51.8290847],[8.1400907,51.8290809],[8.1400459,51.8290838],[8.140011,51.8290876],[8.1399793,51.829095],[8.1399416,51.8291077],[8.1399169,51.8291228],[8.1398863,51.8291483],[8.1397552,51.8294079],[8.1397162,51.8294875],[8.1396476,51.8295439],[8.1395563,51.8299133],[8.1395388,51.8300252],[8.139538,51.8300982],[8.1393389,51.830094],[8.1393101,51.8300529],[8.1391463,51.8300424],[8.1389134,51.8300711],[8.1386898,51.8300986],[8.1384507,51.8301281],[8.1382266,51.8301533],[8.1380709,51.8301729],[8.1378998,51.8301962],[8.1378637,51.8302004],[8.1377002,51.8302205],[8.1376674,51.8302245],[8.1374768,51.8302492],[8.1374527,51.8302514],[8.1372513,51.8302758],[8.1370549,51.8302999],[8.1368408,51.8303068],[8.1368092,51.8304419],[8.13659,51.8304105],[8.1364476,51.8303872],[8.1362944,51.8303616],[8.1360964,51.8303295],[8.1358911,51.8302958],[8.1357229,51.8302682],[8.1337495,51.8299445],[8.1336487,51.8299301],[8.1335763,51.8298859],[8.1335454,51.8297782],[8.1335333,51.8297409],[8.1334823,51.8297169],[8.1334113,51.8297045],[8.1328825,51.8297372],[8.1328493,51.8296357],[8.1328643,51.8295986],[8.1328829,51.8295586],[8.1327708,51.8290813],[8.1327449,51.8289726]]}}, +{"type":"Feature","properties":{"betweenness":0.13333333333333333,"source":4732996149,"target":9373476223,"ordering":2,"length":668,"length_cumulative":2819},"geometry":{"type":"LineString","coordinates":[[8.1449265,51.8217864],[8.1450115,51.8217733],[8.1450493,51.8217597],[8.1451779,51.8215365],[8.1454238,51.8210563],[8.1454173,51.8209226],[8.1455471,51.8208808],[8.1456762,51.8208161],[8.1459203,51.8206827],[8.146033,51.820629],[8.1467005,51.8203619],[8.1468323,51.8203092],[8.1469548,51.8203735],[8.1471132,51.8203757],[8.1473994,51.8203796],[8.1476672,51.8203785],[8.1483731,51.8203757],[8.1491444,51.8203631],[8.1493807,51.8203593],[8.1496014,51.820344],[8.1499532,51.8203195],[8.1503634,51.820275],[8.1507723,51.8201966],[8.1510778,51.8200783],[8.1516005,51.819876],[8.1524804,51.8195268],[8.1526988,51.8194367],[8.1527541,51.8194138],[8.1528048,51.8193937]]}}, +{"type":"Feature","properties":{"betweenness":0.13333333333333333,"source":4732996149,"target":7950720782,"ordering":3,"length":2651,"length_cumulative":5471},"geometry":{"type":"LineString","coordinates":[[8.1520264,51.8484757],[8.1519978,51.8484823],[8.1518931,51.8484804],[8.1517906,51.8484524],[8.1517245,51.8483893],[8.151662,51.8482767],[8.1516004,51.848174],[8.151548,51.8481264],[8.1514515,51.8480747],[8.1514019,51.8479797],[8.1513524,51.8479191],[8.1512992,51.8478751],[8.1511488,51.8475813],[8.1509557,51.8472744],[8.1509341,51.8472176],[8.1509099,51.8471647],[8.150863,51.8469779],[8.1508635,51.8469275],[8.1508648,51.8467998],[8.1508947,51.8462624],[8.1509546,51.8455539],[8.1509604,51.8454822],[8.151009,51.8448857],[8.1502117,51.8448026],[8.1490251,51.844679],[8.1471115,51.8444909],[8.1462413,51.8444031],[8.1461926,51.8443975],[8.1462313,51.8439659],[8.1462105,51.8431084],[8.1462408,51.8411562],[8.1462112,51.8410936],[8.1455744,51.8412004],[8.145508,51.8408637],[8.1454814,51.8406229],[8.1455142,51.8404074],[8.1455594,51.840299],[8.1456531,51.8395614],[8.1457001,51.8394038],[8.1455576,51.8394137],[8.1455456,51.8393731],[8.1453417,51.8393963],[8.1451892,51.8393764],[8.1453095,51.8390973],[8.1453435,51.8389025],[8.1453452,51.8388613],[8.1453434,51.8387749],[8.1453699,51.8387023],[8.1453652,51.8386389],[8.14535,51.8385757],[8.1453387,51.8385289],[8.1453753,51.8385042],[8.1454004,51.8384746],[8.1454124,51.8384419],[8.1454103,51.8384085],[8.1453945,51.8383764],[8.1453659,51.838348],[8.1453265,51.8383251],[8.1453391,51.8382838],[8.1453652,51.8381981],[8.1453601,51.8380752],[8.1453534,51.8379412],[8.145341,51.8376837],[8.1453385,51.837558],[8.1453174,51.8365726],[8.1453179,51.8364711],[8.1453209,51.8357852],[8.145316,51.8355193],[8.1453016,51.8347414],[8.1452808,51.834127],[8.1452753,51.8339823],[8.145273,51.8339221],[8.1452726,51.8339148],[8.1452629,51.8336919],[8.1452615,51.8336589],[8.14526,51.833624],[8.1452571,51.8335584],[8.1451929,51.8335587],[8.1451915,51.8334841],[8.1451741,51.8334505],[8.1451613,51.8334207],[8.14516,51.8332988],[8.1451533,51.8330324],[8.1451459,51.8328107],[8.1451372,51.8326479],[8.1451372,51.832601],[8.1451513,51.8325505],[8.1451486,51.8324021],[8.1451373,51.8322368],[8.1451332,51.832147],[8.1451229,51.8320114],[8.1451271,51.8318527],[8.1451144,51.8317621],[8.1451076,51.8315034],[8.1451111,51.8311664],[8.1451077,51.8309762],[8.1451117,51.8308946],[8.1451151,51.8307864],[8.1451077,51.8306501],[8.145097,51.8304408],[8.1450909,51.8303654],[8.1450742,51.8303066],[8.145056,51.8302753],[8.1449253,51.8299589],[8.1448826,51.8297409],[8.1441966,51.8296879],[8.1437988,51.8296503],[8.1434585,51.8296147],[8.1434156,51.8296176],[8.1428317,51.8295441],[8.1428389,51.8295266],[8.1428526,51.8294925]]}}, +{"type":"Feature","properties":{"betweenness":0.13333333333333333,"source":2600979593,"target":401335408,"ordering":4,"length":791,"length_cumulative":6262},"geometry":{"type":"LineString","coordinates":[[8.1430919,51.8192871],[8.1427431,51.8190843],[8.1427072,51.8190627],[8.142485,51.8189366],[8.1419384,51.818649],[8.1416804,51.8185271],[8.1407882,51.8181459],[8.1406635,51.8180926],[8.1399376,51.8178238],[8.1398086,51.817772],[8.1396989,51.8178677],[8.1396148,51.8178389],[8.139526,51.8177889],[8.1393105,51.8176],[8.139143,51.817629],[8.1391276,51.8175908],[8.1373871,51.8179],[8.1371027,51.8179458],[8.1355949,51.8181889],[8.1353918,51.8182414],[8.1348347,51.8183922],[8.1342495,51.8185465],[8.1331107,51.818833]]}}, +{"type":"Feature","properties":{"betweenness":0.13333333333333333,"source":5416742037,"target":401335408,"ordering":5,"length":1369,"length_cumulative":7631},"geometry":{"type":"LineString","coordinates":[[8.1327449,51.8289726],[8.1326402,51.8289134],[8.1325877,51.8289163],[8.1318958,51.8289655],[8.1315935,51.8288962],[8.1312541,51.8288184],[8.1313915,51.8285141],[8.131423,51.828315],[8.1314027,51.8281112],[8.1313889,51.8280586],[8.1312342,51.827496],[8.1311896,51.8273079],[8.1311855,51.8272596],[8.1313421,51.8268639],[8.1313841,51.8268027],[8.1314149,51.8267664],[8.1314453,51.8267436],[8.1314711,51.8267296],[8.1314422,51.8267044],[8.131435,51.8266945],[8.1314401,51.826686],[8.1314944,51.826661],[8.1315687,51.8266353],[8.1316626,51.8266169],[8.1317355,51.8266128],[8.1319201,51.8266193],[8.1319361,51.8266177],[8.1319446,51.8266089],[8.1319494,51.8265912],[8.1319526,51.8265698],[8.1319569,51.826541],[8.1317761,51.8265195],[8.1315549,51.8265196],[8.1315505,51.8261902],[8.1315456,51.826132],[8.1315279,51.825615],[8.1315538,51.8248325],[8.1315499,51.8244874],[8.1315511,51.8244363],[8.1315485,51.8240641],[8.1315535,51.823607],[8.1315806,51.8227184],[8.1315947,51.8220483],[8.1315969,51.8215619],[8.1316015,51.8210047],[8.1316077,51.8206533],[8.1316369,51.8190348],[8.1316378,51.8189833],[8.1323047,51.8189958],[8.132563,51.8189696],[8.1331107,51.818833]]}}, +{"type":"Feature","properties":{"betweenness":0.066666666666666666,"source":2600979593,"target":9373476223,"ordering":6,"length":58,"length_cumulative":7690},"geometry":{"type":"LineString","coordinates":[[8.1445888,51.821036],[8.1446861,51.8210187],[8.1451551,51.8209575],[8.1453329,51.8209468],[8.1454173,51.8209226]]}} +] +} diff --git a/tests/test_data/oelde_seed_points.cpg b/tests/test_data/oelde_seed_points.cpg new file mode 100644 index 0000000..3ad133c --- /dev/null +++ b/tests/test_data/oelde_seed_points.cpg @@ -0,0 +1 @@ +UTF-8 \ No newline at end of file diff --git a/tests/test_data/oelde_seed_points.dbf b/tests/test_data/oelde_seed_points.dbf new file mode 100644 index 0000000..1072c00 Binary files /dev/null and b/tests/test_data/oelde_seed_points.dbf differ diff --git a/tests/test_data/oelde_seed_points.geojson b/tests/test_data/oelde_seed_points.geojson new file mode 100644 index 0000000..8c289c3 --- /dev/null +++ b/tests/test_data/oelde_seed_points.geojson @@ -0,0 +1,12 @@ +{ +"type": "FeatureCollection", +"name": "oelde_seed_points", +"features": [ +{ "type": "Feature", "properties": { "fid": 1 }, "geometry": { "type": "Point", "coordinates": [ 8.1529, 51.84924 ] } }, +{ "type": "Feature", "properties": { "fid": 2 }, "geometry": { "type": "Point", "coordinates": [ 8.1429, 51.82924 ] } }, +{ "type": "Feature", "properties": { "fid": 3 }, "geometry": { "type": "Point", "coordinates": [ 8.1329, 51.81924 ] } }, +{ "type": "Feature", "properties": { "fid": 4 }, "geometry": { "type": "Point", "coordinates": [ 8.1529, 51.81924 ] } }, +{ "type": "Feature", "properties": { "fid": 5 }, "geometry": { "type": "Point", "coordinates": [ 8.1429, 51.81924 ] } }, +{ "type": "Feature", "properties": { "fid": 6 }, "geometry": { "type": "Point", "coordinates": [ 8.1329, 51.82924 ] } } +] +} diff --git a/tests/test_data/oelde_seed_points.prj b/tests/test_data/oelde_seed_points.prj new file mode 100644 index 0000000..f45cbad --- /dev/null +++ b/tests/test_data/oelde_seed_points.prj @@ -0,0 +1 @@ +GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]] \ No newline at end of file diff --git a/tests/test_data/oelde_seed_points.qmd b/tests/test_data/oelde_seed_points.qmd new file mode 100644 index 0000000..773f4aa --- /dev/null +++ b/tests/test_data/oelde_seed_points.qmd @@ -0,0 +1,26 @@ + + + + + + dataset + + + + + + + + GEOGCRS["WGS 84",ENSEMBLE["World Geodetic System 1984 ensemble",MEMBER["World Geodetic System 1984 (Transit)"],MEMBER["World Geodetic System 1984 (G730)"],MEMBER["World Geodetic System 1984 (G873)"],MEMBER["World Geodetic System 1984 (G1150)"],MEMBER["World Geodetic System 1984 (G1674)"],MEMBER["World Geodetic System 1984 (G1762)"],ELLIPSOID["WGS 84",6378137,298.257223563,LENGTHUNIT["metre",1]],ENSEMBLEACCURACY[2.0]],PRIMEM["Greenwich",0,ANGLEUNIT["degree",0.0174532925199433]],CS[ellipsoidal,2],AXIS["geodetic latitude (Lat)",north,ORDER[1],ANGLEUNIT["degree",0.0174532925199433]],AXIS["geodetic longitude (Lon)",east,ORDER[2],ANGLEUNIT["degree",0.0174532925199433]],USAGE[SCOPE["Horizontal component of 3D system."],AREA["World."],BBOX[-90,-180,90,180]],ID["EPSG",4326]] + +proj=longlat +datum=WGS84 +no_defs + 3452 + 4326 + EPSG:4326 + WGS 84 + longlat + EPSG:7030 + true + + + + diff --git a/tests/test_data/oelde_seed_points.shp b/tests/test_data/oelde_seed_points.shp new file mode 100644 index 0000000..de54ad8 Binary files /dev/null and b/tests/test_data/oelde_seed_points.shp differ diff --git a/tests/test_data/oelde_seed_points.shx b/tests/test_data/oelde_seed_points.shx new file mode 100644 index 0000000..bbbbc63 Binary files /dev/null and b/tests/test_data/oelde_seed_points.shx differ diff --git a/tests/test_growbikenet.py b/tests/test_growbikenet.py index 12de877..197f690 100644 --- a/tests/test_growbikenet.py +++ b/tests/test_growbikenet.py @@ -12,6 +12,8 @@ # WORK LOCALLY BUT NOT THROUGH GITHUB # +# Test successes +# # @pytest.fixture # def validation_gdf_betweenness_grid_fromscratch(): # gdf = gpd.read_file(import_path+"badalona-growbikenet-betweenness-grid_square-from_scratch.geojson") @@ -112,6 +114,8 @@ +# Test fails + # def test_growbikenet_case_fail_rail1(): # """Verify that when there are too few rail stations (Oelde), a @@ -144,6 +148,54 @@ # ) +# Test import file formats geojson and shp (gpkg already tested above) + +@pytest.fixture +def validation_gdf_betweenness_file_fromscratch(): + gdf = gpd.read_file(import_path+"oelde-growbikenet-betweenness-file-from_scratch.geojson") + return gdf +def test_growbikenet_betweenness_file_geojson_fromscratch_success_offline(validation_gdf_betweenness_file_fromscratch): + """Verify that the offline version of growbikenet works as intended, with + geojson seed_points import. + betweenness, file, from scratch + """ + gbn.constants._CRS_CALCULATIONS = 'auto' + edges_ordered = gbn.growbikenet( + city_query="Oelde", + ordering="betweenness", + export_data=False, + import_files={ + 'growable_network': "oelde_growable_network.gpkg", + 'seed_points': "oelde_seed_points.geojson", + }, + ) + assert_frame_equal( + validation_gdf_betweenness_file_fromscratch[valcols], + edges_ordered[valcols], + check_dtype=False, + ) +def test_growbikenet_betweenness_file_shp_fromscratch_success_offline(validation_gdf_betweenness_file_fromscratch): + """Verify that the offline version of growbikenet works as intended, with + geojson seed_points import. + betweenness, file, from scratch + """ + gbn.constants._CRS_CALCULATIONS = 'auto' + edges_ordered = gbn.growbikenet( + city_query="Oelde", + ordering="betweenness", + export_data=False, + import_files={ + 'growable_network': "oelde_growable_network.gpkg", + 'seed_points': "oelde_seed_points.shp", + }, + ) + assert_frame_equal( + validation_gdf_betweenness_file_fromscratch[valcols], + edges_ordered[valcols], + check_dtype=False, + ) + + # Tests with settings