# umbra-py — full LLM context

> A Python-first toolkit for Umbra's open SAR (synthetic aperture radar) data. It searches Umbra's static STAC catalog -- which publishes no upstream search API -- streams cloud-optimized products, and renders quicklooks, footprint maps, change composites and timescans. Because there is no Umbra STAC API, this library is the de-facto programmatic front door to a public, multi-terabyte SAR archive.

umbra-py collapses two kinds of friction. The *mechanical* friction -- searching a catalog with no search endpoint, resuming multi-GB downloads, streaming cloud-optimized GeoTIFFs -- is handled by the deterministic core (`requests` + `click`, no heavy dependency in the base install). The *interpretive* friction -- which product type to ask for, why two polarizations must not be differenced, what a decibel stretch means -- is handled by making the library AI-legible: the CLI emits JSON, items expose `to_llm_context()` context cards, `umbra context` prints the domain document machine-readably, and the archive is reachable through two AI-native front doors -- an MCP server (`umbra mcp`) and a read-only STAC API (`umbra serve`). Heavy geospatial dependencies (rasterio, matplotlib, folium, xarray, sarpy) live behind extras and load lazily, so an agent can search and reason over metadata with nothing extra installed.

Determinism boundary: the core library is deterministic and never calls a model. Anything AI-facing (this document, the context cards, the MCP server, the STAC API) either describes the library or exposes it as tools -- models plan, describe and narrate; the library searches, downloads and renders. A model output never becomes a coordinate, a URL or a filter without passing through the deterministic layer.

## Product types

Ordered easiest-to-use first (GEC) to rawest (CPHD). Prefer GEC unless the task needs complex or phase data.

- **GEC** — Geocoded Ellipsoid Corrected image: a cloud-optimized GeoTIFF, map-projected and analysis-ready. The easiest product to use and the usual starting point.
- **CSI** — Color Sub-aperture Image: a quick-look RGB GeoTIFF that colorizes sub-aperture/frequency content. Good for eyeballing a scene, not for radiometric measurement.
- **SIDD** — Sensor Independent Derived Data: a geocoded, detected (amplitude) image in NITF. Map-projected like GEC but in the standard NGA format.
- **SICD** — Sensor Independent Complex Data: full complex data in the slant plane (not map-projected). Needed for interferometry and advanced processing; not a display image.
- **CPHD** — Compensated Phase History Data: the raw signal phase history, the least-processed product. For signal-level work, not for viewing.

Polarization caveat: Polarizations are not interchangeable: an HH scene and a VV scene of the same place measure different scattering and must not be differenced for change detection. Compare like polarization with like.

## Search parameters

Filters shared by the `umbra search` CLI, `UmbraCatalog.search` and `CatalogIndex.search`. Build a valid query in one shot:

- **bbox** — Footprint filter as (min_lon, min_lat, max_lon, max_lat) in WGS84 degrees. Items whose footprint overlaps the box are returned.
- **intersects** — GeoJSON polygon filter (Polygon / MultiPolygon, or a Feature / FeatureCollection wrapping one). Items whose footprint overlaps the polygon are returned -- a tighter spatial filter than the rectangular bbox, and the one to use for an area of interest that isn't a rectangle (a coastline, a border, a catchment). Mutually exclusive with bbox/place.
- **place** — Free-text place name (e.g. 'Port of Long Beach'). Geocoded to a bbox via Nominatim; resolve it yourself with geocode_place if you want to inspect the box first. Mutually informative with bbox, not required.
- **area** — Substring match against the Umbra task (AOI campaign) name, e.g. 'Centerfield, Utah'. Tasks group every pass of one site over time. Set fuzzy=True to match it loosely instead (see 'fuzzy').
- **fuzzy** — When true, widen 'area' from a literal substring to a deterministic token-wise match: word-order- and punctuation-independent and tolerant of a small typo, so 'utah centerfield' or 'centrfield' still reach 'Centerfield, Utah'. No model call, and a strict superset of the substring match (it never drops a result). Semantic aliasing ('grain storage north dakota' -> 'Beet Piler - ND') is out of scope.
- **start** — Earliest acquisition date, inclusive. An ISO YYYY-MM-DD date, a bare year or year-month (2024, 2024-03), or a relative expression resolved deterministically with no model call: 'today', 'yesterday', '3 months ago', 'last month'. Spans snap to their first day.
- **end** — Latest acquisition date, inclusive. Same formats as start; a bare year, month or period ('2024', 'last month') snaps to that span's last day, so start='2024' end='2024' covers the whole year.
- **products** — Restrict to items exposing these product types (any of GEC, CSI, SIDD, SICD, CPHD). Omit to accept all.
- **polarizations** — Keep only items exposing at least one of these polarizations (e.g. ['VV'], case-insensitive). The SAR-native filter that keeps a change comparison like-with-like -- HH and VV image different scattering physics and must not be differenced. An item with no polarization metadata is excluded when this is set.
- **min_incidence** — Lower bound (inclusive, degrees) on the view incidence angle. An item with no incidence metadata is excluded when this is set.
- **max_incidence** — Upper bound (inclusive, degrees) on the view incidence angle. An item with no incidence metadata is excluded when this is set.
- **max_resolution** — Keep only items at least this fine: both range and azimuth resolution must be <= this many metres. An item missing a resolution is excluded. A set acquisition-property filter excludes items lacking that property (the STAC Query-extension convention).
- **limit** — Maximum number of items to return.
- **max_per_task** — Cap items per task. Use 1 for a 'one pin per site' world view; omit for the full time series of each site.

