OpenStreetMap quickstart — current-state features (Overpass)¶
This notebook teaches the Overpass half of the earthlens.osm backend: how to pull
current-state OpenStreetMap features for a small area and work with the result. By the
end you will be able to run a named query, read the returned
FeatureCollection, and map it.
earthlens.osm is a vector backend: download() returns a pyramids FeatureCollection
(a geopandas.GeoDataFrame subclass, CRS EPSG:4326) and also writes one file. OSM data is
ODbL (share-alike), so every download emits a LicenseWarning — credit
'© OpenStreetMap contributors' when you redistribute.
Setup¶
The imports for the whole notebook. EarthLens is the unified entry point; matplotlib
draws the maps. We also pick a small output directory — keep OSM bboxes small, the public
Overpass service is shared infrastructure.
import time
from pathlib import Path
import matplotlib.pyplot as plt
from earthlens.core import EarthLens
OUT_DIR = Path('osm_output')
OUT_DIR.mkdir(exist_ok=True)
!!! note
The public Overpass API allows only 2 concurrent slots per client. This notebook runs
several queries, so we pause briefly (time.sleep) between them to stay a good citizen of
the shared service — bursting would earn an HTTP 429.
The area of interest¶
A tiny bounding box over central Heidelberg, Germany — dense, well-mapped OSM coverage so the
queries return features quickly. The box is lat_lim / lon_lim in degrees (WGS84).
| argument | meaning | value here |
|---|---|---|
lat_lim |
[south, north] |
[49.40, 49.42] |
lon_lim |
[west, east] |
[8.67, 8.71] |
LAT_LIM = [49.40, 49.42]
LON_LIM = [8.67, 8.71]
Quickstart — hospitals as a FeatureCollection¶
The shortest end-to-end example: pick the overpass:hospitals named query via
variables=, give it the bbox, and download(). The backend builds the Overpass QL, runs
the live query, and returns the features. (The LicenseWarning you see is the ODbL notice —
expected on every result.)
hospitals = EarthLens(
data_source='osm',
variables=['overpass:hospitals'],
lat_lim=LAT_LIM,
lon_lim=LON_LIM,
path=str(OUT_DIR),
).download()
len(hospitals), type(hospitals).__name__
Each row is one OSM element. The osm_id / osm_type columns identify it, the element's OSM
tags ride as their own columns, and geometry is a shapely Point (a node) or Polygon (a
building footprint). Let's peek at a few identifying columns.
cols = [
c
for c in ['osm_id', 'osm_type', 'amenity', 'name', 'geometry']
if c in hospitals.columns
]
hospitals[cols].head()
Map the result¶
A FeatureCollection is a GeoDataFrame, so .plot() maps it directly. Point and polygon
hospitals are coloured by their geometry type.
ax = hospitals.plot(
column='osm_type',
categorical=True,
legend=True,
markersize=40,
alpha=0.8,
figsize=(7, 6),
)
ax.set_title('Hospitals in central Heidelberg (OSM via Overpass)')
ax.set_xlabel('longitude')
ax.set_ylabel('latitude')
plt.show()
Another named query — the road network¶
overpass:roads returns every highway way as a LineString. The named queries are listed
by EarthLens.list_datasets('osm'); the <protocol>: prefix selects Overpass vs ohsome.
EarthLens.list_datasets('osm')
time.sleep(12) # let the Overpass slots recover before the next query
roads = EarthLens(
data_source='osm',
variables=['overpass:roads'],
lat_lim=LAT_LIM,
lon_lim=LON_LIM,
path=str(OUT_DIR),
).download()
ax = roads.plot(linewidth=0.6, color='#444', figsize=(7, 6))
ax.set_title(f'{len(roads)} road segments (overpass:roads)')
ax.set_xlabel('longitude')
ax.set_ylabel('latitude')
plt.show()
Raw Overpass QL (power users)¶
When the named queries aren't enough, pass your own Overpass QL via query=. A {bbox}
placeholder is filled with the request bbox; the query must request JSON output
([out:json]). Here we fetch museums (tourism=museum).
time.sleep(12) # be gentle with the shared Overpass service
museums = EarthLens(
data_source='osm',
variables=['overpass:hospitals'], # still required to route to Overpass
lat_lim=LAT_LIM,
lon_lim=LON_LIM,
query='[out:json][timeout:180];(node["tourism"="museum"]({bbox}););out geom;',
path=str(OUT_DIR),
).download()
museums[[c for c in ['osm_id', 'name', 'geometry'] if c in museums.columns]].head()
Takeaway¶
EarthLens('osm', variables=['overpass:<query>'], lat_lim=…, lon_lim=…).download()returns aFeatureCollectionof current-state OSM features.- Named queries cover the common cases; a raw
query=(JSON output) is the escape hatch. - Keep the bbox small, and honour the ODbL attribution / share-alike obligation.
Next: ohsome_history.ipynb shows the history-aware ohsome protocol.