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 value | Behaviour |
|---|---|
"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 floorGDAL 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:
| Parameter | Type | Default | Description |
|---|---|---|---|
layers | list[tuple[str, bytes]] | — | List of (label, raster_bytes) pairs. Each raster must be a single-band presence mask. |
fig_w | float | 10 | Figure width in inches. |
fig_h | float | 8 | Figure height in inches. |
max_pixels | int | 2000 | Decimate above this longest-edge pixel count before rendering. |
colors | list or None | None | Matplotlib color values, one per layer. Defaults to the tab10 qualitative cycle. |
title | str | "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:
| Parameter | Type | Default | Description |
|---|---|---|---|
df | DataFrame | — | A Spark DataFrame with a tile column. Filter it before calling — only the first limit rows are pulled to the driver. |
tile_col | str | "tile" | Name of the tile struct column. |
mode | str | "facet" | Rendering mode: "facet" (grid of thumbnails), "first" (single tile), or "mosaic" (stitch same-CRS tiles into one georeferenced image). |
limit | int or None | mode default | Maximum 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_w | float | 10 | Figure width in inches. |
fig_h | float | 10 | Figure height in inches. |
max_pixels | int | 2000 | Decimate above this longest-edge pixel count before rendering. |
composite | str | "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 viarasterio.merge. All tiles must share the same CRS and the same dtype/band count; aValueErroris raised on mismatch. The merged array is decimated tomax_pixelsbefore 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).