GISWLH/earth-embedding

A unified Python interface to Earth embeddings: image encoders, location encoders, and precomputed geospatial products.

Python

1

12 commits

updated Oct 17, 2026

See the code

README

earth-embedding — hand-drawn project banner

Earth Embedding logo

Earth Embedding

A shared Python interface for Earth observation images, locations, and embedding products.

English · 简体中文 · 日本語

Python License Models Validation Tests Hugging Face Docs

Quickstart · Compare 22 models · Hugging Face & resources · Notebooks · Docs · Contribute

One call, any model

emb = get_embedding("prithvi", spatial=spatial, temporal=temporal, output=output)

Choose a place, a time window, and an output. Swap the model name to explore 16 image configurations, 3 location encoders, and 3 precomputed products. The familiar rs-embed geographic API is preserved; Earth Embedding adds location models, direct product access, and multi-model comparison.

git clone https://github.com/GISWLH/earth-embedding.git
cd earth-embedding
python -m pip install -e ".[plot,location]"
# For image/product routes that use Earth Engine:
earthengine authenticate
from earth_embedding import PointBuffer, TemporalSpec, OutputSpec, get_embedding

spatial = PointBuffer(lon=114.41, lat=30.52, buffer_m=640)
temporal = TemporalSpec.range("2021-05-01", "2021-10-31")
output = OutputSpec.grid()  # Or OutputSpec.pooled() for a feature vector.

emb = get_embedding("prithvi", spatial=spatial, temporal=temporal, output=output)

# The same geographic interface also works for Esri's location encoder.
gle = get_embedding("esri_gle", spatial=spatial, output=output, grid_step_m=80)

Use Python 3.12+. First use downloads the selected weights. Image routes need their model dependencies and imagery access; Esri GLE runs directly in PyTorch without Earth Engine or ArcGIS. Annual products use TemporalSpec.year(2021); location encoders need no date.

22 models, one figure

Real Wuhan comparison: Sentinel-2 reference and all 22 model configurations

One region, 22 real outputs. Image encoders, location encoders (including Esri GLE), and precomputed products appear together. This is a qualitative gallery: each panel uses its own PCA colors and retains its own spatial support. Equal colors across panels do not indicate equal features or classes. The gallery reuses verified historical Wuhan image/product outputs and adds real location inference. Inputs, provenance, and reproduction. Dates differ across these archived runs; SatVision's historical proxy input and Copernicus's coarse product window are labeled in the figure and provenance.

from earth_embedding import compare_embeddings, plot_embedding_comparison

comparison = compare_embeddings(
    ["prithvi", "dofa", "remoteclip", "satclip", "geoclip", "esri_gle"],
    spatial=spatial,
    temporal=temporal,
    output=output,
    model_options={name: {"grid_step_m": 80}
                   for name in ("satclip", "geoclip", "esri_gle")},
    on_error="record",  # Keep successful panels; show each failure explicitly.
)
fig = plot_embedding_comparison(comparison, columns=3)
fig.savefig("comparison.png", dpi=180, bbox_inches="tight")

Set models=None to select the entire 22-entry catalog. Give annual products a year through model_options; the complete example does this for you and saves the figure, feature arrays, and a run report:

# All catalog models, one PNG. Requires their runtimes, weights and data access.
python examples/compare_models.py --models all --out outputs/comparison
# A smaller CPU run with no imagery download or Earth Engine authentication.
python examples/compare_models.py --models satclip geoclip esri_gle --device cpu

Results are available as comparison.embeddings["prithvi"]; failures are reported in comparison.errors. Models run sequentially and release their cached runtimes between requests by default. Comparison notebook.

Compare location encoders at global and local scales

SatCLIP, GeoCLIP and Esri GLE on shared global and Wuhan coordinate grids

These encoders use longitude and latitude, with no satellite observation date. Their spatial patterns show learned geographic priors. Adjust the region and sampling spacing with the same spatial and grid_step_m arguments.

Origin and attribution. Earth Embedding is an independently maintained extension of CyberGIS rs-embed, created by Dingqi Ye and contributors. We retain its Apache-2.0 license and acknowledge its APIs, adapters, and engineering foundation. The upstream paper describes rs-embed; our manuscript and extensions are separate work. See provenance.

Images, longitude and latitude, and precomputed products connect through Earth Embedding to geospatial analysis workflows.

More runnable examples

Python 3.12+, CPU. Install from this Git repository; no PyPI release is assumed. The small real samples are bundled and SHA-256 verified. No Earth Engine login or private paths are needed.

git clone https://github.com/GISWLH/earth-embedding.git
cd earth-embedding
python -m pip install -e ".[demo,aef]"
Location to embedding to map; features and labels to spatial holdout, classifier and measured results.

1. AEF 2021 → PCA map

from earth_embedding.demo import load_demo, pca_colors, plot_map
data = load_demo("aef")
colors = pca_colors(data.features)
fig = plot_map(data.samples, colors, title="San Francisco Bay Area | AEF 2021 | PCA RGB")
fig.savefig("aef-pca.png", dpi=160)

AEF 2021 PCA

San Francisco Bay Area and surroundings, 122.6–121.6° W / 37.3–38.3° N, about 88 × 111 km. 5,933 real Google / Google DeepMind AEF 2021 overview cells at 1,280 m support; the checked bundle is 2.1 MB. RGB shows descriptive principal components, not land-cover classes. Sampling and licenses: full tutorial. To repeat official GCS reads use fetch_aef_demo() from earth_embedding.demo; the first map above works offline.

