Skip to content

HEALPix Zarr tile layers#7

Open
danielfdsilva wants to merge 13 commits into
mainfrom
feature/healpix-zarr-layer
Open

HEALPix Zarr tile layers#7
danielfdsilva wants to merge 13 commits into
mainfrom
feature/healpix-zarr-layer

Conversation

@danielfdsilva

@danielfdsilva danielfdsilva commented May 20, 2026

Copy link
Copy Markdown
Member

Deck.gl layer for HEALPix rasters in Zarr, plus a draft store spec, a Sentinel-2 conversion example, and a demo app.

Summary

On this branch:

Together these show how a multiscale HEALPix raster dataset can be explored.


Zarr file structure

The layer only reads HEALPix Pyramid Zarr (Zarr v3). The draft spec is docs/specs/healpix-pyramid-zarr.md.

A store is a tree of resolution levels (nside_128/, nside_256/, up to base_nside). Each level has:

  • cell_id: which HEALPix cells have data (sparse; no row means no value)
  • parent_offsets: CSR index from parent cell to row range in the packed arrays (parent_offsets in the spec)
  • bands/<name>: one float array per variable (e.g. b04, b03, b02 for Sentinel-2)

Root metadata lists bands, the resolution range, and how parent grids relate to data nside.

Chunking parent_offsets. The array length is 12 * nside_parent² + 1. It can be huge, but each tile load only needs parent_offsets[p] and parent_offsets[p+1] to get rows for parent p. Over HTTP, Zarr reads whole chunks. If the CSR index is one chunk, every tile pulls the full array again. Chunks around 4096 entries (~32 KB for uint64) usually mean a lookup is one small range request. The layer then slices cell_id and the requested bands/<name> with [rowStart:rowEnd]. Step-by-step: Reader load sequence in the spec.

This spec is a suggestion. I'm not very familiar with everything that goes into a spec like this one, but I needed something to start with, and on which to base the layer implementation.


Sentinel-2 conversion (example)

sentinel2-zhealpix/ is an example of building a conformant store from real scenes. Nothing in the layer imports it at runtime; it only writes Zarr the layer can open.

Stage What it does
download Pull Sentinel-2 L2A reflectance zarrs locally
healpix Reproject each scene to HEALPix at a chosen nside
merge Mosaic scenes into one base array
pyramid Build coarser levels and parent_offsets

Output: mosaic.zarr, ready to host.

cd sentinel2-zhealpix
uv run python -m sentinel2_zhealpix run-all \
  --urls https://example.com/S2B_MSIL2A_20260101T110351_T29SND.zarr \
  --out-dir ./output

More detail: sentinel2-zhealpix/README.md.


HealpixZarrTileLayer

HealpixZarrTileLayer draws a remote or local Zarr store on a deck.gl map. It:

  • picks HEALPix nside from zoom
  • loads viewport tiles (plus a small margin) via deck.gl's Tileset2D
  • renders bands through HealpixCellsLayer in @developmentseed/deck.gl-healpix
  • deduplicates HTTP with CachedZarrStore

Example

import { HealpixZarrTileLayer } from '@developmentseed/deck.gl-healpix-zarr';
import { HEALPIX_COLOR_MODE_RGB } from '@developmentseed/deck.gl-healpix';

const layer = new HealpixZarrTileLayer({
  url: 'https://example.com/mosaic.zarr',
  bands: ['b04', 'b03', 'b02'],
  colorMode: HEALPIX_COLOR_MODE_RGB,
  onMetadata: (meta) => console.log('Available bands:', meta.bands),
});

Full demo: https://deck.gl-healpix.ds.io/examples/zarr-tiles/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant