Reference basemaps — coastlines, borders & relief¶
cleopatra.reference draws fixed public cartographic reference data under your own
plot — the cartopy ax.coastlines() / GeoAxes.stock_img() niche, and the vector/raster
sibling of cleopatra.tiles.
add_features— a Natural Earth vector layer:coastline,borders,land,ocean,rivers,lakes(across110m/50m/10m).add_relief— a global hypsometric relief backdrop (low/medium).natural_earth/relief— raw-data accessors (no drawing).
The data is fetched once from a cleopatra release and cached under ~/.cleopatra/naturalearth.
add_relief and crs= reprojection need the cleopatra[tiles] extra (Pillow / pyproj);
drawing vector layers in EPSG:4326 needs only numpy + matplotlib.
Two ways to call. Use the standalone add_* functions on any matplotlib axes (shown
throughout below), or call them straight from a geographic glyph (ArrayGlyph, MeshGlyph,
VectorGlyph, FlowGlyph, PolygonGlyph, ScatterGlyph), which inherit GeoMixin and draw
on the glyph's own axes.
Lon/lat maps set
ax.set_aspect("equal")so 1° longitude and 1° latitude render at the same scale (otherwise the defaultaspect="auto"stretches the map to fill the figure).
The drawing cells below are tagged
nbval-skipbecause they fetch data over the network and use the optional[tiles]extra; their saved outputs are shown in the rendered docs.
%matplotlib inline
import matplotlib.pyplot as plt
from cleopatra.reference import (
add_features,
add_relief,
available_layers,
available_relief_resolutions,
available_resolutions,
natural_earth,
relief,
)
print("layers: ", available_layers())
print("vector resolutions:", available_resolutions())
print("relief resolutions:", available_relief_resolutions())
layers: ['coastline', 'land', 'ocean', 'rivers', 'lakes', 'borders'] vector resolutions: ['110m', '50m', '10m'] relief resolutions: ['low', 'medium']
Calling from a glyph (GeoMixin)¶
Geographic glyphs inherit cleopatra.geo.GeoMixin, so add_tiles, add_features, and
add_relief are available as methods — no separate import, and they draw on the glyph's own
axes. Plot the glyph first, then add the basemap. The standalone functions used in the rest
of this notebook are equivalent and also work on a plain axes.
import numpy as np
from cleopatra.scatter_glyph import ScatterGlyph
# A few cities as (lon, lat) points.
lon = np.array([-74.0, -0.1, 2.35, 13.4, 37.6, 139.7, 151.2])
lat = np.array([40.7, 51.5, 48.9, 52.5, 55.8, 35.7, -33.9])
glyph = ScatterGlyph(lon, lat, values=np.arange(len(lon)))
glyph.plot()
glyph.add_features("coastline", "110m", colors="0.3", linewidths=0.6) # from the glyph
glyph.add_features("borders", "110m", colors="0.6", linewidths=0.4)
glyph.ax.set_aspect("equal") # 1 deg lon == 1 deg lat, so the map is not stretched
glyph.ax.set_title("ScatterGlyph + glyph.add_features (GeoMixin)")
Text(0.5, 1.0, 'ScatterGlyph + glyph.add_features (GeoMixin)')
A relief backdrop¶
add_relief places a global hypsometric image behind your data. Plot your data first — the
helper reads the current axis limits and preserves them.
fig, ax = plt.subplots(figsize=(9, 4.5))
ax.set_xlim(-180, 180)
ax.set_ylim(-90, 90)
ax.set_aspect("equal")
add_relief(ax, resolution="low")
ax.set_title("Global hypsometric relief — add_relief")
plt.show()
Vector line layers — coastline & borders¶
Line layers (coastline, rivers, borders) render as a LineCollection. Style them with
colors / linewidths.
fig, ax = plt.subplots(figsize=(9, 4.5))
ax.set_xlim(-180, 180)
ax.set_ylim(-90, 90)
ax.set_aspect("equal")
add_features(ax, "coastline", "110m", colors="black", linewidths=0.6)
add_features(ax, "borders", "110m", colors="0.5", linewidths=0.5)
ax.set_title("Coastline + country borders — add_features")
plt.show()
Filled polygon layers (holes handled)¶
Polygon layers (land, ocean, lakes) render as a filled PathCollection. Interior rings
are cut out correctly, so ocean shows the continents as holes rather than flooding the map.
Style with facecolors / edgecolors / linewidths.
fig, ax = plt.subplots(figsize=(7, 6))
ax.set_xlim(-25, 45)
ax.set_ylim(30, 72)
ax.set_aspect("equal")
add_features(ax, "ocean", "50m", facecolors="#a6cee3")
add_features(ax, "land", "50m", facecolors="#f4f1de", edgecolors="0.5", linewidths=0.4)
add_features(ax, "coastline", "50m", colors="navy", linewidths=0.7)
add_features(ax, "borders", "50m", colors="0.4", linewidths=0.5)
ax.set_title("Europe — filled land/ocean + coastline + borders")
plt.show()
Relief + features together¶
Layer vectors over the relief backdrop. add_relief defaults to zorder=-1 so it sits behind
everything; add_features defaults to zorder=0.
fig, ax = plt.subplots(figsize=(9, 4.5))
ax.set_xlim(-180, 180)
ax.set_ylim(-90, 90)
ax.set_aspect("equal")
add_relief(ax, "low")
add_features(ax, "coastline", "110m", colors="black", linewidths=0.5)
add_features(ax, "borders", "110m", colors="0.3", linewidths=0.4)
ax.set_title("Relief backdrop with coastline + borders")
plt.show()
Reprojection with crs=¶
The source data is EPSG:4326. If your axes are in another CRS, pass crs= and the geometry is
reprojected to match (requires pyproj). Vertices that fall on a projection singularity (the
poles in Web Mercator) are dropped automatically. Projected coordinates are metres, so equal
aspect keeps the shapes true.
fig, ax = plt.subplots(figsize=(6, 6))
ax.set_xlim(-2.0e6, 5.0e6) # Web Mercator metres over Europe
ax.set_ylim(4.0e6, 1.1e7)
ax.set_aspect("equal")
add_features(ax, "land", "50m", crs=3857, facecolors="0.9", edgecolors="0.5", linewidths=0.4)
add_features(ax, "coastline", "50m", crs=3857, colors="navy", linewidths=0.7)
ax.set_title("Reprojected to Web Mercator (EPSG:3857)")
plt.show()
Raw data accessors¶
Need the geometry/array without drawing? natural_earth returns a list of (N, 2) lon/lat
arrays, and relief returns an (H, W, 3) uint8 RGB array.
coast = natural_earth("coastline", "110m")
print("coastline parts:", len(coast), "| first part shape:", coast[0].shape)
rgb = relief("low")
print("relief array:", rgb.shape, rgb.dtype)
coastline parts: 134 | first part shape: (11, 2) relief array: (360, 720, 3) uint8
Caching & dependencies¶
- First call downloads the asset from the cleopatra
basemap-data-v1release and caches it under~/.cleopatra/naturalearth; later calls work offline. Override the location with theCLEOPATRA_CACHE_DIRenvironment variable. add_featuresin EPSG:4326 needs only numpy + matplotlib.add_relief(Pillow) andcrs=reprojection (pyproj) need thecleopatra[tiles]extra:pip install "cleopatra[tiles]".- List valid arguments with
available_layers(),available_resolutions(), andavailable_relief_resolutions().