Skip to content

Comments

Use Lapack solve to more accurately compute affine reverse transforms.#3315

Merged
snowman2 merged 14 commits intorasterio:mainfrom
groutr:npsolve
Dec 11, 2025
Merged

Use Lapack solve to more accurately compute affine reverse transforms.#3315
snowman2 merged 14 commits intorasterio:mainfrom
groutr:npsolve

Conversation

@groutr
Copy link
Contributor

@groutr groutr commented Feb 27, 2025

With certain transforms, directly inverting the transform matrix leads to subtle numerical inaccuracies. Using np.linalg.solve avoids these issues.

Replaces #3313
Fixes #3310

On certain transforms, directly inverting the transform matrix leads to subtle numerical inaccuracies. Using np.linalg.solve avoids these issues.
This should work more nicely with affine 3.0 and its new array interface.
@groutr
Copy link
Contributor Author

groutr commented Feb 27, 2025

It looks like there are two other locations where we invert the transform. Should we review that code as well in light of the findings in #3313?

row2 = ceil(row2)
rows = np.array([top, top, bottom, bottom]) + eps
cols = np.array([left, right, right, left]) + eps
rows, cols = rowcol(src.transform, rows, cols)
Copy link
Contributor Author

@groutr groutr Mar 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default for rowcol is to floor results. The tests pass.
Oddly, when trying to exactly match the old behavior (op=float and doing the floor/ceil calls), the test_warp_no_reproject test fails.

The two transforms do not match.

Affine(9.545306945486766, 0.0, -11858134.818413004,
       0.0, -9.545306945486766, 4813698.2926443005) = <open DatasetReader name='test_warp_no_reproject0/test.tif' mode='r'>.transform
Affine(9.5546285343, 0.0, -11858134.818413004,
       0.0, -9.5546285343, 4813698.2926443005) = <open DatasetReader name='tests/data/shade.tif' mode='r'>.transform

@groutr
Copy link
Contributor Author

groutr commented Mar 3, 2025

@sgillies I believe this should be ready for a preliminary review.
Some things to note:

  1. In warp.py, I removed the epsilon adjustment because I couldn't find any mathematical justification for it.
  2. In warp.py, I removed the floor/ceil calls. This seemed to make the resulting transform slightly wrong in some cases.
  3. I re-implemented geometry_window to hopefully be much easier to read/understand.
  4. I noticed that at least two keyword arguments had been deprecated in the docstring for geometry_window, but no warnings were issued. I added deprecation warnings consistent with other areas of rasterio. pixel_precision seems to be unused for awhile now and so I added a warning for that as well.

@groutr
Copy link
Contributor Author

groutr commented Mar 6, 2025

The test failures look like they might be related to #3301

@geowurster
Copy link
Contributor

With a moderate risk of an under informed drive-by comment: have you considered using GDALInvGeoTransform()? I have encountered issues with the affine package producing very slightly different results than GDAL transformers invoked through the Python SWIG bindings. Ultimately I found stability by using the equivalent to GDALApplyGeoTransform() and GDALInvGeoTransform(). Of course a GDAL geotransform and an affine.Affine() object are not exactly the same thing, so I'm sure this is easier said than done.

@groutr
Copy link
Contributor Author

groutr commented Apr 18, 2025

@geowurster, unfortunately, gdal uses the same numerically unstable method to compute the inverse geotransform as affine.

@geowurster
Copy link
Contributor

@groutr ah, thanks.

@groutr
Copy link
Contributor Author

groutr commented Jun 16, 2025

@sgillies @snowman2 I believe this should be ready for review/merge.

@snowman2 snowman2 added this to the 1.5.0 milestone Dec 2, 2025
@snowman2 snowman2 requested a review from sgillies December 9, 2025 20:54
@snowman2
Copy link
Member

@groutr mind updating this PR to the latest?

@groutr
Copy link
Contributor Author

groutr commented Dec 11, 2025

@groutr mind updating this PR to the latest?

Updated with the latest changes.

Co-authored-by: Alan D. Snow <[email protected]>
@snowman2 snowman2 merged commit 1694c33 into rasterio:main Dec 11, 2025
17 checks passed
@snowman2
Copy link
Member

Thanks @groutr 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

tests/test_indexing.py fails on Linux Intel x86 (openSUSE i586 and Debian i386)

3 participants