2. Esri GLE → location map

from earth_embedding import get_location_embeddings
from earth_embedding.demo import load_demo, pca_colors, plot_map
data = load_demo("bayarea")
points = data.samples[["center_lon", "center_lat"]].to_numpy()
gle = get_location_embeddings("esri_gle", points, device="cpu", batch_size=128)
fig = plot_map(data.samples, pca_colors(gle.data), title="San Francisco Bay Area | Esri GLE | PCA RGB")
fig.savefig("esri-gle-pca.png", dpi=160)

Esri GLE PCA

5,933 San Francisco Bay Area locations; official ~3.7 MB weights download once and run directly in PyTorch. No ArcGIS/ArcPy. GLE has no observation year; colors show a geographic prior, not a dated land-cover map.

3. Embeddings + labels → classification

from earth_embedding.demo import classify_demo, plot_classification
result = classify_demo()
print({k: result["metrics"][k] for k in ("oa", "macro_f1", "balanced_accuracy")})
fig = plot_classification(result)
fig.savefig("bayarea-classification.png", dpi=160)

San Francisco Bay Area reference, held-out predictions, errors and confusion matrix

OAMacro-F1Balanced AccuracyTrain / test / buffer / excluded
91.39%87.49%85.65%3383 / 2173 / 375 / 2

Newly computed regional software demo, not current global paper results. Four classes: built, vegetation, cropland, water. South trains, north tests, with a ≥5.5 km geographic gap; two bare cells are excluded. There are only 9 cropland training cells, so class imbalance limits this fixed holdout. Scaler and Logistic Regression fit training rows only (seed 42). Gray cells are unscored. Class counts, source/license, split, metrics and limits.

Notebooks

01 · AEF · 02 · Esri GLE · 03 · Classification · 04 · Export / reuse

Notebooks 01–04 contain real execution outputs and maps. Execution receipt · Complete tutorial · Editable Excalidraw. Notebook 04 exports and safely reloads batches; it does not rank products with unequal spatial support. 05 · Compare models includes executed three-model CPU comparison outputs and an optional full-catalog cell; see its execution receipt.

Why Earth Embedding?

Remote sensing models expose different inputs, preprocessing rules, spatial supports, and access methods. Earth Embedding makes those differences explicit while providing reusable interfaces for obtaining features. Start with satellite imagery, a list of locations, or an existing embedding product; receive embedding values and provenance metadata for your own analysis.

  • Three entry points: image encoders, location encoders, and precomputed embedding products, organized by the object a user actually receives.
  • 22 catalog entries: 16 image configurations, 3 location encoders, and 3 precomputed products. The catalog includes optional integrations; consult the validation report for actual execution status.
  • Location-only inference: SatCLIP, GeoCLIP, and Esri Global Location Encoder share a [longitude, latitude] interface. Esri's lightweight weights run directly in PyTorch.
  • Direct AlphaEarth data access: discover official Google Cloud Storage tiles and sample 64-dimensional vectors without Earth Engine authentication.
  • Reusable outputs: pooled vectors, supported spatial grids, batch extraction, export helpers, and model/source metadata.
  • Research connections: a release-object taxonomy, globally distributed evaluation design, and Wuhan diagnostics documented separately from integration tests.

The earth_embedding import and earth-embedding command are the new entry points. Existing rs_embed imports and rs-embed commands remain available for compatibility.

Installation

Use Python 3.12 or later. Install this project from its Git repository; the instructions below do not assume an earth-embedding release on PyPI.

python -m pip install "earth-embedding @ git+https://github.com/GISWLH/earth-embedding.git"

For optional features or development:

git clone https://github.com/GISWLH/earth-embedding.git
cd earth-embedding
python -m pip install -e ".[location,aef]"
Extra / environmentWhen you need it
Base installationCore APIs and the dependencies declared in pyproject.toml
.[location]GeoCLIP's official Python package; SatCLIP and Esri GLE use bundled runtimes
.[aef]Rasterio and PyArrow for direct AlphaEarth COG sampling and Parquet indexes
.[benchmark]Scikit-learn for the spatial-holdout evaluation example
.[terratorch]TerraMind's TerraTorch runtime; Prithvi uses a bundled runtime
.[dev,full,location,aef,benchmark]Development checks and these optional integrations

PyTorch must match your hardware. Model weights may download on first use; image encoders can require substantial memory. Neither the catalog command nor the describe command performs model inference:

earth-embedding models --json
earth-embedding describe satclip

For Earth Engine imagery/product routes, authorize your account with earthengine authenticate and configure an eligible Cloud project (EE_PROJECT when required). The direct location and GCS examples below do not initialize Earth Engine.

Three quickstarts

1. Locations to embeddings

No image acquisition or date selection is needed. Inputs are WGS84 degrees in longitude, latitude order; even a single point is a two-dimensional array.

from earth_embedding import get_location_embeddings

locations = [[-122.42, 37.77], [139.76, 35.68], [-0.12, 51.51]]
result = get_location_embeddings("satclip", locations, device="cpu")
print(result.data.shape)  # (3, 256)
print(result.meta)

# Esri's official ~3.7 MB model package downloads and caches on first use.
esri = get_location_embeddings("esri_gle", locations, device="cpu")
print(esri.data.shape)  # (3, 256)

# Install .[location] first; GeoCLIP returns 512 features per location.
geoclip = get_location_embeddings("geoclip", locations, device="cpu")

Esri GLE uses its official pretrained weights with direct PyTorch inference; ArcGIS and ArcPy are not required. Downloads are pinned by SHA-256, and a local .dlpk or satclip.pth can be supplied for offline use. Esri's model terms apply separately. See Esri GLE setup and the validation report.

Location embeddings describe a learned geographic prior. Querying the same location with a different year does not produce an observation of land-cover change.

2. A place and time to image embeddings

Use the geographic API to fetch the configured imagery and run an image encoder. This example needs authorized Earth Engine access, model weights, and the model's runtime dependencies.

from earth_embedding import PointBuffer, TemporalSpec, OutputSpec, get_embedding

result = get_embedding(
    "remoteclip",
    spatial=PointBuffer(lon=-122.42, lat=37.77, buffer_m=320),
    temporal=TemporalSpec.range("2021-05-01", "2021-10-31"),
    output=OutputSpec.pooled(),
    device="cpu",
)
print(result.data.shape)
print(result.meta)

Already have imagery? get_image_embedding(model, pixels, spatial=..., temporal=..., sensor=..., device=...) accepts local CHW or TCHW arrays without fetching imagery. Supply the adapter's exact band order, sensor units, and time contract; an arbitrary RGB array is not valid input for every model. See API reference and model documentation.

3. AlphaEarth embeddings directly from Google Cloud Storage

Download the official footprint index once, then select a year and area. The index is global; check its size before downloading.

curl -L -o aef_index.parquet https://storage.googleapis.com/alphaearth_foundations/satellite_embedding/v1/annual/aef_index.parquet
from earth_embedding import BBox, find_aef_tiles, sample_aef

tiles = find_aef_tiles(
    "aef_index.parquet",
    spatial=BBox(-122.43, 37.76, -122.41, 37.78),
    year=2021,
)
result = sample_aef([[-122.42, 37.77]], tiles=tiles)
print(result.data.shape)  # (1, 64)
print(result.meta["source_for_point"])

The sampler performs CRS transformation, byte-range COG reads, signed-int8 dequantization, and nodata handling. Keep candidate tiles within one year. Missing coverage raises by default; strict=False preserves those rows as NaN. Network errors remain explicit errors.

Google's official GCS guide documents provider-paid access as of July 2026 and annual coverage from 2017 through 2025. See data access for the CSV/GeoParquet/GeoPackage indexes, object manifest, Earth Engine alternative, and required attribution. AEF model weights are not distributed by this project.

Model catalog

Classification follows the delivered object and evaluated input contract. Architecture, resolution, learning signal, and evaluation eligibility are separate properties. An adapter's presence is an integration statement; it is not a guarantee of current data access, checkpoint availability, or successful execution on your machine.

Model ID / guideClassCurrent adapter inputUpstream sourceWeights or product
remoteclipA · imageSentinel-2 RGBSourceHugging Face model
satmaeA · imageSentinel-2 RGBSourceHugging Face model
satmaeppA · imageSentinel-2 RGBSourceHugging Face model
satmaepp_s2_10bA · imageSentinel-2 10 bandsSourceHugging Face model
scalemaeA · imageSentinel-2 RGB + ground resolutionSourceHugging Face model
wildsatA · imageSentinel-2 RGBSourceofficial download
prithviA · imageSentinel-2 6 bands + time/locationSourceHugging Face model
terrafmA · imageSentinel-2 12 bands or Sentinel-1 VV/VHSourceHugging Face model
terramindA · imageSentinel-2 12 bandsSourceHugging Face model
dofaA · imageMultispectral imagery + wavelengthsSourceHugging Face model
fomoA · imageSentinel-2 12 bandsSourceofficial download
thorA · imageSentinel-2 10 bandsSourceHugging Face model
satvisionA · image14 calibrated TOA channelsSourceHugging Face model
anysatA · imageSentinel-2 10-band time seriesSourceHugging Face model
galileoA · imageSentinel-2 10-band time seriesSourceHugging Face model
agrifmA · imageSentinel-2 10-band time seriesSourceofficial download
satclipB · locationLongitude/latitude onlySourceHugging Face model
geoclipB · locationLongitude/latitude onlySourceofficial download
esri_gleB · locationLongitude/latitude onlySourceofficial download
tesseraC · productPublished GeoTessera embedding tilesSourceofficial product
gseC · productAnnual Google Satellite Embedding productSourceofficial product
copernicusC · product0.25-degree embedding productSourceHugging Face dataset

Checkpoint packaging, default variants and model terms. These are upstream resources, not weights republished by this project.

The taxonomy also includes C2 sampled embedding collections. No C2 adapter is claimed in this 22-entry catalog. Model-lineage names alone do not determine a class: published weights and a precomputed product can be separate releases.

A workflow you can reuse

StageInterfaceWhat to check
Discoverearth-embedding models --json, describe MODELInput requirements, supported output, optional dependencies
Inspect imageryinspect_provider_patch(...)Coverage, bands, pixel values, shape, acquisition window
Encode imagesget_embedding(...), get_image_embedding(...)Provider or local input; correct preprocessing
Encode locationsget_location_embeddings(...)WGS84 [lon, lat], model/checkpoint, device
Read AEF datafind_aef_tiles(...), sample_aef(...)Year, coverage, CRS, nodata, source URL
Scale extractionget_embeddings_batch(...), export_batch(...)Consistent configuration, cache, metadata, error handling
AnalyzeYour downstream estimator and spatial splitsTask labels, leakage, matched support, uncertainty

Results expose .data and .meta. Persist both: a feature matrix without its model revision, coordinates, dates, and preprocessing choices is difficult to reproduce. Feature dimensions and spatial grid support vary across models; the library does not make vectors from different encoders interchangeable.

What can you build?

  • Land-cover classifiers using pooled tile features and spatially separated training/test regions.
  • Built-up, vegetation, and water fraction regressors with labels aggregated to matching spatial support.
  • Water masks or segmentation experiments where the selected model exposes suitable dense features.
  • Similarity search and retrieval within a model's embedding space, with geographic holdouts for evaluation.
  • Location-prior baselines that help distinguish geographic regularities from information in imagery.
  • Repeated product queries across available annual layers, with consistent geometry and explicit time coverage.

These are downstream workflows you can implement with the features; they are not universal pretrained prediction heads supplied by every adapter.

Evaluate saved embeddings with a spatial holdout

The evaluation example consumes saved features without fetching imagery. Supply a metadata CSV with sample_id,target,split,spatial_group, and one NPZ per model containing X and sample_id. Use train / test splits whose spatial groups are disjoint.

python -m pip install -e ".[benchmark]"
python examples/evaluate_embeddings.py --metadata metadata.csv --features satclip=satclip.npz geoclip=geoclip.npz --task classification --out evaluation.json

The script aligns all models to the same finite cohort, fits scaling and linear estimators on training rows only, and records cohort/input hashes. For regression use --task regression. Define a meaningful spatial split before running it; this example does not reproduce final manuscript scores.

From manuscript to reusable software

Our manuscript work motivates three additions to the software: an explicit release taxonomy, comparable input/output contracts, and evaluation provenance. The frozen manuscript benchmark contains 20 systems: A16 + B1 (SatCLIP) + C3. The software catalog now has 22 adapters because GeoCLIP and Esri GLE are additional integrations; this does not expand the paper's evaluated set automatically.

The revised main evaluation uses a globally distributed 640 m design. Wuhan 567/2,173-tile materials provide local and historical diagnostics and retain their own scope. Evaluation covers classification, fraction regression, and supported dense-output tasks; matched spatial support and spatial holdouts matter more than a single aggregate ranking. SatVision and Copernicus-Embed retain their taxonomy classes even where their spatial support makes them ineligible for a controlled comparison.

See research scope and evidence boundaries. The manuscript is under development; this repository does not claim an accepted RSE paper, a final leaderboard, or that a smoke test establishes scientific superiority.

Validation and current limits

The validation report separates unit tests, real model inference, and live data access. The Bay Area integration receipt verifies the regional AEF sample and all three README examples. Notebook execution and held-out classification metrics are recorded separately.

Data providers can require authentication, quotas, or terms acceptance. Some models need specialized packages or large checkpoints. Esri GLE's weights retain Esri's model terms. A location encoder has no temporal observations. Coarse products cannot be made equivalent to a 10 m field by resampling. Read limitations before designing a comparison.

Documentation and examples

The hero and logo are editable hand-drawn Excalidraw assets. See the artwork source and rendering instructions.

Contribute

Useful contributions include adapters with explicit input contracts, reproducible failure reports, small executable examples, provider-access fixes, and improvements to English, Chinese, or Japanese documentation. Start with CONTRIBUTING.md and open an issue with a model's official source, license, checkpoint, and a concrete use case.

Priorities include broader environment validation, reproducible user-supplied imagery examples, more precomputed-product access routes, and carefully documented C2 integrations. These are development directions, not promises of currently implemented functionality.

Cite and acknowledge

For this extension, cite the software repository and the commit or release you used; machine-readable metadata is in CITATION.cff. Cite the original rs-embed paper when using its framework, and the original model/data publications for the artifacts used in your analysis. Our research manuscript will receive its own citation when a public bibliographic record is available.

