Skip to content

Releases: xarray-contrib/xarray-spatial

v0.9.9

05 May 19:35
f42106b

Choose a tag to compare

Version 0.9.9 - 2026-05-05

Bug fixes and improvements

  • Add geotiff edge-case tests and integer-coord fallback (#1482) (#1492)
  • Use synchronous dask scheduler for different-CRS merge parity test (#1495)
  • Fetch COG tiles concurrently in HTTP path to mask RTT (#1487)
  • Geotiff polish: validation, caching caps, parallelism thresholds, memory guards (#1488) (#1493)
  • Round-trip transform, crs, and tag metadata through to_geotiff/open_geotiff (#1484) (#1494)
  • Tighten geotiff reader: partial-tile shape check, ModelTransformation rotation guard (#1486) (#1491)
  • Add geotiff writer test matrix (#1483) (#1490)
  • Stream tile writes per dask chunk segment to bound peak memory in to_geotiff (#1485) (#1489)
  • Add regression test for GPU pred=3 multi-sample TIFFs (#1479) (#1481)
  • Make cubic resample prefilter explicit so chunk seams stay sub-eps (#1464) (#1478)
  • Preserve input float dtype through resample() (#1467) (#1476)
  • Resample polish: fix cubic depth comment, tighten NaN threshold, add edge tests (#1475)
  • Fix dask aggregate boundary contamination and clean up bookkeeping (#1469) (#1477)
  • Support 3D rasters, expose nodata, document target_resolution tuple in resample (#1466) (#1474)
  • Cover cupy median/mode, dask+cupy, integer input, target_resolution tuple in resample tests (#1470) (#1473)
  • Refresh transform and nodata attrs on resample output (#1465) (#1472)
  • Inline dask aggregate kernel in resample (#1463) (#1468)
  • Emit fresh grid metadata and propagate _FillValue in reproject (#1458) (#1462)
  • Polish reproject/merge docstrings and cover Inf and parameter edge cases (#1459) (#1461)
  • Batch CuPy reductions and drop redundant copies in reproject (#1460)
  • Add transform_precision parameter to merge() (#1452) (#1456)
  • Preserve non-spatial coords through reproject() and merge() (#1455)
  • Guard _apply_vertical_shift against non-finite coords; add vertical CRS tests (#1453)
  • Honor per-raster nodata sentinels in merge() (#1448) (#1449)
  • Preserve input attrs through reproject() and merge() (#1446)
  • Fix dask reproject dtype and same-CRS dask merge (#1450)
  • Validate raster inputs in reproject public APIs (#1431) (#1432)
  • Add memory guard and scalar validation to generate_terrain (#1443) (#1444)
  • Validate scalar parameters in hydro public APIs (#1427) (#1428)
  • Validate mannings_n DataArray values in flood (#1437) (#1438)
  • Add _validate_raster on secondary DataArray args in hydro (#1425) (#1426)
  • Validate grid/bounds/precision params in reproject (#1433) (#1434)
  • Validate cellsize in hydro public APIs (#1429) (#1430)
  • Validate pathfinding inputs and cap waypoints (#1439) (#1440)
  • Validate raster/mask inputs in polygonize (#1441) (#1442)
  • Add memory guard to flow_direction_mfd numpy/cupy backends (#1423) (#1424)
  • Reject NaN/Inf in reproject scalar inputs (#1435) (#1436)
  • Lazy assembly for hand_mfd dask path (#1416) (#1417)
  • Return NaN from glcm_texture angle=None when no angle has valid pairs (#1408) (#1409)
  • Use ground distance for sky_view_factor horizon angle (#1407) (#1410)
  • Exclude centre cell from morph_erode/dilate when kernel[centre]==0 (#1397) (#1398)
  • Use sized slice in dask morph chunk writeback (#1399) (#1400)
  • Merge sink_d8 labels across dask tile boundaries (#1394) (#1395)
  • Reject complex dtypes in _validate_raster() (#1384) (#1387)
  • Reject underflowing sigma_spatial in bilateral() (#1390) (#1392)
  • Use int64 row_ptr in _build_row_csr_numba (#1388) (#1391)
  • Reject mixed-backend arrays in validate_arrays() (#1383) (#1386)
  • Reject non-positive inputs in wpm() (#1382) (#1385)
  • Guard _idw knearest against unbounded grid x k allocation (#1377) (#1380)
  • Validate raster dtype in convolve_2d() (#1389) (#1393)
  • Reject all-zero rasters in mesh_utils.create_triangulation (#1378) (#1381)
  • Validate dtypes per band in mahalanobis() (#1376) (#1379)
  • Guard owa() against unbounded criteria stack (#1370) (#1375)
  • Guard spline() TPS against unbounded memory allocations (#1372) (#1374)
  • Reject n_samples<=0 in mcda sensitivity (#1371) (#1373)
  • Guard flow_path_d8() against unbounded memory allocations (#1364) (#1368)
  • Guard flow_path_mfd() against unbounded memory allocations (#1365) (#1369)
  • Guard flow_path_dinf() against unbounded memory allocations (#1363) (#1367)
  • Guard snap_pour_point_d8() against unbounded memory allocations (#1362) (#1366)
  • Guard sink_d8() against unbounded memory allocations (#1356) (#1361)

v0.9.8

29 Apr 19:33
48cf420

Choose a tag to compare

Version 0.9.8 - 2026-04-29

Bug fixes and improvements

  • Guard stream_order_dinf() against unbounded memory allocations (#1350) (#1354)
  • Guard basin_d8() against unbounded memory allocations (#1357) (#1359)
  • Guard flow_length_dinf() against unbounded memory allocations (#1355) (#1358)
  • Guard flow_length_mfd() against unbounded memory allocations (#1351) (#1353)
  • Guard stream_order_mfd() against unbounded memory allocations (#1349) (#1352)
  • Guard watershed_dinf() against unbounded memory allocations (#1345) (#1348)
  • Guard stream_link_dinf() against unbounded memory allocations (#1343) (#1347)
  • Guard hand_dinf() against unbounded memory allocations (#1344) (#1346)
  • Guard stream_link_mfd() against unbounded memory allocations (#1337) (#1341)
  • Guard flow_length_d8() against unbounded memory allocations (#1327) (#1332)
  • Guard hand_d8() against unbounded memory allocations (#1323) (#1326)
  • Guard hand_mfd() against unbounded memory allocations (#1338) (#1340)
  • Guard watershed_mfd() against unbounded memory allocations (#1339) (#1342)
  • Guard watershed_d8() against unbounded memory allocations (#1329) (#1330)
  • Guard fill_d8() against unbounded eager allocations (#1334) (#1336)
  • Guard stream_link_d8() against unbounded memory allocations (#1333) (#1335)
  • Guard stream_order_d8() against unbounded memory allocations (#1328) (#1331)
  • Guard flow_accumulation_dinf() against unbounded memory allocations (#1322) (#1325)
  • Guard flow_accumulation_mfd() against unbounded memory allocations (#1321) (#1324)
  • Guard gpu_rtx hillshade and viewshed against unbounded GPU allocations (#1308) (#1310)
  • Guard min_observable_height() against unbounded boolean stack (#1317) (#1320)
  • Guard flow_accumulation() against unbounded eager allocations (#1318) (#1319)
  • Reject NaN/Inf weights in mcda combine and ahp_weights (#1311) (#1312)
  • Support TIFF predictor=3 on the CPU write path (#1313) (#1314)
  • Guard kriging() against unbounded N x N and grid x N allocations (#1307) (#1309)
  • Guard surface_distance() against unbounded eager allocations (#1303) (#1305)
  • Guard landforms() against unbounded kernel allocations (#1302) (#1304)
  • Enforce equal band shapes in true_color() (#1293) (#1301)
  • Guard sky_view_factor() against unbounded eager allocations (#1299) (#1300)
  • Guard resample() against unbounded output allocations (#1295) (#1297)
  • Guard sieve() numpy and cupy backends against oversized rasters (#1296) (#1298)
  • Guard kde and line_density against oversize output grids (#1287) (#1289)
  • Reject oversize focal kernels before allocation (#1284) (#1286)
  • Guard mahalanobis allocations against oversized rasters (#1288) (#1290)
  • Guard true_color() eager backends against oversized rasters (#1291) (#1292)
  • Add memory guard to geodesic slope/aspect (#1283) (#1285)
  • Validate dt against CFL stability bound in diffuse() (#1281) (#1282)
  • Cap erode() parameters and run memory guard on every backend (#1275) (#1277)
  • Validate cellsize in curvature() (#1270) (#1272)
  • Add memory guard to emerging_hotspots public API (#1274) (#1276)
  • Validate input rasters in edge_detection public API (#1271) (#1273)
  • Guard diffuse() against unbounded allocations and steps loop (#1267) (#1268)
  • Add memory guards to dasymetric public API (#1261) (#1263)
  • Guard cost_distance CuPy backend against oversize rasters (#1262) (#1264)
  • Guard morphology kernel allocations against oversized kernels (#1256) (#1258)
  • Cap window_size and distance in glcm_texture (#1257) (#1259)
  • Guard cost_distance numpy path against oversize rasters (#1252) (#1253)

v0.9.7

24 Apr 00:08
1de9a4e

Choose a tag to compare

New features

  • Add kernel density estimation (KDE) (#1170)
  • Add standalone raster resampling (#1152) (#1172)
  • Add GPU COG overview support (#1150) (#1174)
  • Add geometry simplification to polygonize() (#1176)
  • Add polygon clipping function (#1144) (#1173)
  • Add hypsometric_integral to zonal module (#1073)

Bug fixes and improvements

  • Fix dask OOM in visibility and viewshed modules (#1167)
  • QA/QC: align sieve with GDAL and add parity tests (#1169)
  • Numba-ize visibility module loops (#1177) (#1179)
  • Fix hillshade gradient to use Horn's method (#1175) (#1178)
  • Fix duplicate notebook numbers and restructure to standard format (#1181)
  • Fix OOM in geotiff dask read, sieve memory, and reproject GPU fallback (#1183)
  • Add memory guards to reproject CuPy paths and output grid (#1186, #1187) (#1188)
  • Fix NaN pixels producing spurious polygons in numpy/dask backends (#1190) (#1194)
  • Fix CuPy Bellman-Ford iteration limit in cost_distance (#1192)
  • Fix geotiff unbounded allocation DoS and VRT path traversal (#1189)
  • Fix KDE all-zero output with descending-coordinate templates (#1199)
  • Fix crop=True dropping boundary pixels when all_touched=True (#1197) (#1200)
  • Add allocation guards to GPU read and VRT read paths (#1196)
  • Fix resample interpolation coordinate mapping (#1202) (#1204)
  • Fix float32 truncation in balanced_allocation iteration loop (#1203) (#1205)
  • Fix bump OOM with int32 coords, default-count cap, per-chunk dask partitioning (#1206) (#1208)
  • Pass dask chunks to rasterize in clip_polygon to keep mask lazy (#1207) (#1209)
  • Cut head_tail_breaks and box_plot dask re-scans (#1213)
  • Fuse hypsometric_integral dask path to a single graph evaluation (#1212)
  • Cap dask graph size in read_geotiff_dask and batch adler32 transfers (#1211)
  • Bound per-tile allocations in TIFF reader (#1215) (#1216)
  • Fix GPU predictor kernel stride for multi-sample tiled TIFFs (#1220) (#1222)
  • Reject TIFFs whose declared tile grid exceeds TileOffsets length (#1219) (#1221)
  • Reject oversize rasterize outputs before allocation (#1223) (#1224)
  • Fix cupy zonal_stats silently ignoring nodata_values=0 (#1227) (#1228)
  • Guard viewshed numpy path against oversize rasters (#1229) (#1230)
  • Reject integer-dtyped input in perlin() (#1232) (#1233)
  • Reject oversize bump output rasters before allocation (#1231) (#1234)
  • Clamp bilateral kernel radius to raster extent (#1236) (#1238)
  • Fix CPU fp_predictor_decode for multi-band predictor=3 TIFFs (#1247) (#1250)
  • Guard natural_breaks against oversize Jenks matrices (#1246) (#1248)
  • Handle degenerate input in equal_interval (#1244) (#1245)
  • Reject oversize convolution kernels before allocation (#1241) (#1243)
  • Guard contour segment buffers against oversize allocation (#1240) (#1242)

v0.9.6

05 Apr 20:04
dbbf813

Choose a tag to compare

New features

  • Multi-observer viewshed and line-of-sight profiles (#1145) (#1160)
  • Sieve filter for removing small raster clumps (#1159)

Bug fixes and improvements

  • Faster sieve labeling, with convergence warning (#1163)
  • Dask laziness docs and regression tests (#1164) (#1165)
  • Fix README feature matrix to match codebase (#1155) (#1158)
  • Fix 196 test-suite warnings (#1148) (#1157)
  • ASV benchmarks for 6 modules changed in v0.9.5 (#1156)
  • Caveat and assumption admonitions in docs (#1134)
  • Miscellaneous code sweeps (#1161)

v0.9.5

31 Mar 20:24
45c714e

Choose a tag to compare

Bug fixes and improvements

  • Add GPU memory guard to reproject dask+cupy path (#1131)
  • Add memory guard to surface_distance geodesic dd_grid (#1129)
  • Add memory guard to dasymetric validate_disaggregation (#1127)
  • Replace boolean indexing with lazy reductions in normalize dask paths (#1125)
  • Keep northness/eastness lazy on dask arrays (#1123)
  • Add memory guard to erosion dask paths (#1121)
  • Add memory guard to cost_distance iterative Dijkstra and da.block assembly (#1119)
  • Fix diffusion dask OOM by passing scalar diffusivity directly to chunks (#1117)
  • Fix balanced_allocation OOM with lazy source extraction and memory guard (#1115)
  • Fix zonal dask memory guards and stats filtering (#1112)

v0.9.4

31 Mar 12:13
0ad1feb

Choose a tag to compare

New features

  • Streaming TIFF write for dask inputs (#1084) (#1108)
  • Add dtype, compression_level, and VRT output to geotiff I/O (#1083) (#1085)

Bug fixes and improvements

  • Use float64 in Jenks natural breaks internals (#1100) (#1101)
  • Fix multi-metric output mislabeling in glcm_texture (#1106) (#1107)
  • Fix inverted decay and off-by-one in bump spread (#1102) (#1103)
  • Propagate NaN from curve_number in curve_number_runoff (#1104) (#1105)
  • Fix target_elev contaminating horizon in dask viewshed distance sweep (#1098) (#1099)
  • Preserve float64 precision in convolve_2d (#1096) (#1097)
  • Fix SAVI formula: (1+L) was in denominator instead of numerator (#1094) (#1095)
  • Fix NaN handling in focal_stats CUDA kernels (#1092) (#1093)
  • Fix three accuracy bugs in zonal stats dask backend (#1090) (#1091)
  • Add longitude normalization to CUDA inverse projection kernels (#1089)
  • Fix three accuracy bugs in reproject resampling kernels (#1087)
  • Fix three accuracy bugs in open_geotiff/to_geotiff (#1081) (#1082)

v0.9.3

28 Mar 04:33

Choose a tag to compare

New features

  • GeoTIFF/COG reader and writer with GPU acceleration and datum transforms (#1035) (#1062)
  • nvJPEG GPU acceleration for JPEG-compressed GeoTIFFs (#1050) (#1055)
  • LZ4 and LERC compression codecs for GeoTIFF (#1063)
  • Dask-native out-of-core reproject and merge module (#1031)
  • MCDA module for spatial multi-criteria decision analysis (#1030) (#1058)
  • Edge detection filters: Sobel, Laplacian, Prewitt (#1042)
  • Focal variety statistic (#1040) (#1043)
  • NDSI, NDBI, BAI, MSAVI2, and OSAVI spectral indices (#1044)
  • Northness and eastness aspect functions (#1039) (#1041)
  • Rescale and standardize normalization utilities (#1028)
  • Morphological gradient, white top-hat, and black top-hat operators (#1026)
  • D-inf and MFD variants of flow_path, watershed, and HAND (#1020)
  • D-infinity flow length computation (#1012) (#1013)
  • MFD flow length computation (#1011)
  • Vegetation-aware flood modeling: roughness, curve number, and depth from land cover (#1029)
  • Lightweight CRS parser, removes hard pyproj dependency (#1072)
  • plot() accessors for DataArray and Dataset (#1074)
  • fused_overlap and multi_overlap dask graph utilities (#1071)
  • rechunk_no_shuffle utility (#1068)

Bug fixes and improvements

  • Fix D-inf flow direction odd facet decomposition per Tarboton 1997 (#1005)
  • Fix CuPy uint8 overflow and CUDA cubic NaN fallback (#1054) (#1064)
  • Fix stale full pipeline benchmark numbers in README (#1077) (#1079)
  • Fix duplicate prefix numbers in user guide notebooks (#1076) (#1078)
  • Memory-safe rechunk, preview chunk budget, plot improvements (#1075)
  • Reduce dask graph size for large raster reprojection (#1065)
  • Speed up cost_distance iterative tile Dijkstra 2-4x (#1023)
  • Faster polygonize: single-pass tracing, JIT merge helpers, batch shapely (#1010)
  • Rename GeoTIFF API to xarray conventions (#1047) (#1061)
  • Section index in README feature matrix (#1033) (#1034)
  • Dask example for reproject (#1066)
  • Porto taxi trajectory rasterization example (#1022)
  • Polygonize benchmark comparing xrspatial vs rasterio (#1006) (#1007)

v0.9.2

14 Mar 00:35
8d10a15

Choose a tag to compare

New features

  • Vector rasterize function for polygons, lines, and points (#989) (#990)
  • preview() for memory-safe raster downsampling (#987)
  • D-inf and MFD stream ordering and link segmentation (#983) (#984)
  • Zonal functions accept vector zones directly (#999)
  • Dask backends for rasterize() (#997)

Bug fixes and improvements

  • Fix rasterize accuracy: GPU ceil, half-open fill, all_touched pairing (#995) (#996)
  • Fix scanline row gaps, speed up rasterize, add resolution/like/merge params (#991)
  • Rasterization fixes (#992)
  • Fix cupy failures in balanced_allocation and corridor (#985)
  • Refactor preview to avoid rechunking (#988)
  • Replace datashader with matplotlib in user guide notebooks (#1002)
  • Refactor user guide notebooks 10-31 to standard structure (#1003)
  • Water/land classification example in GLCM notebook (#994)
  • Source/reference column in README feature matrix (#977) (#978)
  • Small notebook fixes

v0.9.1

05 Mar 05:39
ec48ebf

Choose a tag to compare

New Features

  • Add contour line extraction via marching squares (#964) (#974)
  • Add GLCM texture metrics (#963) (#973)
  • Add sky-view factor function (#962) (#972)
  • Add bilateral filter for feature-preserving smoothing (#969) (#970)

v0.9.0

05 Mar 00:48
b66c00e

Choose a tag to compare

Version 0.9.0 - 2026-03-04

New Features

  • Add least-cost corridor analysis (#965) (#968)
  • Add native Dask+CuPy backends for hydrology core functions (#952) (#966)
  • Add native CUDA kernel for hydraulic erosion (#961) (#967)
  • Add CuPy and Dask+CuPy backends for kriging (#951) (#960)
  • Add NDWI and MNDWI water indices (#959)
  • Add morphological raster operators (#949) (#958)
  • Add TPI-based landform classification (#950) (#957)
  • Add MFD flow direction and accumulation (#946) (#956)
  • Add balanced service area partitioning (#939) (#943)
  • Add Dinf support to flow_accumulation() (#945)
  • Add scalar diffusion solver (#940) (#944)
  • Add multi_stop_search for multi-waypoint routing (#935) (#937)
  • Add raster-based dasymetric mapping module (#930) (#936)
  • Add interpolation tools: IDW, Kriging, and Spline (#932) (#934)

Bug Fixes & Improvements

  • Remove esri.py and datashader from core dependencies (#953)
  • Add HAND and TWI to README feature matrix (#954) (#955)
  • Add missing API reference docs for ~30 undocumented functions (#941) (#942)
  • Remove unnecessary array copies to reduce memory allocations (#933)