Xarray Accessor¶
import zeit registers a .zeit accessor on every xarray.DataArray (and, to save or show results, on every xarray.Dataset). Its methods run the C++ algorithms over Dask chunks, so they work on cubes larger than memory and on clusters. On a dask-backed cube the algorithms are lazy: call .compute(), or write the result with save_raster or to_zarr_optimized. An in-memory cube gives an in-memory result.
Chunk in space, never in time
Each pixel needs its whole history, so keep time (and band, for CCDC) in a single chunk: cube.chunk({"time": -1, "y": 512, "x": 512}). See Parallel & Cloud Processing.
| Method | Input dims | Output | Parameters as in |
|---|---|---|---|
landtrendr |
(time, y, x) |
xr.Dataset of vertices |
zeit.landtrendr |
ccdc |
(time, band, y, x) |
xr.Dataset of segments |
zeit.ccdc |
bfast_monitor |
(time, y, x) |
xr.Dataset of metrics |
zeit.bfast_monitor |
bfast_lite |
(time, y, x) |
xr.Dataset of metrics |
zeit.bfast_lite |
bfast |
(time, y, x) |
xr.Dataset of metrics |
zeit.bfast |
mann_kendall |
(time, y, x) |
xr.Dataset of metrics |
zeit.mann_kendall |
phenology |
(time, y, x) |
xr.Dataset of metrics, by year or season |
zeit.phenology |
twdtw |
(time, y, x) or (time, band, y, x) |
xr.Dataset of classes and distances |
zeit.twdtw |
smooth |
(time, ...) |
the smoothed DataArray |
zeit.smooth |
snic |
(..., y, x) |
xr.Dataset of labels and means |
zeit.snic |
som |
(..., y, x) |
xr.Dataset of clusters and prototypes |
zeit.som |
tmask |
(time, band, y, x) |
clear (time, y, x) |
zeit.tmask |
save |
any with y, x (also on a Dataset) |
writes a raster, returns its path | zeit.save_raster |
plot |
any with y, x (also on a Dataset) |
the viewer, a window or a figure | zeit.plot |
to_zarr_optimized |
any with y, x |
writes a Zarr store | below |
Each algorithm method returns an xr.Dataset with one variable per output, selected by name: result.slope, result["TRS5.sos"].
Change detection¶
landtrendr¶
LandTrendr on this (time, y, x) cube: the same as zeit.landtrendr(cube, **kwargs), with the same keyword arguments (direction, max_segments, nodata, fitted, …) and the same xarray.Dataset of vertices. The years come from the time coordinate. A dask-backed cube stays lazy and is computed block by block.
ndvi = ndvi.chunk({"time": -1, "y": 512, "x": 512})
lt = ndvi.zeit.landtrendr(max_segments=6) # direction="loss": NDVI drops
loss = zeit.extract_events(lt, min_magnitude=2000) # still lazy
zeit.save_raster(loss, "results/") # computed while written
ccdc¶
CCDC on this (time, band, y, x) cube of reflectance × 10,000: the same as zeit.ccdc(cube, **kwargs), with the same keyword arguments (qa, bands, max_segments, conseq_anom, …) and the same xarray.Dataset of segments. The dates come from the time coordinate. A dask-backed cube stays lazy and is computed block by block, with time and band in one chunk.
cube = cube.chunk({"time": -1, "band": -1, "y": 512, "x": 512})
segments = cube.zeit.ccdc(qa="fmask") # QA band by name; still lazy
zeit.save_raster(segments, "ccdc_out/") # computed while written
bfast_monitor¶
BFAST Monitor on this (time, y, x) cube: the same as zeit.bfast_monitor(cube, monitor_start, **kwargs), with the same keyword arguments (order, h, period, alpha, nodata, …) and the same xarray.Dataset of metrics. start_time and frequency come from the time coordinate unless given. A dask-backed cube stays lazy.
ndvi_16d = ndvi_16d.chunk({"time": -1, "y": 512, "x": 512})
bfm = ndvi_16d.zeit.bfast_monitor("2022-01-01") # still lazy
zeit.save_raster(bfm, "results/bfm") # computed while written
bfast_lite¶
BFAST Lite on this (time, y, x) cube: the same as zeit.bfast_lite(cube, **kwargs).
bfast¶
Classic BFAST on this (time, y, x) cube: the same as zeit.bfast(cube, **kwargs).
Time-series analysis¶
mann_kendall¶
Mann-Kendall test and Theil-Sen slope on this (time, y, x) cube: the same as zeit.mann_kendall(cube, **kwargs), with the same keyword arguments (method, alpha, lag, period, …) and the same xarray.Dataset of metrics.
mk = annual_ndvi.zeit.mann_kendall(method="hamed_rao")
slope = mk.slope.where(mk.h == 1) # significant slopes only
phenology¶
Phenology on this (time, y, x) cube: the same as zeit.phenology(cube, **kwargs), with the same keyword arguments (curve, annual, max_seasons, weights, …) and the same xarray.Dataset of 21 metrics. The day numbering and the first year come from the time coordinate.
pheno = ndvi_16d.zeit.phenology(curve="beck", weights=weights)
sos = pheno["TRS5.sos"] # (year, y, x), day of year
twdtw¶
TWDTW classification of this cube: the same as zeit.twdtw(cube, patterns, **kwargs), with the same keyword arguments (steepness, midpoint, cycle, max_elapsed, …) and the same xarray.Dataset. A dask-backed cube stays lazy.
smooth¶
Smoothing of this cube along time: the same as zeit.smooth(cube, **kwargs) (method, lmbda, weights, …).
snic¶
SNIC superpixels of this map or cube: the same as zeit.snic(da, **kwargs). The cube is loaded into memory.
som¶
Self-organizing map clusters of this map or cube: the same as zeit.som(da, **kwargs).
tmask¶
Tmask on this (time, band, y, x) cube: the same as zeit.tmask(cube, **kwargs).
Saving and showing results¶
The results of the algorithms are Datasets; .zeit.save and .zeit.plot write or show them (or any map or cube) without leaving a chain of calls:
zeit.landtrendr(ndvi).zeit.save("results/lt") # one GeoTIFF per variable
zeit.extract_events(lt).yod.zeit.plot(basemap="satellite") # one map
lt.zeit.plot() # a selector of the variables
save¶
Writes this map, cube or result: the same as zeit.save_raster(data, path, **kwargs), with its keyword arguments (nodata, dtype, compress, driver, …). A Dataset with a path without extension becomes a folder with one GeoTIFF per variable; with .tif, one multiband raster. Returns the Path written. A lazy result is computed while it is written.
plot¶
Shows this map, cube or result: the same as zeit.plot(data, **kwargs), with its keyword arguments (var, fit, basemap, vector, static, save, …): the interactive viewer in a notebook, a window in a script, a figure with static=True or save=. A Dataset opens with a selector of its variables.
Storage¶
to_zarr_optimized¶
Rechunks the array spatially and writes it to a Zarr store with consolidated metadata, locally or to object storage (s3://, gs://). With a Dask-backed array, this is the step that triggers the computation, and every worker writes its own chunks.
| Parameter | Type | Default | Description |
|---|---|---|---|
store_path |
str |
required | Local path or fsspec URL. |
chunk_size |
dict |
{"y": 512, "x": 512} |
Chunk sizes of the stored array. |