geobridge 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- geobridge-0.1.0/.gitignore +24 -0
- geobridge-0.1.0/LICENSE +21 -0
- geobridge-0.1.0/PKG-INFO +331 -0
- geobridge-0.1.0/README.md +249 -0
- geobridge-0.1.0/geobridge/__init__.py +130 -0
- geobridge-0.1.0/geobridge/auth.py +191 -0
- geobridge-0.1.0/geobridge/modules/__init__.py +1 -0
- geobridge-0.1.0/geobridge/modules/cds_download.py +445 -0
- geobridge-0.1.0/geobridge/modules/discover.py +661 -0
- geobridge-0.1.0/geobridge/modules/extract.py +703 -0
- geobridge-0.1.0/geobridge/modules/form.py +464 -0
- geobridge-0.1.0/geobridge/modules/fuse.py +340 -0
- geobridge-0.1.0/geobridge/modules/style.py +317 -0
- geobridge-0.1.0/geobridge/modules/wmts.py +462 -0
- geobridge-0.1.0/geobridge/semantic/__init__.py +0 -0
- geobridge-0.1.0/geobridge/semantic/arco_overrides.yaml +67 -0
- geobridge-0.1.0/geobridge/semantic/arco_snapshot.yaml +44456 -0
- geobridge-0.1.0/geobridge/semantic/cds_snapshot.yaml +6333 -0
- geobridge-0.1.0/geobridge/semantic/engine.py +501 -0
- geobridge-0.1.0/geobridge/semantic/vocabulary.yaml +1122 -0
- geobridge-0.1.0/pyproject.toml +87 -0
- geobridge-0.1.0/scripts/refresh_arco_catalogue.py +452 -0
- geobridge-0.1.0/scripts/refresh_catalogue.py +372 -0
- geobridge-0.1.0/smoke_test.py +347 -0
- geobridge-0.1.0/tests/__init__.py +0 -0
- geobridge-0.1.0/tests/test_auth.py +103 -0
- geobridge-0.1.0/tests/unit/__init__.py +0 -0
- geobridge-0.1.0/tests/unit/test_auth.py +88 -0
- geobridge-0.1.0/tests/unit/test_discover.py +253 -0
- geobridge-0.1.0/tests/unit/test_extract.py +174 -0
- geobridge-0.1.0/tests/unit/test_semantic.py +135 -0
- geobridge-0.1.0/tests/unit/test_style.py +96 -0
- geobridge-0.1.0/tests/unit/test_wmts.py +147 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Claude
|
|
2
|
+
.claude/
|
|
3
|
+
|
|
4
|
+
# Python
|
|
5
|
+
__pycache__/
|
|
6
|
+
*.py[cod]
|
|
7
|
+
*.pyo
|
|
8
|
+
.DS_Store
|
|
9
|
+
|
|
10
|
+
# Virtual environments
|
|
11
|
+
.venv/
|
|
12
|
+
venv/
|
|
13
|
+
env/
|
|
14
|
+
|
|
15
|
+
# Distribution / packaging
|
|
16
|
+
dist/
|
|
17
|
+
build/
|
|
18
|
+
*.egg-info/
|
|
19
|
+
|
|
20
|
+
# Jupyter
|
|
21
|
+
.ipynb_checkpoints/
|
|
22
|
+
|
|
23
|
+
# folders
|
|
24
|
+
examples/
|
geobridge-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 GeoBridge contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
geobridge-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: geobridge
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python bridge between Copernicus Data Stores (C3S, CAMS, CEMS) and mainstream GIS operations
|
|
5
|
+
Project-URL: Homepage, https://github.com/ECMWFCode4Earth/GeoBridge
|
|
6
|
+
Project-URL: Repository, https://github.com/ECMWFCode4Earth/GeoBridge
|
|
7
|
+
Project-URL: Issues, https://github.com/ECMWFCode4Earth/GeoBridge/issues
|
|
8
|
+
Author: Kostas Fokeas and Ilias Machairas
|
|
9
|
+
License: MIT License
|
|
10
|
+
|
|
11
|
+
Copyright (c) 2026 GeoBridge contributors
|
|
12
|
+
|
|
13
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
14
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
15
|
+
in the Software without restriction, including without limitation the rights
|
|
16
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
17
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
18
|
+
furnished to do so, subject to the following conditions:
|
|
19
|
+
|
|
20
|
+
The above copyright notice and this permission notice shall be included in all
|
|
21
|
+
copies or substantial portions of the Software.
|
|
22
|
+
|
|
23
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
24
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
25
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
26
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
27
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
28
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
29
|
+
SOFTWARE.
|
|
30
|
+
License-File: LICENSE
|
|
31
|
+
Keywords: CAMS,CEMS,ERA5,GIS,WMTS,climate,copernicus,earth-observation,geotiff,zarr
|
|
32
|
+
Classifier: Development Status :: 3 - Alpha
|
|
33
|
+
Classifier: Intended Audience :: Developers
|
|
34
|
+
Classifier: Intended Audience :: Science/Research
|
|
35
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
39
|
+
Classifier: Topic :: Scientific/Engineering :: Atmospheric Science
|
|
40
|
+
Classifier: Topic :: Scientific/Engineering :: GIS
|
|
41
|
+
Requires-Python: >=3.10
|
|
42
|
+
Requires-Dist: pyyaml>=6.0
|
|
43
|
+
Provides-Extra: dev
|
|
44
|
+
Requires-Dist: build; extra == 'dev'
|
|
45
|
+
Requires-Dist: cfgrib>=0.9.10; extra == 'dev'
|
|
46
|
+
Requires-Dist: dask>=2023.1; extra == 'dev'
|
|
47
|
+
Requires-Dist: fsspec>=2023.1; extra == 'dev'
|
|
48
|
+
Requires-Dist: mypy>=1.8; extra == 'dev'
|
|
49
|
+
Requires-Dist: numpy>=1.24; extra == 'dev'
|
|
50
|
+
Requires-Dist: owslib>=0.28; extra == 'dev'
|
|
51
|
+
Requires-Dist: pyproj>=3.5; extra == 'dev'
|
|
52
|
+
Requires-Dist: pytest-cov>=4.1; extra == 'dev'
|
|
53
|
+
Requires-Dist: pytest>=7.4; extra == 'dev'
|
|
54
|
+
Requires-Dist: rasterio>=1.3; extra == 'dev'
|
|
55
|
+
Requires-Dist: responses>=0.23; extra == 'dev'
|
|
56
|
+
Requires-Dist: rioxarray>=0.14; extra == 'dev'
|
|
57
|
+
Requires-Dist: ruff>=0.4; extra == 'dev'
|
|
58
|
+
Requires-Dist: types-pyyaml; extra == 'dev'
|
|
59
|
+
Requires-Dist: types-requests; extra == 'dev'
|
|
60
|
+
Requires-Dist: xarray>=2023.1; extra == 'dev'
|
|
61
|
+
Requires-Dist: zarr>=2.16; extra == 'dev'
|
|
62
|
+
Provides-Extra: full
|
|
63
|
+
Requires-Dist: cfgrib>=0.9.10; extra == 'full'
|
|
64
|
+
Requires-Dist: dask>=2023.1; extra == 'full'
|
|
65
|
+
Requires-Dist: fsspec>=2023.1; extra == 'full'
|
|
66
|
+
Requires-Dist: numpy>=1.24; extra == 'full'
|
|
67
|
+
Requires-Dist: owslib>=0.28; extra == 'full'
|
|
68
|
+
Requires-Dist: pyproj>=3.5; extra == 'full'
|
|
69
|
+
Requires-Dist: rasterio>=1.3; extra == 'full'
|
|
70
|
+
Requires-Dist: rioxarray>=0.14; extra == 'full'
|
|
71
|
+
Requires-Dist: xarray>=2023.1; extra == 'full'
|
|
72
|
+
Requires-Dist: zarr>=2.16; extra == 'full'
|
|
73
|
+
Provides-Extra: zarr
|
|
74
|
+
Requires-Dist: dask>=2023.1; extra == 'zarr'
|
|
75
|
+
Requires-Dist: fsspec>=2023.1; extra == 'zarr'
|
|
76
|
+
Requires-Dist: numpy>=1.24; extra == 'zarr'
|
|
77
|
+
Requires-Dist: rasterio>=1.3; extra == 'zarr'
|
|
78
|
+
Requires-Dist: rioxarray>=0.14; extra == 'zarr'
|
|
79
|
+
Requires-Dist: xarray>=2023.1; extra == 'zarr'
|
|
80
|
+
Requires-Dist: zarr>=2.16; extra == 'zarr'
|
|
81
|
+
Description-Content-Type: text/markdown
|
|
82
|
+
|
|
83
|
+
# GeoBridge
|
|
84
|
+
|
|
85
|
+
**Python library that bridges Copernicus Data Stores into mainstream GIS workflows.**
|
|
86
|
+
|
|
87
|
+
GeoBridge removes the technical friction GIS users face when working with
|
|
88
|
+
Copernicus climate, atmosphere, and emergency data. It resolves dataset
|
|
89
|
+
discovery, authentication, and access-method differences into a single
|
|
90
|
+
ergonomic API that produces analysis-ready Cloud Optimized GeoTIFFs.
|
|
91
|
+
|
|
92
|
+
The library is the foundation for the project's QGIS plugin.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## What it does
|
|
97
|
+
|
|
98
|
+
- **Discovery.** `gb.discover()` lists every dataset in the Copernicus
|
|
99
|
+
catalogue with filters for keyword, service, variable, bounding box, and
|
|
100
|
+
time range — all from a locally bundled snapshot, no network needed.
|
|
101
|
+
- **Authentication.** A single `gb.authenticate()` call handles credential
|
|
102
|
+
resolution for the new ARCO bearer-token model.
|
|
103
|
+
- **Extraction — ARCO path.** `gb.zarr_to_geotiff()` pulls a spatial / temporal
|
|
104
|
+
subset from the ARCO Zarr Data Lake and writes it as a Cloud Optimized
|
|
105
|
+
GeoTIFF, ready for QGIS or ArcGIS.
|
|
106
|
+
- **Extraction — CDS API path.** `gb.cds_to_geotiff()` submits a download job
|
|
107
|
+
through the standard CDS API for datasets that are not yet in the ARCO lake,
|
|
108
|
+
converts the result to GeoTIFF, and streams it to disk.
|
|
109
|
+
- **WMTS.** `gb.wmts_layer()` returns a ready-to-use WMTS layer object for
|
|
110
|
+
live tile streaming inside QGIS or Leaflet.
|
|
111
|
+
- **Form schema.** `gb.fetch_form()` and `gb.fetch_constraints()` retrieve the
|
|
112
|
+
server-side parameter form for any dataset so your UI can build validated
|
|
113
|
+
request widgets. `gb.valid_variables_for_product_type()` filters the variable
|
|
114
|
+
list to what the selected product type actually supports.
|
|
115
|
+
- **Styling.** `gb.to_qgis_style()` generate
|
|
116
|
+
calibrated colour ramps for known Copernicus variables.
|
|
117
|
+
- **Fusion.** `gb.fuse()` co-registers multiple layers onto a common grid
|
|
118
|
+
for joint analysis (e.g. heat + air quality).
|
|
119
|
+
- **Semantics.** `gb.semantic_search()` resolves user themes like
|
|
120
|
+
"urban heat island" or "wildfire risk" into concrete dataset and
|
|
121
|
+
workflow recommendations. `gb.list_themes()` and `gb.list_use_cases()`
|
|
122
|
+
enumerate the built-in vocabulary.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## How to run it
|
|
127
|
+
|
|
128
|
+
### Prerequisites
|
|
129
|
+
|
|
130
|
+
- **Python 3.10 or newer.** GeoBridge does not support older Python.
|
|
131
|
+
- **A free Copernicus account.** Register at
|
|
132
|
+
https://cds.climate.copernicus.eu and copy your personal access token
|
|
133
|
+
from your profile page.
|
|
134
|
+
- **macOS, Linux, or Windows with WSL2.** Native Windows may work but is
|
|
135
|
+
not tested.
|
|
136
|
+
|
|
137
|
+
### Step 1 — Create a clean environment
|
|
138
|
+
|
|
139
|
+
A separate environment avoids dependency conflicts with anything else you
|
|
140
|
+
have installed. With Conda (recommended because some geospatial libraries
|
|
141
|
+
need compiled C bindings that pip alone struggles with):
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
conda create -n geobridge python=3.11 -y
|
|
145
|
+
conda activate geobridge
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Or with `venv`:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
python3.11 -m venv ~/.venvs/geobridge
|
|
152
|
+
source ~/.venvs/geobridge/bin/activate
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Step 2 — Install the geospatial stack
|
|
156
|
+
|
|
157
|
+
If you used Conda, install the heavy native dependencies through
|
|
158
|
+
conda-forge first:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
conda install -c conda-forge rasterio rioxarray zarr fsspec httpio dask -y
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
This avoids the most common build failures (GDAL, PROJ, libtiff).
|
|
165
|
+
|
|
166
|
+
### Step 3 — Clone and install GeoBridge
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
git clone https://github.com/YOUR_USERNAME/geobridge.git
|
|
170
|
+
cd geobridge
|
|
171
|
+
pip install -e ".[zarr]"
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
`-e` installs in editable mode so you can pull updates without
|
|
175
|
+
reinstalling. The `[zarr]` extra adds the optional dependencies needed
|
|
176
|
+
for `zarr_to_geotiff()`. Use `.[full]` to also get OWSLib (WMTS) and
|
|
177
|
+
cfgrib (GRIB support).
|
|
178
|
+
|
|
179
|
+
### Step 4 — Configure your credentials
|
|
180
|
+
|
|
181
|
+
Create `~/.cdsapirc` with your personal access token:
|
|
182
|
+
|
|
183
|
+
```
|
|
184
|
+
key: YOUR-CDS-API-KEY-HERE
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Then protect the file so other users on the machine cannot read it:
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
chmod 600 ~/.cdsapirc
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Alternatively, export your key as an environment variable instead of
|
|
194
|
+
writing it to a file:
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
export CDS_API_KEY=YOUR-CDS-API-KEY-HERE
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Step 5 — Verify the installation
|
|
201
|
+
|
|
202
|
+
Run the bundled smoke test. It exercises every module without making
|
|
203
|
+
network calls:
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
PYTHONPATH=. python smoke_test.py
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Expected: nine stages all pass, ending with `ALL SMOKE TESTS PASSED`.
|
|
210
|
+
|
|
211
|
+
### Step 6 — Run the Athens demo
|
|
212
|
+
|
|
213
|
+
This is the end-to-end demonstration. It extracts ERA5 temperature for
|
|
214
|
+
Athens summer 2023, writes a Cloud Optimized GeoTIFF, and generates a
|
|
215
|
+
matching QGIS style:
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
python examples/athens_urban_heat.py
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Expected runtime is roughly one minute on a reasonable broadband
|
|
222
|
+
connection. The output appears in `./athens_outputs/`. Open the `.tif` in
|
|
223
|
+
QGIS, load the `.qml` style alongside it, and you should see Athens
|
|
224
|
+
temperatures rendered with a calibrated colour ramp.
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## Repository layout
|
|
229
|
+
|
|
230
|
+
```
|
|
231
|
+
geobridge/ ← repository root
|
|
232
|
+
├── README.md ← this file
|
|
233
|
+
├── LICENSE ← MIT
|
|
234
|
+
├── pyproject.toml ← installable Python package
|
|
235
|
+
├── smoke_test.py ← offline smoke test (9 stages)
|
|
236
|
+
│
|
|
237
|
+
├── geobridge/ ← Python package
|
|
238
|
+
│ ├── __init__.py ← public API exports
|
|
239
|
+
│ ├── auth.py ← bearer-token authentication
|
|
240
|
+
│ ├── modules/
|
|
241
|
+
│ │ ├── discover.py ← catalogue discovery
|
|
242
|
+
│ │ ├── extract.py ← ARCO Zarr → GeoTIFF
|
|
243
|
+
│ │ ├── cds_download.py ← CDS API → GeoTIFF (non-ARCO datasets)
|
|
244
|
+
│ │ ├── wmts.py ← WMTS layer
|
|
245
|
+
│ │ ├── form.py ← dataset form schema & constraints
|
|
246
|
+
│ │ ├── style.py ← QGIS QML export
|
|
247
|
+
│ │ └── fuse.py ← multi-layer co-registration
|
|
248
|
+
│ └── semantic/
|
|
249
|
+
│ ├── engine.py ← rule-based query resolver
|
|
250
|
+
│ ├── vocabulary.yaml ← themes and use cases
|
|
251
|
+
│ ├── arco_overrides.yaml ← Zarr URLs and variable aliases
|
|
252
|
+
│ ├── arco_snapshot.yaml ← ARCO catalogue snapshot (generated)
|
|
253
|
+
│ └── cds_snapshot.yaml ← STAC catalogue snapshot (generated)
|
|
254
|
+
│
|
|
255
|
+
├── scripts/
|
|
256
|
+
│ ├── refresh_catalogue.py ← maintainer-side CDS STAC refresh
|
|
257
|
+
│ └── refresh_arco_catalogue.py ← maintainer-side ARCO snapshot refresh
|
|
258
|
+
│
|
|
259
|
+
├── examples/
|
|
260
|
+
│ ├── athens_urban_heat.py ← end-to-end ERA5 demo
|
|
261
|
+
│ ├── example_utci.py ← UTCI thermal comfort demo
|
|
262
|
+
│ ├── examplepm2.5.py ← CAMS PM2.5 air quality demo
|
|
263
|
+
│ └── ... ← additional live-test scripts
|
|
264
|
+
│
|
|
265
|
+
└── tests/
|
|
266
|
+
├── test_auth.py
|
|
267
|
+
└── unit/ ← pytest unit tests
|
|
268
|
+
├── test_discover.py
|
|
269
|
+
├── test_auth.py
|
|
270
|
+
├── test_extract.py
|
|
271
|
+
├── test_style.py
|
|
272
|
+
├── test_semantic.py
|
|
273
|
+
└── test_wmts.py
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
## Maintainer workflow
|
|
279
|
+
|
|
280
|
+
### Refreshing catalogue snapshots
|
|
281
|
+
|
|
282
|
+
The `cds_snapshot.yaml` and `arco_snapshot.yaml` files are regenerated
|
|
283
|
+
periodically from the live ECMWF catalogues. End users never run these
|
|
284
|
+
scripts; they get the snapshots bundled with whatever GeoBridge version
|
|
285
|
+
they install.
|
|
286
|
+
|
|
287
|
+
To refresh the CDS STAC snapshot (maintainers only):
|
|
288
|
+
|
|
289
|
+
```bash
|
|
290
|
+
python scripts/refresh_catalogue.py --limit 5 --output /tmp/test.yaml # quick test
|
|
291
|
+
python scripts/refresh_catalogue.py # full run
|
|
292
|
+
git diff geobridge/semantic/cds_snapshot.yaml
|
|
293
|
+
git add geobridge/semantic/cds_snapshot.yaml
|
|
294
|
+
git commit -m "Refresh CDS catalogue snapshot"
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
To refresh the ARCO snapshot:
|
|
298
|
+
|
|
299
|
+
```bash
|
|
300
|
+
python scripts/refresh_arco_catalogue.py
|
|
301
|
+
git add geobridge/semantic/arco_snapshot.yaml
|
|
302
|
+
git commit -m "Refresh ARCO catalogue snapshot"
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Adding a new ARCO dataset
|
|
306
|
+
|
|
307
|
+
1. Visit the dataset page on https://cds.climate.copernicus.eu and open
|
|
308
|
+
the "Analysis ready data" tab.
|
|
309
|
+
2. Copy the Zarr URLs (typically there are two: `time_chunked` and
|
|
310
|
+
`geo_chunked`).
|
|
311
|
+
3. Verify each URL responds with a 200 status:
|
|
312
|
+
|
|
313
|
+
```bash
|
|
314
|
+
curl -I -H "Authorization: Bearer $CDS_API_KEY" "https://.../.zmetadata"
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
4. Add an entry to `geobridge/semantic/arco_overrides.yaml` following the
|
|
318
|
+
schema of existing entries.
|
|
319
|
+
5. Add the variable aliases (CDS long-form name → ARCO short-form name)
|
|
320
|
+
by inspecting the Zarr store with `xarray.open_zarr()` and listing
|
|
321
|
+
`ds.data_vars`.
|
|
322
|
+
|
|
323
|
+
---
|
|
324
|
+
|
|
325
|
+
## License
|
|
326
|
+
|
|
327
|
+
MIT. See `LICENSE`.
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
## Acknowledgements
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
# GeoBridge
|
|
2
|
+
|
|
3
|
+
**Python library that bridges Copernicus Data Stores into mainstream GIS workflows.**
|
|
4
|
+
|
|
5
|
+
GeoBridge removes the technical friction GIS users face when working with
|
|
6
|
+
Copernicus climate, atmosphere, and emergency data. It resolves dataset
|
|
7
|
+
discovery, authentication, and access-method differences into a single
|
|
8
|
+
ergonomic API that produces analysis-ready Cloud Optimized GeoTIFFs.
|
|
9
|
+
|
|
10
|
+
The library is the foundation for the project's QGIS plugin.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## What it does
|
|
15
|
+
|
|
16
|
+
- **Discovery.** `gb.discover()` lists every dataset in the Copernicus
|
|
17
|
+
catalogue with filters for keyword, service, variable, bounding box, and
|
|
18
|
+
time range — all from a locally bundled snapshot, no network needed.
|
|
19
|
+
- **Authentication.** A single `gb.authenticate()` call handles credential
|
|
20
|
+
resolution for the new ARCO bearer-token model.
|
|
21
|
+
- **Extraction — ARCO path.** `gb.zarr_to_geotiff()` pulls a spatial / temporal
|
|
22
|
+
subset from the ARCO Zarr Data Lake and writes it as a Cloud Optimized
|
|
23
|
+
GeoTIFF, ready for QGIS or ArcGIS.
|
|
24
|
+
- **Extraction — CDS API path.** `gb.cds_to_geotiff()` submits a download job
|
|
25
|
+
through the standard CDS API for datasets that are not yet in the ARCO lake,
|
|
26
|
+
converts the result to GeoTIFF, and streams it to disk.
|
|
27
|
+
- **WMTS.** `gb.wmts_layer()` returns a ready-to-use WMTS layer object for
|
|
28
|
+
live tile streaming inside QGIS or Leaflet.
|
|
29
|
+
- **Form schema.** `gb.fetch_form()` and `gb.fetch_constraints()` retrieve the
|
|
30
|
+
server-side parameter form for any dataset so your UI can build validated
|
|
31
|
+
request widgets. `gb.valid_variables_for_product_type()` filters the variable
|
|
32
|
+
list to what the selected product type actually supports.
|
|
33
|
+
- **Styling.** `gb.to_qgis_style()` generate
|
|
34
|
+
calibrated colour ramps for known Copernicus variables.
|
|
35
|
+
- **Fusion.** `gb.fuse()` co-registers multiple layers onto a common grid
|
|
36
|
+
for joint analysis (e.g. heat + air quality).
|
|
37
|
+
- **Semantics.** `gb.semantic_search()` resolves user themes like
|
|
38
|
+
"urban heat island" or "wildfire risk" into concrete dataset and
|
|
39
|
+
workflow recommendations. `gb.list_themes()` and `gb.list_use_cases()`
|
|
40
|
+
enumerate the built-in vocabulary.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## How to run it
|
|
45
|
+
|
|
46
|
+
### Prerequisites
|
|
47
|
+
|
|
48
|
+
- **Python 3.10 or newer.** GeoBridge does not support older Python.
|
|
49
|
+
- **A free Copernicus account.** Register at
|
|
50
|
+
https://cds.climate.copernicus.eu and copy your personal access token
|
|
51
|
+
from your profile page.
|
|
52
|
+
- **macOS, Linux, or Windows with WSL2.** Native Windows may work but is
|
|
53
|
+
not tested.
|
|
54
|
+
|
|
55
|
+
### Step 1 — Create a clean environment
|
|
56
|
+
|
|
57
|
+
A separate environment avoids dependency conflicts with anything else you
|
|
58
|
+
have installed. With Conda (recommended because some geospatial libraries
|
|
59
|
+
need compiled C bindings that pip alone struggles with):
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
conda create -n geobridge python=3.11 -y
|
|
63
|
+
conda activate geobridge
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Or with `venv`:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
python3.11 -m venv ~/.venvs/geobridge
|
|
70
|
+
source ~/.venvs/geobridge/bin/activate
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Step 2 — Install the geospatial stack
|
|
74
|
+
|
|
75
|
+
If you used Conda, install the heavy native dependencies through
|
|
76
|
+
conda-forge first:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
conda install -c conda-forge rasterio rioxarray zarr fsspec httpio dask -y
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
This avoids the most common build failures (GDAL, PROJ, libtiff).
|
|
83
|
+
|
|
84
|
+
### Step 3 — Clone and install GeoBridge
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
git clone https://github.com/YOUR_USERNAME/geobridge.git
|
|
88
|
+
cd geobridge
|
|
89
|
+
pip install -e ".[zarr]"
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
`-e` installs in editable mode so you can pull updates without
|
|
93
|
+
reinstalling. The `[zarr]` extra adds the optional dependencies needed
|
|
94
|
+
for `zarr_to_geotiff()`. Use `.[full]` to also get OWSLib (WMTS) and
|
|
95
|
+
cfgrib (GRIB support).
|
|
96
|
+
|
|
97
|
+
### Step 4 — Configure your credentials
|
|
98
|
+
|
|
99
|
+
Create `~/.cdsapirc` with your personal access token:
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
key: YOUR-CDS-API-KEY-HERE
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Then protect the file so other users on the machine cannot read it:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
chmod 600 ~/.cdsapirc
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Alternatively, export your key as an environment variable instead of
|
|
112
|
+
writing it to a file:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
export CDS_API_KEY=YOUR-CDS-API-KEY-HERE
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Step 5 — Verify the installation
|
|
119
|
+
|
|
120
|
+
Run the bundled smoke test. It exercises every module without making
|
|
121
|
+
network calls:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
PYTHONPATH=. python smoke_test.py
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Expected: nine stages all pass, ending with `ALL SMOKE TESTS PASSED`.
|
|
128
|
+
|
|
129
|
+
### Step 6 — Run the Athens demo
|
|
130
|
+
|
|
131
|
+
This is the end-to-end demonstration. It extracts ERA5 temperature for
|
|
132
|
+
Athens summer 2023, writes a Cloud Optimized GeoTIFF, and generates a
|
|
133
|
+
matching QGIS style:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
python examples/athens_urban_heat.py
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Expected runtime is roughly one minute on a reasonable broadband
|
|
140
|
+
connection. The output appears in `./athens_outputs/`. Open the `.tif` in
|
|
141
|
+
QGIS, load the `.qml` style alongside it, and you should see Athens
|
|
142
|
+
temperatures rendered with a calibrated colour ramp.
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Repository layout
|
|
147
|
+
|
|
148
|
+
```
|
|
149
|
+
geobridge/ ← repository root
|
|
150
|
+
├── README.md ← this file
|
|
151
|
+
├── LICENSE ← MIT
|
|
152
|
+
├── pyproject.toml ← installable Python package
|
|
153
|
+
├── smoke_test.py ← offline smoke test (9 stages)
|
|
154
|
+
│
|
|
155
|
+
├── geobridge/ ← Python package
|
|
156
|
+
│ ├── __init__.py ← public API exports
|
|
157
|
+
│ ├── auth.py ← bearer-token authentication
|
|
158
|
+
│ ├── modules/
|
|
159
|
+
│ │ ├── discover.py ← catalogue discovery
|
|
160
|
+
│ │ ├── extract.py ← ARCO Zarr → GeoTIFF
|
|
161
|
+
│ │ ├── cds_download.py ← CDS API → GeoTIFF (non-ARCO datasets)
|
|
162
|
+
│ │ ├── wmts.py ← WMTS layer
|
|
163
|
+
│ │ ├── form.py ← dataset form schema & constraints
|
|
164
|
+
│ │ ├── style.py ← QGIS QML export
|
|
165
|
+
│ │ └── fuse.py ← multi-layer co-registration
|
|
166
|
+
│ └── semantic/
|
|
167
|
+
│ ├── engine.py ← rule-based query resolver
|
|
168
|
+
│ ├── vocabulary.yaml ← themes and use cases
|
|
169
|
+
│ ├── arco_overrides.yaml ← Zarr URLs and variable aliases
|
|
170
|
+
│ ├── arco_snapshot.yaml ← ARCO catalogue snapshot (generated)
|
|
171
|
+
│ └── cds_snapshot.yaml ← STAC catalogue snapshot (generated)
|
|
172
|
+
│
|
|
173
|
+
├── scripts/
|
|
174
|
+
│ ├── refresh_catalogue.py ← maintainer-side CDS STAC refresh
|
|
175
|
+
│ └── refresh_arco_catalogue.py ← maintainer-side ARCO snapshot refresh
|
|
176
|
+
│
|
|
177
|
+
├── examples/
|
|
178
|
+
│ ├── athens_urban_heat.py ← end-to-end ERA5 demo
|
|
179
|
+
│ ├── example_utci.py ← UTCI thermal comfort demo
|
|
180
|
+
│ ├── examplepm2.5.py ← CAMS PM2.5 air quality demo
|
|
181
|
+
│ └── ... ← additional live-test scripts
|
|
182
|
+
│
|
|
183
|
+
└── tests/
|
|
184
|
+
├── test_auth.py
|
|
185
|
+
└── unit/ ← pytest unit tests
|
|
186
|
+
├── test_discover.py
|
|
187
|
+
├── test_auth.py
|
|
188
|
+
├── test_extract.py
|
|
189
|
+
├── test_style.py
|
|
190
|
+
├── test_semantic.py
|
|
191
|
+
└── test_wmts.py
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## Maintainer workflow
|
|
197
|
+
|
|
198
|
+
### Refreshing catalogue snapshots
|
|
199
|
+
|
|
200
|
+
The `cds_snapshot.yaml` and `arco_snapshot.yaml` files are regenerated
|
|
201
|
+
periodically from the live ECMWF catalogues. End users never run these
|
|
202
|
+
scripts; they get the snapshots bundled with whatever GeoBridge version
|
|
203
|
+
they install.
|
|
204
|
+
|
|
205
|
+
To refresh the CDS STAC snapshot (maintainers only):
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
python scripts/refresh_catalogue.py --limit 5 --output /tmp/test.yaml # quick test
|
|
209
|
+
python scripts/refresh_catalogue.py # full run
|
|
210
|
+
git diff geobridge/semantic/cds_snapshot.yaml
|
|
211
|
+
git add geobridge/semantic/cds_snapshot.yaml
|
|
212
|
+
git commit -m "Refresh CDS catalogue snapshot"
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
To refresh the ARCO snapshot:
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
python scripts/refresh_arco_catalogue.py
|
|
219
|
+
git add geobridge/semantic/arco_snapshot.yaml
|
|
220
|
+
git commit -m "Refresh ARCO catalogue snapshot"
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Adding a new ARCO dataset
|
|
224
|
+
|
|
225
|
+
1. Visit the dataset page on https://cds.climate.copernicus.eu and open
|
|
226
|
+
the "Analysis ready data" tab.
|
|
227
|
+
2. Copy the Zarr URLs (typically there are two: `time_chunked` and
|
|
228
|
+
`geo_chunked`).
|
|
229
|
+
3. Verify each URL responds with a 200 status:
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
curl -I -H "Authorization: Bearer $CDS_API_KEY" "https://.../.zmetadata"
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
4. Add an entry to `geobridge/semantic/arco_overrides.yaml` following the
|
|
236
|
+
schema of existing entries.
|
|
237
|
+
5. Add the variable aliases (CDS long-form name → ARCO short-form name)
|
|
238
|
+
by inspecting the Zarr store with `xarray.open_zarr()` and listing
|
|
239
|
+
`ds.data_vars`.
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
## License
|
|
244
|
+
|
|
245
|
+
MIT. See `LICENSE`.
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## Acknowledgements
|