## License and attribution

All Umbra open data is licensed CC-BY-4.0. Attribution is mandatory and must survive every derived product -- including model-generated text describing the data. Use the string: "Contains Umbra open data, licensed under CC BY 4.0."

## CLI command reference

The CLI subcommands map 1:1 to library functions. Run any command with `--help` for its full options; `--json` emits a machine-readable result on the commands that produce one (`search`, `info`, `download`, `index info`, `preflight`, `chips`, `describe`, `ask`, `watch`, `semantic search`, `embed similar`/`search`, and the render commands `change`/`timescan`/`swipe`/`gallery`/`map`/`stack`) -- see `docs/schemas/` for the shapes, one published contract per document.

- `umbra ask` — Plan a catalog search from a plain-language question with a model.
- `umbra change` — Render multi-temporal SAR change: a color composite or a time-lapse.
- `umbra chips` — Cut SAR scenes into fixed-size, georeferenced ML training tiles.
- `umbra context` — Print the library's LLM context document as JSON.
- `umbra convert` — Convert a downloaded SICD (complex) product to a map-ready GeoTIFF.
- `umbra demo` — Build a self-serve interactive catalog explorer as one HTML page.
- `umbra describe` — Describe a SAR scene in plain language with a vision model.
- `umbra download` — Download asset(s) of an item given its STAC JSON URL.
- `umbra embed` — Visual similarity search over the archive (embedding-based, C5).
- `umbra embed build` — Render and embed acquisition quicklooks into a scene-similarity index.
- `umbra embed fetch` — Download the published scene-embedding index for instant similarity search.
- `umbra embed info` — Show what a scene index holds: scene-vector count, model and dimension.
- `umbra embed search` — Find archived scenes matching a plain-language QUERY ("ships at a berth").
- `umbra embed similar` — Find archived scenes that look like the acquisition at ITEM_URL.
- `umbra gallery` — Render search results as a browseable HTML SAR thumbnail gallery.
- `umbra index` — Build and inspect a local SQLite catalog index for fast offline search.
- `umbra index bake` — Reverse-geocode indexed acquisitions and cache their place labels.
- `umbra index bake-thumbnails` — Render a small SAR quicklook per acquisition and cache it in the index.
- `umbra index build` — Walk Umbra's archive and persist matching acquisitions into the index.
- `umbra index export` — Export a local index to stac-geoparquet for serverless catalog search.
- `umbra index export-thumbnails` — Write the index's baked thumbnails to a shareable sidecar database.
- `umbra index fetch` — Download the published prebuilt catalog index for instant local search.
- `umbra index fetch-thumbnails` — Download the published SAR thumbnails and merge them into the index.
- `umbra index info` — Show what a local index holds: item count, date span and task count.
- `umbra index update` — Cheaply refresh an existing index by re-walking only recent acquisitions.
- `umbra info` — Show a summary of a STAC item.
- `umbra llms-txt` — Print the project's llms.txt context bundle to stdout.
- `umbra load` — Load a clipped/decimated SAR scene from a STAC item URL to a GeoTIFF.
- `umbra map` — Render search results as an interactive map or GeoJSON file.
- `umbra mcp` — Run the umbra Model Context Protocol server (stdio transport).
- `umbra preflight` — Ask which complex acquisitions can support a measurement, before downloading any.
- `umbra quicklook` — Render a standalone SAR quicklook image from a STAC item URL.
- `umbra search` — Search the catalog by area, date and product type.
- `umbra semantic` — Semantic (embedding-based) task-name search -- the model-backed layer of natural-language search.
- `umbra semantic build` — Embed the index's task names into a semantic search index.
- `umbra semantic info` — Show what a semantic index holds: task-vector count, model and dimension.
- `umbra semantic search` — Rank Umbra task/site names by how well they match a plain-language QUERY.
- `umbra serve` — Run a read-only STAC API over the catalog index (HTTP server).
- `umbra showcase` — Assemble a static, hostable showcase site into a directory.
- `umbra sites` — Rank the archive's most repeat-imaged sites -- where change detection has something to measure.
- `umbra stack` — Co-register a site's acquisitions into one analysis-ready datacube.
- `umbra swipe` — Render an interactive before/after swipe map of two SAR passes.
- `umbra tiles` — Tile the whole catalog into a single-file PMTiles vector archive.
- `umbra timescan` — Collapse a whole SAR time series into one temporal-statistics image.
- `umbra view` — Explore one SAR scene at full resolution in an interactive web viewer.
- `umbra watch` — Report only acquisitions new since the last run -- standing site monitoring.

