Skip to content

Fetch and stream grid data

You are viewing in-progress documentation for v2 (Beta). Switch to the stable version for the current production release.

A grid’s raster values are read back per band, per chunk. Large grids are tiled into chunks so you can stream them without pulling the whole array at once; you fetch each chunk and place it into the full array using the chunk’s offset. This guide walks that loop.

  1. An API key: my-api-key.

  2. A domain and a completed grid: your-domain-id and your-grid-id — e.g. the fuel-load grid from Build a surface fuel grid from LANDFIRE.

GET the grid. Two fields drive the rest: georeference.shape (the full (height, width)) and chunks.count (how many chunks to fetch per band).

GET grid
curl -X 'GET' \
'https://api-v2-prod-nyvjyh5ywa-uw.a.run.app/domains/your-domain-id/grids/your-grid-id' \
-H 'accept: application/json' \
-H 'api-key: my-api-key'

bands lists the band keys you can request. chunks.count here is 1 (this grid fits in a single tile); a larger grid reports more, laid out count_by_axis.

GET /grids/{{GRID_ID}}/data/{band}/{chunk_index}. The response carries the chunk’s own shape, an offset into the full array, the chunk’s affine transform, and the values.

GET data/fuel_load.1hr/0
curl -X 'GET' \
'https://api-v2-prod-nyvjyh5ywa-uw.a.run.app/domains/your-domain-id/grids/your-grid-id/data/fuel_load.1hr/0' \
-H 'accept: application/json' \
-H 'api-key: my-api-key'

data.values is the real chunk data — a flat array of shape[0] × shape[1] values in order ("C", row-major). It’s shown abridged above; the full chunk here is 30 × 45 = 1350 floats. Two formats:

  • densevalues holds every cell, in order.
  • sparsevalues holds only the cells that differ from fill_value, paired with indices. Reconstruct by filling with fill_value then scattering values into indices. The API uses this automatically when a chunk is mostly one value (e.g. a masked grid that’s largely zero).

For each band, loop chunk_index from 0 to chunks.count - 1, and drop each chunk into the full array at its offset:

Fetch all chunks and reassemble a band
import numpy as np
import requests
API_KEY = "my-api-key"
DOMAIN_ID = "your-domain-id"
GRID_ID = "your-grid-id"
BAND = "fuel_load.1hr"
BASE = "https://api-v2-prod-nyvjyh5ywa-uw.a.run.app"
HEADERS = {"api-key": API_KEY}
# 1. Read the grid to learn its full shape and how many chunks it has.
grid = requests.get(
f"{BASE}/domains/{DOMAIN_ID}/grids/{GRID_ID}", headers=HEADERS
).json()
height, width = grid["georeference"]["shape"]
chunk_count = grid["chunks"]["count"]
# 2. Fetch each chunk and place it into the full array using its offset.
full = np.full((height, width), np.nan, dtype="float32")
for i in range(chunk_count):
chunk = requests.get(
f"{BASE}/domains/{DOMAIN_ID}/grids/{GRID_ID}/data/{BAND}/{i}",
headers=HEADERS,
).json()
ch, cw = chunk["shape"]
row0, col0 = chunk["metadata"]["offset"]
data = chunk["data"]
if data["format"] == "dense":
tile = np.array(data["values"], dtype="float32").reshape((ch, cw))
else: # sparse: a fill value plus explicit (index, value) pairs
tile = np.full((ch, cw), data["fill_value"], dtype="float32")
tile.flat[data["indices"]] = data["values"]
full[row0 : row0 + ch, col0 : col0 + cw] = tile
print(full.shape, np.nanmin(full), np.nanmax(full)) # (30, 45) 0.0 1.30018...
  • Forgetting it’s per band. Each data/{band}/{chunk_index} call returns one band. Loop over bands (from step 1) as well as over chunks.
  • Ignoring offset. Concatenating chunks in fetch order mis-places them. Always position a chunk with its metadata.offset — that’s what makes the reassembled array correct for multi-chunk grids.
  • Assuming dense. Handle both dense and sparse — the format can vary by chunk, so branch on data.format rather than assuming.
  • Grid not completed. Data is only readable once the grid finishes; chunks is null and there’s nothing to fetch while it’s pending.