Skip to content

Emit fresh grid metadata and propagate _FillValue through reproject() and merge()#1462

Merged
brendancol merged 1 commit intomainfrom
metadata-polish-transform-res-fillvalue-spatial-dims
May 4, 2026
Merged

Emit fresh grid metadata and propagate _FillValue through reproject() and merge()#1462
brendancol merged 1 commit intomainfrom
metadata-polish-transform-res-fillvalue-spatial-dims

Conversation

@brendancol
Copy link
Copy Markdown
Contributor

Closes #1458.

Follow-up to #1446 covering three small metadata items in xrspatial/reproject/__init__.py.

Changes

Fresh transform and res on output. Both reproject() and merge() previously popped transform and res because the input values described the old grid. The output grid is fully known from _compute_output_grid (returns res_x, res_y, and bounds), so we now emit:

  • attrs['res'] = (res_x, res_y)
  • attrs['transform'] = (res_x, 0.0, left, 0.0, -res_y, top) — rasterio 6-tuple convention.

The geotiff reader in this repo does not emit transform or res into attrs itself, so there was no in-repo convention to match. The rasterio form is the standard one external code expects.

merge() honours _find_spatial_dims. The helper at line 63 already exists and reproject() uses it. merge() was hardcoded to dims[-2] and dims[-1] in two places. Both now call _find_spatial_dims, so inputs with lat/lon dims (or other non-y/x layouts) work correctly.

_FillValue propagation. _detect_nodata reads _FillValue as a fallback nodata key, but neither output set _FillValue. When the input has _FillValue, the output now gets the resolved nodata in both nodata and _FillValue. When the input has no _FillValue, the output stays clean.

Tests

Added eight tests in TestMetadataPreservation:

  • fresh transform and res emission for reproject() and merge()
  • transform and res emitted even when the input had neither
  • merge() succeeds with lat/lon dims and preserves them on output
  • _FillValue round-trips through both functions when the input sets it, and stays absent when the input does not

Two existing tests that asserted transform/res were dropped have been updated to assert that the new (fresh) values differ from the stale input values.

Test plan

  • pytest xrspatial/tests/test_reproject.py -x (188 passed)

Three small follow-ups to PR #1446 in `xrspatial/reproject/__init__.py`:

- `reproject()` and `merge()` re-emit `attrs['transform']` and
  `attrs['res']` for the new output grid instead of dropping them. The
  transform uses the rasterio 6-tuple convention
  `(res_x, 0.0, left, 0.0, -res_y, top)`. The geotiff reader does not
  itself write these attrs, so there is no in-repo convention to match
  and the rasterio form is used as the default.
- `merge()` uses `_find_spatial_dims` instead of assuming the last two
  dims are spatial, both when collecting per-raster shapes and when
  building the output coords.
- Both functions copy the resolved nodata value into `_FillValue` when
  the input set `_FillValue`. Inputs that did not set `_FillValue` get
  no `_FillValue` on output.

Tests in `TestMetadataPreservation` cover the fresh transform/res
values, absence-of-input behaviour, `_find_spatial_dims` use with
lat/lon dims, and `_FillValue` round-trip for both functions.
@github-actions github-actions Bot added the performance PR touches performance-sensitive code label May 4, 2026
@brendancol brendancol merged commit 265ba9d into main May 4, 2026
11 checks passed
@brendancol brendancol deleted the metadata-polish-transform-res-fillvalue-spatial-dims branch May 5, 2026 03:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

performance PR touches performance-sensitive code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Re-emit fresh transform/res, propagate _FillValue, use _find_spatial_dims in merge

1 participant