GeoTessera

repository·main·Indexed 43 days ago

https://github.com/ucam-eo/geotessera

A Python library interface for accessing, exporting, and visualizing Tessera geofoundation model embeddings. It provides tools to handle 128-channel representation maps at 10m resolution derived from Sentinel-1 and Sentinel-2 imagery, featuring a Zarr-based cloud-native API, CLI for GeoTIFF and web map exports, and utilities for dequantizing int8 embeddings to float32.

Tokens
64.9K
Snippets
199
Records
246
Agent score
56%

What's inside GeoTessera

  1. Understand the GeoTessera Data Access Layer

    main

    GeoTessera streams manifests, embedding tiles, and landmasks via HTTPS from the Source Cooperative repository. It uses a urllib3 connection pool for efficient downloads and implements several reliability features:

    • Per-output-dir mirroring: Tiles are saved to the directory specified by --output (or embeddings_dir) and persist for reuse.
    • Connection pooling: Reuses connections for thousands of per-tile GET requests.
    • Retries: Uses exponential backoff for rate limiting, server errors, and dropped connections (honouring Retry-After).
    • Integrity checking: Validates response integrity via ETag (MD5) and raises errors on truncated responses.
    • Conditional caching: Uses If-Modified-Since for manifests to minimize bandwidth.
    • Resumable downloads: Skips existing files in the output directory on rerun.
    • Progress callbacks: Provides real-time feedback on download speed and size.
  2. Understand the GeoTessera layered architecture

    main

    GeoTessera uses a layered architecture to manage data from storage to user interface:

    1. User Interface Layer: Provides CLI commands (e.g., geotessera download, visualize, webmap) and a Python API via the GeoTessera class.
    2. Core Processing Layer: Handles the main logic through the GeoTessera class, uses a Registry for Parquet-based data discovery, and manages visualization.
    3. Data Access Layer: Manages HTTPS downloads (using urllib3), Zarr v3 cloud-native streaming, Rasterio for GeoTIFF I/O, and GeoPandas for geospatial operations.
    4. Storage Layer: Accesses the Source Cooperative repository, Zarr stores, and a local cache located at ~/.cache/geotessera/.
  3. Understand Matryoshka embedding depths in Zarr stores

    main

    Starting with v2 embeddings, GeoTessera uses a 'Matryoshka' style where embedding dimensions are ordered by importance. This allows the Zarr store to provide multiple 'depth' arrays that serve different use cases without the cost of reading the full 128-dimensional vector:

    • embeddings_d4: 4-dimensional embeddings for browsing, wide-area screening, and RGB rendering.
    • embeddings_d16: 16-dimensional embeddings for moderate-fidelity analysis.
    • embeddings: The full 128-dimensional embedding for high-fidelity ML work.

    All depth arrays share the same shard grid as the main embeddings array, ensuring that a single shard coordinate refers to the same spatial location across all depths. However, they use different inner chunk granularities to optimize for HTTP overhead and index size.

  4. Access Matryoshka depths in v2 stores

    main

    V2 stores may contain prefix arrays (Matryoshka embeddings) alongside full embeddings. You can select a specific published prefix using the depth parameter. The prefix corresponds to the first $N$ dimensions of the full embedding. Selecting fewer dimensions reduces output size and transfer volume.

    from geotessera.registry import zarr_store_url
    
    gt2 = GeoTesseraZarr(zarr_store_url("v2"))
    # depth=16 selects the first 16 dimensions
    embeddings16 = gt2.sample_points(coords, year=2024, depth=16)
  5. Understand the Registry System and Manifest Structure

    main

    GeoTessera uses a Parquet-based registry system to manage the large Tessera dataset. This allows for efficient spatial and temporal filtering using pandas DataFrames.

    Each manifest.parquet contains the following columns used for querying:

    • lon: Longitude of the tile center.
    • lat: Latitude of the tile center.
    • year: Data year (ranging from 2017-2025).
    • file_size: File size in bytes (used for download planning).

    When you request tiles for a bounding box, the library queries this manifest, filters by year and variant, and then fetches the matching tiles via HTTPS from the Source Cooperative mirror.

  6. Understand Dataset Versions and Variants

    main

    GeoTessera embeddings are organized by two orthogonal axes: dataset version and dataset variant.

    • Dataset Version: Refers to the trained Tessera model (e.g., 1.0, 1.1, or 2.0). Different versions have different 128-channel feature spaces; vectors from different versions are not comparable.
    • Dataset Variant: For a specific version, this is an independent model run or release channel (e.g., vultr, cambridge, 2B-L~beta1).

    CRITICAL: Never mix embeddings from different (version, variant) pairs in the same analysis (e.g., for cosine similarity, clustering, or training). Even if the grid geometry matches, the numeric values and channel semantics differ across versions/variants.

    Recommendation: Use 1.1 / cambridge for new projects.

  7. Verify data provenance using metadata

    main

    Because NPY tiles are always stored under the same local directory name (global_0.1_degree_representation/) regardless of the variant used, you must check the metadata to ensure you are using the correct dataset.

    • NPY Downloads: Check the tessera_metadata.json sidecar file in the output directory for the resolved (version, variant).
    • GeoTIFF Exports: Check the following metadata tags embedded in the file:
      • TESSERA_DATASET_VERSION
      • TESSERA_DATASET_VERSION_PATH
      • TESSERA_DATASET_VARIANT
  8. Access embeddings via GeoTesseraZarr (Cloud-Native)

    main

    The GeoTesseraZarr class provides cloud-native access to embeddings using the geoemb: convention in Zarr v3 format. Data is organized by UTM zone (e.g., utm30/, utm31/).

    Key Access Patterns

    • Point sampling: Use sample_points() or sample_at() to extract embeddings at specific coordinates across zones.
    • Region reading:
      • read_region(): Loads rectangular areas as mosaics with CRS and transform metadata.
      • read_region_quantized(): Returns int8 values and scales (uses 1/4 the bytes).
    • Streaming: iter_region() yields a region as row strips, suitable for inference on regions larger than memory.
    • Patch reading: read_patch() reads fixed-size squares centered on a point, merging across UTM zones if necessary.
    • Matryoshka Depths: Use the depth= parameter on read methods to select a specific prefix array on stores that declare one.
    • Zone access: open_zone() returns an xarray Dataset with a .tessera accessor.
    • Diagnostics: Use probe() to check a location's status. It returns (embedding, status), where status can be valid, water, nodata, or outside. Use this instead of checking for NaNs to distinguish between water and missing data.
  9. Verify Data Integrity during Downloads

    main

    GeoTessera performs automatic integrity checks on all downloaded files (embeddings, scales, and landmasks):

    • Length Check: Every file is verified against the response Content-Length.
    • MD5 Check: If the server's ETag is a content MD5 (common for single-part uploads like landmask TIFFs and scales), an MD5 is computed over the streamed body and compared.

    If a mismatch is detected, the download is rejected and a retry with exponential backoff is triggered. This ensures that corrupt or truncated files do not reach your local cache or output directory.

  10. How the tile download and dequantization works

    main

    The tile workflow involves two main steps: retrieving raw embeddings and exporting them to a usable format.

    1. Retrieve embeddings: GeoTessera downloads quantized int8 embeddings (grid_X.XX_Y.YY.npy) and their corresponding float32 scale files (grid_X.XX_Y.YY_scales.npy) via HTTPS.
    2. Dequantization: The quantized values are converted back to float32 using geotessera.dequantize_embedding(quantized_embedding, scales). This helper handles scale broadcasting and missing values.

    Tile Grid Details:

    • Grid System: 0.1-degree grid.
    • Tile Size: ~11km x 11km at the equator.
    • Naming: Tiles are named by their center coordinates (e.g., grid_0.15_52.05).
    • Bounds: A tile at (lon, lat) covers [lon - 0.05°, lon + 0.05°] and [lat - 0.05°, lat + 0.05°].
    • Resolution: 10m per pixel.
    import geotessera
    # Example of manual dequantization if you have the arrays
    # dequantized = geotessera.dequantize_embedding(quantized_array, scales_array)
  11. How the Tessera 0.1-degree grid works

    main

    Tessera embeddings are organized on a fixed 0.1-degree grid system. Understanding this grid is essential for calculating tile boundaries and identifying valid tile centers.

    Grid Properties:

    • Grid spacing: 0.1° latitude × 0.1° longitude.
    • Tile naming: Tiles are named by their center coordinates (e.g., grid_0.15_52.05).
    • Coverage: Each tile spans from (center - 0.05°) to (center + 0.05°).
    • Resolution: Approximately 11km × 11km at the equator.

    Coordinate Calculations: For a tile at center coordinates (lon, lat):

    • west = lon - 0.05
    • east = lon + 0.05
    • south = lat - 0.05
    • north = lat + 0.05

    Valid Tile Centers: Centers must be aligned to 0.1-degree boundaries. Examples of valid centers include (0.05, 52.05), (0.15, 52.05), and (-0.05, 51.95). Values like (0.07, 52.03) are invalid as they are off-grid.

    # For a tile at center coordinates (lon, lat)
    west = lon - 0.05
    east = lon + 0.05  
    south = lat - 0.05
    north = lat + 0.05
    
    # Valid tile centers (examples)
    valid_centers = [
        (0.05, 52.05),   # Northwest Europe
        (0.15, 52.05),   # Adjacent tile
        (-0.05, 51.95),  # Southwest tile
    ]
    
    # Invalid centers (not on grid)
    invalid_centers = [
        (0.07, 52.03),   # Off-grid
        (0.1, 52.1),     # Off by 0.05°
    ]
  12. How the Tessera tile grid and data storage works

    main

    Tessera embeddings are organized into a 0.1-degree grid system.

    Grid Geometry

    • Tile size: ~0.1° × 0.1° (approx. 11km × 11km at the equator).
    • Naming: Tiles are named by their center coordinates (e.g., grid_0.15_52.05).
    • Bounds: A tile at center (lon, lat) covers [lon ± 0.05°, lat ± 0.05°].
    • Resolution: 10m per pixel.

    Data Format and Dequantization

    Embeddings are stored in a quantized format to save space. To use them, you must dequantize them:

    1. Quantized embeddings (grid_X.XX_Y.YY.npy): int8 type, shape (height, width, 128).
    2. Scale files (grid_X.XX_Y.YY_scales.npy): float32 type, contains scale factors.
    3. Dequantization formula: final_embedding = quantized_embedding.astype('f4') * scales.

    Storage and Manifests

    • Manifests: A Parquet-based per-version manifest is used for fast spatial lookups. These are cached in ~/.cache/geotessera/.
    • Persistence: Downloaded tiles are stored in your specified --output directory and are resumable (skipped if they already exist).