Calculating Centrality using the Export Endpoint¶
Complex network analysis, such as calculating different centrality measures, surpass the capabilites of the openrouteservice. There exist a lot of tools for network analyses that are much better suited for these tasks.
To support these kinds of analyses, the road network that the openrouteservice uses for route calculation can be exported. This training aims to show the usage of the openrouteservice /export
endpoint, how to parse the endpoints output into GeoJSON and how to import it into networkx for centrality analyses.
Setup¶
Load all necessary modules
import openrouteservice as ors
import geojson
import folium
import networkx as nx
from branca.colormap import linear
from folium import plugins
Visualization Utilities¶
We define a few utility functions to aid with visualization later.
from math import atan2, pi
def calcRotation(line_points):
fromCoord = line_points[0]
toCoord = line_points[1]
dx = fromCoord[0] - toCoord[0]
dy = fromCoord[1] - toCoord[1]
# calculate angle to draw arrow
rot = atan2(dx, dy) * 180 / pi
return 180 - rot
def calcLocation(line_points):
fromCoord = line_points[0]
toCoord = line_points[1]
dx = toCoord[0] - fromCoord[0]
dy = toCoord[1] - fromCoord[1]
return [toCoord[0] - 0.05*dx, toCoord[1] - 0.05*dy]
Set up openrouteservice¶
Make sure that you have a personal key for the public openrouteservice API. Insert your API key below.
api_key = '5b3ce3597851110001cf6248fc20d2ec7ea24e968d74e1bab4bfbe46'
Create a ORS client which will be used to send request to the API.
ors_client = ors.Client(key=api_key)
Export Endpoint - Parse Results to GeoJSON¶
Define a bounding box in the format [[lon_min, lat_min],[lon_max, lat_max]]
for which you want to export data, as well as the profile that you want to export the graph for.
In this example, we'll use the driving-car
profile and focus on Heidelberg, Germany.
profile = "driving-car"
#bbox = [[8.677139,49.412872],[8.690443,49.421080]] # Neuenheim
#bbox = [[8.655967,49.382834],[8.718537,49.435273]] # Heidelberg
bbox = [[8.668069,49.398477],[8.697079,49.426174]] # Neuenheim + Bergheim + Weststadt
The export endpoint has not been included into the openrouteservice-py module yet, but it includes the request()
method to direct requests to any url. We can use this to request from the /export
-endpoint.
resp = ors_client.request(url = f'/v2/export/{profile}', get_params = {}, post_json = {'bbox': bbox})
The output format is defined in our backend documentation We will first transform our response into a GeoJSON that can then be visualized and exported.
# parse all nodes into Points, add ID to feature, add to FeatureCollection
points = {}
node_list = []
for node in resp['nodes']:
point = geojson.Point(node['location'])
points[node['nodeId']] = point
feature = geojson.Feature(geometry=point, properties={"ID": node['nodeId']})
node_list.append(feature)
node_collection = geojson.FeatureCollection(node_list)
# parse all edges into LineString, add weight to Feature, add to FeatureCollection
edge_list = []
for edge in resp['edges']:
line = geojson.LineString((points[edge['fromId']], points[edge['toId']]))
feature = geojson.Feature(geometry=line, properties={"weight": edge['weight'], "direction": f"{edge["fromId"]} -> {edge["toId"]}"})
edge_list.append(feature)
edge_collection = geojson.FeatureCollection(edge_list)
We now have two FeatureCollections that we could export or visualize rather easily.
Note, that there is quite a bit of data that is getting extracted, so the nodes have been disabled by default to not crowd the view. You can enable them by clicking the layer control in the top right.
geoJSONMap = folium.Map(location = [49.411085, 8.685894], zoom_start = 13)
folium.GeoJson(edge_collection, name="Edges", tooltip=folium.GeoJsonTooltip(fields=['weight', 'direction'])).add_to(geoJSONMap)
layer = folium.GeoJson(node_collection, name="Nodes", marker=folium.CircleMarker(radius = 5, color="black", weight=3), tooltip=folium.GeoJsonTooltip(fields=['ID']), show=False).add_to(geoJSONMap)
# Set the view to view everything
geoJSONMap.fit_bounds(layer.get_bounds())
folium.LayerControl().add_to(geoJSONMap)
geoJSONMap