Skip to main content

Raster

VizX Overview · Multi-Layer Compositor · PMTiles Viewers

Raster rendering

Both plotters auto-decimate rasters larger than max_pixels on either axis, and apply a per-band 2nd–98th percentile stretch to integer rasters whose values exceed 255 (typical for EO data — Sentinel-2 UInt16 reflectance, Landsat, etc.) so the visible range isn't clipped. NoData is honored (masked) and excluded from the stretch statistics.

The composite parameter controls how bands are combined into a single image:

composite valueBehaviour
"auto" (default)1 band → viridis colormap; 3+ bands → RGB composite
"depth"Per-pixel count of bands covering each pixel, rendered as a viridis gradient; pixels covered by no band are transparent

composite="depth" is intended for multi-band presence-mask stacks (e.g. rasterized H3 cells from several thresholds) where an RGB composite would appear mostly black. For single-band constant-value masks — such as a solid coverage footprint — composite="auto" renders the footprint as a solid viridis tone over a light-grey background rather than a blank plot.

plot_raster

plot_raster(raster_bytes, *, fig_w=10, fig_h=10, max_pixels=2000, composite="auto")

Render a raster from its in-memory bytes — e.g. a tile's raster field collected from a GeoBrix DataFrame:

from databricks.labs.gbx.vizx import plot_raster

row = df.select("tile").first()
plot_raster(row["tile"]["raster"])

# For a multi-band presence-mask stack, show how many bands cover each pixel:
plot_raster(row["tile"]["raster"], composite="depth")

plot_file

plot_file(path, *, fig_w=10, fig_h=10, max_pixels=2000, composite="auto")

