Skip to main content

KyFromAbove LiDAR, DEM, and orthoimagery data access for Python

Project description

PyPI version Python versions CI License Docs QGIS Plugin

abovepy

KyFromAbove LiDAR, DEM, orthoimagery, and oblique imagery data access for Python.

Kentucky's KyFromAbove program provides statewide 2ft DEMs, 3-inch orthoimagery, 3-inch oblique imagery, and COPC LiDAR point clouds — all publicly available on S3 with a STAC API for discovery. abovepy gives you Pythonic access to all of it, plus server-side terrain analysis via TiTiler. No credentials required.

Install

pip install abovepy

Optional extras:

pip install abovepy[lidar]    # COPC/LAZ point cloud support
pip install abovepy[viz]      # leafmap + matplotlib visualization
pip install abovepy[all]      # Everything

Quick Start

Search by county name

import abovepy

# Find DEM tiles covering Franklin County
tiles = abovepy.search(county="Franklin", product="dem_phase3")
print(tiles)

Search by bounding box

tiles = abovepy.search(
    bbox=(-84.9, 38.15, -84.8, 38.25),
    product="dem_phase3"
)

Download tiles

paths = abovepy.download(tiles, output_dir="./data")

Mosaic into a single raster

vrt = abovepy.mosaic(paths, output="frankfort.vrt")

Search by point with feet-based buffer

# 500-foot radius around a point (uses EPSG:3089 for accurate measurement)
tiles = abovepy.search(
    point=(-84.87, 38.20),
    buffer_feet=500,
    product="dem_phase3"
)

Corridor search

from shapely.geometry import LineString

# Search along a road centerline with 200ft buffer on each side
road = LineString([(-84.90, 38.20), (-84.85, 38.19), (-84.82, 38.21)])
tiles = abovepy.search(geometry=road, buffer_feet=200, product="ortho_phase3")

Stream without downloading

data, profile = abovepy.read(
    tiles.iloc[0].asset_url,
    bbox=(-84.85, 38.18, -84.82, 38.21)
)

Data quality validation

result = abovepy.search(county="Pike", product="dem_phase3")

# Check for data quality issues
warnings = result.validate()
for w in warnings:
    print(f"Warning: {w}")
# Warning: 3 tile(s) (12%) have no acquisition date metadata.

Provenance metadata

# Generate source documentation for deliverables
prov = result.provenance()
print(prov["source_program"])       # KyFromAbove
print(prov["acquisition_period"])   # 2022-2025
print(prov["native_crs"])           # EPSG:3089
print(prov["tile_count"])           # 42
print(prov["estimated_size_mb"])    # 210.0

Explore available products

print(abovepy.info())
#   product        display_name                format  resolution  phase  crs
#   dem_phase1     DEM Phase 1 (5ft)           COG     5ft         1      EPSG:3089
#   dem_phase2     DEM Phase 2 (2ft)           COG     2ft         2      EPSG:3089
#   dem_phase3     DEM Phase 3 (2ft)           COG     2ft         3      EPSG:3089
#   ortho_phase1   Orthoimagery Phase 1 ...    COG     6in         1      EPSG:3089
#   ...plus oblique products

Terrain analysis (server-side)

Generate hillshade, slope, and contour tiles directly from the TiTiler-pgSTAC server — no downloads needed:

from abovepy.titiler import hillshade_tile_url, slope_tile_url, contour_tile_url

# Hillshade TileJSON URL — use in MapLibre/Leaflet/leafmap
url = hillshade_tile_url(bbox=(-84.9, 38.15, -84.8, 38.25))

# Slope in degrees
url = slope_tile_url(bbox=(-84.9, 38.15, -84.8, 38.25))

# Contour lines every 50ft
url = contour_tile_url(bbox=(-84.9, 38.15, -84.8, 38.25), increment=50)

Interactive notebook maps

# Display a hillshade map in Jupyter (requires pip install abovepy[viz])
m = abovepy.show("dem_phase3", county="Franklin", algorithm="hillshade")
m  # renders interactive leafmap

Persistent virtual mosaics

Register a search with TiTiler-pgSTAC to get a shareable tile URL:

search_id = abovepy.register_search("dem_phase3", bbox=(-84.9, 38.15, -84.8, 38.25))
from abovepy.searches import search_tile_url
url = search_tile_url(search_id)  # stable TileJSON URL

Oblique imagery

Access Phase 3 oblique imagery from 4 camera directions (backward, forward, left, right):

