v2.0.0 — Production Ready
580 Tests Passing
119 Model Architectures
503 Datasets
25 Production Notebooks
GeoAI = Optional Plugin Only

The standalone Geospatial AI
platform — satellite to insight

PyGeoVision v2.0 is a fully independent geospatial AI platform with its own 119-model registry, foundation models (DINOv3 12 variants + Prithvi-EO-2.0 600M), production training stack, FastAPI serving, and edge/cloud deployment. PyGeoFetch (22 satellite providers) and GeoAI (legacy AI subsystems) are optional enhancements — not dependencies.

119
Own Models
503
Datasets
580
Tests
25
Notebooks
22+
Providers (opt)
10
Pipelines
12
DINOv3 Models
pip install pygeovision
Apache 2.0 Python 3.10+ PyTorch 2.0+
Release Notes

What's New in v2.0

PyGeoVision v2.0 is a major architectural change: the platform is now fully standalone with its own complete AI stack. GeoAI is no longer a dependency — it's an optional plugin.

Areav1.0v2.0Change
ArchitectureRequires GeoAIFully standaloneBreaking
Model registry14 architectures119 architectures+105
Dataset registry503 datasetsNew
Tests passing208580+372
Foundation modelsDINOv3 (12 variants, SAT-493M) + Prithvi-EO-2.0 (600M)New
VLMCLIP + RemoteCLIP + Moondream 2New
Serving APIFastAPI + WebSocket streamingNew
Edge deploymentONNX Runtime + Jetson TensorRT FP16New
Cloud deploymentAWS SageMaker + Azure ML + GCP Vertex AINew
Few-shot learningPrototypical networks (DINOv2-Large)New
AutoML / HPOOptuna integration, +2–4 mIoU typicalNew
Time-seriesGeoTimeSeries + anomaly detectionNew
MonitoringDrift detection + tracker + Slack/webhook alertsNew
Production notebooks25 notebooks, 357 cells, all 25 domainsNew
GeoAI integrationRequired dependencyOptional plugin (pip install "pygeovision[geoai]")Improved
Breaking change for v1.0 users: PyGeoVision v2.0 no longer installs GeoAI automatically. If you use client.geoai.*, install the optional plugin: pip install "pygeovision[geoai]". All v1.0 APIs remain backward-compatible.
Design

Architecture — Standalone with Optional Plugins

PyGeoVision v2.0 ships its own complete geospatial AI stack — no GeoAI or PyGeoFetch dependency required. Both are optional enhancements available as extras.

🧠
PyGeoVision Core
pygeovision — standalone AI
CORE119 model architectures (own registry)
CORE503 registered datasets
COREGeoTrainer + GeospatialMixedLoss
CORETiledInference — Gaussian blend
COREDINOv3 — 12 variants (SAT-493M + web)
COREPrithvi-EO-2.0 — 600M, HLS global
CORECLIP + RemoteCLIP + Moondream 2
COREAuto-labeling — 7 sources
COREFastAPI serving + WebSocket
COREONNX + Jetson + AWS / Azure / GCP
COREFew-shot, AutoML, Timeseries, 3D
COREDrift monitoring + alerts
CORE10 end-to-end pipelines
CORECLI — 15 command groups
CORE25 production notebooks
🛰️
PyGeoFetch Plugin
pygeofetch — optional data layer
OPTIONAL22 satellite providers
OPTIONALFederated STAC search
OPTIONALParallel downloads + SHA256
OPTIONALKeyring auth management
OPTIONALPost-processing chains
OPTIONALYAML pipeline orchestration
OPTIONALSearch result caching
OPTIONALCron scheduling
Without PyGeoFetch, all AI APIs work directly with local GeoTIFF files. No satellite credentials needed to use the AI stack.
🔌
GeoAI Plugin
geoai-py — optional AI extras
OPTIONALExtra segmenters (BuildingExtractor)
OPTIONALGroundedSAM (DINO + SAM)
OPTIONALRF-DETR detection
OPTIONALTessera pre-computed embeddings
OPTIONALLeafmap visualisation (Jupyter)
OPTIONALCloud masking (GeoAI ESRGAN)
OPTIONALLegacy GeoAI subsystem API
Not required. PyGeoVision's own stack — DINOv3, Prithvi, CLIP, Moondream, ChangeFormer, SegFormer — covers the same tasks natively.
Getting Started

Up and running in 5 minutes

PyGeoVision works immediately with local GeoTIFF files — no cloud credentials required. Add PyGeoFetch later if you need satellite data acquisition.

1
Install
# Core — AI inference + training, no cloud needed pip install "pygeovision[geo,train]" # Add foundation models (DINOv3, Prithvi) pip install "pygeovision[geo,train,foundation]" # Add VLM (CLIP, Moondream) pip install "pygeovision[vlm]" # Everything pip install "pygeovision[all]" pygeovision status
2
Run inference on a local GeoTIFF (no credentials needed)
import pygeovision as pgv from pygeovision.models import get_model from pygeovision.inference.tiled import TiledInference model = get_model("segformer-b2", num_classes=2, pretrained=True) inf = TiledInference(model, chip_size=512, overlap=64) result= inf.infer("my_scene.tif", "buildings.tif") # {n_chips, duration_seconds, chips_per_second}
3
Use DINOv3 or Prithvi foundation models (own stack)
# DINOv3 — satellite pre-trained (SAT-493M) from pygeovision.models.foundation.dinov3 import DINOv3Backbone backbone = DINOv3Backbone("dinov3_vitl16_sat") emb = backbone.extract_embeddings("scene.tif") # (1, 1024) # Prithvi-EO-2.0 land cover from pygeovision.models.foundation.prithvi import PrithviTasks tasks = PrithviTasks("prithvi_eo_2_0") lc = tasks.land_cover("scene.tif", source="sentinel2")
4
Add satellite data (optional — PyGeoFetch)
# pip install pygeofetch ← separate optional install client = pgv.PyGeoVision() results = client.search( bbox=(-0.15, 51.47, -0.10, 51.52), date_range=("2024-06-01","2024-06-30"), providers=["planetary_computer"], # free, no auth cloud_cover_max=10, ) downloads = client.download(results[:1], post_process=["reproject:EPSG:4326","cog"])

Full Python walkthrough

quickstart.py
import pygeovision as pgv
from pygeovision.models import get_model
from pygeovision.models.foundation.dinov3 import DINOv3Backbone
from pygeovision.models.foundation.prithvi import PrithviTasks
from pygeovision.inference.tiled import TiledInference
from pygeovision.training.trainer import GeoTrainer

client = pgv.PyGeoVision()
print(client)
# PyGeoVision(v2.0.0 | models=119 | datasets=503 | pygeofetch=optional | geoai=optional)

# ── 1. Own model registry — 119 architectures ────────────────────────────
model = get_model("segformer-b2", num_classes=5, in_channels=6, pretrained=True)

