Skip to content

test(integration): RS_Resample parity between SedonaDB and Sedona Spark - #1219

Merged
james-willis merged 20 commits into
apache:mainfrom
james-willis:jw/parity-resample
Sep 4, 2026
Merged

test(integration): RS_Resample parity between SedonaDB and Sedona Spark#1219
james-willis merged 20 commits into
apache:mainfrom
james-willis:jw/parity-resample

Conversation

@james-willis

@james-willis james-willis commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Two follow-ups ride along with the resample module:

  • DecodedRaster.random / DecodedRaster.write_geotiff — addresses @paleolimbot's _anchor comment on test(integration): compare() accepts an optional expected anchor #1218 by combining the random-raster constructors: one definition of the standard raster (seeded pixels on the RANDOM_GRID_* defaults), which write_random_geotiff and create_random_raster_view now delegate to. An expected= anchor is the same object the fixture registers, so they cannot drift; the duplicated grid constants and the module-local _anchor helper are gone. write_geotiff refuses per-band nodata (GeoTIFF nodata is file-wide), and a round-trip unit test pins the default grid to the historical transform.
  • This PR's CI runs the parity suite for the first time (the ci(python): run the Sedona Spark raster parity suite in CI #1217 lane is on this branch via main).

The next step of the parity roadmap from #1203/#1212: RS_Resample, probed first on both engines, then locked in with anchored compare() calls where agreement holds and xfail-cataloged where it doesn't. RS_MapAlgebra is out of scope (SedonaDB doesn't implement it; the roadmap docstring is updated accordingly).

Engines agreeing with each other is not proof either is right — every
engine returning the same wrong thing passes the parity claim. compare()
now takes an optional keyword-only expected= asserted on the subject
first (references are anchored transitively): anything assert_result
accepts for table results, a DecodedRaster for raster results.

Anchor the tests whose expected value is trivially known: the getter
test (written nodata and NULL) and all four passing setter tests (the
exact seeded pixels, grid, and per-band nodata) — the setter tests would
previously have passed if both engines no-opped identically.
Includes the commits of apache#1211 (bbox placement in the raster fixture
writers) and converts the anchored tests' explicit grid placement to
bbox=. The anchors keep their GDAL transform tuples — that is the
decoded representation assert_decoded_equal compares, not a placement
choice.
The nearest-neighbour path agrees bit-for-bit across dimension mode, scale
mode (including grown-extent border fill), and the reference-raster and
grid-snap overloads; those cases are locked with hand-computed expected=
anchors. Interpolating algorithms diverge: Sedona Spark really implements
only NearestNeighbor, Bilinear, and Bicubic, silently resampling nearest
for every other name it accepts, and even the shared Bilinear/Bicubic
kernels differ pixel-wise from GDAL's. Divergences are xfail-cataloged.

13 passing tests, 12 xfails. RS_MapAlgebra is out of scope (SedonaDB does
not implement it).
Same exactly-one bbox/gdal_transform surface as the write_* helpers, so
anchors can state a north-up grid readably. The instance always carries a
gdal_transform afterwards (decoders produce transforms and
assert_decoded_equal compares them); bbox is construction sugar, derived
from the pixel shape with rasterio's from_bounds.
DecodedRaster now takes the same exactly-one bbox/gdal_transform surface
as the writers (apache#1211), so the anchors state the same BBOX the fixtures
are placed with and the duplicate transform constant goes away.
With DecodedRaster's bbox construction (apache#1211), every extent-preserving
resample anchors on the fixture's own BBOX, and the grown/snapped grids
state their extents readably instead of as transform tuples.
main's trinary override semantics (apache#1198) changed SedonaDB's
RS_SetBandNoDataValue(rast, band, NULL) from propagating the NULL to
clearing that band's nodata (probe: a band holding 7.0 comes back
cleared while band 2 keeps its 7.0); Sedona Spark still returns a NULL
raster. Split the combined NULL-args test: NULL band index still agrees
(both NULL), NULL value is xfail-cataloged.
Addresses the _anchor review comment on apache#1218: the standard random raster
now has one definition. DecodedRaster.random builds it (seeded pixels on
the RANDOM_GRID_* defaults, scalar nodata broadcast per band),
DecodedRaster.write_geotiff writes it (GeoTIFF nodata is file-wide, so
per-band anchors refuse to write), and write_random_geotiff and
DBEngine.create_random_raster_view delegate to them. Anchors are the same
object the fixture registers, so they cannot drift apart — the duplicated
BANDS/HEIGHT/WIDTH/BBOX constants and the module-local _anchor helper in
the parity suites go away.
test_rs_raster_out.py becomes test_rs_setbandnodatavalue.py — the parity
suite keeps one module per RS_ function.
The python-wheels workflow runs this suite with a reduced dependency set
(see apache#1230); both new tests resolve a bbox through rasterio.

@paleolimbot paleolimbot left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@james-willis
james-willis merged commit d45636e into apache:main Sep 4, 2026
5 checks passed
@james-willis
james-willis deleted the jw/parity-resample branch September 4, 2026 20:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants