Python library that bridges Copernicus Data Stores into mainstream GIS workflows.
GeoBridge removes the technical friction GIS users face when working with Copernicus climate, atmosphere, and emergency data. It resolves dataset discovery, authentication, and access-method differences into a single ergonomic API that produces analysis-ready Cloud Optimized GeoTIFFs.
The library is the foundation for the project's QGIS plugin.
- Discovery.
gb.discover()lists every dataset in the Copernicus catalogue with filters for keyword, service, variable, bounding box, and time range — all from a locally bundled snapshot, no network needed.gb.discover_one()fetches a single dataset by ID. - Authentication. A single
gb.authenticate()call handles credential resolution for the new ARCO bearer-token model. - Extraction — ARCO path.
gb.zarr_to_geotiff()pulls a spatial / temporal subset from the ARCO Zarr Data Lake and writes it as a Cloud Optimized GeoTIFF, ready for QGIS or ArcGIS.gb.list_datasets()andgb.list_variables()enumerate what's available through this path. - Extraction — CDS API path.
gb.cds_to_geotiff()submits a download job through the standard CDS API for datasets that are not yet in the ARCO lake, converts the result to GeoTIFF, and streams it to disk. As a prototype this path is only validated for a curated set of datasets (gb.discover(cds_download_only=True), or thecds_download_supportedflag incds_snapshot.yaml); other datasets raise unless you passallow_unsupported=True. - WMTS.
gb.wmts_layer()returns a ready-to-use WMTS layer object for live tile streaming inside QGIS. - Time series.
gb.point_time_series()andgb.point_value()sample a single point over time via WMTS GetFeatureInfo requests — no download, best for a handful to a few dozen time steps.gb.zarr_point_time_series()reads the same point directly out of the ARCO Zarr archive in a few chunked range-requests, and is the one to prefer for long time ranges. - Form schema.
gb.fetch_form()andgb.fetch_constraints()retrieve the server-side parameter form for any dataset so your UI can build validated request widgets.gb.valid_variables_for_product_type()filters the variable list to what the selected product type actually supports, andgb.validate_request()checks a full request dict against the dataset's constraints before you submit it. - Styling.
gb.to_qgis_style()generate calibrated colour ramps for known Copernicus variables. - Fusion.
gb.fuse()co-registers two layers onto a common grid for joint analysis (e.g. heat + air quality). The resampling kernel is picked per layer from what the variable means and whether the grid is being coarsened or refined (averagefor continuous fields,modefor categorical masks,maxfor extrema), and can be overridden withmethod=. - Semantics.
gb.semantic_search()resolves user themes like "urban heat island" or "wildfire risk" into concrete dataset and workflow recommendations.gb.semantic_resources()returns the matching resources directly.gb.list_themes()andgb.list_use_cases()enumerate the built-in vocabulary.
- Python 3.10 or newer. GeoBridge does not support older Python.
- A free Copernicus account. Register at https://cds.climate.copernicus.eu and copy your personal access token from your profile page.
- macOS, Linux, or Windows with WSL2. Native Windows may work but is not tested.
A separate environment avoids dependency conflicts with anything else you have installed. With Conda (recommended because some geospatial libraries need compiled C bindings that pip alone struggles with):
conda create -n geobridge python=3.11 -y
conda activate geobridgeOr with venv:
python3.11 -m venv ~/.venvs/geobridge
source ~/.venvs/geobridge/bin/activateIf you used Conda, install the heavy native dependencies through conda-forge first:
conda install -c conda-forge rasterio rioxarray zarr fsspec httpio dask -yThis avoids the most common build failures (GDAL, PROJ, libtiff).
GeoBridge is published on PyPI: https://pypi.org/project/geobridge/
pip install "geobridge[full]"The [full] extra adds everything: xarray/rasterio/zarr for
zarr_to_geotiff(), plus OWSLib (WMTS) and cfgrib (GRIB support). Use
geobridge[zarr] instead if you only need the ARCO extraction path, or
plain pip install geobridge for the lightweight core (discover(),
wmts_layer(), to_qgis_style(), and the semantic search functions all
work with only pyyaml, the sole hard runtime dependency — no extra
needed).
If you're contributing to GeoBridge itself, install from a clone in editable mode instead so your local edits take effect immediately:
git clone https://github.com/ECMWFCode4Earth/GeoBridge
cd geobridge
pip install -e ".[dev]"Create ~/.cdsapirc with your personal access token:
key: YOUR-CDS-API-KEY-HERE
Then protect the file so other users on the machine cannot read it:
chmod 600 ~/.cdsapircAlternatively, export your key as an environment variable instead of writing it to a file:
export CDS_API_KEY=YOUR-CDS-API-KEY-HEREgeobridge/ ← repository root
├── README.md ← this file
├── LICENSE ← MIT
├── pyproject.toml ← installable Python package
├── smoke_test.py ← offline smoke test (9 stages)
│
├── geobridge/ ← Python package
│ ├── __init__.py ← public API exports
│ ├── auth.py ← bearer-token authentication
│ ├── modules/
│ │ ├── discover.py ← catalogue discovery
│ │ ├── extract.py ← ARCO Zarr → GeoTIFF
│ │ ├── cds_download.py ← CDS API → GeoTIFF (non-ARCO datasets)
│ │ ├── wmts.py ← WMTS layer
│ │ ├── form.py ← dataset form schema & constraints
│ │ ├── style.py ← QGIS QML export
│ │ ├── timeseries.py ← point value / time series (WMTS & Zarr)
│ │ ├── fuse.py ← two-layer co-registration
│ │ └── resampling.py ← semantics-aware resampling kernels for fuse()
│ └── semantic/
│ ├── engine.py ← rule-based query resolver
│ ├── vocabulary.yaml ← themes and use cases
│ ├── arco_overrides.yaml ← Zarr URLs and variable aliases
│ ├── arco_snapshot.yaml ← ARCO catalogue snapshot (generated)
│ └── cds_snapshot.yaml ← STAC catalogue snapshot (generated)
│
├── scripts/
│ ├── refresh_catalogue.py ← maintainer-side CDS STAC refresh
│ └── refresh_arco_catalogue.py ← maintainer-side ARCO snapshot refresh
│
├── examples/
│ ├── athens_urban_heat.py ← end-to-end ERA5 demo
|
│
└── tests/
├── test_auth.py
└── unit/ ← pytest unit tests
├── test_discover.py
├── test_auth.py
├── test_extract.py
├── test_style.py
├── test_semantic.py
├── test_catalog.py
├── test_fuse.py
├── test_resampling.py
└── test_wmts.py
The cds_snapshot.yaml and arco_snapshot.yaml files are regenerated
periodically from the live ECMWF catalogues. End users never run these
scripts; they get the snapshots bundled with whatever GeoBridge version
they install.
To refresh the CDS STAC snapshot (maintainers only):
python scripts/refresh_catalogue.py --limit 5 --output /tmp/test.yaml # quick test
python scripts/refresh_catalogue.py # full run
git diff geobridge/semantic/cds_snapshot.yaml
git add geobridge/semantic/cds_snapshot.yaml
git commit -m "Refresh CDS catalogue snapshot"To refresh the ARCO snapshot:
python scripts/refresh_arco_catalogue.py
git add geobridge/semantic/arco_snapshot.yaml
git commit -m "Refresh ARCO catalogue snapshot"-
Visit the dataset page on https://cds.climate.copernicus.eu and open the "Analysis ready data" tab.
-
Copy the Zarr URLs (typically there are two:
time_chunkedandgeo_chunked). -
Verify each URL responds with a 200 status:
curl -I -H "Authorization: Bearer $CDS_API_KEY" "https://.../.zmetadata"
-
Add an entry to
geobridge/semantic/arco_overrides.yamlfollowing the schema of existing entries. -
Add the variable aliases (CDS long-form name → ARCO short-form name) by inspecting the Zarr store with
xarray.open_zarr()and listingds.data_vars.
MIT. See LICENSE.