## AI-native interfaces

- **MCP server** (`umbra mcp` / `uvx --from 'umbra-py[mcp]' umbra-mcp`, `[mcp]` extra) — exposes `search_catalog`, `get_item`, `geocode_place`, `index_stats`, `quicklook`, `change_composite`, `timescan`, `download_asset`, `watch_site` (report only passes new since the last check) and `find_similar` / `find_similar_text` (visual similarity search over a prebuilt scene-embedding index) as MCP tools. The imagery tools return the rendered PNG as an MCP image block. Also serves a `umbra://context` resource and the `monitor-site` / `watch-site` / `find-similar-scenes` / `survey-region` prompts.
- **STAC API** (`umbra serve`, `[serve]` extra) — a read-only STAC API over the same `CatalogIndex`: landing page, `/conformance`, `/collections`, `/collections/{id}`, `/collections/{id}/items`, `/collections/{id}/items/{item_id}`, item search over `GET /search` and `POST /search` (bbox, datetime interval, ids, limit, token pagination), and `GET`/`POST /sites` to rank the most repeat-imaged sites (the discovery step before the analysis routes), with an OpenAPI doc at `/docs`.

## Module guide

The library's layers, each with the opening of its source docstring. Read top-to-bottom to follow a scene from discovery to presentation.

### `umbra_py/catalog.py` (UmbraCatalog)

Search Umbra's published open SAR data.

### `umbra_py/index.py` (CatalogIndex)

A local SQLite index of Umbra acquisitions for fast, repeatable search.

### `umbra_py/models.py` (UmbraItem)

Lightweight representations of Umbra STAC items.

### `umbra_py/download.py` (download_asset)

Download Umbra data assets over anonymous HTTPS, with resume support.

### `umbra_py/load.py` (to_xarray / to_stack / to_geotiff)

Analysis-ready loading of Umbra SAR imagery into ``xarray`` (the *load* step).

### `umbra_py/viz/__init__.py` (quicklook / maps / change / timescan / gallery)

Visualization helpers for Umbra search results.

### `umbra_py/context.py` (llm_context)

Self-describing context for language-model consumers.

### `umbra_py/mcp_server.py` (umbra-mcp)

``umbra-mcp`` — a Model Context Protocol server over :mod:`umbra_py`.

### `umbra_py/serve.py` (umbra serve)

``umbra serve`` -- a read-only STAC API façade over the local catalog index.

---

Contains Umbra open data, licensed under CC BY 4.0.

