Skip to content

API

terrazarr.to_geozarr(data, output, *, groups=None, chunk_size=256, shard_size=4096, sharding=True, method='mean', nodata=None, min_dimension=None, compressor=DEFAULT_COMPRESSOR, window_shards=None, resume=False, max_retries=3, crs_groups=None, gcp_group=None, store=None, s3_profile=None)

Write an xarray object as a GeoZarr multiscale pyramid.

The counterpart of rioxarray's to_raster for GeoZarr: data becomes level 0 of a zarr v3 store and every further level is its 2**L reduction, with CRS, transform and multiscales metadata on each level. data must have y/x dimensions and a CRS readable by rioxarray (ds.rio.crs); a dask-backed object is written lazily, in windows, with bounded memory whatever its size. Also available as the accessor ds.terrazarr.to_geozarr(output, ...).

Parameters:

Name Type Description Default
data (DataArray, Dataset or DataTree)

A DataArray is written as the variable data (or its name); a Dataset as the root group; a DataTree group by group (see groups).

required
output str

Output store: a local path or an s3:// URL (credentials from the environment).

required
groups iterable of str

For a DataTree, the groups to write as pyramids; default the root when it holds data variables, otherwise every group that does.

None
chunk_size int

Zarr chunk on y/x, the tile a client fetches.

256
shard_size int

Zarr shard on y/x with sharding, i.e. how many chunks travel in one object, and the dask block on y/x in every case; a multiple of chunk_size.

4096
sharding bool

Write sharded arrays (one object per shard) instead of one object per chunk.

True
method (mean, sum, min, max, median, nearest)

Reduction from one level to the next.

"mean"
nodata float

Numeric nodata value, excluded from the reduction; NaN is always nodata. A block with less than 30 % valid pixels becomes nodata (sum: only a block with no valid pixel).

None
min_dimension int

Stop adding levels when both dimensions are below this; default chunk_size.

None
compressor zarr codec

Codec for every level's data variables, see :func:make_compressor; default Blosc zstd level 3 with byte shuffle, None for no compression.

DEFAULT_COMPRESSOR
window_shards int

Level 0 is written in windows of this many blocks per axis, one dask compute each (default 32). Bounds the memory of the process that holds the dask graph.

None
resume bool

What to do with a level 0 already on the store. False: use it as it is when it is valid, without checking that it is complete, and write it from scratch when it is absent or invalid. True: check the completion marker of the level, skip a complete level and write only the windows an interrupted run left out; a level without a marker cannot be resumed and is rewritten.

False
max_retries int

Attempts per window, and per band in the fallback path.

3
crs_groups optional

Groups that need CRS information on a best-effort basis, and the group holding ground control points (Sentinel-1 inputs).

None
gcp_group optional

Groups that need CRS information on a best-effort basis, and the group holding ground control points (Sentinel-1 inputs).

None
store zarr store

Store to write to, built from output when omitted.

None
s3_profile str

Kept for compatibility; credentials come from the environment.

None

Returns:

Type Description
DataTree

The written pyramid, one child per level.

Accessors

Importing terrazarr registers the terrazarr accessor on xarray.Dataset and xarray.DataArray, so any object with a CRS readable by rioxarray can be written directly:

import terrazarr  # noqa: F401  (registers the accessor)
import xarray as xr

ds = xr.open_dataset("in.zarr", engine="zarr", chunks={"y": 4096, "x": 4096})
ds.terrazarr.to_geozarr("out.zarr", chunk_size=256, shard_size=4096, method="mean", nodata=0)

Command line

terrazarr --input IN --output OUT [options]
option default meaning
--chunk-size 256 zarr chunk on y/x, the tile a client fetches
--shard-size 4096 zarr shard on y/x with --sharding, and the dask block in every case; a multiple of the chunk size
--sharding off write sharded arrays, one object per shard
--method mean mean, sum, min, max, median or nearest; sum adds the valid pixels, keeps the source dtype (integers saturate) and is nodata only where no pixel is valid
--nodata none numeric nodata, excluded from the reduction; NaN is always nodata
--compressor, --clevel zstd, 3 Blosc codec and level for every level's data; none for uncompressed
--workers, --threads-per-worker, --memory-limit 8, 1, auto the dask cluster; several single-threaded processes beat one multi-threaded one, since zarr assembles chunks on one event loop per process
--window-shards 32 level-0 blocks per axis and per window; the main process holds one window's graph at a time
--resume off check an existing level 0: skip it when its completion marker says complete, write only the windows an interrupted run left out; a level 0 without a marker is rewritten. Without --resume, a valid level 0 is used as it is, without checking that it is complete, and an absent or invalid one is written from scratch

The input is a zarr store, local or s3://, with y and x dimensions and a CRS; S3 credentials come from AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and, for S3-compatible stores, AWS_ENDPOINT_URL. Environment variables TERRAZARR_WINDOW_SHARDS, TERRAZARR_FUSE_LEVEL_1 (0 disables the fused level 1) and TERRAZARR_MIN_BLOCKS_FROM_STORE set the defaults of the corresponding knobs.

Output layout and conventions

A pyramid is a zarr v3 group with one child group per level, 0 for the native resolution and L for the level with 2**L native pixels per pixel, each holding the data variables, the x and y coordinates and a CF spatial_ref grid-mapping variable with crs_wkt and a GeoTransform, so every level is georeferenced on its own and opens with rioxarray. The root group declares the zarr-conventions it follows and carries their attributes:

convention version attributes written
multiscales v1 multiscales.layout: one entry per level with asset, transform (scale and translation relative to level 0), spatial:shape, spatial:transform, spatial:bbox; resampling_method
proj v1 proj:code, proj:wkt2
spatial v1 spatial:dimensions, spatial:bbox, spatial:transform, spatial:registration (pixel)

The root also carries a native-CRS tile matrix set and tile matrix limits in the form (tile_matrix_set, tile_matrix_limits), one tile matrix per level with the chunk as tile, used by the EOPF GeoZarr data model. Metadata is consolidated at every level and at the root. Arrays are zarr v3 with the sharding codec when sharding is on (chunks of chunk_size² inside shards of shard_size²), Blosc-compressed by default, with the fill value NaN for floating-point data and the dtype's zero otherwise; a numeric nodata is excluded from every reduction and written back as the value of blocks that fall below 30 % valid pixels.

Geometry is exact: level L has exactly 2**L native pixels per pixel, anchored on the native top-left corner, so spatial:transform of level L is the native transform scaled by 2**L, and levels whose shape is not a multiple of 2**L are trimmed rather than stretched. Integer overviews are rounded to nearest; min and max stay in the source dtype; median is computed in float32 for integers up to 16 bits and float64 otherwise; nearest takes the pixel at the centre of each block.

Resume

Level 0 (with level 1, which is reduced from the same blocks) is written in windows, and the level-0 group records every window done in the attribute terrazarr:windows_done and sets terrazarr:level0_complete at the end. Running to_geozarr(..., resume=True) (--resume) again on an interrupted store finishes the missing windows and does not rewrite the rest; a complete store is left untouched, and a level 0 without a marker cannot be checked and is rewritten. Without resume, a valid level 0 on the store is used as it is, even if an interrupted run left it incomplete, and an absent or invalid one is written from scratch. Every further level is built from the previous one on the store and skipped when present.