# ── 2. Tiled inference — own stack, no GeoAI ─────────────────────────────
inf    = TiledInference(model, chip_size=512, overlap=64, blend_mode="gaussian")
result = inf.infer("large_scene.tif", "prediction.tif")
# → {n_chips: 24, duration_seconds: 1.1, chips_per_second: 44.7}

# ── 3. DINOv3 — own foundation stack ─────────────────────────────────────
backbone   = DINOv3Backbone("dinov3_vitl16_sat")   # SAT-493M pre-training
embeddings = backbone.extract_embeddings("scene.tif")    # (1, 1024)
features   = backbone.extract_features("scene.tif")      # (H_p, W_p, 1024)
attention  = backbone.get_attention_maps("scene.tif")     # saliency map

# ── 4. Prithvi-EO-2.0 — own foundation stack ─────────────────────────────
tasks      = PrithviTasks("prithvi_eo_2_0")
land_cover = tasks.land_cover("scene.tif", source="sentinel2")
crop_map   = tasks.crop_mapping("scene.tif", source="sentinel2")
flood      = tasks.flood_detection("scene.tif", source="sentinel2")

# ── 5. Auto-label without any manual annotation ──────────────────────────
ms    = client.labeling.microsoft_buildings(bbox=(-0.15,51.47,-0.10,51.52))
fused = client.labeling.pipeline(bbox=(-0.15,51.47,-0.10,51.52),
    sources=[{"type":"microsoft_buildings","weight":1.5},{"type":"osm","weight":1.0}])

# ── 6. GeoTrainer — own training pipeline ────────────────────────────────
from pygeovision.losses.segmentation import GeospatialMixedLoss
from pygeovision.training.callbacks import EarlyStopping, ModelCheckpoint
loss    = GeospatialMixedLoss(weights={"combo":0.5,"boundary":0.3,"ohem":0.2})
trainer = GeoTrainer(model=model, task="segmentation", num_classes=5, epochs=100,
                      learning_rate=6e-5, mixed_precision="bf16", loss_fn=loss)

# ── 7. Serve as REST API ────────────────────────────────────────────────
from pygeovision.serving import InferenceServer
server = InferenceServer(auth_keys={"prod":"SECRET"})
server.register("seg_v1", "model.onnx", task="segmentation", num_classes=5)
server.serve(host="0.0.0.0", port=8080)

# ── 8. Optional: PyGeoFetch satellite data ───────────────────────────────
# pip install pygeofetch
results   = client.search(bbox=(-0.15,51.47,-0.10,51.52),
    date_range=("2024-06-01","2024-06-30"), providers=["planetary_computer"])
downloads = client.download(results[:1], post_process=["cog"])

# ── 9. Optional: GeoAI plugin ────────────────────────────────────────────
# pip install "pygeovision[geoai]"
# ga = client.geoai   # lazy-loads geoai-py on first access
# ga.detect.grounded("aerial.tif", "swimming pools")  # GroundedSAM

Interactive demo

pygeovision v2.0 — interactive demo
$ pygeovision status Select a command above and click ▶ Run
$
Satellite Data — PyGeoFetch (Optional)

Data Acquisition via PyGeoFetch

When PyGeoFetch is installed (pip install pygeofetch), PyGeoVision can search and download satellite data from 22+ providers. This is entirely optional — all AI APIs work with local GeoTIFF files without any satellite credentials.

No satellite credentials? That's fine. Pass any local GeoTIFF directly to any AI API: get_model("segformer-b2") + TiledInference work immediately. PyGeoFetch is only needed for automated imagery acquisition.
data_optional.py
# Add credentials (10 providers are free — no credentials needed)
client.add_credentials("usgs",       username="user", password="pass")
client.add_credentials("planet",     api_key="PL-xxxx")
client.add_credentials("copernicus", client_id="id",  client_secret="secret")

# Search (free: planetary_computer, aws_earth, element84, esa_scihub, jaxa_earth …)
results = client.search(
    bbox            = (-0.15, 51.47, -0.10, 51.52),
    date_range      = ("2024-06-01", "2024-06-30"),
    providers       = ["planetary_computer"],
    cloud_cover_max = 10,
    sort_by         = "cloud_cover",
)

# Download with post-processing
downloads = client.download(results[:2],
    output_dir   = "./data/",
    parallel     = 4,
    post_process = ["reproject:EPSG:32618", "cog"],
    bands        = ["B02","B03","B04","B08","B11","B12"],
)

# YAML pipeline (recurring workflow)
p = client.create_pipeline("weekly_s2")
p.search(bbox=..., providers=["planetary_computer"], date_range="last_7_days")
p.download(post_process=["cog"], parallel=4)
p.schedule(cron="0 3 * * 1")
p.save("weekly.yaml")
p.run(dry_run=True)
PyGeoFetch — Optional Data Plugin

22 Satellite Data Providers

Available when PyGeoFetch is installed. 10 providers work with no credentials at all.

planetary_computerOpen
Microsoft STAC. Sentinel-1/2, Landsat 8/9, MODIS, NAIP, COP-DEM. SAS tokens auto-generated.
STACSAR
aws_earthOpen
AWS Earth Open Data. Sentinel-2 COGs, Landsat Collection 2, NAIP. Direct S3.
STAC
element84Open
Element 84 Earth Search. Sentinel-2 L2A, Landsat Col 2, Sentinel-1 RTC.
STACSAR
noaa_big_dataOpen
GOES-16/17/18 weather imagery and NEXRAD radar.
esa_scihubOpen
ESA public mirrors. Sentinel-1/2/3/5P Copernicus archives.
SAR
jaxa_earthOpen
JAXA ALOS 30m World 3D DSM and PALSAR-2 global forest map.
SAR
isro_bhuvanOpen
ISRO Bhuvan. ResourceSat-2/2A (5.8m), Cartosat-1 (2.5m).
inpe_cbersOpen
Brazil INPE CBERS-4 and CBERS-4A. 5–40m optical.
digitalglobeOpen
Maxar Open Data. Sub-metre WorldView disaster response.
<1m
geoserver_genericOpen
Generic OGC WMS/WFS/WCS for any GeoServer endpoint.
usgs🔐 Auth
USGS Earth Explorer. Landsat 1–9, ASTER, MODIS. M2M API.
STAC
copernicus🔐 Auth
Copernicus Data Space. Sentinel-1/2/3/5P. OAuth2.
STACSAR
nasa_earthdata🔐 Auth
NASA CMR. MODIS, VIIRS, ICESat-2, GEDI, ASTER.
STAC
nasa_earthdata_cloud🔐 Auth
Cloud-native NASA on AWS. Temporary S3 credentials auto-refreshed.
STAC
opentopography🔐 Auth
SRTM 30/90m, COP-DEM 30m, NASADEM, global LiDAR.
planet🔐 Auth
Planet Labs. PlanetScope (3m daily), SkySat (50cm).
STAC<1m
sentinel_hub🔐 Auth
Sentinel Hub Processing API. All Sentinels, Landsat, evalscripts.
SAR
maxar_gbdx🔐 Auth
Maxar WorldView 1–4, GeoEye-1. 30–50cm commercial.
<1m
airbus_oneatlas🔐 Auth
Airbus Pléiades (50cm) and SPOT 6/7 (1.5m).
STAC<1m
alaska_satellite_facility🔐 Auth
ASF DAAC. Sentinel-1 SLC/GRD, ALOS PALSAR.
SAR
google_earth_engine🔐 Auth
GEE catalog proxy. Multi-petabyte global via service account.
SAR
terrabotics🔐 Auth
TerraBotics archive and tasking. Sub-metre commercial.
<1m
PyGeoVision Core — Own AI Stack

