-
Notifications
You must be signed in to change notification settings - Fork 2
OsmGT Wiki
OsmGt is a geospatial python library to help you to play with OpenStreetMap (OSM) roads data and to do network analysis with Graph-tool.
This library offers some main features :
- get roads data into a Geodataframe (GeoPandas) : vehicle or pedestrian paths [more coming soon]
- generate a graph-tool graph linked to the roads GeoDataframe (topolygy checking and fixing)
- add new nodes on the network to extend you network analysis
Additional features about OpenStreetMap data are available
- get OSM points of interest
Also, OsmGt can be a tool to do some common network analysis:
- (a lot of ) shortest paths
- isochrones based on time and distance
Of course you can use the geodataframe and the graph without this functions according to your specific requirements.
Don"t forge to check these examples on this Jupyter Notebook
conda install -c amauryval osmgt
Before to present code lines, we have to present you some prerequisites informations about functions arguments.
You can load/compute data from:
- a location name (ex: Lyon) ; a Nominatim api call is done to catch the boundaries of the input location name area
- a bounding box (min_x=-74.018433, min_y=40.718087, max_x=-73.982749, max_y=40.733356)
You can load a specific network based on the transport mode (from Overpass Turbo query):
- vehicle mode: will create a directed graph, because direction are important
- pedestrian mode (freeway are not load here for example): will create an undirected graph
- more will comming soon...
2 methods are available.
- Get roads network from a location name :
from osmgt import OsmGt
roads_osmgt_initialized = OsmGt.roads_from_location(
location_name="Lyon",
mode="vehicle", # or "pedestrian"
additional_nodes=my_additional_nodes_gdf # eat a GeoDataframe [optional]
)
# You can get the GeoDataframe
roads_gdf = roads_osmgt_initialized.get_gdf()
# You can get the graph-tool graph based on the roads gdf built
roads_graph = roads_osmgt_initialized.get_graph()
As you can see add additionals nodes on your next network:
- with a nodes Geodataframe (attributes are preserved)
- Get roads network from a bounding box:
from osmgt import OsmGt
roads_osmgt_initialized = OsmGt.roads_from_bbox(
bbox_values=(min_x=-74.018433, min_y=40.718087, max_x=-73.982749, max_y=40.733356),
mode="vehicle", # or "pedestrian"
additional_nodes=my_additional_nodes_gdf # eat a GeoDataframe [optional]
)
# You can get a roads GeoDataframe
roads_gdf = roads_osmgt_initialized.get_gdf()
# the topology processing generate a column named "topo_uuid" used as unique id for each features, because the network has been fixing (intersection, connection...)
# OSM attributes are present, especially the OSM ID named "id" (not unique after processing)
# You can get the graph-tool graph based on the roads GeoDataframe built above
roads_graph = roads_osmgt_initialized.get_graph()
Of course you are free to use the graph-tool library !
Roads Geodataframe returns all the existing OSM attributes. Also OsmGt creates some news fields :
- topo_uuid: unique id created during the topology fixing ;
- topology: value indicates the topology fix applied (split, added or unchanged) ;
- osm_url: OSM url to the original object (based on the OSM id: 'id' column).
2 methods are available.
- Get POIs from a location name:
from osmgt import OsmGt
pois_initialized = OsmGt.pois_from_location(
location_name="Lyon"
)
pois_gdf = pois_initialized .get_gdf()
- Get POIs from a bounding box:
from osmgt import OsmGt
pois_initialized = OsmGt.pois_from_bbox(
bbox_values=(min_x=-74.018433, min_y=40.718087, max_x=-73.982749, max_y=40.733356),
)
pois_gdf = pois_initialized .get_gdf()
Now we can use the GeoDataframe output as argument on the OsmGt.roads_from_bbox() method to add all the POIs found on the roads network !
POIs Geodataframe returns all the existing OSM attributes. Also OsmGt creates some news fields :
- topo_uuid: unique id created during the topology fixing ;
- osm_url: OSM url to the original object (based on the OSM id: 'id' column).
For roads and POIs, you can get the shapely geometry study area (Polygon) of your loaded data:
roads_study_area_geom = roads_osmgt_initialized.study_area
pois_study_area_geom = pois_initialized.study_area
You can analyse the topology of the output data
roads_topology_gdfs = roads_osmgt_initialized.topology_checker()
You can visualize the graph build and export it to a image
roads_graph = roads_osmgt_initialized.get_graph()
roads_graph.plot()
Now you have load some data. So we can play with the graph-tool library, compute some network analysis.
We are starting with this:
from osmgt import OsmGt
bbox_area = (74.018433, 40.718087, -73.982749, 40.733356)
pois_gdf = OsmGt.pois_from_bbox(
bbox_values=bbox_area
)
roads_osmgt_initialized = OsmGt.roads_from_bbox(
bbox_values=bbox_area,
mode="vehicle",
additional_nodes=pois_gdf
)
# You have a roads GeoDataframe
roads_gdf = roads_osmgt_initialized.get_gdf()
# You have a graph-tool graph based on the roads GeoDataframe built above
roads_graph = roads_osmgt_initialized.get_graph()
Be careful: if you apply some geometry changes on the output roads Geodataframe, the roads graph generated won't match anymore, because the link between them is based on the node wkt geometry value :
- graph is build with the start and end geom wkt nodes of each road lines
- graph edge are based on the "topo_uuid" linestring value
- graph edge weigth based on the line length
That's why the graph-tool graph have some specified methods to link the roads GeoDataframe:
roads_graph = roads_osmgt_initialized.get_graph()
# find a specific vertex based on the name (means geom wkt)
a_vertex = roads_graph.find_vertex_from_name("POINT (1 0)") # vertex (or node)
an_edge = roads_graph.find_edge_from_name("10_0") # edge (meaning linestring on the GeoDataframe)
# find a specific edge/vertex based on a graph-tool edge/vertex
an_edge = roads_graph.edge_names[a_graph_tool_edge]
a_vertex = roads_graphaph.vertex_names[a_graph_tool_vertex]
So if you are doing a shortest path computing, you can match the shortest path graph-tool output with your GeoDataframe with these methods. You can find an example here at this topic ; but OsmGt can help you to do some network analysis!
You can find some examples from here
OsmGt have other method to help you to do some network analysis:
- shortest paths ;
- isochrones.
2 methods are available:
- Find some shortest paths from a location name
from osmgt import OsmGt
shortest_paths_gdf = OsmGt.shortest_path_from_location(
location_name="Lyon",
source_target_points=source_targets_pairs, # a list of tuples containing a source and target shapely Point,
mode="pedestrian", # or "vehicle"
)
- Find some shortest paths from a bounding box
from osmgt import OsmGt
shortest_paths_gdf = OsmGt.shortest_path_from_bbox(
bbox_values=(74.018433, 40.718087, -73.982749, 40.733356),
source_target_points=source_targets_pairs, # a list of tuples containing a source and target shapely Point,
mode="pedestrian", # or "vehicle"
)
Each function returns 1 GeoDataframe containing all the shortest paths computed
You can find these attributes :
- source_node: the geom wkt of the source node ;
- target_node: the geom wkt of the target node ;.
- osm_ids: the list of the OSM id used by the shortest path computed ;
- osm_urls: the list of the OSM url of each path feature (based on the OSM id).
2 methods are available:
- create isochrone based on times
from osmgt import OsmGt
isochrones_polygons_gdf, isochrones_lines_gdf = OsmGt.isochrone_from_coordinates(
source_node=source_point, # a shapely Point
isochrones_times=[2, 5, 10], # in minutes, so we'll create 3 isochrones based on time
trip_speed=3, # km/h
mode="pedestrian", # or "vehicle"
)
- create isochrone based on distances
from osmgt import OsmGt
isochrones_polygons_gdf, isochrones_lines_gdf = isochrone_distance_from_coordinates(
source_node=source_point, # a shapely Point
distances=[100, 1000], # in meters, so we'll create 2 isochrones based on distance
trip_speed=3, # km/h
mode="pedestrian", # or "vehicle"
)
Each function returns 2 GeoDataframe containing:
- isochrones polygons
- roads network concerned and tagged by each isochrone
- Isochrones based on times (minutes)
Mode : pedestrian :
- Isochrones based on distances (meters)
Mode : pedestrian :
And if you want to use an other mode (here vehicle) :
About isochrones polygons attributes:
- iso_name: the name of the isochrone based on the time (in minutes) ;
- iso_distance: the distance of the isochrone (in meters).
About isochrones lines attributes:
- OSM attributes
- topo_uuid: unique id created during the topology fixing ;
- topology: value indicates the topology fix applied (split, added or unchanged) ;
- osm_url: OSM url to the original object (based on the OSM id: 'id' column).
- iso_name: the name of the isochrone based on the time (in minutes) ;
- iso_distance: the distance of the isochrone (in meters).
I recommend to use both (roads and isochrones polygons) outputs for interpreting the results, roads iso attributes are precise. After a very detailed analysis, you can notice some slight "error" between roads and polygons. It's caused by the tolerance value used to build polygon isochrones, so data interpretation can be difficult.
Some higher isochrones "eat" lower isochrone:
Some isochrones areas can be ambiguous :
OsmGt isochrones results can be used to have a broad view of the accessibility, so take care if you want to use them to make some spatial analysis
Also, isochrones polygons output need some improvements in order to fill some interiors polygons which are not consistent with theirs neighbors isochrones (fix is on going).