Just joining this thread, but I think this point is incredibly important. You need to know how coords are specified in the metadata! Nice job illustrating the fuzziness in the example!
I ran a similar test for stackstac.stac
and it appears that this difference does not apply to xy_coords
?
The four images above were built from code like this:
l30_stack = ss.stack(itemsL30,
assets = ['B05'],
epsg = epsg, # epsg (3979 if set to poly) # epsg (32614 if set to UTM)
resolution = 30,
bounds = bbox,
resampling = Resampling.bilinear, # bilinear # cubic # nearest
chunksize = (1, -1, -1, -1),
xy_coords = 'topleft', # center # topleft
gdal_env = gdalEnv)
With just changes to xy_coords
and epsg
(keeping to local UTM or reprojecting to national proj, as I do in my work). All of these used bilinear resampling, but same patterns held true for cubic and nearest neighbor.
As you can see, xy_coords
does not impact “blurriness” like anchor
does. The only change is the values are shifted half a pixel between topleft
and center
. The blurriness in this case occurs when reprojecting from the local UTM grid to a national projection - as would be expected (and required for wide-area analysis when you need everything projected onto the same pixel grid).
So that begs the question, is topleft
or center
the “correct” pixel placement? I though it would be topleft
for HLS, as noted in the User Guide and mentioned by @Andrew_Mullen. But it actually appears that center
is most accurate to the real world:
In these comparisons, left is topleft
and right is center
. These are using the national projection, not UTM, but the patterns are the same.
So I guess the takeaway is that for stackstac
that xy_coords = center
is the proper way, at least for HLS. I guess this is because it integrates with xarray
, which likes pixel center coordinates. And that it is not work the same as anchor
does with odc.stac.load
?
EDIT: I also played around some with snap_bounds = False
in stackstac.stack
and it does impact pixel values, but I can’t really tell if its preferred over the default (snap_bounds = True
) if already reprojecting?
What anchor=
does in odc-stac
is NOT at all the same as stackstac
s xy_coords=
. Data that comes out of odc-stac
always places location of the center
of the OUTPUT pixel in the x/y coordinates. Specifying anchor=
only changes how OUTPUT pixel grid is snapped to the world, once the OUTPUT pixel grid is decided, data from sources will be “re-projected” to the OUTPUT grid unless OUTPUT pixel grid is exactly aligned with the source data pixel grid, in which case these pixels are just pasted into the appropriate section of the output image (non-blurry output case, anchor on OUTPUT matches anchor used by the source grid).
In the case of stackstac
, xy_coords=
changes what point within the pixel is recorded in the x,y coordinate arrays, it does not change at all how pixels are loaded. And the ONLY VALID CHOICE is to use xy_coords=center
, because that’s what the rest of xarray ecosystem assumes is stored in those coords. Note that the default is xy_coords=topleft
, which is WRONG and confusing, and should be changed in stackstac
lib. Hence no difference in the image whether it’s center
or topleft
@ZZMitch.
I’d like to share a benchmark report by @Kirill888 comparing odc-stac
and stackstac
, which highlights the superior performance of odc-stac
in many common use cases:
Benchmark: odc-stac vs stackstac
Personally, I remain hesitant to adopt stackstac
due to its limited test coverage as written in the stackstac
’s limitations.
This discussion from two years ago still provides a good summary of the key differences between the two libraries.
That said, I’m still exploring how best to use either odc-stac
or stackstac
to access original Sentinel-2 SAFE products via the CDSE STAC API. If anyone has experience or insights on this, I’d appreciate your input!