feat: support instance-configurable CRS for GeoZarr storage#92
Merged
Conversation
Add `crs` key to climate-api.yaml (defaults to EPSG:4326).
- config.get_crs() reads the instance CRS; DEFAULT_CRS constant guards
backwards compatibility for instances without an explicit crs key
- build_dataset_zarr uses the instance CRS for GeoZarr metadata and
the xproj CRS assignment in the multiscales path
- For WGS84 instances spatial dims are normalised to longitude/latitude
as before; for other CRS (e.g. UTM33) they are normalised to x/y to
reflect that coordinate values are in metres, not degrees
- GET /zarr/{dataset_id} now includes crs, proj4, and bounds fields so
zarr-layer clients can configure reprojection without hard-coding them
- climate-api.yaml.example documents the new optional key
Contributor
There was a problem hiding this comment.
Pull request overview
Adds instance-configurable CRS support for GeoZarr storage (via climate-api.yaml) and extends the /zarr/{dataset_id} listing response with CRS metadata so clients can configure reprojection without hard-coded CRS details.
Changes:
- Introduces
config.get_crs()withDEFAULT_CRS(EPSG:4326) and example config docs. - Updates Zarr building to write GeoZarr CRS metadata from instance config (instead of hardcoding WGS84) and adjusts coordinate normalisation expectations in tests/docs.
- Extends
/zarr/{dataset_id}store listing withcrs,proj4, andbounds.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
climate_api/config.py |
Adds DEFAULT_CRS and get_crs() config accessor. |
climate_api/data_manager/services/downloader.py |
Uses instance CRS for GeoZarr metadata and renames spatial dims during Zarr build. |
climate_api/ingestions/services.py |
Extends /zarr listing response with CRS/proj4/bounds helpers. |
climate-api.yaml.example |
Documents optional crs: key. |
tests/test_config.py |
Adds tests for get_crs() default/config/invalid type. |
tests/test_downloader.py |
Updates coordinate-normalisation expectations and pyramid coarsening dims. |
docs/user_guide.md |
Updates examples to use x/y dimensions. |
docs/adding_custom_datasets.md |
Updates coordinate-normalisation guidance for custom datasets. |
…ust proj4 conversion - get_crs() validates the CRS string is parseable via pyproj at config load time, so misconfigured instances fail fast with a clear error (not during Zarr build) - get_dataset_zarr_store_info_or_404() reads proj:code from the store's own GeoZarr attributes first, falling back to the instance config CRS; avoids mismatch when the config CRS changes after a store was built - _crs_to_proj4() returns str|None and catches CRS errors instead of propagating a 500; _read_zarr_attrs() is extracted as a shared helper for both bounds and CRS - Add test for unknown EPSG code (EPSG:999999) to lock in the early-failure behaviour
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #90.
Summary
crskey toclimate-api.yaml(defaults toEPSG:4326, fully backwards-compatible)build_dataset_zarrreads the instance CRS and writes it into GeoZarr metadata (proj:code,spatial:bbox) instead of hardcoding WGS84x/yregardless of CRS — no special-casing for WGS84GET /zarr/{dataset_id}response includes three new fields:crs,proj4, andbounds, read from the store's own GeoZarr attributes (falls back to instance config) — so clients like zarr-layer can configure on-the-fly reprojection without hard-coding CRS detailsHow to use
For a national instance storing data in Norwegian UTM33:
Download functions for native-CRS datasets (e.g. seNorge in UTM33) can write
x/ycoordinates directly — no reprojection needed before saving.Breaking change
None. Instances without a
crskey continue to useEPSG:4326and produce identical output.Note: all Zarr stores now use
x/yas the canonical spatial dimension names (previouslylongitude/latitudefor WGS84). If downstream clients select by dim name, they will need updating.zarr-layer client
The new
proj4andboundsfields inGET /zarr/{dataset_id}let the client build layer props dynamically:Test plan
tests/test_config.py—get_crs(): default, explicit value, non-string, unknown EPSG code (e.g.EPSG:999999) all fail fast with clear errorsGET /zarr/{dataset_id}returnscrs,proj4, andboundsfor a WGS84 dataset