import pandas as pd, geopandas as gpd
import movingpandas as mpd
@@ -318,99 +318,118 @@ notebook created by Anita Graser.
+
Parts of this section of the notebook have been readapted from this notebook created by Anita Graser.
8.1.1 Downaloding GPS traces from the OpenStreetMap
-def bbox_to_osm_format(bbox): ““” Convert bounding box coordinates to OSM API format.
-Parameters
-----------
-bbox: tuple
- A tuple containing the bounding box coordinates in the order (north, south, east, west).
-
-Returns
--------
-bbox_str: str
- A string representing the bounding box in the format "west,south,east,north".
-"""
-north, south, east, west = bbox
-bbox = f"{west},{south},{east},{north}"
-return bbox
We can try to get OSM traces around the Uni of Liverpool Campus. Feel free to change the area.
-
-import osmnx as ox
-# Define the place name
-= "University of Liverpool, UK"
- place_name
-# Get the latitude and longitude
-= ox.geocoder.geocode(place_name)
- latitude, longitude
-# Create the bbox
-= ox.utils_geo.bbox_from_point((latitude, longitude), dist = 1500)
- bbox = bbox_to_osm_format(bbox) # needs to be {west},{south},{east},{north} for OSM Api bbox
-
-The get_osm_traces
function below retrieves GPS traces from OpenStreetMap within a specified bounding box, processing up to a user-defined maximum number of pages. It uses a while loop to fetch and parse GPS data into GeoDataFrames, querying the OSM API by incrementally updating the page number until no more data is available or the maximum page limit is reached.
-Upon fetching the data, the function concatenates these individual GeoDataFrames into a single comprehensive GeoDataFrame. Before returning the final GeoDataFrame, it cleans the dataset by dropping a predefined list of potentially irrelevant or empty columns.
-
-def get_osm_traces(max_pages = 2, bbox='16.18, 48.09, 16.61, 48.32'):
+
+import osmnx as ox
+# Define the place name
+= "University of Liverpool, UK"
+ place_name
+# Get the latitude and longitude
+= ox.geocoder.geocode(place_name)
+ latitude, longitude
+# Create the bbox
+= ox.utils_geo.bbox_from_point((latitude, longitude), dist = 1500)
+ bbox bbox
+
+(53.420732655032396,
+ 53.39375304496761,
+ -2.9432044446907044,
+ -2.988462877347038)
+
+
+We need the bbox_to_osm_format
function below to convert our bounding box coordinates into the format required by the OpenStreetMap (OSM) API. The input tuple contains coordinates in the order (north, south, east, west). The function rearranges these values into the string “west,south,east,north”, which is the format expected by OSM for API queries.
+
+def bbox_to_osm_format(bbox):
"""
- Retrieve OpenStreetMap GPS traces within a specified bounding box.
+ Convert bounding box coordinates to OSM API format.
Parameters
----------
- max_pages: int, optional
- The maximum number of pages to retrieve. Defaults to 2.
- bbox: str, optional
- The bounding box coordinates in the format 'west, south, east, north'. Defaults to '16.18, 48.09, 16.61, 48.32'.
-
- Returns
- -------
- final_gdf: GeoDataFrame
- A GeoDataFrame containing the retrieved GPS traces.
- """
-
- = []
- all_data = 0
- page
- while (True) and (page <= max_pages):
- # Constructing the URL to query OpenStreetMap API for GPS trackpoints within a specified bounding box and page number
- = f'https://api.openstreetmap.org/api/0.6/trackpoints?bbox={bbox}&page={page}'
- url
- # Sending a GET request to the constructed URL
- = requests.get(url)
- response
- # Checking if the response status code is not 200 (indicating success) or if the response content is empty
- # If either condition is met, the loop breaks, indicating no more data to retrieve
- if response.status_code != 200 or not response.content:
- break
-
- # Reading the content of the response, which contains GPS trackpoints data, into a GeoDataFrame
- # The 'layer' parameter specifies the layer within the GeoDataFrame where trackpoints will be stored
- = gpd.read_file(BytesIO(response.content), layer='track_points')
- gdf
-if gdf.empty:
- break
-
-
- all_data.append(gdf)+= 1
- page
- # Concatenate all GeoDataFrames into one
- = gpd.GeoDataFrame(pd.concat(all_data, ignore_index=True))
- final_gdf
- # dropping empty columns
- = ['ele', 'course', 'speed', 'magvar', 'geoidheight', 'name', 'cmt', 'desc',
- columns_to_drop 'src', 'url', 'urlname', 'sym', 'type', 'fix', 'sat', 'hdop', 'vdop',
- 'pdop', 'ageofdgpsdata', 'dgpsid']
-
- = final_gdf.drop(columns=[col for col in columns_to_drop if col in final_gdf.columns])
- final_gdf return final_gdf
+ bbox: tuple
+ A tuple containing the bounding box coordinates in the order (north, south, east, west).
+
+ Returns
+ -------
+ bbox_str: str
+ A string representing the bounding box in the format "west,south,east,north".
+ """
+= bbox
+ north, south, east, west = f"{west},{south},{east},{north}"
+ bbox return bbox
+
+
+= bbox_to_osm_format(bbox) # needs to be {west},{south},{east},{north} for OSM Api
+ bbox bbox
+
+'-2.988462877347038,53.39375304496761,-2.9432044446907044,53.420732655032396'
+
+
+The get_osm_traces
function below retrieves GPS traces from OpenStreetMap within a specified bounding box, processing up to a user-defined maximum number of pages. It uses a while loop to fetch and parse GPS data into GeoDataFrames, querying the OSM API by incrementally updating the page number until no more data is available or the maximum page limit is reached.
+Upon fetching the data, the function concatenates these individual GeoDataFrames into a single comprehensive GeoDataFrame. Before returning the final GeoDataFrame, it cleans the dataset by dropping a predefined list of potentially irrelevant or empty columns.
+
+def get_osm_traces(max_pages = 2, bbox='16.18, 48.09, 16.61, 48.32'):
+"""
+ Retrieve OpenStreetMap GPS traces within a specified bounding box.
+
+ Parameters
+ ----------
+ max_pages: int, optional
+ The maximum number of pages to retrieve. Defaults to 2.
+ bbox: str, optional
+ The bounding box coordinates in the format 'west, south, east, north'. Defaults to '16.18, 48.09, 16.61, 48.32'.
+
+ Returns
+ -------
+ final_gdf: GeoDataFrame
+ A GeoDataFrame containing the retrieved GPS traces.
+ """
+
+ = []
+ all_data = 0
+ page
+ while (True) and (page <= max_pages):
+ # Constructing the URL to query OpenStreetMap API for GPS trackpoints within a specified bounding box and page number
+ = f'https://api.openstreetmap.org/api/0.6/trackpoints?bbox={bbox}&page={page}'
+ url
+ # Sending a GET request to the constructed URL
+ = requests.get(url)
+ response
+ # Checking if the response status code is not 200 (indicating success) or if the response content is empty
+ # If either condition is met, the loop breaks, indicating no more data to retrieve
+ if response.status_code != 200 or not response.content:
+ break
+
+ # Reading the content of the response, which contains GPS trackpoints data, into a GeoDataFrame
+ # The 'layer' parameter specifies the layer within the GeoDataFrame where trackpoints will be stored
+ = gpd.read_file(BytesIO(response.content), layer='track_points')
+ gdf
+if gdf.empty:
+ break
+
+
+ all_data.append(gdf)+= 1
+ page
+ # Concatenate all GeoDataFrames into one
+ = gpd.GeoDataFrame(pd.concat(all_data, ignore_index=True))
+ final_gdf
+ # dropping empty columns
+ = ['ele', 'course', 'speed', 'magvar', 'geoidheight', 'name', 'cmt', 'desc',
+ columns_to_drop 'src', 'url', 'urlname', 'sym', 'type', 'fix', 'sat', 'hdop', 'vdop',
+ 'pdop', 'ageofdgpsdata', 'dgpsid']
+
+ = final_gdf.drop(columns=[col for col in columns_to_drop if col in final_gdf.columns])
+ final_gdf return final_gdf
We initially download 2 pages of GSP traces. We can try with higher numbers to get more data. More recent traces are downloaded first.
-
-= 2 # pages of data,
- max_pages = get_osm_traces(max_pages, bbox) gps_track_points
+
+= 2 # pages of data,
+ max_pages = get_osm_traces(max_pages, bbox) gps_track_points
-
- gps_track_points.head()
+
+ gps_track_points.head()
@@ -473,12 +492,12 @@
-= 0.5) # still are trackpoints still gps_track_points.plot(markersize
+
+= 0.5) # still are trackpoints still gps_track_points.plot(markersize
@@ -489,16 +508,16 @@
-= mpd.TrajectoryCollection(gps_track_points, 'track_fid', t='time')
- osm_traces print(f'The OSM traces download contains {len(osm_traces)} tracks')
+
+= mpd.TrajectoryCollection(gps_track_points, 'track_fid', t='time')
+ osm_traces print(f'The OSM traces download contains {len(osm_traces)} tracks')
The OSM traces download contains 14 tracks
-
-for track in osm_traces:
-print(f'Track {track.id}: length={track.get_length(units="km"):.2f} km')
+
+for track in osm_traces:
+print(f'Track {track.id}: length={track.get_length(units="km"):.2f} km')
Track 0: length=9.96 km
Track 1: length=3.02 km
@@ -518,13 +537,13 @@
-from holoviews import opts, dim
-import hvplot.pandas
-
-= {'linewidth':5, 'capstyle':'round', 'figsize':(9,3), 'legend':True}
- plot_defaults =['wheel_zoom'], frame_width=500, frame_height=400))
- opts.defaults(opts.Overlay(active_tools= {'tiles':None, 'cmap':'Viridis', 'colorbar':True} hvplot_defaults
+
+from holoviews import opts, dim
+import hvplot.pandas
+
+= {'linewidth':5, 'capstyle':'round', 'figsize':(9,3), 'legend':True}
+ plot_defaults =['wheel_zoom'], frame_width=500, frame_height=400))
+ opts.defaults(opts.Overlay(active_tools= {'tiles':None, 'cmap':'Viridis', 'colorbar':True} hvplot_defaults