Skip to main content

Load a STAC collection into xarray with dask

Project description

StackSTAC

Documentation Status Binder

Turn a list of STAC items into a 4D xarray DataArray (dims: time, band, y, x), including reprojection to a common grid. The array is a lazy Dask array, so loading and processing the data in parallel—locally or on a cluster—is just a compute() call away.

For more information and examples, please see the documentation.

import stackstac
import pystac_client

URL = "https://earth-search.aws.element84.com/v1"
catalog = pystac_client.Client.open(URL)

stac_items = catalog.search(
    intersects=dict(type="Point", coordinates=[-105.78, 35.79]),
    collections=["sentinel-2-l2a"],
    datetime="2020-04-01/2020-05-01"
).get_all_items()

stack = stackstac.stack(stac_items)
print(stack)
<xarray.DataArray 'stackstac-fefccf3d6b2f9922dc658c114e79865b' (time: 13, band: 17, y: 10980, x: 10980)>
dask.array<fetch_raster_window, shape=(13, 17, 10980, 10980), dtype=float64, chunksize=(1, 1, 1024, 1024), chunktype=numpy.ndarray>
Coordinates: (12/24)
  * time                        (time) datetime64[ns] 2020-04-01T18:04:04 ......
    id                          (time) <U24 'S2B_13SDV_20200401_0_L2A' ... 'S...
  * band                        (band) <U8 'overview' 'visual' ... 'WVP' 'SCL'
  * x                           (x) float64 4e+05 4e+05 ... 5.097e+05 5.098e+05
  * y                           (y) float64 4e+06 4e+06 ... 3.89e+06 3.89e+06
    view:off_nadir              int64 0
    ...                          ...
    instruments                 <U3 'msi'
    created                     (time) <U24 '2020-09-05T06:23:47.836Z' ... '2...
    sentinel:sequence           <U1 '0'
    sentinel:grid_square        <U2 'DV'
    title                       (band) object None ... 'Scene Classification ...
    epsg                        int64 32613
Attributes:
    spec:        RasterSpec(epsg=32613, bounds=(399960.0, 3890220.0, 509760.0...
    crs:         epsg:32613
    transform:   | 10.00, 0.00, 399960.00|\n| 0.00,-10.00, 4000020.00|\n| 0.0...
    resolution:  10.0

Once in xarray form, many operations become easy. For example, we can compute a low-cloud weekly mean-NDVI timeseries:

lowcloud = stack[stack["eo:cloud_cover"] < 40]
nir, red = lowcloud.sel(band="B08"), lowcloud.sel(band="B04")
ndvi = (nir - red) / (nir + red)
weekly_ndvi = ndvi.resample(time="1w").mean(dim=("time", "x", "y")).rename("NDVI")
# Call `weekly_ndvi.compute()` to process ~25GiB of raster data in parallel. Might want a dask cluster for that!

Installation

pip install stackstac

Windows notes:

It's a good idea to use conda to handle installing rasterio on Windows. There's considerably more pain involved with GDAL-type installations using pip. Then pip install stackstac.

Things stackstac does for you:

  • Figure out the geospatial parameters from the STAC metadata (if possible): a coordinate reference system, resolution, and bounding box.
  • Transfer the STAC metadata into xarray coordinates for easy indexing, filtering, and provenance of metadata.
  • Efficiently generate a Dask graph for loading the data in parallel.
  • Mediate between Dask's parallelism and GDAL's aversion to it, allowing for fast, multi-threaded reads when possible, and at least preventing segfaults when not.
  • Mask nodata and rescale by STAC item asset scales/offsets.
  • Display data in interactive maps in a notebook, computed on the fly by Dask.

Limitations:

  • Raster data only! We are currently ignoring other types of assets you might find in a STAC (XML/JSON metadata, point clouds, video, etc.).
  • Single-band raster data only! Each band has to be a separate STAC asset—a separate red, green, and blue asset on each Item is great, but a single RGB asset containing a 3-band GeoTIFF is not supported yet.
  • COGs work best. "Normal" GeoTIFFs that aren't internally tiled, or don't have overviews, will see much worse performance. Sidecar files (like .msk files) are ignored for performance. JPEG2000 will probably work, but probably be slow unless you buy kakadu. Formats make a big difference.
  • BYOBlocksize. STAC doesn't offer any metadata about the internal tiling scheme of the data. Knowing it can make IO more efficient, but actually reading the data to figure it out is slow. So it's on you to set this parameter. (But if you don't, things should be fine for any reasonable COG.)
  • Doesn't make geospatial data any easier to work with in xarray. Common operations (picking bands, clipping to bounds, etc.) are tedious to type out. Real geospatial operations (shapestats on a GeoDataFrame, reprojection, etc.) aren't supported at all. rioxarray might help with some of these, but it has limited support for Dask, so be careful you don't kick off a huge computation accidentally.
  • I haven't even written tests yet! Don't use this in production. Or do, I guess. Up to you.

Roadmap:

Short-term:

  • Write tests and add CI (including typechecking)
  • Support multi-band assets
  • Easier access to s3://-style URIs (right now, you'll need to pass in gdal_env=stackstac.DEFAULT_GDAL_ENV.updated(always=dict(session=rio.session.AWSSession(...))))
  • Utility to guess blocksize (open a few assets)
  • Support item assets to provide more useful metadata with collections that use it (like S2 on AWS)
  • Rewrite dask graph generation once the Blockwise IO API settles

Long term (if anyone uses this thing):

  • Support other readers (aiocogeo?) that may perform better than GDAL for specific formats
  • Interactive mapping with xarray_leaflet, made performant with some Dask graph-rewriting tricks to do the initial IO at coarser resolution for lower zoom levels (otherwize zooming out could process terabytes of data)
  • Improve ergonomics of xarray for raster data (in collaboration with rioxarray)
  • Implement core geospatial routines (warp, vectorize, vector stats, GeoPandas/spatialpandas interop) in Dask

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

stackstac-0.5.1.tar.gz (59.2 kB view details)

Uploaded Source

Built Distribution

stackstac-0.5.1-py3-none-any.whl (64.3 kB view details)

Uploaded Python 3

File details

Details for the file stackstac-0.5.1.tar.gz.

File metadata

  • Download URL: stackstac-0.5.1.tar.gz
  • Upload date:
  • Size: 59.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: pdm/2.17.3 CPython/3.9.4 Darwin/22.6.0

File hashes

Hashes for stackstac-0.5.1.tar.gz
Algorithm Hash digest
SHA256 1af0e1251100fe506b1f3c035ffcc34111ad67b264275d14a6775c4991e5f7f6
MD5 19cd91b66fc5bc79557c23c7f0a4e69d
BLAKE2b-256 a2ed4a258f240b9a2354a3c09a15124ff670613663d6ddc96ddeeeb7d8532cc4

See more details on using hashes here.

File details

Details for the file stackstac-0.5.1-py3-none-any.whl.

File metadata

  • Download URL: stackstac-0.5.1-py3-none-any.whl
  • Upload date:
  • Size: 64.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: pdm/2.17.3 CPython/3.9.4 Darwin/22.6.0

File hashes

Hashes for stackstac-0.5.1-py3-none-any.whl
Algorithm Hash digest
SHA256 3c596c9ccf502b6230b1c9e970a8099eeb94df867d0dea2fd45071223cb581e7
MD5 ed5936334f505d37a863e6809e848b41
BLAKE2b-256 0d1b629745491592dbeba18bfcb06d22bcefd988fc40dc5a8dbf168517565e38

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page