Skip to content

Commit

Permalink
fix: handling of rotated geoboxes
Browse files Browse the repository at this point in the history
We no longer need to keep `_transform` attribute
on the pixel axis to support cropping of rotated
geoboxes. Original mapping is now stored in a
serializable way on `spatial_ref` coordinate in a
"standard gdal" attribute `GeoTransform`.

Previous setup didn't survive round trip to zarr,
with this it should.
  • Loading branch information
Kirill888 committed May 12, 2024
1 parent cccf059 commit e975e3f
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 16 deletions.
26 changes: 12 additions & 14 deletions odc/geo/_xr_interop.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
from .math import (
affine_from_axis,
approx_equal_affine,
is_affine_st,
maybe_int,
resolution_from_affine,
)
Expand Down Expand Up @@ -386,7 +387,7 @@ def xr_coords(

if isinstance(gbox, GCPGeoBox):
coords: Dict[Hashable, xarray.DataArray] = {
name: _mk_pixel_coord(name, sz, None)
name: _mk_pixel_coord(name, sz)
for name, sz in zip(gbox.dimensions, gbox.shape)
}
gcps = gbox.gcps()
Expand All @@ -399,7 +400,7 @@ def xr_coords(
}
else:
coords = {
name: _mk_pixel_coord(name, sz, transform)
name: _mk_pixel_coord(name, sz)
for name, sz in zip(gbox.dimensions, gbox.shape)
}

Expand All @@ -414,14 +415,11 @@ def xr_coords(
def _mk_pixel_coord(
name: str,
sz: int,
transform: Optional[Affine],
) -> xarray.DataArray:
data = numpy.arange(0.5, sz, dtype="float32")
xx = xarray.DataArray(
data, coords={name: data}, dims=(name,), attrs={"units": "pixel"}
)
if transform is not None:
xx.encoding["_transform"] = transform[:6]
return xx


Expand Down Expand Up @@ -531,16 +529,16 @@ def _extract_transform(
except ValueError:
return None

if original_transform is not None and approx_equal_affine(
transform, original_transform
):
transform = original_transform
if original_transform is not None:
if not is_affine_st(original_transform):
# non-axis aligned geobox detected
# adjust transform
# world <- pix' <- pix
transform = original_transform * transform

if approx_equal_affine(transform, original_transform):
transform = original_transform

if not gcp and (_pix2world := _xx.encoding.get("_transform", None)) is not None:
# non-axis aligned geobox detected
# adjust transform
# world <- pix' <- pix
transform = Affine(*_pix2world) * transform
return transform


Expand Down
3 changes: 1 addition & 2 deletions tests/test_xr_interop.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,7 @@ def test_geobox_xr_coords():
assert cc["spatial_ref"].attrs["spatial_ref"] == gbox.crs.wkt
assert isinstance(cc["spatial_ref"].attrs["grid_mapping_name"], str)
assert isinstance(cc["spatial_ref"].attrs["GeoTransform"], str)
assert cc["x"].encoding["_transform"] == _gbox.affine[:6]
assert cc["y"].encoding["_transform"] == _gbox.affine[:6]
assert xr_zeros(_gbox, dtype="uint16").odc.geobox == _gbox

# geographic CRS
A = mkA(0, scale=(0.1, -0.1), translation=(10, 30))
Expand Down

0 comments on commit e975e3f

Please sign in to comment.