Hello,
When trying to replace some rioxarray code by odc.geo code to make it lazy and dask-compliant, I was surprised to see that xr_reproject seems to take into account the resampling value given by the user only in case of upscaling. In case of downscaling, I'm suspecting odc.geo performs only a simple decimation.
Here is my code:
import xarray as xr
import rioxarray
from affine import Affine
from odc.geo import xr as odc_geo_xr # noqa: F401
from odc.geo.geobox import GeoBox
def test_reproj(path: str, new_width, new_height, resampling):
# Open with rioxarray
with (
xr.set_options(keep_attrs=True),
rioxarray.set_options(export_grid_mapping=False),
rioxarray.open_rasterio(
path,
chunks="auto",
masked=True,
) as xda,
):
# Reproject with rioxarray
xda1 = xda.rio.reproject(
xda.rio.crs,
shape=(new_height, new_width),
resampling=resampling,
)
xda1.rio.to_raster(fr"rioxarray_{round(xda1.rio.resolution()[0])}m_{resampling}.tif")
# Reproject with dask + odc-geo
src_affine = xda.rio.transform()
xda = xda.odc.reproject(
how=GeoBox(
(new_height, new_width),
src_affine * Affine.scale(xda.rio.width / new_height, xda.rio.height / new_height),
xda.rio.crs,
),
resampling=resampling,
dst_nodata=xda.rio.encoded_nodata,
)
# Set nodata in rioxr's way and remove odc.geo nodata in attributes
xda.attrs.pop("nodata", None)
xda.rio.write_nodata(xda.rio.encoded_nodata, encoded=True, inplace=True)
xda.rio.to_raster(rf"odc_geo_{round(xda.rio.resolution()[0])}m_{resampling}.tif")
Maybe there is something I haven't correctly understood regarding the way to use xr_reproject?
# Around 1500m of resolution (downscaling) + nearest
test_reproj(
"LC09_L2SP_152041_20220828_20220830_02_T1_SR_B4.TIF",
resampling=0,
new_width=153, new_height=156,
)
# Around 15m of resolution (upscaling) + nearest
test_reproj(
"LC09_L2SP_152041_20220828_20220830_02_T1_SR_B4.TIF",
resampling=0,
new_width=15342, new_height=15622,
)
# Around 1500m of resolution (downscaling) + bilinear
test_reproj(
"LC09_L2SP_152041_20220828_20220830_02_T1_SR_B4.TIF",
resampling=1,
new_width=153, new_height=156,
)
# Around 15m of resolution (upscaling) + bilinear
test_reproj(
"LC09_L2SP_152041_20220828_20220830_02_T1_SR_B4.TIF",
resampling=1,
new_width=15342, new_height=15622,
)
For the upsampling, the result is quite convincing, the images are almost the same.
|
Rioxarray |
odc.geo |
| Nearest + upsampling ✔️ |
 |
 |
| Bilinear + upsampling ✔️ |
 |
 |
In the case of nearest + downscaling, odc.geo gives sth that looks like nearest (but might be simple decimation), when rioxarray gives a results with correct resampling.
|
Rioxarray |
odc.geo |
| Nearest + downsampling ❓ |
 |
 |
In the case of bilinear+ downscaling, odc.geo gives sth completely wrong, when rioxarray gives again a results with correct resampling.
|
Rioxarray |
odc.geo |
| Bilinear + downsampling ❌ |
 |
 |
Here is the link to a zip containing all the results: https://seafile.unistra.fr/f/772545d7b8bc4b15a7c4/?dl=1
PS: there are also other edge effects, I can open dedicated issues if you want:
odc.geo doesn't compute properly the right corner (see screenshots)
- the size of
odc.geo files is almost doubled on disk
- for a given size when downsampling, the resolution is not exactly the same as GDAL's
Tested with Python 3.9.19
rioxarray (0.15.0) deps:
rasterio: 1.3.10
xarray: 2024.3.0
GDAL: 3.8.4
GEOS: 3.11.3
PROJ: 9.3.1
odc-geo version: 0.4.8
And Python 3.11.13
rioxarray (0.19.0) deps:
rasterio: 1.4.3
xarray: 2025.7.0
GDAL: 3.6.2
GEOS: 3.11.1
PROJ: 9.1.1
odc-geo version: 0.4.10
All with the same result.
Hello,
When trying to replace some
rioxarraycode byodc.geocode to make it lazy and dask-compliant, I was surprised to see thatxr_reprojectseems to take into account the resampling value given by the user only in case of upscaling. In case of downscaling, I'm suspectingodc.geoperforms only a simple decimation.Here is my code:
Maybe there is something I haven't correctly understood regarding the way to use
xr_reproject?For the upsampling, the result is quite convincing, the images are almost the same.
In the case of nearest + downscaling, odc.geo gives sth that looks like nearest (but might be simple decimation), when rioxarray gives a results with correct resampling.
In the case of bilinear+ downscaling, odc.geo gives sth completely wrong, when rioxarray gives again a results with correct resampling.
Here is the link to a zip containing all the results: https://seafile.unistra.fr/f/772545d7b8bc4b15a7c4/?dl=1
PS: there are also other edge effects, I can open dedicated issues if you want:
odc.geodoesn't compute properly the right corner (see screenshots)odc.geofiles is almost doubled on diskTested with Python 3.9.19
And Python 3.11.13
All with the same result.