STAC Subpackage#
The pyramids.stac subpackage connects pyramids to the
SpatioTemporal Asset Catalog ecosystem — searching STAC
APIs, reading assets as pyramids Dataset / NetCDF objects, building cubes,
signing cloud credentials, and writing STAC Items back out. Everything is
GDAL-native (no rasterio, no xarray) and duck-typed over the STAC
Item/Asset contract, so pystac is never imported by pyramids itself — raw STAC
JSON dicts work as well as pystac.Item objects.
Module layout#
classDiagram
class Signer {
<<protocol>>
+name
+sign_request(request)
+sign_item(item)
+sign_href(href) str
+gdal_env() dict
}
class AnonymousSigner
class AWSRequesterPaysSigner
class BearerTokenSigner
class PlanetaryComputerSigner
class EarthdataSigner
class CDSESigner
Signer <|.. AnonymousSigner
Signer <|.. AWSRequesterPaysSigner
Signer <|.. BearerTokenSigner
Signer <|.. PlanetaryComputerSigner
Signer <|.. EarthdataSigner
Signer <|.. CDSESigner
Public API at a glance#
| Concern | Symbol | Page |
|---|---|---|
| Open a STAC API client | open_client |
Client & search |
| Typed item search | search (bbox/intersects/datetime/query/CQL2) |
Client & search |
Read one asset → Dataset/NetCDF |
load_asset · which_engine · resolved_href |
Assets |
Read proj/raster/eo metadata (no file open) |
read_extension_metadata |
Assets |
| Mosaic one asset across items (lazy VRT) | build_vrt_from_stac |
Assets |
Download assets to local files ([stac] extra) |
download_item |
Assets |
Serialize items ↔ GeoParquet ([parquet] extra) |
to_geoparquet · from_geoparquet |
Assets |
| Cloud credentials (6 signers) | Signer protocol + concrete signers |
Signers |
Two STAC entry points live on the raster classes (documented there):
DatasetCollection.from_stac(items, asset, *, signer, align, skip_missing, groupby, like, crs, resolution, bounds)— build a time-stacked cube from STAC items (single asset → time stack, or a list of assets → band axis;groupby="solar_day"mosaics same-overpass tiles;like=/crs+resolution+boundsmatches a target grid). See DatasetCollection.DatasetCollection.from_point(lat, lon, *, collection, bands, start_date, end_date, edge_size, resolution)— a cubo-style point + edge-size convenience cube. See DatasetCollection.Dataset.to_stac_item(item_id, *, asset_href, …)— describe a raster as a STAC Item dict (proj+rasterextensions). See I/O.
Install#
open_client / search need the [stac] extra (which also bundles the optional
asset downloader stac-asset); read_extension_metadata, load_asset,
build_vrt_from_stac, to_stac_item, and the signers need only core pyramids:
pip install 'pyramids-gis[stac]' # client/search + download_item
pip install 'pyramids-gis[stac,parquet]' # + GeoParquet round-trip
See the STAC tutorial for an end-to-end walkthrough, the offline STAC notebook, and the live-endpoint notebooks for Earth Search (anonymous) and the Planetary Computer (signed).
Client & search#
pyramids.stac.client
#
Open a pystac-client Client with a pyramids signer wired in.
This thin wrapper attaches a :class:~pyramids.stac.signers.Signer to both
pystac-client hooks at once — modifier (post-response Item rewrite) and
request_modifier (pre-send HTTP request signing) — so the caller never has
to remember which boundary a given signer cares about.
pystac-client is an optional dependency. Install with one of:
- PyPI:
pip install 'pyramids-gis[stac]' - conda-forge:
conda install -c conda-forge pyramids-stac
open_client(url, *, signer=None, headers=None, timeout=30)
#
Open a STAC API client with a pyramids signer wired into both hooks.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str
|
STAC API root URL (e.g. an |
required |
signer
|
Signer | None
|
A :class: |
None
|
headers
|
dict[str, str] | None
|
Optional static HTTP headers added to every request. |
None
|
timeout
|
float | None
|
Per-request timeout in seconds. |
30
|
Returns:
| Type | Description |
|---|---|
Any
|
A |
Raises:
| Type | Description |
|---|---|
OptionalPackageDoesNotExist
|
When |
Examples:
- Open a public catalog anonymously (requires the
[stac]extra):>>> from pyramids.stac import open_client # doctest: +SKIP >>> client = open_client("https://earth-search.aws.element84.com/v1") # doctest: +SKIP >>> search = client.search(collections=["sentinel-2-l2a"], max_items=1) # doctest: +SKIP >>> next(search.items()).collection_id # doctest: +SKIP 'sentinel-2-l2a' - Wire a bearer-token signer into both hooks:
Source code in src/pyramids/stac/client.py
pyramids.stac.search
#
Typed STAC item-search helper (PB-3).
A thin, typed wrapper over pystac_client.Client.search that makes the common
AOI / time / cloud query one call and returns an ItemCollection ready for
:meth:pyramids.dataset.DatasetCollection.from_stac. It:
- opens a client from a URL (or accepts an already-open
Client); - gates a CQL2
filteron the endpoint advertising theFILTERconformance class, raising a clear error instead of pystac-client's opaque one; - accepts a shapely geometry or a GeoJSON dict for
intersects; - bounds the query at the API —
bbox/datetime/max_items/limitare forwarded toclient.searchso the server (and paging) does the work (M3). This contrasts with :func:pyramids.dataset._stac.from_stac, whose ownbbox/max_itemsare client-side post-filters over an already-materialised item list.
pystac-client is an optional dependency. Install with one of:
- PyPI:
pip install 'pyramids-gis[stac]' - conda-forge:
conda install -c conda-forge pyramids-stac
search(client_or_url, collections, *, bbox=None, intersects=None, datetime=None, query=None, filter=None, sortby=None, max_items=None, limit=None, signer=None)
#
Run a STAC item search and return the matched ItemCollection.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
client_or_url
|
Any
|
An open |
required |
collections
|
str | Sequence[str]
|
Collection id, or a sequence of collection ids, to search. |
required |
bbox
|
Sequence[float] | None
|
Optional |
None
|
intersects
|
Any
|
Optional AOI geometry — a shapely geometry (anything with a
|
None
|
datetime
|
Any
|
Optional RFC 3339 datetime or interval string
(e.g. |
None
|
query
|
Any
|
Optional |
None
|
filter
|
Any
|
Optional CQL2 filter (cql2-json dict or cql2-text string). When
given, the endpoint must advertise the |
None
|
sortby
|
Any
|
Optional sort specification forwarded to the API. |
None
|
max_items
|
int | None
|
Optional cap on the total number of items returned (bounds paging at the API). |
None
|
limit
|
int | None
|
Optional page size forwarded to the API. |
None
|
signer
|
Any
|
Optional signer used only when |
None
|
Returns:
| Type | Description |
|---|---|
Any
|
The |
Any
|
|
Raises:
| Type | Description |
|---|---|
OptionalPackageDoesNotExist
|
When |
ValueError
|
When both |
Examples:
- Search a collection over an AOI and time window, then build a cube
(requires the
[stac]extra and network access):>>> from pyramids.stac import search # doctest: +SKIP >>> from pyramids.dataset import DatasetCollection # doctest: +SKIP >>> items = search( # doctest: +SKIP ... "https://earth-search.aws.element84.com/v1", ... "sentinel-2-l2a", ... bbox=(11.0, 46.0, 11.2, 46.2), ... datetime="2023-06/2023-08", ... query={"eo:cloud_cover": {"lt": 20}}, ... max_items=10, ... ) >>> cube = DatasetCollection.from_stac(items, asset=["red", "green", "blue"]) # doctest: +SKIP
Source code in src/pyramids/stac/search.py
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | |