-
Notifications
You must be signed in to change notification settings - Fork 51
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Coordinate computation does not take into accound inverted axis in center
mode
#93
Comments
@Kirill888 thanks a ton for looking into this. I'm sorry that I haven't had time to work on #68 at all, so I appreciate you digging in. I wonder if this fixes it: diff --git a/stackstac/prepare.py b/stackstac/prepare.py
index 8f28ceb..545fcf7 100644
--- a/stackstac/prepare.py
+++ b/stackstac/prepare.py
@@ -400,9 +400,9 @@ def to_coords(
half_xpixel, half_ypixel = xres / 2, yres / 2
minx, miny, maxx, maxy = (
minx + half_xpixel,
- miny + half_ypixel,
+ miny - half_ypixel,
maxx + half_xpixel,
- maxy + half_ypixel,
+ maxy - half_ypixel,
)
height, width = spec.shape Reading that code, looks like I forgot that stackstac/stackstac/raster_spec.py Lines 23 to 31 in 3a58906
|
@gjoseph92 no worries. Regarding your change, this will "fix it" for a most common case where Y axis has "negative resolution", i.e. top row has lowest Y coordinate, but it will break for all other cases. GeoTIFF can encode equivalent axis aligned data in 4 different ways depending on which corner is picked as reference. Say you have xx = xr.DataArray(...)
a = xx[:,:]
b = xx[:,::-1]
c = xx[::-1, :]
d = xx[::-1, ::-1] Images So to address this issue for all possible geotiffs out there you really need to compute sign per axis, including X axis, although I have not seen files like that in the wild. - half_xpixel, half_ypixel = xres / 2, yres / 2
+ sx, sy = numpy.sign(transform.a), numpy.sign(transform.e)
+ half_xpixel, half_ypixel = (s*res/2 for s, res in zip([sx, sy], [xres, yres]) |
Yeah, I agree that having saying "X resolution is always positive, Y is always negative" is a bit fast and loose. I remember going back and forth on this a bit when I wrote the code initially. I did this because a) resolution, as a positive number, is more intuitive to users to specify and b) when looking at multiple assets at different resolutions and trying to pick the finest, you want them to all be positive numbers (even if some assets are "flipped" and some aren't). Technically, maybe this is more GSD? I think, though, that in stackstac's case, by construction we really are guaranteed that X is positive and Y is negative. stackstac isn't reading any GeoTIFFs—it's deciding what transform to tell rasterio to use when it reads the GeoTIFFs later. In the implementation of the So stackstac is always going to warp any orientation of GeoTIFF into positive-X, negative-Y. This may not be what you're expecting, but with that diff I posted, I think it would no longer be wrong: the xarray coordinates would match up to the correct pixels. Eventually though, we should support respecting the orientation of a transform given by the |
Thanks for the explanation. I have assumed that
So if the desired behaviour is to normalize coordinates to be
Then that's fine. But then what are the situations where this code path happens: stackstac/stackstac/prepare.py Lines 413 to 420 in 3a58906
It looks like by construction transform is always rectinlinear with inverted Y axis:
stackstac/stackstac/raster_spec.py Lines 23 to 31 in 3a58906
That one is hard, GDAL/rasterio certainly use negative sign to indicate "direction" when reporting resolution, but I agree that this is awkward in a lot of cases. But I guess this is separate concern from coordinate value computation. |
Yeah, I think that entire codepath for
I don't think it's really the desired behavior... just what the behavior currently is. I plan on keeping that behavior for now and just fixing that issue, but we should better support native projection/resolution in the future. |
Closed in #94 |
Thanks @gjoseph92 and @Kirill888 for fixing this and #68 ! |
To be compatible with
rioxarray
one needs to usestackstac.stack(..., xy_coords="center")
when computing X/Y coordinate values. When using this mode on data that contains "inverted Y axis", a most common scenario, Y axis coordinates are offset by 1 pixel size into positive direction.I have made a small reproducer. Data is a global synthetic image with 1 degree per pixel in
EPSG:4326
, when loading it withxy_coords="center"
you would expect Y coordinate to span from-89.5 to 89.5
, but instead it goes from90.5 to -88.5
.https://nbviewer.org/gist/Kirill888/b3dad8afdc10b37cd21af4aea8f417e3/stackstac-xy_coords-error-report.ipynb
https://gist.github.com/Kirill888/b3dad8afdc10b37cd21af4aea8f417e3
This causes issue reported earlier here: #68
Code that performs computation of the coordinate just offsets "top-left" coordinate by positive half pixel size, but instead should offset by
sign(coord[1] - coord[0])*abs(resolution)*0.5
The text was updated successfully, but these errors were encountered: