Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,7 @@ Tips
To run a subset of tests::

$ pytest test/unit/test_show_versions.py::test_get_main_info

When using NumPy's ``assert_almost_equal`` to compare affine transforms, pass
``tuple(transform)`` for both operands. This compares all nine coefficients
with the requested precision and avoids treating Affine 3 objects as scalars.
1 change: 1 addition & 0 deletions docs/history.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ History

Latest
------
- DEP: Require rasterio>=1.5.1 and affine>=3 for matrix multiplication support (#939)

0.23.0
------
Expand Down
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ classifiers = [
requires-python = ">=3.12"
dependencies = [
"packaging",
"rasterio>=1.4.3",
"rasterio>=1.5.1",
"affine>=3",
# https://github.com/pydata/xarray/issues/11000
"xarray>=2026.2",
"pyproj>=3.3",
Expand Down
11 changes: 6 additions & 5 deletions rioxarray/_spatial_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import math
import warnings
from collections.abc import Hashable
from typing import Any, Iterable, Optional, Union
from typing import Any, Iterable, Optional, Union, cast

import numpy
import rasterio.mask
Expand Down Expand Up @@ -114,12 +114,13 @@ def affine_to_coords(
dict: x and y coordinate arrays.

"""
transform = affine * affine.translation(0.5, 0.5)
# Affine's typed overloads do not cover NumPy coordinate arrays.
transform = cast(Any, affine @ affine.translation(0.5, 0.5))
if affine.is_rectilinear and not _affine_has_rotation(affine):
x_coords, _ = transform * (numpy.arange(width), numpy.zeros(width))
Comment thread
snowman2 marked this conversation as resolved.
_, y_coords = transform * (numpy.zeros(height), numpy.arange(height))
x_coords, _ = transform @ (numpy.arange(width), numpy.zeros(width))
_, y_coords = transform @ (numpy.zeros(height), numpy.arange(height))
else:
x_coords, y_coords = transform * numpy.meshgrid(
x_coords, y_coords = transform @ numpy.meshgrid(
numpy.arange(width),
numpy.arange(height),
)
Expand Down
2 changes: 1 addition & 1 deletion rioxarray/rioxarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ def transform(self, recalc: bool = False) -> Affine:
src_resolution_x, src_resolution_y = self.resolution(recalc=recalc)
except (DimensionMissingCoordinateError, DimensionError):
return Affine.identity() if transform is None else transform
return Affine.translation(src_left, src_top) * Affine.scale(
return Affine.translation(src_left, src_top) @ Affine.scale(
src_resolution_x, src_resolution_y
)

Expand Down
19 changes: 13 additions & 6 deletions test/integration/test_integration_rioxarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,8 @@ def test_pad_box(modis_clip):
assert padded_size == original_size
else:
assert_almost_equal(
xdi.rio._cached_transform(), padded_ds.rio._cached_transform()
tuple(xdi.rio._cached_transform()),
tuple(padded_ds.rio._cached_transform()),
)
for padded_size, original_size in zip(padded_ds.shape, xdi.shape):
assert padded_size == original_size
Expand Down Expand Up @@ -353,7 +354,9 @@ def test_clip_box(modis_clip):
except KeyError:
xdc_values = xdc.values
assert_almost_equal(clipped_ds_values, xdc_values)
assert_almost_equal(clipped_ds.rio.transform(), xdc.rio.transform())
assert_almost_equal(
tuple(clipped_ds.rio.transform()), tuple(xdc.rio.transform())
)
# make sure it safely writes to netcdf
clipped_ds.to_netcdf(modis_clip["output"])

Expand Down Expand Up @@ -381,7 +384,9 @@ def test_clip_box__auto_expand(modis_clip):
except KeyError:
xdc_values = xdc.values
assert_almost_equal(clipped_ds_values, xdc_values)
assert_almost_equal(clipped_ds.rio.transform(), xdc.rio.transform())
assert_almost_equal(
tuple(clipped_ds.rio.transform()), tuple(xdc.rio.transform())
)
# make sure it safely writes to netcdf
clipped_ds.to_netcdf(modis_clip["output"])

Expand Down Expand Up @@ -549,7 +554,9 @@ def test_slice_xy(modis_clip):
except KeyError:
xdc_values = xdc.values
assert_almost_equal(clipped_ds_values, xdc_values)
assert_almost_equal(clipped_ds.rio.transform(), xdc.rio.transform())
assert_almost_equal(
tuple(clipped_ds.rio.transform()), tuple(xdc.rio.transform())
)
# make sure it safely writes to netcdf
clipped_ds.to_netcdf(modis_clip["output"])

Expand Down Expand Up @@ -1428,7 +1435,7 @@ def test_make_coords__calc_trans(open_func, modis_reproject):
dst_height=heightr,
)

assert_almost_equal(calculated_transform, calculated_transformr)
assert_almost_equal(tuple(calculated_transform), tuple(calculated_transformr))
# check to see if they all match
if not isinstance(open_func, partial):
assert_almost_equal(
Expand Down Expand Up @@ -1477,7 +1484,7 @@ def test_make_coords__attr_trans(open_func, modis_reproject):
dst_width=widthr,
dst_height=heightr,
)
assert_almost_equal(attr_transform, calculated_transformr)
assert_almost_equal(tuple(attr_transform), tuple(calculated_transformr))
# check to see if they all match
if not isinstance(open_func, partial):
assert_almost_equal(
Expand Down
12 changes: 12 additions & 0 deletions test/unit/test_spatial_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import numpy
from affine import Affine

from rioxarray._spatial_utils import affine_to_coords


def test_affine_to_coords_avoids_deprecated_matrix_multiplication() -> None:
transform = Affine(1, 0, 0, 0, -1, 4)
coords = affine_to_coords(transform, width=4, height=4)

numpy.testing.assert_array_equal(coords["x"], [0.5, 1.5, 2.5, 3.5])
numpy.testing.assert_array_equal(coords["y"], [3.5, 2.5, 1.5, 0.5])
Loading