Model Registry — 119 Architectures

PyGeoVision's own model registry — load any of 119 architectures by name. Pretrained weights auto-downloaded from HuggingFace Hub. No GeoAI required.

model_registry.py
from pygeovision.models import get_model, list_models
from pygeovision.models.registry import ModelRegistry

# List by task
list_models(task="segmentation")      # 24 architectures
list_models(task="detection")          # 18 architectures
list_models(task="change_detection")   # 12 architectures
list_models(task="foundation")         # 12 architectures (DINOv3 + Prithvi)
list_models(task="vlm")               # 9 architectures (CLIP, Moondream)

# Load by name (pretrained weights downloaded automatically)
model = get_model("segformer-b2", num_classes=5, in_channels=6, pretrained=True)
model = get_model("changeformer",  num_classes=4, in_channels=4)
model = get_model("geoyolo-v8",    num_classes=10, pretrained=True)
model = get_model("prithvi_eo_2_0")
model = get_model("dinov3_vitl16_sat")

# Registry API
registry = ModelRegistry()
registry.list(task="segmentation", pretrained_only=True)
registry.info("prithvi_eo_2_0")      # params, tasks, input format
FamilyCountKey Architectures
Segmentation24U-Net variants, SegFormer B0–B5, DeepLabV3+, PSPNet, Mask2Former, SAM, SAM2
Detection18GeoYOLO v5/v8/v9/v10/v11, DETR, RT-DETR, RF-DETR, FCOS, RetinaNet, Faster R-CNN
Classification16ViT variants, Swin Transformer, EfficientNet B0–B7, ResNet, DenseNet, ConvNeXt
Change Detection12ChangeFormer, ChangeSTAR, BIT, DSAMNet, SNUNet, DTCDSCN, FC-EF, FC-Siam
Foundation12DINOv3 (6 ViT + 4 ConvNeXt, web + SAT), Prithvi-EO-1.0, Prithvi-EO-2.0
VLM9CLIP ViT-B/32 & ViT-L/14, OpenCLIP, RemoteCLIP L/14, GeoRSCLIP, Moondream 2, LLaVA-Geo
3D / Point Cloud8PointNet, PointNet++, RandLA-Net, KPConv, Point Transformer, PointMamba
Other20ESRGAN (SR), CHMv2 (canopy height), BioMassNet, SAR despeckling

Dataset Registry — 503 Datasets

datasets.py
from pygeovision.datasets import DatasetRegistry, DatasetLoader

registry = DatasetRegistry()
registry.list(task="segmentation", sensor="sentinel2")
registry.list(task="change_detection")
registry.info("spacenet_buildings")
registry.download("deepglobe_roads", output_dir="./datasets/")

loader   = DatasetLoader(registry)
train_ds = loader.load("spacenet_buildings", split="train", chip_size=512)

# 503 datasets covering:
# Buildings · Roads · Land cover · Change detection · Crops · Floods
# Wildfire · SAR · VHR · Hyperspectral · Point cloud · Time series
# SpaceNet 1–8, DOTA v1/v2, iSAID, DIOR, DeepGlobe, BigEarthNet,
# FloodNet, xBD, BreizhCrops, SEN12MS, MillionAID, RS5M, and 450+ more
PyGeoVision Core — Foundation Models

Foundation Models — Own Stack (No GeoAI)

DINOv3 and Prithvi-EO-2.0 are integrated directly into PyGeoVision's codebase. Weights auto-downloaded from HuggingFace Hub on first use. GeoAI not required.

DINOv3 — 12 Variants

Critical: Always use get_transform(model_name) — it auto-selects the correct normalisation stats. Using ImageNet stats with a SAT-pre-trained model silently costs 10–20 mIoU points.
dinov3.py
from pygeovision.models.foundation.dinov3 import (
    DINOv3Backbone, get_transform, finetune_dinov3, CHMv2Model,
    WEB_MEAN, WEB_STD,     # ImageNet — for LVD-1689M web pre-trained
    SAT_MEAN, SAT_STD,     # Satellite — for SAT-493M pre-trained ← DIFFERENT
)

# get_transform() auto-selects correct stats for the model name
transform = get_transform("dinov3_vitl16_sat")   # satellite stats
transform = get_transform("dinov3_vitl16")        # ImageNet stats

backbone = DINOv3Backbone("dinov3_vitl16_sat")   # 300M, 1024-dim, SAT-493M

# Feature extraction
embeddings = backbone.extract_embeddings("scene.tif")     # (1, 1024) — global CLS
features   = backbone.extract_features("scene.tif")       # (H_p, W_p, 1024) — spatial
attention  = backbone.get_attention_maps("scene.tif")      # saliency map

# Canopy height — DINOv3 CHMv2 (1m global, GEDI calibrated)
chm    = CHMv2Model()
result = chm.predict_canopy_height("sentinel2.tif")  # mean_m, max_m, coverage_pct
biomass= chm.estimate_biomass("sentinel2.tif")         # t DM/ha

# Fine-tuning (task: "segmentation" | "classification")
result = finetune_dinov3(
    model_name="dinov3_vitl16_sat", dataset=my_dataset,
    task="segmentation", num_classes=7, epochs=50,
    learning_rate=1e-5,          # low LR for SAT pre-trained
    mixed_precision=True,         # BF16 — critical for ViT-L
)
Model NameParamsPre-trainingEmbed dimRecommended for
dinov3_vits1621MWeb LVD-1689M384Fast inference
dinov3_vitb1686MWeb LVD-1689M768Balanced
dinov3_vitl16300MWeb LVD-1689M1024High accuracy (web images)
dinov3_vitl16_sat300MSAT-493M1024Satellite imagery ★ Recommended
dinov3_vit7b16_sat6.7BSAT-493M4096State-of-the-art ★
dinov3_convnext_base89MWeb1024Convolutional features
+ 6 more variants (ViT-S+, ViT-7B web, ConvNeXt tiny/small/large)

Prithvi-EO-2.0 — 600M Parameters

Critical — band ordering: Prithvi ALWAYS expects HLS format. Wrong band order = silent accuracy loss. Always call map_bands(data, source="sentinel2") first.
prithvi.py
from pygeovision.models.foundation.prithvi import (
    Prithvi, PrithviTasks, PrithviMultiTemporal,
    map_bands, normalise_hls, finetune_prithvi,
)

# HLS band order: Blue(B02) Green(B03) Red(B04) NIR(B08) SWIR1(B11) SWIR2(B12)
data_hls  = map_bands(data, source="sentinel2")   # remaps S2 → HLS order
data_norm = normalise_hls(data_hls)               # divides by HLS_SCALE_FACTOR=10000.0

# Task predictions (all auto-apply map_bands + normalise internally)
tasks      = PrithviTasks("prithvi_eo_2_0")
land_cover = tasks.land_cover("sentinel2.tif", source="sentinel2")       # 9 classes
crops      = tasks.crop_mapping("sentinel2.tif", source="sentinel2")     # 10 crops
flood      = tasks.flood_detection("sentinel2.tif", source="sentinel2")  # binary
defor      = tasks.deforestation_detection("sentinel2.tif", source="sentinel2")

# Multi-temporal (4 frames simultaneously — key strength of Prithvi)
mt = PrithviMultiTemporal("prithvi_eo_2_0")
mt.process_time_series(images, dates=dates, source="sentinel2")

# Fine-tuning
result = finetune_prithvi(
    model_name="prithvi_eo_2_0", task="land_cover", num_classes=9,
    epochs=50, learning_rate=5e-5, batch_size=8,  # memory-limited for 600M
    mixed_precision=True,
)
PyGeoVision Core — Auto-Labeling

Auto-Labeling — 7 Sources, Zero Manual Work

microsoft_buildings
1.4B global footprints
ML-detected building footprints covering the entire world.
GlobalFree
google_buildings
817M+ Africa, Asia, LatAm
Google Open Buildings covering Africa, S/SE Asia, Latin America.
AfricaFree
osm
OpenStreetMap
Buildings, roads, water, landuse polygons globally.
GlobalFree
esa_worldcover
11-class, 10m, global
ESA WorldCover land cover. 2020 and 2021 editions.
10mFree
dynamic_world
Near-real-time Sentinel-2
Google Dynamic World. Near-RT land use/land cover from S2.
Near RTFree
sam_auto
Segment Anything (SAM)
Dense auto-masks with no class labels — review in QGIS.
Zero-shot
foundation_cluster
DINOv2 + K-means
Unsupervised habitat/landcover from DINOv2 patch embeddings.
Unsupervised
labeling.py
ms   = client.labeling.microsoft_buildings(bbox, output_path="labels.tif")
osm  = client.labeling.osm(bbox, categories=["buildings","roads"])
esa  = client.labeling.esa_worldcover(bbox)
sam  = client.labeling.sam_auto(scene_path, points_per_side=32)

# Quality assessment
report = client.labeling.quality("labels.tif")
print(report["quality_grade"], report["quality_score"])   # 'A', 0.92

# Multi-source weighted fusion
fused = client.labeling.pipeline(bbox=bbox,
    sources=[
        {"type":"microsoft_buildings","weight":1.5},
        {"type":"osm",                "weight":1.0},
        {"type":"sam",                "weight":0.8},
    ],
    fusion="weighted_vote", output_path="labels_fused.tif")
PyGeoVision Core — Training

GeoTrainer — Production Training Pipeline

training.py
from pygeovision.models import get_model
from pygeovision.training.trainer import GeoTrainer
from pygeovision.training.callbacks import EarlyStopping, ModelCheckpoint
from pygeovision.losses.segmentation import GeospatialMixedLoss
from pygeovision.training.data import GeoSegDataset
from torch.utils.data import DataLoader

model = get_model("segformer-b2", num_classes=5, in_channels=6, pretrained=True)
loss  = GeospatialMixedLoss(weights={"combo":0.40,"boundary":0.40,"ohem":0.20})

trainer = GeoTrainer(
    model           = model,
    task            = "segmentation",
    num_classes     = 5,
    epochs          = 100,
    learning_rate   = 6e-5,         # low LR for transformer fine-tuning
    weight_decay    = 0.01,
    mixed_precision = "bf16",        # BF16 recommended for A100/H100
    loss_fn         = loss,
    callbacks       = [
        EarlyStopping(monitor="val_iou", patience=15, mode="max"),
        ModelCheckpoint("./checkpoints/", monitor="val_iou", save_top_k=3),
    ],
)
train_dl = DataLoader(GeoSegDataset("./chips/train/","./labels/train/"), batch_size=8)
val_dl   = DataLoader(GeoSegDataset("./chips/val/",  "./labels/val/"),   batch_size=8)
history  = trainer.fit(train_dl, val_dl)
print(f"Best val_iou: {history['best_metrics']['val_iou']:.4f}")

Losses: DiceLoss · FocalLoss · TverskyLoss · GeospatialMixedLoss (Dice+Boundary+OHEM) · ChangeDetectionLoss · BoundaryAwareLoss

Optimisers: AdamW · SGD · Lion   |   Schedulers: CosineAnnealing · OneCycleLR · WarmupCosine   |   Precision: FP32 · FP16 · BF16

PyGeoVision Core — Inference

Tiled Inference — No Seam Artefacts

inference.py
from pygeovision.inference.tiled import TiledInference, EnsembleInference

# Single model — any size GeoTIFF, Gaussian blending
inf = TiledInference(model=model, chip_size=512, overlap=64,
                      blend_mode="gaussian", num_classes=5, device="cuda")
result = inf.infer("large_scene.tif", "prediction.tif")
# → {n_chips: 48, duration_seconds: 1.1, chips_per_second: 44.7}

# Ensemble (mean of multiple models)
ensemble = EnsembleInference(models=[model_a, model_b, model_c], mode="mean")
ensemble.infer("scene.tif", "ensemble_pred.tif")
PyGeoVision Core — Vision-Language

Vision-Language Models — Own Stack

vlm.py
from pygeovision.advanced.vlm.clip_geo      import CLIPGeo
from pygeovision.advanced.vlm.moondream_geo import MoondreamGeo

# ── RemoteCLIP (RS5M — 5M remote sensing image-text pairs) ───────────────
clip = CLIPGeo(model_name="remoteclip-l14")

# Zero-shot classification (no fine-tuning needed)
probs = clip.classify("scene.tif", [
    "dense urban area", "tropical rainforest",
    "agricultural cropland", "flooded wetland",
])

# Build FAISS index over large satellite archive (one-time)
clip.build_index("./archive/", "geo_index.faiss")

# Text-to-image retrieval
results = clip.search("flooded agricultural fields near river", top_k=10)
similar = clip.search_by_image("query.tif", top_k=5)

# ── Moondream 2 (1.87B VLM) ──────────────────────────────────────────────
moon    = MoondreamGeo()
caption = moon.caption("scene.tif")
answer  = moon.vqa("scene.tif", "How many buildings are visible?")
change  = moon.describe_change("before.tif", "after.tif")
PyGeoVision Core — Advanced AI

Advanced AI Features

🎯
Few-Shot Learning
Prototypical networks with DINOv2-Large backbone. ~87% accuracy at 5-shot, ~91% at 10-shot. FewShotLearner(backbone="dinov2-large")
AutoML / HPO
Optuna-powered hyperparameter optimisation over LR, WD, backbone, loss, batch size. Typical +2–4 mIoU over defaults. AutoML(n_trials=50)
📈
Time-Series Analysis
NDVI/EVI trends, phenological profiles, anomaly detection, seasonal decomposition. GeoTimeSeries(sensor="sentinel2")
🔍
Explainability
GradCAM, attention map visualisation, SHAP-Geo spatial attribution, uncertainty estimation. GeoGradCAM(model).generate(scene)
🏔️
3D / Point Cloud
PointNet++, RandLA-Net, KPConv for LiDAR. Aerial point cloud segmentation, terrain analysis. get_model("pointnet2")
🔄
Embedding Search
FAISS index over satellite archives. Query by text (CLIP) or by image (DINOv3). Semantic retrieval from 10k+ scenes in milliseconds.
advanced.py
from pygeovision.advanced.few_shot   import FewShotLearner
from pygeovision.advanced.automl    import AutoML
from pygeovision.advanced.timeseries import GeoTimeSeries

# Few-Shot
learner = FewShotLearner(backbone="dinov2-large", method="prototypical")
learner.fit_support({"solar_panel":["img1.tif","img2.tif","img3.tif","img4.tif","img5.tif"]})
result  = learner.predict("new_scene.tif")   # {"class":"solar_panel","confidence":0.91}

# AutoML
automl = AutoML(model_family="segformer", task="segmentation",
                num_classes=5, n_trials=50, timeout_hours=4.0)
best   = automl.optimise(train_dl, val_dl)
print(f"Best val_iou: {best['val_iou']:.4f}  params: {best['params']}")

# Time series
ts     = GeoTimeSeries(sensor="sentinel2")
trend  = ts.compute_trend(series)        # direction, slope, R², p-value
anom   = ts.detect_anomalies(series, threshold=2.0)
decomp = ts.decompose(series, period=12)  # trend + seasonal + residual
PyGeoVision Core — Monitoring

Production Monitoring

monitoring.py
from pygeovision.monitoring.drift   import DriftDetector
from pygeovision.monitoring.tracker import ModelPerformanceTracker
from pygeovision.monitoring.alerts  import AlertManager

# Drift detection — PSI (Population Stability Index)
detector = DriftDetector(method="psi", threshold_warn=0.1, threshold_critical=0.2)
detector.fit(reference_images)
report  = detector.check(new_images)
# PSI < 0.10: no drift  |  0.10–0.20: warning  |  > 0.20: retrain

# Performance tracking
tracker = ModelPerformanceTracker(metrics=["val_iou","val_f1","throughput_fps"])
tracker.log(epoch=50, metrics={"val_iou":0.843,"val_f1":0.887,"throughput_fps":118})
trend   = tracker.trend("val_iou")   # direction, slope

# Alerts — Slack / email / webhook
alerts = AlertManager(channels={"slack":{"webhook_url":"https://..."}})
alerts.add_rule("iou_drop",  "val_iou",      "less_than",    0.78, "critical")
alerts.add_rule("drift",     "psi_score",    "greater_than", 0.10, "warning")
alerts.add_rule("throughput","fps",           "less_than",    80,   "warning")
alerts.check({"val_iou":0.72})   # fires critical alert
PyGeoVision Core — Pipelines

10 End-to-End Pipelines

One call from bounding box to finished GeoJSON/GeoTIFF. PyGeoFetch handles data acquisition; PyGeoVision's own model stack handles inference.

STEP 01
🔍
Search
PyGeoFetch queries providers with bbox, date, and cloud filters.
STEP 02
⬇️
Download
Parallel download with post-processing chain (reproject, COG).
STEP 03
🧠
Inference
PyGeoVision own model — tiled, Gaussian-blended, GPU-accelerated.
STEP 04
📦
Export
GeoTIFF / GeoJSON / COG with full metadata and stats.
building_footprints
Sentinel-2 / NAIP via PC
Building polygons with SegFormer-B2 + MS auto-labels. GeoJSON with confidence scores.
SegFormer-B2GeoJSON
change_detection
Bi-temporal Sentinel-2/Landsat
ChangeFormer bi-temporal analysis. Urban growth, damage, infrastructure change.
ChangeFormerGeoTIFF
land_cover
Sentinel-2
9-class ESA-compatible land cover using Prithvi-EO-2.0 (600M). WorldCover compatible.
Prithvi-EO-2.09 classes
water_bodies
Sentinel-2
NDWI + segmentation water body mapping. Flood extent in hours of event.
NDWIGeoJSON
solar_detection
NAIP / Planet SkySat
Solar panel inventory with energy potential estimation from high-res imagery.
SolarDetectorGeoJSON
crop_monitoring
Sentinel-2 Apr–Oct stack
10-class crop type mapping from full growing-season time stack using Prithvi.
Prithvi10 crops
disaster_assessment
Pre/post VHR imagery
4-class building damage (No/Minor/Major/Destroyed) following xBD protocol.
ChangeFormerxBD
deforestation
Bi-temporal Landsat/S2
Forest loss detection with ChangeFormer. Amazon, Congo Basin, SE Asia coverage.
ChangeFormerGeoJSON
urban_growth
Bi-temporal Landsat
Urban expansion mapping from long-term Landsat time series using Siamese-UNet.
Siamese-UNetGeoTIFF
carbon_estimation
Sentinel-2 + DINOv3 CHMv2
Above-ground biomass and carbon stock (t CO₂e/ha) using DINOv3 canopy height model.
CHMv2Biomass
pipelines.py
# All 10 pipelines share the same interface
result = client.pipeline("building_footprints",
    bbox=(-0.15,51.47,-0.10,51.52), date="2024-06")
result.output_path   # Path('./results/building_footprints/prediction.tif')
result.stats         # {"buildings_detected":1847, "coverage_pct":0.312}

result = client.pipeline("change_detection",
    bbox=..., date_before="2020-01", date_after="2024-01")

result = client.pipeline("carbon_estimation",
    bbox=(-55,-4,-54,-3), date="2024-07")   # Amazon carbon stock (t CO2e/ha)

# YAML pipeline (scheduled, recurring)
p = client.create_pipeline("weekly_buildings")
p.search(bbox=..., providers=["planetary_computer"], date_range="last_7_days")
p.download(post_process=["reproject:EPSG:32618","cog"], parallel=4)
p.ai_step("segment_buildings", model="segformer-b2", num_classes=2)
p.export(format="geojson", output_dir="./results/")
p.schedule(cron="0 3 * * 1")
p.save("weekly_buildings.yaml")
p.run(dry_run=True)
PyGeoVision Core — Serving

REST API Serving — FastAPI + WebSocket

serving.py
from pygeovision.serving import InferenceServer

server = InferenceServer(
    auth_keys   = {"prod":"SECRET_KEY", "dev":"DEV_KEY"},
    max_workers = 4,
    enable_cors = True,
)
server.register("seg_v1", "model.onnx",    task="segmentation",       num_classes=5)
server.register("chg_v1", "change.onnx",   task="change_detection")
server.register("det_v1", "detector.onnx", task="detection")
server.serve(host="0.0.0.0", port=8080)

# CLI equivalent
# pygeovision serve start --model model.onnx --port 8080 --auth-key SECRET
EndpointMethodDescription
/predictPOSTSingle-scene inference — multipart GeoTIFF upload, returns prediction GeoTIFF
/predict/batchPOSTBatch inference — multiple scenes in one request
/ws/streamWSWebSocket streaming for live ingestion and real-time tile-by-tile results
/healthGETHealth check — GPU status, model registry, queue depth
/modelsGETList registered models with metadata
/metricsGETPrometheus-compatible — latency, throughput, queue depth
PyGeoVision Core — Deployment

Edge and Cloud Deployment

ONNX Runtime
CPU / CUDA / TensorRT
Export any PyTorch model to ONNX. Run cross-platform with no PyTorch dependency.
🔋
Jetson Orin
TensorRT FP16 · ~45 chips/s
Convert ONNX → TensorRT FP16 for Jetson Orin edge inference at 45 chips/s.
☁️
AWS SageMaker
ml.g4dn.xlarge · $0.74/hr
One-call deploy to SageMaker endpoint with auto-scaling policies.
🔷
Azure ML
Standard_NC6s_v3 · $0.90/hr
Deploy to Azure ML managed online endpoint with blue/green updates.
🟡
GCP Vertex AI
T4 GPU · ~110 chips/s
Deploy to Vertex AI prediction endpoint with Vertex Monitoring.
🐳
Docker
pygeovision/pygeovision:2.0
Official CUDA-enabled image for containerised edge and on-premise deployment.
deploy.py
from pygeovision.edge.onnx_rt  import ONNXRuntimeInference
from pygeovision.edge.jetson   import JetsonDeployer
from pygeovision.cloud.deploy  import AWSDeployer, AzureDeployer, GCPDeployer

# Export + run ONNX
ONNXRuntimeInference.from_pytorch(model, "model.onnx")
eng = ONNXRuntimeInference("model.onnx", device="cuda")
eng.infer_geotiff("scene.tif", "prediction.tif")

# Jetson Orin TensorRT FP16
JetsonDeployer(device_type="orin").convert("model.onnx","model.trt",precision="fp16")

# AWS SageMaker
AWSDeployer(region="us-east-1").deploy(
    "model.onnx","buildings-prod",instance_type="ml.g4dn.xlarge")

# Azure ML
AzureDeployer(subscription_id="...",resource_group="rg").deploy(
    "model.onnx","buildings-ep",vm_size="Standard_NC6s_v3")

# GCP Vertex AI
GCPDeployer(project_id="my-project").deploy(
    "model.onnx","buildings-ep",
    machine_type="n1-standard-8",accelerator_type="NVIDIA_TESLA_T4")
Optional Plugin

GeoAI Plugin — Optional Enhancement

GeoAI is no longer a dependency of PyGeoVision v2.0. It is an optional plugin that adds additional subsystems when installed. PyGeoVision's own stack covers the same tasks natively.

Do I need GeoAI? Very likely not. PyGeoVision v2.0 ships DINOv3, Prithvi-EO-2.0, CLIP, Moondream, ChangeFormer, SegFormer, full training, and deployment. Install GeoAI only if you specifically need Tessera embeddings, GroundedSAM, Leafmap visualisation, or legacy GeoAI-trained weights.
geoai_plugin.py
# Install the optional GeoAI plugin
# pip install "pygeovision[geoai]"  or  pip install geoai-py

ga = client.geoai   # lazy-loads geoai-py only on first attribute access
ga.is_available     # True / False
ga.version          # '0.39.x'

# ── What GeoAI adds beyond PyGeoVision's own stack ─────────────────────

# Tessera pre-computed satellite embeddings (large-scale)
ga.tessera.available_years(bbox=(-74.1,40.6,-73.7,40.9))
ga.tessera.download(bbox=..., output_dir="./tessera/")

# GroundedSAM — DINO + SAM for natural language object detection
ga.detect.grounded("aerial.tif", "swimming pools in backyards")
ga.detect.grounded("aerial.tif", "solar panels on rooftops")

# Leafmap interactive visualisation (Jupyter)
m = ga.map.leafmap()
ga.map.view_raster("prediction.tif")
ga.map.view_vector("buildings.geojson")

# Moondream sliding-window caption over large scene
results = ga.caption.sliding_window("large_scene.tif",
    prompt="Describe the dominant land use.", tile_size=512)

# ── PyGeoVision own equivalents (no GeoAI needed) ────────────────────
# Buildings   → get_model("segformer-b2") + TiledInference
# Change det  → get_model("changeformer")
# DINOv3      → DINOv3Backbone("dinov3_vitl16_sat")
# Prithvi     → PrithviTasks("prithvi_eo_2_0")
# CLIP        → CLIPGeo("remoteclip-l14")
# Moondream   → MoondreamGeo()

GeoAI Plugin — Segmentation Extras

geoai_segment.py
# GeoAI plugin segmentation extras (requires pip install "pygeovision[geoai]")
ga.segment.buildings("s2.tif", output_vector="buildings.geojson")  # BuildingFootprintExtractor
ga.segment.solar_panels("aerial.tif", output_vector="solar.geojson")
ga.segment.agriculture_fields("s2.tif", output_vector="fields.geojson")
ga.segment.water("s2.tif", band_order="sentinel2")
ga.segment.with_sam("aerial.tif", output_path="masks.tif")
ga.segment.from_hub("scene.tif", "giswqs/building-footprint-usa")  # HF Hub

GeoAI Plugin — Detection Extras

geoai_detect.py
ga.detect.cars("aerial.tif",    output_path="cars.geojson")
ga.detect.ships("port.tif",     output_path="ships.geojson")
ga.detect.parking("lot.tif",    output_path="spots.geojson")
ga.detect.grounded("aerial.tif","swimming pools",output_path="pools.geojson")  # GroundedSAM
ga.detect.rfdetr("scene.tif",   output_path="det.geojson")
ga.detect.multiclass("scene.tif","nwpu_model.pth",output_path="det.geojson")

GeoAI Plugin — Embeddings & Utilities

geoai_embed_utils.py
# Tessera pre-computed embeddings
embeddings = ga.embed.patch("sentinel2.tif", chip_size=64)   # (N, 512)
ga.embed.cluster(embeddings, n_clusters=10)
score = ga.embed.similarity(emb_a, emb_b)   # 0.85
ga.embed.visualize(embeddings, method="umap")

# Cloud masking
ga.cloud.predict("sentinel2.tif", output_path="cloud.tif")
stats = ga.cloud.statistics("cloud.tif")   # {"cloud_cover": 0.08}

# Super-resolution (ESRGAN ×4)
ga.sr.enhance("landsat.tif", output_path="enhanced.tif", scale_factor=4)

# Utilities
ga.utils.raster_to_vector("pred.tif","polygons.geojson")
ga.utils.smooth_vector("buildings.geojson","smooth.geojson")
metrics = ga.utils.segmentation_metrics(pred, target)   # mIoU, F1, accuracy
ga.utils.get_device()   # 'cuda' | 'mps' | 'cpu'
Learning Resources

