Skip to content

rasterize: descending-x like silently mislabels output coords #2568

@brendancol

Description

@brendancol

Describe the bug

rasterize(like=...) silently produces spatially wrong output when the template like DataArray has a descending x-axis (largest x first, smallest last).

The comment at xrspatial/rasterize.py:2936 says "descending-x templates would hit the same bug class and are not supported here," but the code neither rejects descending-x nor flips columns to compensate. _extract_grid_from_like notes the issue and moves on.

Ascending y is already handled at line 3349-3350: the burned array is flipped along axis 0 so result.sel(y=...) lines up with the geometry in world coordinates. There's no equivalent for x.

When a descending-x like is passed, the rasterizer writes pixels using ascending-x column order (column 0 = xmin), but reuse_like_coords at line 3340 assigns the descending-x coord array unchanged. A polygon at world x=0.5 ends up labelled under coord x=3.5.

Expected behavior

result.sel(x=world_x) should return the burned value at world_x regardless of whether like.x is ascending or descending. Either flip the output along axis 1 to match the coords, or reject descending-x with a clear ValueError (the existing comment already claims it is unsupported).

Reproducer

import numpy as np
import xarray as xr
from shapely.geometry import box
from xrspatial.rasterize import rasterize

# Descending-x like grid
x_desc = np.linspace(3.5, 0.5, 4)  # descending
y = np.linspace(3.5, 0.5, 4)
like = xr.DataArray(
    np.zeros((4, 4)), dims=['y', 'x'], coords={'y': y, 'x': x_desc},
)

# Burn a 1x1 box at world (0.5, 0.5) -- the lower-left corner
result = rasterize([(box(0, 0, 1, 1), 1.0)], like=like, fill=0)

# Expected: result.sel(x=0.5, y=0.5).item() == 1.0
# Actual:   result.sel(x=0.5, y=0.5).item() == 0.0
#           result.sel(x=3.5, y=0.5).item() == 1.0  (mislabelled)

Impact

Any coord-aware downstream op (xr.align, .sel, slope/aspect, zonal stats keyed off coords) operates on the wrong cells. The output looks plausible but is spatially wrong. No exception is raised.

Additional context

  • Same bug class as rasterize(like=...) silently flips spatial meaning when y coordinates ascend #2170 (ascending-y), which was fixed by the axis-0 flip.
  • Fix should be small and local: detect descending-x in _extract_grid_from_like, carry it on _LikeGrid, and flip axis 1 in rasterize when reusing coords. Or reject with ValueError.
  • Worth confirming descending-y is genuinely covered by the existing y-flip path while you're in there.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions