Skip to content

'xr_reproject' takes user-given resampling into account only in case of upscaling, not in case of downscaling #236

@remi-braun

Description

@remi-braun

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 ✔️ Image Image
Bilinear + upsampling ✔️ Image Image

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 ❓ Image Image

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 ❌ Image Image

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
Image

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions