This repository has been archived on 2026-03-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
rio-tiler-tms/CLAUDE.md
2026-02-25 09:28:37 +08:00

3.9 KiB
Raw Permalink Blame History

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

This is a collection of FastAPI-based tile servers that use rio-tiler to serve COG (Cloud Optimized GeoTIFF) files as dynamic map tiles. The project serves imagery from different planetary bodies:

  • app.py - NJ 2020 aerial imagery (I7D16.tif) - UInt16 data with per-band rescaling
  • app_world.py - Natural Earth global basemap (HYP_HR_SR_OB_DR_cog.tif) - uint8 RGB
  • app_mars.py - Mars MGS MOLA global basemap - Uses custom Mars CRS in equidistant cylindrical projection

Running the Servers

Each app is an independent FastAPI application. Run with uvicorn:

# Run NJ imagery server (default port 8000)
uvicorn app:app --reload

# Run world basemap server
uvicorn app_world:app --port 8001 --reload

# Run Mars basemap server
uvicorn app_mars:app --port 8002 --reload

Architecture

Common Pattern (app.py, app_world.py)

All apps follow the same pattern using rio_tiler.io.Reader:

  1. Tile endpoint (/tiles/{z}/{x}/{y}.png) - Reads COG tiles and returns PNG
  2. TileJSON endpoint (/tilejson.json) - Returns TileJSON 2.2.0 metadata
  3. Optional viewer (/) - app.py includes a Leaflet.js viewer

Key rio-tiler concepts:

  • Reader(DATA_PATH) context manager for reading COGs
  • cog.tile(x, y, z) to extract tiles
  • img.render() with img_profiles for output formatting
  • cog.get_geographic_bounds() for bounds in geographic CRS
  • cog.minzoom/cog.maxzoom for zoom levels

Mars CRS (app_mars.py)

The Mars server uses a custom TileMatrixSet to handle Mars-specific coordinate system:

  • CRS: Simple Cylindrical Mars (equidistant cylindrical, meters)
  • Sphere radius: 3,396,190 m (vs Earth's ~6,378,137 m)
  • Extent: ±πR in x, ±πR/2 in y (calculated from Mars radius)
  • matrix_scale=[2, 1]: 2×1 tiles at zoom 0, matching Cesium's GeographicTilingScheme

Critical design decision: TMS and TIF both use the same Mars CRS (eqc meters). Avoid using longlat (degrees) because PROJ would attempt datum transformation through WGS84, causing "PROJ: eqc: Invalid latitude" errors due to the large sphere radius difference.

MARS_CRS = CRS.from_proj4(
    "+proj=eqc +lat_ts=0 +lat_0=0 +lon_0=0 +x_0=0 +y_0=0 +a=3396190 +b=3396190 +units=m +no_defs"
)

MARS_TMS = TileMatrixSet.custom(
    crs=MARS_CRS,
    extent=(-_MAX_X, -_MAX_Y, _MAX_X, _MAX_Y),
    matrix_scale=[2, 1],
)

Pass custom TMS to Reader: Reader(DATA_PATH, tms=MARS_TMS)

Data Handling

Rescaling (app.py)

For UInt16 imagery, use per-band rescaling based on p2/p98 statistics:

RESCALE = [
    (6130, 40453),   # Red
    (10641, 41211),  # Green
    (12482, 36323),  # Blue
]

img.render(img_format="PNG", rescale=RESCALE, **img_profiles.get("png", {}))

uint8 Data (app_world.py, app_mars.py)

No rescaling needed for pre-scaled uint8 imagery:

img.render(img_format="PNG", **img_profiles.get("png", {}))

Dependencies

Managed via uv with pyproject.toml:

  • fastapi - Web framework
  • rio-tiler - COG tiling engine
  • rasterio - GeoTIFF I/O
  • uvicorn - ASGI server
  • pyproj, morecantile - CRS and TMS handling (for Mars app)

Adding New Tile Servers

To add a new COG tile server:

  1. Copy the appropriate template (app.py for UInt16, app_world.py/app_mars.py for uint8)
  2. Update DATA_PATH to point to your COG file in data/
  3. For non-Earth data, create a custom CRS/TMS following app_mars.py pattern
  4. Adjust rescaling if needed for UInt16 data
  5. Update app metadata (title, description)
  6. Run with uvicorn on a unique port

File Structure

data/               # COG files (gitignored)
├── I7D16.tif
├── HYP_HR_SR_OB_DR_cog.tif
└── Mars_MGS_MOLA_...tif

app.py              # NJ imagery server
app_world.py        # World basemap server
app_mars.py         # Mars basemap server
pyproject.toml      # uv dependencies