from abovepy.obliques import list_oblique_seasons, search_obliques

seasons = list_oblique_seasons()
frames = search_obliques(direction="bwd", season=seasons[-1], max_items=10)
# Each frame has: frame_id, tif_url, json_url, season, direction

Examples

DEM Phase Comparison

Compare 5ft Phase 1 vs 2ft Phase 3 resolution from the same tile in Frankfort:

DEM Phase Comparison

Hillshade from Streamed DEM

Compute a hillshade directly from a cloud-hosted DEM tile — no download required:

Hillshade

Streamed DEM Window

Read just the pixels you need with a bounding box:

Stream Window

Ortho RGB Extract

Pull 3-inch true-color imagery of the Kentucky State Capitol:

Ortho RGB

Kentucky River REM

Relative Elevation Model showing height above the Kentucky River in Frankfort:

Kentucky River REM

Mine Volume Estimate

Estimate cut volume for an active mine permit in Perry County using DEM differencing:

Mine Volume

Search Results Map

Visualize tile coverage for Franklin County:

Search Results

DEM Change Detection

Compare Phase 1 vs Phase 3 DEM over a Pike County mining area to detect terrain change:

DEM Change Detection

Flood Inundation Simulation

Simulate rising water levels on a DEM — watch the Kentucky River floodplain fill:

Flood Inundation

Flood Simulation GIF

Slope & Aspect Analysis

Compute slope and aspect from DEM for terrain analysis:

Slope & Aspect

Elevation Contours over Hillshade

Overlay 10ft/50ft contour lines on a shaded relief map:

Contour Map

Elevation Profile

Extract a cross-valley transect showing the Kentucky River valley profile:

Elevation Profile

Land Use Change

Side-by-side ortho imagery across phases showing development over time:

Land Use Change

Multi-County Tile Coverage

Map DEM tile coverage across five Central Kentucky counties:

Multi-County Coverage

Multi-Product Site Assessment

Combine ortho, DEM, hillshade, and slope for a single area:

Site Assessment

Product Gallery

One tile from each product type - DEM Phase 1/2/3 and Ortho Phase 3:

Product Gallery

pgSTAC Terrain Previews

Server-side DEM elevation, hillshade, and ortho previews generated from TiTiler-pgSTAC:

pgSTAC Terrain Previews

Oblique Site Inspection

Four-direction oblique frame coverage summarized for rapid site inspection:

Oblique Site Inspection

See examples/scripts/ for the full source code behind each image and demo.

Available Products

Product Resolution Format Collection ID
dem_phase1 5ft COG dem-phase1
dem_phase2 2ft COG dem-phase2
dem_phase3 2ft COG dem-phase3
ortho_phase1 6 inch COG orthos-phase1
ortho_phase2 6 inch COG orthos-phase2
ortho_phase3 3 inch COG orthos-phase3
laz_phase1 Varies LAZ laz-phase1
laz_phase2 Varies COPC laz-phase2
laz_phase3 Varies COPC laz-phase3
oblique_phase3_bwd 3 inch COG obliques-phase3*
oblique_phase3_fwd 3 inch COG obliques-phase3*
oblique_phase3_left 3 inch COG obliques-phase3*
oblique_phase3_right 3 inch COG obliques-phase3*

* Oblique STAC collection pending — use search_obliques() for S3-based discovery.

All data is natively in EPSG:3089 (Kentucky Single Zone, US feet). abovepy accepts bounding boxes in EPSG:4326 by default.

ArcGIS Pro Toolbox

An ArcGIS Pro Python Toolbox is included in arcgis/AbovePro.pyt with tools for:

  • Find KyFromAbove Tiles — draw extent, pick product, see available tiles
  • Download Tiles — download with progress tracking
  • Download and Load — download + add to map in one step
  • DEM Hillshade — automated DEM → hillshade workflow
  • County Download — download by county name dropdown

See ArcGIS Pro Toolbox Guide for installation and usage.

Web Visualization

abovepy generates TiTiler-compatible URLs for web map integration:

from abovepy.titiler import cog_tile_url, collection_tile_url, hillshade_tile_url

# Individual COG via standalone TiTiler
url = cog_tile_url(tiles.iloc[0].asset_url)

# Entire collection via TiTiler-pgSTAC (no individual URLs needed)
url = collection_tile_url("dem_phase3", bbox=(-84.9, 38.15, -84.8, 38.25))

