OpenStreetMap history — building footprints over time (ohsome)¶
This notebook teaches the ohsome half of the earthlens.osm backend: OSM is
history-aware, so you can ask what the map looked like at a point in time. We pull building
footprints for two yearly snapshots of the same area and compare them.
Like the Overpass path, ohsome returns a vector FeatureCollection (EPSG:4326) and emits the
ODbL LicenseWarning. Unlike Overpass, an ohsome query needs a time (start= / end=).
Setup¶
Imports and a small output directory. The same tiny Heidelberg bbox as the quickstart.
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)
LAT_LIM = [49.40, 49.42]
LON_LIM = [8.67, 8.71]
A single historical snapshot¶
ohsome:buildings returns building footprints as they existed at the start date. ohsome's
own columns ride along: @osmId (the element id) and @snapshotTimestamp (the snapshot
instant). Here we ask for the state on 1 January 2018.
buildings_2018 = EarthLens(
data_source='osm',
variables=['ohsome:buildings'],
lat_lim=LAT_LIM,
lon_lim=LON_LIM,
start='2018-01-01',
path=str(OUT_DIR),
).download()
len(buildings_2018), buildings_2018['@snapshotTimestamp'].iloc[0]
Map the 2018 footprints¶
The footprints are polygons; plot them filled.
ax = buildings_2018.plot(
facecolor='#9ecae1', edgecolor='#3182bd', linewidth=0.3, figsize=(7, 6)
)
ax.set_title(f'{len(buildings_2018)} building footprints — 2018-01-01 (ohsome)')
ax.set_xlabel('longitude')
ax.set_ylabel('latitude')
plt.show()
Compare two snapshots — how the map grew¶
Because ohsome is history-aware, the same query at a later date shows how mapping progressed. We pull the 2023 snapshot and compare the building counts — OSM coverage grows over time as contributors add detail.
buildings_2023 = EarthLens(
data_source='osm',
variables=['ohsome:buildings'],
lat_lim=LAT_LIM,
lon_lim=LON_LIM,
start='2023-01-01',
path=str(OUT_DIR),
).download()
counts = {'2018': len(buildings_2018), '2023': len(buildings_2023)}
counts
A quick bar chart makes the growth between the two snapshots legible.
fig, ax = plt.subplots(figsize=(4, 4))
ax.bar(list(counts), list(counts.values()), color=['#9ecae1', '#3182bd'])
ax.set_title('Mapped building footprints, same bbox')
ax.set_ylabel('feature count')
plt.show()
Raw ohsome filter (power users)¶
Pass your own ohsome filter via
filter= to query any tag combination — here, parks (leisure=park) as polygons at the
2023 snapshot.
parks = EarthLens(
data_source='osm',
variables=['ohsome:buildings'], # still required to route to ohsome
lat_lim=LAT_LIM,
lon_lim=LON_LIM,
start='2023-01-01',
filter='leisure=park and geometry:polygon',
path=str(OUT_DIR),
).download()
len(parks)
Takeaway¶
- ohsome adds a time axis to OSM: pass
start=(and optionallyend=) to get the map as it was, or a range. - The result carries
@osmId/@snapshotTimestampso you can track features across time. - A raw
filter=queries any tag combination; the ODbL obligation applies to ohsome data too.
See quickstart.ipynb for the current-state Overpass protocol.