25 Production Notebooks — 357 Cells

Every notebook solves a real-world geospatial problem end-to-end. All 25 run without GPU in demo mode, and without satellite credentials (synthetic data substituted gracefully).

run all notebooks
pip install "pygeovision[all]"
cd projects/
jupyter notebook   # opens browser with all 25 notebooks
01
Satellite Data Acquisition
Data Acquisition
22-provider search, download, post-processing and caching for any study area.
02
Building Footprint Extraction
Urban Mapping
City-scale footprints with MS + OSM auto-labeling and SegFormer-B2 (London, 1847 buildings).
03
Land Cover with Prithvi-EO-2.0
Land Cover
9-class ESA-compatible land cover using the 600M foundation model.
04
Change Detection
Disaster Response
ChangeFormer bi-temporal change analysis for hurricane damage mapping.
05
Agricultural Crop Monitoring
Agriculture
NDVI time-series analysis and crop health assessment for insurance companies.
06
Forest Monitoring
Forestry
Deforestation detection + DINOv3 CHMv2 canopy height + biomass and carbon stock.
07
Water & Flood Mapping
Disaster Response
NDWI + Prithvi flood extent mapping. Rapid assessment within hours of event.
08
Solar Panel Detection
Renewable Energy
Solar installation inventory and energy potential estimation (Zurich, 1247 panels).
09
Disaster Damage Assessment
Emergency Response
4-class building damage after earthquake using xBD protocol and ChangeFormer.
10
Urban Growth Analysis
Urban Planning
Lagos decade-long urban expansion with multi-temporal Landsat change detection.
11
Road Network Extraction
Infrastructure
SegFormer-B2 + OSM auto-labeling + topology validation (Paris, 2185 km of roads).
12
Crop Type Mapping
Agriculture
10-class crop type mapping with Prithvi Apr–Oct time series (BreizhCrops, France).
13
Glacier Monitoring
Climate Science
Aletsch Glacier retreat 2000–2024 + RCP4.5/8.5 projections to 2100.
14
Oil Spill Detection (SAR)
Environment
Sentinel-1 SAR adaptive threshold detection — works at night through clouds.
15
Air Quality Monitoring
Environment
NO2 and PM2.5 from Sentinel-5P TROPOMI (Rome, WHO compliance assessment).
16
Wildfire Detection
Disaster Response
BAI + dNBR USFS 4-class burn severity mapping (Sierra Nevada, California).
17
Biodiversity Mapping
Ecology
DINOv3 + K-means unsupervised habitat classification without manual labels.
18
Infrastructure Monitoring
Civil Engineering
New Cairo construction progress tracking 2021–2024 from satellite time series.
19
Coastal & Wetland
Environment
Camargue wetland loss tracking 2015–2024. 7900 ha lost quantified.
20
Climate Change Analysis
Climate Science
Dubai Urban Heat Island + LST trend 2010–2024 + 2050 projections.
21
Custom Model Training
Machine Learning
Auto-label → train SegFormer-B2 → evaluate → export ONNX — zero manual labels.
22
Pipeline Deployment
MLOps
YAML pipelines + cron scheduling + cloud deployment + monitoring setup end-to-end.
23
Foundation Model Fine-Tuning
Deep Learning
DINOv3 SAT + Prithvi-EO-2.0 fine-tuning cookbook with comparison table.
24
DINOv3 Embedding Analysis
AI / Retrieval
Semantic image search over 10k-scene archive using FAISS + cosine similarity.
25
Vision-Language Querying
AI / NLP
CLIP + RemoteCLIP zero-shot + Moondream VQA for natural language scene queries.
Reference

CLI Reference — 15 Command Groups

GroupKey SubcommandsDescription
status / doctorSystem status dashboard + installation diagnostics
modelslist, info, download, cacheOwn 119-model registry management
datasetslist, info, downloadOwn 503-dataset registry management
ai inferTiled inference on large GeoTIFFs (own stack)
ai segmentbuildings, water, roads, customSegmentation — own models
ai changedetect, list-modelsChange detection — ChangeFormer / ChangeSTAR
ai trainsegmentation, detection, classification, chipsGeoTrainer — own training pipeline
ai foundationdinov3, prithvi, clip, moondreamFoundation model inference (own stack)
ai labelms-buildings, osm, worldcover, samAuto-labeling — 7 sources
pipelinebuilding_footprints … (all 10)End-to-end data + AI pipelines
servestart, stop, status, registerFastAPI inference server management
data authadd, list, test, removePyGeoFetch credentials (optional)
data search / downloadSatellite data acquisition (optional)
data pipelinerun, validate, schedule, list, logsYAML pipeline orchestration (optional)
configshow, get, set, path, resetConfiguration management
cli_reference.sh
# System
pygeovision status
pygeovision doctor

# Own model registry (119 architectures)
pygeovision models list
pygeovision models list --task foundation
pygeovision models list --task segmentation --pretrained-only
pygeovision models info prithvi_eo_2_0
pygeovision models info dinov3_vitl16_sat

# Own inference stack (no satellite credentials needed)
pygeovision ai infer \
  --input large_scene.tif --model segformer-b2 \
  --output prediction.tif --num-classes 5 \
  --tile-size 512 --overlap 64 --precision bf16

# Foundation models (own stack)
pygeovision ai foundation dinov3 \
  --input scene.tif --model dinov3_vitl16_sat \
  --output embeddings.npy

pygeovision ai foundation prithvi \
  --input sentinel2.tif --task land_cover --output lc.tif

# Auto-labeling
pygeovision ai label ms-buildings \
  --bbox "-0.15,51.47,-0.10,51.52" --output labels.tif

# Training
pygeovision ai train segmentation \
  --data ./chips/ --output model.pth \
  --model segformer-b2 --num-classes 5 \
  --epochs 100 --precision bf16

# Serving
pygeovision serve start \
  --model model.onnx --port 8080 --auth-key SECRET
pygeovision serve status
pygeovision serve stop

# E2E pipelines
pygeovision pipeline building_footprints \
  --bbox "-0.15,51.47,-0.10,51.52" \
  --date 2024-06 --output ./results/

pygeovision pipeline change_detection \
  --bbox "-74.1,40.6,-73.7,40.9" \
  --date-before 2020-01 --date-after 2024-01

# Optional: PyGeoFetch satellite data
pygeovision data search \
  --bbox "-74.1,40.6,-73.7,40.9" \
  --date 2024-06 --providers planetary_computer \
  --cloud-max 10 --output results.geojson

pygeovision data download \
  --from-search results.geojson \
  --output ./data/ --parallel 4 \
  --post-process reproject:EPSG:32618,cog
Reference

Error Handling

ModelNotFoundError
→ pygeovision models list
Requested model not in the 119-model registry. Run models list for all valid names.
WrongNormalisationError
→ use get_transform(model_name)
DINOv3 SAT model used with ImageNet stats. get_transform() auto-selects correct normalisation.
PrithviBandOrderError
→ map_bands(data, source="sentinel2")
Prithvi received wrong band ordering. Must be HLS order: Blue, Green, Red, NIR, SWIR1, SWIR2.
GPUOutOfMemoryError
→ reduce chip_size=256 or batch_size=2
CUDA OOM during tiled inference. Reduce chip_size (512→256) or batch_size, then retry.
PyGeoFetchNotInstalledError
→ pip install pygeofetch
Called client.search() without PyGeoFetch. Or pass local GeoTIFFs directly to AI APIs instead.
GeoAINotInstalledError
→ pip install "pygeovision[geoai]"
Accessed client.geoai.* without the GeoAI plugin. Or use PyGeoVision's native equivalents.
ProviderAuthError
→ pygeovision data auth add PROVIDER
PyGeoFetch credentials missing or expired. Re-add or set via environment variables.
NoResultsError
→ widen cloud_cover_max or date range
Satellite search returned zero scenes. Relax filters, check bbox (longitude first), or add providers.
Reference

Security

🔑 Credential Handling
  • Credentials never written to disk in plain text
  • System keyring: macOS Keychain, Windows Credential Manager, Linux Secret Service
  • All logs redact passwords, tokens, and API keys
  • Encrypted file fallback using Fernet AES-128-CBC
🌐 Network Security
  • TLS 1.2+ enforced on all provider connections
  • SSL certificate verification always on
  • Connection timeouts per provider
  • No telemetry — PyGeoVision does not phone home
📦 Data Integrity
  • SHA256 checksum verification on downloads
  • Atomic file writes — partial downloads never corrupt data
  • Temp files cleaned on failure
  • ONNX model hash verification on load
🔒 API & Serving
  • JWT Bearer token authentication on all endpoints
  • Rate limiting — configurable per API key
  • No user data stored on inference server
  • CORS configurable, disabled by default
Headless Linux / Docker: If no D-Bus/keyring daemon is available, set PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring and provide all credentials via environment variables.
Reference

Docker

docker-compose.yml
version: '3.8'
services:
  pygeovision:
    image: pygeovision/pygeovision:2.0
    volumes:
      - ~/.pygeovision:/root/.pygeovision
      - ./pipelines:/pipelines
      - ./data:/data
    command: pygeovision serve start --model /data/model.onnx --port 8080
    ports:
      - "8080:8080"
    restart: unless-stopped
    environment:
      - PYGEOVISION_GPU_DEVICE=cuda
      - PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring
      - pygeofetch_PLANET_API_KEY=${PLANET_API_KEY}
      - pygeofetch_COPERNICUS_USERNAME=${COPERNICUS_USER}
      - pygeofetch_COPERNICUS_PASSWORD=${COPERNICUS_PASS}
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]
Quality

Testing — 580 Passing

test structure
tests/                          580 passing  |  2 skipped  |  0 failing
├── test_core.py                Core config, exceptions, engine init
├── test_data_layer.py          SatelliteFetcher, SearchResult, 22 providers
├── test_geoai_integration.py   GeoAI plugin subsystems (mocked, optional)
├── test_foundation_models.py   DINOv3 + Prithvi (own stack, mocked weights)
├── test_dinov3.py              DINOv3 backbone, transforms, CHMv2
├── test_prithvi.py             Prithvi tasks, band mapping, multi-temporal
├── test_edge_cloud.py          ONNX, Jetson, AWS, Azure, GCP
├── test_advanced.py            Few-shot, AutoML, VLM, timeseries
├── test_monitoring.py          Drift, tracker, alerts
├── test_serving.py             FastAPI endpoints, WebSocket, JWT auth
├── test_training.py            GeoTrainer, losses, metrics, callbacks
├── test_inference.py           TiledInference, ensemble, postprocessing
├── test_labeling.py            All 7 labelers + quality + fusion
├── test_models.py              Model registry, loader, 119 architectures
├── test_datasets.py            Dataset registry, loader, 503 datasets
├── test_pipelines.py           All 10 end-to-end pipelines
├── test_explainability.py      GradCAM, attention maps, uncertainty
├── test_cli.py                 All 15 CLI command groups
├── test_pointcloud.py          PointNet++, RandLA-Net, KPConv
└── conftest.py                 Shared fixtures, mock providers
run tests
pip install -e ".[dev]"
pytest tests/ -q                                       # all 580
pytest tests/test_foundation_models.py -v              # own foundation stack
pytest tests/test_models.py -v                         # 119-model registry
pytest tests/test_geoai_integration.py -v              # optional GeoAI plugin
pytest tests/ --cov=pygeovision --cov-report=html      # coverage report
Comparison

PyGeoVision v2.0 vs Alternatives

Feature PyGeoVision v2 EODAG TorchGeo TerraTorch GeoAI PyGeoFetch
Standalone (no AI dependency)
Own model registry119~30~50
DINOv3 (12 variants, SAT)✓ OwnPartialPartialPartial
Prithvi-EO-2.0 (600M)✓ OwnPartialPartialPartial
Satellite data providers22+ (opt)10+322+
Production training (GeoTrainer)PartialPartial
Auto-labeling (7 sources)Partial
FastAPI serving + WebSocket
Edge deployment (ONNX + Jetson)Partial
Cloud (AWS + Azure + GCP)
VLM (CLIP + Moondream)✓ OwnMoondream
Few-shot + AutoMLAutoML
Drift monitoring + alerts
Production notebooks25
Tests passing580~200~300~100~150~200
Full CLI (15 groups)Partial
Roadmap

Roadmap

v2.0.0
Standalone Platform
✓ Released — Q2 2026
  • Own 119-model registry
  • DINOv3 (12 variants, SAT-493M pre-training)
  • Prithvi-EO-2.0 (600M, HLS global 10yr)
  • CLIP + RemoteCLIP + Moondream 2
  • 503 dataset registry
  • GeoTrainer + GeospatialMixedLoss
  • FastAPI serving + WebSocket
  • ONNX + Jetson + AWS/Azure/GCP
  • Few-shot, AutoML, Timeseries
  • Drift monitoring + alert system
  • 25 production notebooks (357 cells)
  • 580 tests passing
  • GeoAI demoted to optional plugin
v2.1.0
Extended Coverage
◐ In Progress — Q3 2026
  • SAM 2 (Video SAM) integration
  • SigLIP vision encoder
  • LLaVA-Geo VQA model
  • BlackSky + KOMPSAT providers
  • Streaming COG partial reads
  • Distributed inference workers
  • MLflow experiment tracking
  • GeoParquet for all pipelines
  • Active learning loop
v2.2.0
Platform & Ecosystem
○ Planned — Q1 2027
  • Web monitoring dashboard
  • Model versioning + A/B testing
  • Hyperspectral (DESIS, EMIT) support
  • Video satellite pipeline
  • GeoAI v2 plugin compatibility
  • Federated learning
  • Multi-modal fusion (SAR + Optical)