# Server-side hillshade
url = hillshade_tile_url(bbox=(-84.9, 38.15, -84.8, 38.25))

# Use any of these with MapLibre GL JS, Leaflet, or leafmap

KyFromAbove TiTiler endpoints are used by default. A docker-compose.yml for local TiTiler is in examples/.

Kentucky Engineering Geometry

abovepy includes geometry utilities that work natively in Kentucky State Plane (EPSG:3089, Northing/Easting in US Survey Feet) — the coordinate system surveyors and engineers actually use:

from abovepy import buffer_feet, corridor_buffer
from shapely.geometry import Point, LineString

# Buffer a survey point by 500 feet using State Plane coordinates
site = Point(1_600_000, 312_000)  # Easting, Northing in feet
area = buffer_feet(site, 500.0, input_crs="EPSG:3089")

# Create a corridor polygon from a road centerline (200ft each side)
road = LineString([(1_599_000, 312_000), (1_601_000, 312_500)])
corridor = corridor_buffer(road, 400.0, input_crs="EPSG:3089")

# Also works with WGS84 — reprojects to EPSG:3089 internally
site_wgs84 = Point(-84.87, 38.20)
area = buffer_feet(site_wgs84, 500.0)  # input_crs defaults to EPSG:4326

Command-Line Interface

abovepy includes a full CLI for terminal workflows:

# Search with feet-based buffer
abovepy search --point=-84.87,38.20 --buffer-feet 500 -p dem_phase3

# Get provenance metadata as JSON
abovepy search --county Franklin -p dem_phase3 --format provenance

# Estimate download size
abovepy estimate --county Franklin -p ortho_phase3

# Download tiles (concurrent, resumable)
abovepy download --county Franklin -p dem_phase3 -o ./data --workers 8

# Generate a hillshade tile URL
abovepy tile-url --bbox=-84.9,38.15,-84.8,38.25 --algorithm hillshade

Advanced: Direct STAC Access

For power users who need the full pystac-client:

client = abovepy.KyFromAboveClient()
stac_client = client.get_stac_client()

# Full pystac-client API
results = stac_client.search(
    collections=["dem-phase3"],
    bbox=(-84.9, 38.15, -84.8, 38.25),
    datetime="2022-01-01/..",
).item_collection()

Related Resources

  • kyfromabove-on-aws-examples — Foundational examples for accessing KyFromAbove data on AWS using tile index GeoPackages and boto3. Great reference for understanding the raw S3 data structure that abovepy wraps.
  • kyfromabove-gisconference2025-workshop — 2025 KY GIS Conference workshop covering STAC API access from Python, ArcGIS Pro, and QGIS. Includes building height estimation from COPC LiDAR, DEM change detection, and MosaicJSON workflows.
  • KyFromAbove — Official program site from the Kentucky Division of Geographic Information.
  • STAC Browser — Browse the KyFromAbove STAC catalog interactively.

Data Source

  • STAC API: https://spved5ihrl.execute-api.us-west-2.amazonaws.com/
  • S3 Bucket: s3://kyfromabove/ (public, us-west-2)
  • AWS Open Data Registry: KyFromAbove

License

GPL-3.0 — see LICENSE.


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

abovepy-2.1.0.tar.gz (50.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

abovepy-2.1.0-py3-none-any.whl (65.0 kB view details)

Uploaded Python 3

File details

Details for the file abovepy-2.1.0.tar.gz.

File metadata

  • Download URL: abovepy-2.1.0.tar.gz
  • Upload date:
  • Size: 50.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for abovepy-2.1.0.tar.gz
Algorithm Hash digest
SHA256 30c00c068a2a883c494a41ee1c23c44bd2a6500f4ebaa6917e5de88e72cf4ceb
MD5 4ff53a94b7aea9dd5827791fba08ffc3
BLAKE2b-256 9cb7a843ed4a782c881260765e7083db532e233f901ef4e03cbb8d74fc418149

See more details on using hashes here.

File details

Details for the file abovepy-2.1.0-py3-none-any.whl.

File metadata

  • Download URL: abovepy-2.1.0-py3-none-any.whl
  • Upload date:
  • Size: 65.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for abovepy-2.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c963adba436dcb07143a8056484f9832451af13f6c9210ec91bd599402bf69a5
MD5 825c8b084be7a23ad8ed161aff40ba4f
BLAKE2b-256 30aca31fd83b408b31cbbfaa2db75328a9564c5f6710859b221f19b6354de5c5

See more details on using hashes here.

Supported by

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