Tile pyramids (nbtiles)¶
Pre-tiled, multi-resolution geospatial data — MBTiles, XYZ tile
directories, vector tiles. The native representation is a tile-pyramid
descriptor object the user opens to fetch tiles by (z, x, y); the
underlying I/O is store-based (a SQLite file, a directory, or an
HTTP endpoint), not a single byte stream.
- AssetKind:
AssetKind.TILES - Payload: tile-pyramid descriptor object (format-specific)
- Typed accessor:
Asset.as_tiles() -> Any - Handler protocol:
StoreFormatHandler(always store-based) - Status: Asset envelope and
StoreFormatHandlerprotocol ready; MBTiles and XYZ handlers are on the roadmap.
What's in place today¶
AssetKind.TILESis a first-class kind in the envelope.Asset.as_tiles()returns the payload and raisesIncompatibleAssetKindErroron kind mismatch.Asset.crsis a convenience accessor overextras["crs"].StoreFormatHandlerprotocol exists insunstone.resource, alongsideResourceLocationfor describing where the tile store lives (path, S3 bucket, HTTP base).datasets.yaml'sformatfield is the primary dispatch signal, soformat: mbtilesselects the MBTiles handler explicitly regardless of file extension.
What's coming¶
The two canonical handlers are:
- MBTiles — single SQLite file with random tile access. The
handler opens the file, exposes a tile-fetch callable, and
round-trips zoom range and CRS through
extras. - XYZ — directory tree of
{z}/{x}/{y}.png(or.pbf) tiles. The handler enumerates available zoom levels and resolves individual tiles by coordinate.
Vector tile formats (Mapbox Vector Tiles via pbf) layer on top of
either store.
Reading a tile pyramid (planned API)¶
import sunstone as ss
asset = ss.read("inputs/basemap.mbtiles")
assert asset.kind is ss.AssetKind.TILES
tiles = asset.as_tiles()
tile = tiles.fetch(z=10, x=523, y=400) # bytes / decoded image
The descriptor object opens the store lazily, so reading the asset does not pull all tiles into memory.
Writing tiles¶
Tile pyramids are usually written by an external rendering pipeline
(gdal2tiles, tippecanoe, custom render jobs). The sunstone-py
handler's job is to wrap that output, record its location in
datasets.yaml, and propagate lineage from the source rasters or
vectors.
child = source_raster.derive(
tile_pyramid_descriptor,
slug="basemap-2024",
name="Basemap tiles, 2024",
kind=ss.AssetKind.TILES,
extras_updates={"zoom_min": 0, "zoom_max": 14, "crs": "EPSG:3857"},
)
ss.write(child, "outputs/basemap.mbtiles")
derive() collapses the in-memory tile pyramid through to provenance
metadata; the actual tile bytes are typically already written by the
renderer and the handler just records the manifest.
Extras¶
Tile assets typically carry:
| key | type | purpose |
|---|---|---|
zoom_min |
int |
Lowest zoom level available in the pyramid |
zoom_max |
int |
Highest zoom level available |
crs |
str |
Coordinate reference system (typically EPSG:3857 for web tiles) |
bounds |
tuple | (minx, miny, maxx, maxy) covered by the pyramid |
tile_format |
str |
"png", "jpg", "webp", "pbf" |
Layers as components¶
A vector tile pyramid often carries multiple layers (roads, water,
buildings). Each layer is a ComponentSchema entry with
component_kind="layer", mirroring the way raster bands and tabular
columns are described. Discovery code can list a tile asset's layers
without knowing the tile format.
Design reference¶
See the
design spec
for the StoreFormatHandler contract and the ResourceLocation
dataclass, and the
open-decisions log
for the format-vs-extension dispatch rationale.
See also¶
- Images — single-payload rasters (the input to a tile renderer)
- tensors — n-D variable arrays
- API Reference