Design decisions, dependency rationale, and how abovepy fits together.
User Applications (Jupyter, ArcGIS Pro, scripts, web maps)
│
▼
abovepy ──── COG URLs ───▶ TiTiler (external, optional)
│
▼
pystac-client
│ HTTPS
▼
KyFromAbove STAC API (stac-fastapi on AWS)
│
▼
s3://kyfromabove/ (public bucket: COGs, COPC, LAZ)
There are no abovepy.dem, abovepy.lidar, or abovepy.imagery modules. The STAC query pattern is identical for all products — the only difference is the collection ID. Product type is a parameter to search().
# One function, different products
abovepy.search(county="Pike", product="dem_phase3")
abovepy.search(county="Pike", product="ortho_phase3")
abovepy.search(county="Pike", product="laz_phase2")abovepy is not a STAC framework. It wraps pystac-client with Kentucky-specific opinions: knowing which collections are DEMs vs orthos, knowing EPSG:3089, knowing the phase structure, providing county-name lookups. If you need a general STAC client, use pystac-client directly.
search() returns metadata (tile index). download() fetches bytes. read() streams without downloading. Data is never fetched until explicitly requested.
Mosaics default to VRT (Virtual Raster) — a zero-copy XML file that references the original tiles. GeoTIFF output is only created when the user explicitly requests a .tif path.
The KyFromAbove S3 bucket is public. abovepy never prompts for or requires AWS credentials.
src/abovepy/
├── __init__.py # Public API (search, download, read, mosaic, info)
├── client.py # KyFromAboveClient — main entry point
├── stac.py # pystac-client wrapper + retry + cache
├── products.py # Product registry: names → collection IDs
├── download.py # Download manager (httpx, progress, retry)
├── mosaic.py # VRT builder + rasterio.merge
├── titiler.py # TiTiler URL helpers
├── io/
│ ├── cog.py # COG reads via rasterio (/vsicurl/, windowed)
│ └── pointcloud.py # COPC/LAZ reads (optional dep)
└── utils/
├── crs.py # EPSG:3089 ↔ EPSG:4326
├── bbox.py # Bbox validation + county lookup
└── cache.py # LRU cache for STAC responses
| Package | Purpose |
|---|---|
| pystac-client | STAC API queries |
| rasterio | COG reading, windowed reads, mosaicking |
| geopandas | GeoDataFrame returns for tile indices |
| pyproj | CRS conversion (EPSG:4326 ↔ EPSG:3089) |
| httpx | HTTP client for downloads |
| tqdm | Download progress bars |
| shapely | Geometry operations |
| Extra | Packages | Purpose |
|---|---|---|
lidar |
laspy | COPC/LAZ point cloud reads |
viz |
leafmap, matplotlib | Visualization |
s3 |
boto3 | Direct S3 access |
| Package | Reason |
|---|---|
stackstac |
KyFromAbove is not time-series satellite data. stackstac adds xarray + dask for functionality we don't use. |
requests |
httpx provides async support, HTTP/2, and modern connection pooling. See DL-001. |
titiler (as dep) |
abovepy generates TiTiler-compatible URLs. TiTiler itself is a server deployment, not a library dependency. |
The arcgis/AbovePro.pyt toolbox imports abovepy and adds:
- Native ArcGIS Pro parameter UI (extent widgets, dropdowns)
- Progress messaging via
arcpy.SetProgressor - Map integration (add layers directly to the project)
- Domain workflows: one-click hillshade, county-based downloads
The toolbox calls the Python library — it does not duplicate STAC logic.
The KyFromAbove STAC API supports:
- CQL2 filtering (basic-cql2, cql2-json, cql2-text)
- Collection search with filter, sort, free-text, fields, query
- OGC API Features with fields, query, sort, filter
- Item search with fields, query, sort, filter
abovepy leverages server-side filtering rather than reimplementing it client-side.