stac-rs v0.10

  • 19th Sep 2024
  •  • 
  • 4 min read
  •  • 
  • Tags: 
  • rust
  • stac

Ferris holding the STAC logo

stac-rs is a "hobby" project of mine. I put "hobby" in quotes because I've sunk quite a few tens (hundreds?) of hours into it because I think it might actually Be Useful™ in the real world in the not-to-distant future. I talked about it at FOSS4G-NA 2024, and afterwords discovered that at least one person is using it in production. So, I'm happy to announce the v0.10 release of the core crate, stac.

STAC v1.1.0 🎉

STAC v1.1.0 was released this month, and stac-rs is STAC v1.1.0 by default!

use stac::Item;

let item = Item::new("an-id");
assert_eq!(item.version.to_string(), "1.1.0");

You can migrate existing STAC objects from v1.0.0 to v1.1.0:

use stac::{Item, Migrate, Version};

let mut item: Item = stac::read("item-v1.0.0.json").unwrap();
let item = item.migrate(&Version::v1_1_0).unwrap();
assert_eq!(item.version, Version::v1_1_0);

This migration includes moving raster and eo bands information up to the new bands structure, as described in the best practices.

Formats

With the advent of stac-geoparquet as a potential1 alternative storage format for STAC items, stac-rs now supports three formats:

  • JSON
  • Newline-delimited JSON (ndjson)
  • stac-geoparquet

Each format provides methods to read and write its data either from a Read or a Write, or from Vec<u8> or Bytes:

use stac::{Item, Format, ItemCollection};

let item: Item = Format::json().from_path("item.json").unwrap();

let items: ItemCollection = Format::geoparquet().from_path("items.parquet").unwrap();
Format::ndjson().write("items.ndjson", items);

Object store

fsspec is a widely-used Python library that allows folks to use the same interface to open files from a variety of sources, including the local filesystem and cloud provider blob storage. object_store is the Rust equivalent, and stac v0.10 includes object_store support via some free functions:

use stac::Item;

let href = "s3://bucket/item.json";
let options = [("aws_access_key_id", "...")];
let item: Item = stac::io::get_opts(href, options).await.unwrap();
stac::io::put_opts(href, item, options).await.unwrap();

Other crates

Along with the stac release, we also released:

Next steps

Now that I've got the core library updated, I'm going to spend some time on the Python bindings. Specifically, I've implemented (but not released) a request to add search capabilities to the Python API, particularly to enable writing the search directly to stac-geoparquet:

import stacrs

stacrs.search_to(
    "items.parquet",
    "https://landsatlook.usgs.gov/stac-server",
    collections="landsat-c2l2-sr",
    intersects={"type": "Point", "coordinates": [-105.119, 40.173]},
    sortby="-properties.datetime",
    max_items=1,
)

I'd like to release that, along with some better documentation on how to use the Python bindings and what alternatives you should use when stacrs isn't enough (i.e. pystac and pystac-client). I also need to do a write-up of my FOSS4G-NA 2024 talk to provide more narrative on how to use the CLI.

Get in touch

If you're using stac-rs, or you'd like to use it, get in touch! I'm on Bluesky, or ask anything in the Github Discussions. I think that Rust has a interesting, if niche, place to contribute to the geospatial community, both as a component of our shared open source infrastructure and as a performance-boosting layer for downstream data consumers.

1

The community is still figuring out how exactly stac-geoparquet will interact with the STAC specification. Some sticky points include the awkwardness of updating existing parquet files, and the additional burden on developers to maintain tooling for multiple formats. See the recent Cloud Native Geospatial blog post for more.