@article{ye2026modelplacetimeremote,
  title={Any Model, Any Place, Any Time: Get Remote Sensing Foundation Model Embeddings On Demand},
  author={Ye, Dingqi and Kiv, Daniel and Hu, Wei and Shi, Jimeng and Wang, Shaowen},
  year={2026},
  eprint={2602.23678},
  archivePrefix={arXiv},
  url={https://arxiv.org/abs/2602.23678}
}

We thank the rs-embed contributors, model authors, Google Earth Engine, Google and Google DeepMind, TorchGeo, GeoTessera, TerraTorch, rshf, Microsoft SatCLIP, GeoCLIP, Esri, and the wider Earth observation community. Integration does not imply endorsement.

License

Library code is distributed under Apache-2.0, with inherited attribution retained in NOTICE. Vendored components, model weights, data, and fonts retain their respective licenses. AlphaEarth data is CC-BY-4.0; Esri's software/model terms apply separately. See provenance and licensing.

Editable banner artwork · Excalidraw

alphaearth
earth-observation
embeddings
foundation-models
geoclip
geospatial
python
pytorch
remote-sensing
representation-learning
satclip

GISWLH/earth-embedding

A unified Python interface to Earth embeddings: image encoders, location encoders, and precomputed geospatial products.

Python

1

12 commits

updated Oct 17, 2026

See the code

README

earth-embedding — hand-drawn project banner

Earth Embedding logo

Earth Embedding

A shared Python interface for Earth observation images, locations, and embedding products.

English · 简体中文 · 日本語

Python License Models Validation Tests Hugging Face Docs

Quickstart · Compare 22 models · Hugging Face & resources · Notebooks · Docs · Contribute

One call, any model

emb = get_embedding("prithvi", spatial=spatial, temporal=temporal, output=output)

Choose a place, a time window, and an output. Swap the model name to explore 16 image configurations, 3 location encoders, and 3 precomputed products. The familiar rs-embed geographic API is preserved; Earth Embedding adds location models, direct product access, and multi-model comparison.

git clone https://github.com/GISWLH/earth-embedding.git
cd earth-embedding
python -m pip install -e ".[plot,location]"
# For image/product routes that use Earth Engine:
earthengine authenticate
from earth_embedding import PointBuffer, TemporalSpec, OutputSpec, get_embedding

spatial = PointBuffer(lon=114.41, lat=30.52, buffer_m=640)
temporal = TemporalSpec.range("2021-05-01", "2021-10-31")
output = OutputSpec.grid()  # Or OutputSpec.pooled() for a feature vector.

emb = get_embedding("prithvi", spatial=spatial, temporal=temporal, output=output)

# The same geographic interface also works for Esri's location encoder.
gle = get_embedding("esri_gle", spatial=spatial, output=output, grid_step_m=80)

Use Python 3.12+. First use downloads the selected weights. Image routes need their model dependencies and imagery access; Esri GLE runs directly in PyTorch without Earth Engine or ArcGIS. Annual products use TemporalSpec.year(2021); location encoders need no date.

22 models, one figure

Real Wuhan comparison: Sentinel-2 reference and all 22 model configurations

One region, 22 real outputs. Image encoders, location encoders (including Esri GLE), and precomputed products appear together. This is a qualitative gallery: each panel uses its own PCA colors and retains its own spatial support. Equal colors across panels do not indicate equal features or classes. The gallery reuses verified historical Wuhan image/product outputs and adds real location inference. Inputs, provenance, and reproduction. Dates differ across these archived runs; SatVision's historical proxy input and Copernicus's coarse product window are labeled in the figure and provenance.

from earth_embedding import compare_embeddings, plot_embedding_comparison

comparison = compare_embeddings(
    ["prithvi", "dofa", "remoteclip", "satclip", "geoclip", "esri_gle"],
    spatial=spatial,
    temporal=temporal,
    output=output,
    model_options={name: {"grid_step_m": 80}
                   for name in ("satclip", "geoclip", "esri_gle")},
    on_error="record",  # Keep successful panels; show each failure explicitly.
)
fig = plot_embedding_comparison(comparison, columns=3)
fig.savefig("comparison.png", dpi=180, bbox_inches="tight")

Set models=None to select the entire 22-entry catalog. Give annual products a year through model_options; the complete example does this for you and saves the figure, feature arrays, and a run report:

# All catalog models, one PNG. Requires their runtimes, weights and data access.
python examples/compare_models.py --models all --out outputs/comparison
# A smaller CPU run with no imagery download or Earth Engine authentication.
python examples/compare_models.py --models satclip geoclip esri_gle --device cpu

Results are available as comparison.embeddings["prithvi"]; failures are reported in comparison.errors. Models run sequentially and release their cached runtimes between requests by default. Comparison notebook.

Compare location encoders at global and local scales

SatCLIP, GeoCLIP and Esri GLE on shared global and Wuhan coordinate grids

These encoders use longitude and latitude, with no satellite observation date. Their spatial patterns show learned geographic priors. Adjust the region and sampling spacing with the same spatial and grid_step_m arguments.

Origin and attribution. Earth Embedding is an independently maintained extension of CyberGIS rs-embed, created by Dingqi Ye and contributors. We retain its Apache-2.0 license and acknowledge its APIs, adapters, and engineering foundation. The upstream paper describes rs-embed; our manuscript and extensions are separate work. See provenance.

Images, longitude and latitude, and precomputed products connect through Earth Embedding to geospatial analysis workflows.

More runnable examples

Python 3.12+, CPU. Install from this Git repository; no PyPI release is assumed. The small real samples are bundled and SHA-256 verified. No Earth Engine login or private paths are needed.

git clone https://github.com/GISWLH/earth-embedding.git
cd earth-embedding
python -m pip install -e ".[demo,aef]"
Location to embedding to map; features and labels to spatial holdout, classifier and measured results.

1. AEF 2021 → PCA map

from earth_embedding.demo import load_demo, pca_colors, plot_map
data = load_demo("aef")
colors = pca_colors(data.features)
fig = plot_map(data.samples, colors, title="San Francisco Bay Area | AEF 2021 | PCA RGB")
fig.savefig("aef-pca.png", dpi=160)

AEF 2021 PCA

San Francisco Bay Area and surroundings, 122.6–121.6° W / 37.3–38.3° N, about 88 × 111 km. 5,933 real Google / Google DeepMind AEF 2021 overview cells at 1,280 m support; the checked bundle is 2.1 MB. RGB shows descriptive principal components, not land-cover classes. Sampling and licenses: full tutorial. To repeat official GCS reads use fetch_aef_demo() from earth_embedding.demo; the first map above works offline.

2. Esri GLE → location map

from earth_embedding import get_location_embeddings
from earth_embedding.demo import load_demo, pca_colors, plot_map
data = load_demo("bayarea")
points = data.samples[["center_lon", "center_lat"]].to_numpy()
gle = get_location_embeddings("esri_gle", points, device="cpu", batch_size=128)
fig = plot_map(data.samples, pca_colors(gle.data), title="San Francisco Bay Area | Esri GLE | PCA RGB")
fig.savefig("esri-gle-pca.png", dpi=160)

Esri GLE PCA

5,933 San Francisco Bay Area locations; official ~3.7 MB weights download once and run directly in PyTorch. No ArcGIS/ArcPy. GLE has no observation year; colors show a geographic prior, not a dated land-cover map.

3. Embeddings + labels → classification

from earth_embedding.demo import classify_demo, plot_classification
result = classify_demo()
print({k: result["metrics"][k] for k in ("oa", "macro_f1", "balanced_accuracy")})
fig = plot_classification(result)
fig.savefig("bayarea-classification.png", dpi=160)

San Francisco Bay Area reference, held-out predictions, errors and confusion matrix

OAMacro-F1Balanced AccuracyTrain / test / buffer / excluded
91.39%87.49%85.65%3383 / 2173 / 375 / 2

Newly computed regional software demo, not current global paper results. Four classes: built, vegetation, cropland, water. South trains, north tests, with a ≥5.5 km geographic gap; two bare cells are excluded. There are only 9 cropland training cells, so class imbalance limits this fixed holdout. Scaler and Logistic Regression fit training rows only (seed 42). Gray cells are unscored. Class counts, source/license, split, metrics and limits.

Notebooks

01 · AEF · 02 · Esri GLE · 03 · Classification · 04 · Export / reuse

Notebooks 01–04 contain real execution outputs and maps. Execution receipt · Complete tutorial · Editable Excalidraw. Notebook 04 exports and safely reloads batches; it does not rank products with unequal spatial support. 05 · Compare models includes executed three-model CPU comparison outputs and an optional full-catalog cell; see its execution receipt.

Why Earth Embedding?

Remote sensing models expose different inputs, preprocessing rules, spatial supports, and access methods. Earth Embedding makes those differences explicit while providing reusable interfaces for obtaining features. Start with satellite imagery, a list of locations, or an existing embedding product; receive embedding values and provenance metadata for your own analysis.

  • Three entry points: image encoders, location encoders, and precomputed embedding products, organized by the object a user actually receives.
  • 22 catalog entries: 16 image configurations, 3 location encoders, and 3 precomputed products. The catalog includes optional integrations; consult the validation report for actual execution status.
  • Location-only inference: SatCLIP, GeoCLIP, and Esri Global Location Encoder share a [longitude, latitude] interface. Esri's lightweight weights run directly in PyTorch.
  • Direct AlphaEarth data access: discover official Google Cloud Storage tiles and sample 64-dimensional vectors without Earth Engine authentication.
  • Reusable outputs: pooled vectors, supported spatial grids, batch extraction, export helpers, and model/source metadata.
  • Research connections: a release-object taxonomy, globally distributed evaluation design, and Wuhan diagnostics documented separately from integration tests.

The earth_embedding import and earth-embedding command are the new entry points. Existing rs_embed imports and rs-embed commands remain available for compatibility.

Installation

Use Python 3.12 or later. Install this project from its Git repository; the instructions below do not assume an earth-embedding release on PyPI.

python -m pip install "earth-embedding @ git+https://github.com/GISWLH/earth-embedding.git"

For optional features or development:

git clone https://github.com/GISWLH/earth-embedding.git
cd earth-embedding
python -m pip install -e ".[location,aef]"
Extra / environmentWhen you need it
Base installationCore APIs and the dependencies declared in pyproject.toml
.[location]GeoCLIP's official Python package; SatCLIP and Esri GLE use bundled runtimes
.[aef]Rasterio and PyArrow for direct AlphaEarth COG sampling and Parquet indexes
.[benchmark]Scikit-learn for the spatial-holdout evaluation example
.[terratorch]TerraMind's TerraTorch runtime; Prithvi uses a bundled runtime
.[dev,full,location,aef,benchmark]Development checks and these optional integrations

PyTorch must match your hardware. Model weights may download on first use; image encoders can require substantial memory. Neither the catalog command nor the describe command performs model inference:

earth-embedding models --json
earth-embedding describe satclip

For Earth Engine imagery/product routes, authorize your account with earthengine authenticate and configure an eligible Cloud project (EE_PROJECT when required). The direct location and GCS examples below do not initialize Earth Engine.

Three quickstarts

1. Locations to embeddings

No image acquisition or date selection is needed. Inputs are WGS84 degrees in longitude, latitude order; even a single point is a two-dimensional array.

from earth_embedding import get_location_embeddings

locations = [[-122.42, 37.77], [139.76, 35.68], [-0.12, 51.51]]
result = get_location_embeddings("satclip", locations, device="cpu")
print(result.data.shape)  # (3, 256)
print(result.meta)

# Esri's official ~3.7 MB model package downloads and caches on first use.
esri = get_location_embeddings("esri_gle", locations, device="cpu")
print(esri.data.shape)  # (3, 256)

# Install .[location] first; GeoCLIP returns 512 features per location.
geoclip = get_location_embeddings("geoclip", locations, device="cpu")

Esri GLE uses its official pretrained weights with direct PyTorch inference; ArcGIS and ArcPy are not required. Downloads are pinned by SHA-256, and a local .dlpk or satclip.pth can be supplied for offline use. Esri's model terms apply separately. See Esri GLE setup and the validation report.

Location embeddings describe a learned geographic prior. Querying the same location with a different year does not produce an observation of land-cover change.

2. A place and time to image embeddings

Use the geographic API to fetch the configured imagery and run an image encoder. This example needs authorized Earth Engine access, model weights, and the model's runtime dependencies.

from earth_embedding import PointBuffer, TemporalSpec, OutputSpec, get_embedding

result = get_embedding(
    "remoteclip",
    spatial=PointBuffer(lon=-122.42, lat=37.77, buffer_m=320),
    temporal=TemporalSpec.range("2021-05-01", "2021-10-31"),
    output=OutputSpec.pooled(),
    device="cpu",
)
print(result.data.shape)
print(result.meta)

Already have imagery? get_image_embedding(model, pixels, spatial=..., temporal=..., sensor=..., device=...) accepts local CHW or TCHW arrays without fetching imagery. Supply the adapter's exact band order, sensor units, and time contract; an arbitrary RGB array is not valid input for every model. See API reference and model documentation.

3. AlphaEarth embeddings directly from Google Cloud Storage

Download the official footprint index once, then select a year and area. The index is global; check its size before downloading.

curl -L -o aef_index.parquet https://storage.googleapis.com/alphaearth_foundations/satellite_embedding/v1/annual/aef_index.parquet
from earth_embedding import BBox, find_aef_tiles, sample_aef

tiles = find_aef_tiles(
    "aef_index.parquet",
    spatial=BBox(-122.43, 37.76, -122.41, 37.78),
    year=2021,
)
result = sample_aef([[-122.42, 37.77]], tiles=tiles)
print(result.data.shape)  # (1, 64)
print(result.meta["source_for_point"])

The sampler performs CRS transformation, byte-range COG reads, signed-int8 dequantization, and nodata handling. Keep candidate tiles within one year. Missing coverage raises by default; strict=False preserves those rows as NaN. Network errors remain explicit errors.

Google's official GCS guide documents provider-paid access as of July 2026 and annual coverage from 2017 through 2025. See data access for the CSV/GeoParquet/GeoPackage indexes, object manifest, Earth Engine alternative, and required attribution. AEF model weights are not distributed by this project.

Model catalog

Classification follows the delivered object and evaluated input contract. Architecture, resolution, learning signal, and evaluation eligibility are separate properties. An adapter's presence is an integration statement; it is not a guarantee of current data access, checkpoint availability, or successful execution on your machine.

Model ID / guideClassCurrent adapter inputUpstream sourceWeights or product
remoteclipA · imageSentinel-2 RGBSourceHugging Face model
satmaeA · imageSentinel-2 RGBSourceHugging Face model
satmaeppA · imageSentinel-2 RGBSourceHugging Face model
satmaepp_s2_10bA · imageSentinel-2 10 bandsSourceHugging Face model
scalemaeA · imageSentinel-2 RGB + ground resolutionSourceHugging Face model
wildsatA · imageSentinel-2 RGBSourceofficial download
prithviA · imageSentinel-2 6 bands + time/locationSourceHugging Face model
terrafmA · imageSentinel-2 12 bands or Sentinel-1 VV/VHSourceHugging Face model
terramindA · imageSentinel-2 12 bandsSourceHugging Face model
dofaA · imageMultispectral imagery + wavelengthsSourceHugging Face model
fomoA · imageSentinel-2 12 bandsSourceofficial download
thorA · imageSentinel-2 10 bandsSourceHugging Face model
satvisionA · image14 calibrated TOA channelsSourceHugging Face model
anysatA · imageSentinel-2 10-band time seriesSourceHugging Face model
galileoA · imageSentinel-2 10-band time seriesSourceHugging Face model
agrifmA · imageSentinel-2 10-band time seriesSourceofficial download
satclipB · locationLongitude/latitude onlySourceHugging Face model
geoclipB · locationLongitude/latitude onlySourceofficial download
esri_gleB · locationLongitude/latitude onlySourceofficial download
tesseraC · productPublished GeoTessera embedding tilesSourceofficial product
gseC · productAnnual Google Satellite Embedding productSourceofficial product
copernicusC · product0.25-degree embedding productSourceHugging Face dataset

Checkpoint packaging, default variants and model terms. These are upstream resources, not weights republished by this project.

The taxonomy also includes C2 sampled embedding collections. No C2 adapter is claimed in this 22-entry catalog. Model-lineage names alone do not determine a class: published weights and a precomputed product can be separate releases.

A workflow you can reuse

StageInterfaceWhat to check
Discoverearth-embedding models --json, describe MODELInput requirements, supported output, optional dependencies
Inspect imageryinspect_provider_patch(...)Coverage, bands, pixel values, shape, acquisition window
Encode imagesget_embedding(...), get_image_embedding(...)Provider or local input; correct preprocessing
Encode locationsget_location_embeddings(...)WGS84 [lon, lat], model/checkpoint, device
Read AEF datafind_aef_tiles(...), sample_aef(...)Year, coverage, CRS, nodata, source URL
Scale extractionget_embeddings_batch(...), export_batch(...)Consistent configuration, cache, metadata, error handling
AnalyzeYour downstream estimator and spatial splitsTask labels, leakage, matched support, uncertainty

Results expose .data and .meta. Persist both: a feature matrix without its model revision, coordinates, dates, and preprocessing choices is difficult to reproduce. Feature dimensions and spatial grid support vary across models; the library does not make vectors from different encoders interchangeable.

What can you build?

  • Land-cover classifiers using pooled tile features and spatially separated training/test regions.
  • Built-up, vegetation, and water fraction regressors with labels aggregated to matching spatial support.
  • Water masks or segmentation experiments where the selected model exposes suitable dense features.
  • Similarity search and retrieval within a model's embedding space, with geographic holdouts for evaluation.
  • Location-prior baselines that help distinguish geographic regularities from information in imagery.
  • Repeated product queries across available annual layers, with consistent geometry and explicit time coverage.

These are downstream workflows you can implement with the features; they are not universal pretrained prediction heads supplied by every adapter.

Evaluate saved embeddings with a spatial holdout

The evaluation example consumes saved features without fetching imagery. Supply a metadata CSV with sample_id,target,split,spatial_group, and one NPZ per model containing X and sample_id. Use train / test splits whose spatial groups are disjoint.

python -m pip install -e ".[benchmark]"
python examples/evaluate_embeddings.py --metadata metadata.csv --features satclip=satclip.npz geoclip=geoclip.npz --task classification --out evaluation.json

The script aligns all models to the same finite cohort, fits scaling and linear estimators on training rows only, and records cohort/input hashes. For regression use --task regression. Define a meaningful spatial split before running it; this example does not reproduce final manuscript scores.

From manuscript to reusable software

Our manuscript work motivates three additions to the software: an explicit release taxonomy, comparable input/output contracts, and evaluation provenance. The frozen manuscript benchmark contains 20 systems: A16 + B1 (SatCLIP) + C3. The software catalog now has 22 adapters because GeoCLIP and Esri GLE are additional integrations; this does not expand the paper's evaluated set automatically.

The revised main evaluation uses a globally distributed 640 m design. Wuhan 567/2,173-tile materials provide local and historical diagnostics and retain their own scope. Evaluation covers classification, fraction regression, and supported dense-output tasks; matched spatial support and spatial holdouts matter more than a single aggregate ranking. SatVision and Copernicus-Embed retain their taxonomy classes even where their spatial support makes them ineligible for a controlled comparison.

See research scope and evidence boundaries. The manuscript is under development; this repository does not claim an accepted RSE paper, a final leaderboard, or that a smoke test establishes scientific superiority.

Validation and current limits

The validation report separates unit tests, real model inference, and live data access. The Bay Area integration receipt verifies the regional AEF sample and all three README examples. Notebook execution and held-out classification metrics are recorded separately.

Data providers can require authentication, quotas, or terms acceptance. Some models need specialized packages or large checkpoints. Esri GLE's weights retain Esri's model terms. A location encoder has no temporal observations. Coarse products cannot be made equivalent to a 10 m field by resampling. Read limitations before designing a comparison.

Documentation and examples

The hero and logo are editable hand-drawn Excalidraw assets. See the artwork source and rendering instructions.

Contribute

Useful contributions include adapters with explicit input contracts, reproducible failure reports, small executable examples, provider-access fixes, and improvements to English, Chinese, or Japanese documentation. Start with CONTRIBUTING.md and open an issue with a model's official source, license, checkpoint, and a concrete use case.

Priorities include broader environment validation, reproducible user-supplied imagery examples, more precomputed-product access routes, and carefully documented C2 integrations. These are development directions, not promises of currently implemented functionality.

Cite and acknowledge

For this extension, cite the software repository and the commit or release you used; machine-readable metadata is in CITATION.cff. Cite the original rs-embed paper when using its framework, and the original model/data publications for the artifacts used in your analysis. Our research manuscript will receive its own citation when a public bibliographic record is available.

@article{ye2026modelplacetimeremote,
  title={Any Model, Any Place, Any Time: Get Remote Sensing Foundation Model Embeddings On Demand},
  author={Ye, Dingqi and Kiv, Daniel and Hu, Wei and Shi, Jimeng and Wang, Shaowen},
  year={2026},
  eprint={2602.23678},
  archivePrefix={arXiv},
  url={https://arxiv.org/abs/2602.23678}
}

We thank the rs-embed contributors, model authors, Google Earth Engine, Google and Google DeepMind, TorchGeo, GeoTessera, TerraTorch, rshf, Microsoft SatCLIP, GeoCLIP, Esri, and the wider Earth observation community. Integration does not imply endorsement.

License

Library code is distributed under Apache-2.0, with inherited attribution retained in NOTICE. Vendored components, model weights, data, and fonts retain their respective licenses. AlphaEarth data is CC-BY-4.0; Esri's software/model terms apply separately. See provenance and licensing.

Editable banner artwork · Excalidraw

alphaearth
earth-observation
embeddings
foundation-models
geoclip
geospatial
python
pytorch
remote-sensing
representation-learning
satclip