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?