Render a raster from disk (GeoTIFF, VRT, …) with the same decimation + stretch pipeline. A leading dbfs: or file: scheme is stripped automatically, so scheme-qualified Databricks paths (dbfs:/Volumes/…, file:///Volumes/…) work as well as the bare FUSE path:

from databricks.labs.gbx.vizx import plot_file

plot_file("/Volumes/main/geobrix_samples/geobrix-examples/nyc/dem.tif")

# Coverage-depth view of a multi-band stack on disk:
plot_file("/Volumes/main/my_schema/my_vol/sentinel_stack.tif", composite="depth")

plot_mosaic

plot_mosaic(vrt, *, bbox=None, bbox_crs=None, max_pixels=2000, resampling="bilinear",
show_cells=False, fig_w=10, fig_h=10, composite="auto", bands=None,
stretch="perband", fill=None, emphasis="blend", debug_mode=1) -> None

Render a VRT mini-COG mosaic (produced by the cog_gbx writer with vrtMosaic=true) as a single georeferenced image. vrt may be a path to a .vrt file or a directory containing exactly one .vrt — the directory form is the natural result of a cog_gbx write. All remaining parameters (composite, bands, stretch, fill, emphasis) behave identically to plot_raster and plot_file. Returns None.

max_pixels is a read ceiling, not an upsampling floor

GDAL selects each member's internal overview tier (or block-streams a single decimated read of the base level) so that the decoded pixel count never exceeds max_pixels on either axis. This bounds peak RAM to max_pixels² regardless of mosaic size — a 10,000-cell mosaic costs no more memory than a 4-cell one. It never upsamples: zooming into a viewport backed by an 800-pixel COG yields at most 800 real pixels even with max_pixels=2000. An overview-free COG (e.g. written by the DGGS writer without --overviews) still renders via on-the-fly decimation — you always get something, never a blank plot.

bbox and bbox_crs — pass an optional (minx, miny, maxx, maxy) viewport to zoom into a sub-region. Coordinates are interpreted in bbox_crs if supplied, or in the mosaic's own CRS otherwise. bbox_crs accepts any CRS form recognised by GeoBrix: an integer SRID (4326), an authority string ("EPSG:4326", "ESRI:54008"), a WKT string, or a PROJ4 string. A ValueError is raised if the bbox does not intersect the mosaic.

show_cells — h3 mosaics only: set show_cells=True to overlay the hex-cell boundary of each member tile as a white outline. Raises ValueError for non-h3 mosaics (gridSystem != "h3").

from databricks.labs.gbx.vizx import plot_mosaic

# Render a full h3 mosaic from its output directory.
# The directory contains mosaic.vrt and the per-cell mini-COGs.
plot_mosaic(
"/Volumes/main/geobrix_samples/my_schema/h3_mosaic/",
show_cells=True,
max_pixels=1024,
)

# Viewport zoom: show only the Manhattan area using WGS84 bbox.
plot_mosaic(
"/Volumes/main/geobrix_samples/my_schema/h3_mosaic/mosaic.vrt",
bbox=(-74.02, 40.70, -73.93, 40.78),
bbox_crs="EPSG:4326",
max_pixels=2000,
)

plot_mask_layers

plot_mask_layers(layers, *, fig_w=10, fig_h=8, max_pixels=2000, colors=None, title="coverage layers")

Overlay several single-band presence-mask tiles on one axes, each drawn as a solid colour with a legend. Useful for multi-threshold coverage views — for example, showing which H3 cells contain data at each of several observation-count thresholds.

Parameters:

ParameterTypeDefaultDescription
layerslist[tuple[str, bytes]]List of (label, raster_bytes) pairs. Each raster must be a single-band presence mask.
fig_wfloat10Figure width in inches.
fig_hfloat8Figure height in inches.
max_pixelsint2000Decimate above this longest-edge pixel count before rendering.
colorslist or NoneNoneMatplotlib color values, one per layer. Defaults to the tab10 qualitative cycle.
titlestr"coverage layers"Axes title.

All tiles must share the same grid and extent — for example, produced on a shared canvas via rst_h3_gridspec. Layers are drawn in order: pass the largest footprint first and the smallest last so nested coverage remains visible.

from databricks.labs.gbx.vizx import plot_mask_layers

# Each raster is a single-band H3 presence mask for a different threshold.
# Tiles share the same canvas (same gridspec extent).
plot_mask_layers(
[
("≥ 1 observation", tier1_raster_bytes),
("≥ 10 observations", tier2_raster_bytes),
("≥ 50 observations", tier3_raster_bytes),
],
title="NYC observation coverage by threshold",
)

See the H3 rasterize notebook for a full worked example of building shared-canvas presence-mask layers.

Rendering from a Spark DataFrame

plot_tiles

plot_tiles(df, tile_col="tile", *, mode="facet", limit=None,
fig_w=10, fig_h=10, max_pixels=2000, composite="auto", emphasis="blend")

Render raster tiles directly from a (filtered) Spark DataFrame — no manual materialize step required. Virtual and materialized tiles (v1 and v2 schema) are both handled automatically.

Parameters:

ParameterTypeDefaultDescription
dfDataFrameA Spark DataFrame with a tile column. Filter it before calling — only the first limit rows are pulled to the driver.
tile_colstr"tile"Name of the tile struct column.
modestr"facet"Rendering mode: "facet" (grid of thumbnails), "first" (single tile), or "mosaic" (stitch same-CRS tiles into one georeferenced image).
limitint or Nonemode defaultMaximum rows to pull to the driver. Defaults to 25 (facet), 1 (first), or 64 (mosaic). For facet and mosaic, a UserWarning is issued when the DataFrame has more rows than limit. first silently renders the first tile with no warning — pass a filtered DataFrame to choose which tile. The entire DataFrame is never collected.
fig_wfloat10Figure width in inches.
fig_hfloat10Figure height in inches.
max_pixelsint2000Decimate above this longest-edge pixel count before rendering.
compositestr"auto"Band-composite mode (see Raster rendering above).

Mode notes:

  • "facet" — renders each tile as a separate panel in a grid. Works with any mix of CRS values.
  • "first" — renders the first tile only. Works with any CRS.
  • "mosaic" — merges tiles into a single georeferenced image via rasterio.merge. All tiles must share the same CRS and the same dtype/band count; a ValueError is raised on mismatch. The merged array is decimated to max_pixels before rendering.

Returns: a matplotlib Axes for "first" and "mosaic", a Figure for "facet".

from databricks.labs.gbx.vizx import plot_tiles

# Show the first 4 tiles from a GeoTIFF reader result as a 2×2 grid:
# The reader schema is (source, tile) — path and cellid are nested inside tile.
df = spark.read.format("gtiff_gbx").load("/Volumes/main/samples/sentinel/")
plot_tiles(df.filter("tile.cellid is not null"), mode="facet", limit=4)

# Inspect a single tile quickly:
plot_tiles(df.filter("tile.path = '/Volumes/main/samples/sentinel/B04.tif'"), mode="first")

# Stitch adjacent tiles from a single scene into one image (all must share CRS):
plot_tiles(scene_df, mode="mosaic", limit=16)

Escape hatches

When you need raster math that isn't in the rst_* surface, drop down to NumPy / rasterio per tile with the pyrx escape hatches (tile_to_numpy, rst_apply).