Skip to content

Releases: xarray-contrib/xarray-spatial

v0.10.1

29 May 14:15
57e7c57

Choose a tag to compare

New features

  • accessor: backend-aware .xrs.open_geotiff on DataArray and Dataset (#2598)
  • geotiff: add bbox= to open_geotiff for geographic-space windowed reads (#2556)

Bug fixes and improvements

  • rasterize: honor resolution= exactly when bounds don't divide evenly (#2597)
  • reproject: fix vertical-datum shift crash on integer DEMs (#2596)
  • resample: clamp dask interp overlap depth per axis (#2547) (#2599)
  • zonal: fix trim() with NaN sentinel on numpy and cupy backends (#2559) (#2594)
  • reproject: reject explicit out-of-range nodata for integer dtypes (#2591)
  • zonal: fix cupy backend dropping all-NaN zones and desyncing zone_ids (#2562) (#2589)
  • resample: refresh transform to match actual coord orientation (#2571) (#2587)
  • rasterize: validate resolution= shape and element type (#2576) (#2586)
  • resample: preserve integer precision in nodata mask comparison (#2570) (#2592)
  • zonal: keep hypsometric_integral dask path fully lazy (#2563) (#2593)
  • geotiff: accept projected GeoTIFFs that carry a base geographic CRS (#2603)
  • polygonize: reject non-finite simplify_tolerance (#2575) (#2584)
  • reproject: unit-aware bounds_policy="auto" blow-up detection (#2600)
  • zonal: validate return_type at entry to stats() (#2558) (#2578)
  • resample: validate target_resolution and scale_factor up front (#2574) (#2590)
  • rasterize: support descending-x in like= templates (#2568) (#2595)
  • rasterize: reject zig-zag duplicate-coord patterns in _check_uniform_axis (#2585)
  • polygonize: fix dask chunk-dependent merging and DN corruption (#2601)
  • zonal: make crop() return (0, 0) on all backends when no zone matches (#2580)
  • rasterize: reject partial width/height overrides instead of silent ignore (#2579)
  • zonal: fix crosstab cat_ids overcount when earlier categories are filtered out (#2560) (#2577)
  • resample: preserve scalar non-dim coords and refresh stale nodata attr (#2542) (#2549)
  • zonal: fix hypsometric_integral dask+cupy backend (#2525) (#2529)
  • geotiff: include GB allocation estimate in max_pixels error message (#2554)
  • zonal: raise on 'majority' in zonal_stats dask path instead of silent drop (#2528) (#2531)
  • reproject: fix half-pixel offset in geoid and datum-shift grid lookups (#2508) (#2516)
  • rasterize: reject NaN fill against integer dtype (#2504) (#2512)
  • geotiff: reject distinct per-band nodatavals on write (#2514) (#2519)
  • zonal: guard unbounded allocation in stats(return_type='xarray.DataArray') (#2523) (#2533)
  • zonal: rechunk apply 3D dask output along stacked axis (#2526) (#2532)
  • rasterize: hoist poly_props/poly_global cupy.asarray above all_touched (#2506) (#2510)
  • polygonize: auto-detect attrs['transform'] for output georeferencing (#2536) (#2541)
  • geotiff: reconcile COG write stability across registry, contract, and docstring (#2520)
  • zonal: rename crop(zones_ids=) to crop(zone_ids=) with deprecation shim (#2521) (#2527)
  • reproject: preserve integer dtype in dask+cupy fast path (#2505) (#2509)
  • geotiff: scope max_pixels to the chunk when chunks= is supplied (#2501) (#2502)

v0.10.0

27 May 15:27
6401e0d

Choose a tag to compare

GeoTIFF release contract

Tiers what the public GeoTIFF and COG surface promises for this release.
xrspatial.geotiff.SUPPORTED_FEATURES is the source of truth; the bullets
below mirror it. See the reference page at docs/source/reference/geotiff.rst
for the per-tier semantics and the audit trail.

Stable

  • Local-file GeoTIFF read (open_geotiff) on the eager numpy backend, including windowed reads via window=. Covered by the window-read suite in xrspatial/geotiff/tests/. (epic #2340)
  • Dask reads (read_geotiff_dask). Cross-backend parity against the eager numpy reader is gated by test_backend_parity_matrix.py and test_backend_full_parity_2211.py. (epic #2341)
  • Local-file GeoTIFF write (to_geotiff) on the CPU writer. (epic #2340)
  • Local COG read and write (reader.local_cog, writer.cog) for axis-aligned 2D / 3D rasters with the lossless codecs none, deflate, lzw, zstd, packbits, internal overviews only, and normal CRS / transform / dtype / nodata / band / pixel-is-area / pixel-is-point round-trip. Backed by the writer compliance suite (#2292), the cross-backend parity gate (#2293), and the per-tile byte-budget contract (#2294 / #2298). (epic #2286)
  • Lossless stable codecs: none, deflate, lzw, zstd, packbits. Integer and float byte-for-byte round-trip. (epic #2340)

Advanced

  • fsspec-routed reads (reader.fsspec) and HTTPS reads (reader.http). The transport layer works but the redirect / retry / cache surface is not contracted at the stable bar. (epic #2344)
  • HTTP COG reads (reader.http_cog). Range fetching, range coalescing, the SSRF / private-host filter, and the per-tile byte cap are pinned by the byte-budget contract (#2294 / #2298), but the broader transport surface is tracked separately for stable promotion. (epic #2344)
  • VRT reads (reader.vrt). Limited to simple GDAL VRT mosaics over GeoTIFF sources that agree on CRS, transform orientation, pixel size, dtype, and band count. See the VRT support matrix in docs/source/reference/geotiff.rst. (epic #2342, PR #2321)
  • External .tif.ovr sidecar reads (reader.sidecar_ovr). (epic #2340)
  • Writer overviews and BigTIFF (writer.overviews, writer.bigtiff). (epic #2340)
  • BigTIFF COG writes (writer.bigtiff_cog). The external-interop gate lives in test_bigtiff_cog_compliance_2286.py; promotion to stable follows the same release-cycle soak rule as the rest of the COG surface. (epic #2286)

Experimental

  • GPU reads and writes (reader.gpu, writer.gpu). Cross-backend numerical parity is not claimed at this tier. (epic #2341)
  • Experimental codecs: lerc, jpeg2000, j2k, lz4. Require allow_experimental_codecs=True on both read and write paths. Reader support across GDAL versions is uneven. (epic #2340)
  • Permissive read escape hatches: allow_rotated=True (reader.allow_rotated) and allow_unparseable_crs=True (reader.allow_unparseable_crs). Both bypass a read-side check that the writer normally rejects. (epic #2340)
  • Rich-tag writes: writer.gdal_metadata_xml and writer.extra_tags. Free-form payloads are written verbatim; interop with rasterio, libtiff, and GDAL depends on the payload. Gated by allow_experimental_codecs=True on writes from a fresh DataArray; round-tripped attrs from a previous read are exempt. (epic #2340)

Internal-only

  • codec.jpeg (JPEG-in-TIFF). The encoder writes self-contained JFIF tiles without the TIFF JPEGTables tag (347), so the on-disk output is not interoperable with libtiff, GDAL, or rasterio. Reads and writes require the dedicated allow_internal_only_jpeg=True opt-in; allow_experimental_codecs=True does not unlock this path. (epic #2340)

Unsupported for this release (these combinations fail closed: the writer or reader raises rather than silently producing a wrong result)

  • Warped VRTs (<VRTDataset subClass="VRTWarpedDataset">). (PR #2321)
  • Nested VRTs (a <SourceFilename> pointing at another .vrt). (PR #2321)
  • VRT mosaics whose sources disagree on CRS, pixel size, dtype, or band count without an explicit opt-in. The default raises MixedBandMetadataError. (PR #2321)
  • to_geotiff(..., cog=True, tiled=False). COG output requires the tiled layout. (epic #2286)
  • Rotated transforms on the write path. The reader has an allow_rotated=True escape hatch in the experimental tier; the writer has no equivalent. (epic #2340)
  • 1xN / Nx1 writes without an explicit attrs['transform']. The writer used to borrow the non-degenerate axis's spacing and silently invent the wrong pixel size; the writer now raises. (epic #2340)

Bug fixes and improvements

  • Move shapely from a required dependency to an optional vector extra. shapely (and GEOS) used to load on every import xrspatial because rasterize.py imported it at module top level. It is now imported lazily, so a plain pip install xarray-spatial neither installs nor loads shapely. The only paths that need it are the vector-to-raster functions rasterize and polygonize; install pip install xarray-spatial[vector] to use them. Calling rasterize without shapely raises a clear ImportError pointing at the extra. Follows the same pattern as the matplotlib change (#2494). (#2496)
  • Move matplotlib from a required dependency to an optional plot extra. A plain pip install xarray-spatial no longer pulls in matplotlib (and its pillow / fonttools / kiwisolver / contourpy / cycler / pyparsing chain), since no compute path imports it -- every matplotlib use is a lazy import inside the .xrs.plot accessor helpers. Install pip install xarray-spatial[plot] to use plotting; calling .xrs.plot() without it now raises a clear ImportError pointing at the extra instead of a bare ModuleNotFoundError. pandas stays required because xarray depends on it and several core modules import it directly. (#2494)
  • Reconcile xrspatial.geotiff.SUPPORTED_FEATURES with the GeoTIFF release-contract tiering proposed in epic #2340. Adds reader.windowed at stable (covered by the existing window-read suite) and reader.dask at stable (covered by the cross-backend parity matrix in test_backend_parity_matrix.py and test_backend_full_parity_2211.py). Demotes reader.allow_rotated and reader.allow_unparseable_crs from advanced to experimental to match the epic's placement of permissive read-side escape hatches in the Experimental tier. A new shape test (test_supported_features_shape_2348.py) pins the structural invariants of the mapping (every entry carries a tier label; the tier set is closed at {stable, advanced, experimental, internal_only}; the dict literal contains no duplicate keys) so future drift fails CI. Runtime behaviour of every read and write path is unchanged; this is metadata-only. Callers gating on the exact string value of these two demoted entries will need to update their checks. (#2348)
  • Promote the local COG read and write paths to the stable tier in xrspatial.geotiff.SUPPORTED_FEATURES. SUPPORTED_FEATURES['writer.cog'] and SUPPORTED_FEATURES['reader.local_cog'] now report stable; reader.http_cog stays advanced while the HTTP transport surface is contracted separately. The stable COG contract covers axis-aligned 2D / 3D rasters, the CPU writer and CPU reader, the lossless codecs (none, deflate, lzw, zstd, packbits), internal overviews, and normal CRS / transform / dtype / nodata / band / pixel-is-area / pixel-is-point round-trip. GPU COG paths, experimental codecs, rotated transforms, external .tif.ovr sidecars, file-like destinations with cog=True, BigTIFF COG, and HTTP COG remain outside the contract. Backed by the writer compliance suite (#2292), the cross-backend parity gate (#2293), and the per-tile byte-budget contract (#2294 / #2298). The reference docs (docs/source/reference/geotiff.rst) and the COG overview notebook spell out the full contract. (#2300)
  • Resolve the GeoTIFF writer's GeographicTypeGeoKey / ProjectedCSTypeGeoKey decision via pyproj instead of an EPSG number range. The legacy heuristic (4326 + 4000-4999 -> geographic, else projected) silently mis-tagged geographic CRSes registered outside the 4000-4999 block (NAD83(2011) = 6318, GDA2020 = 7844, WGS 84 (G2139) = 9057, etc.) as projected and projected codes inside the block (4087 / 4088 / 4499) as geographic, corrupting the CRS at write time. The writer now calls pyproj.CRS.from_epsg(...).is_geographic. When pyproj can't classify a code (uninstalled, or installed but the local PROJ database lacks the entry), the writer raises the new UnknownCRSModelTypeError rather than guessing -- a small vetted allowlist (4326, 4269, 4267, 4258, 4283, 4322, 4230, 4019, 4047) is still honoured for the pyproj-missing case. pyproj is now listed under the geotiff extra. (#2277)
  • Shut down the per-tile compression ThreadPoolExecutor on every exit path of the streaming tiled-write code in to_geotiff. The old code only called shutdown(wait=True) after the tile-row loop completed, so any mid-stream raise (compression failure, dask compute failure, file write failure) bypassed shutdown and leaked worker threads. The loop now runs inside try/finally and the finally calls shutdown(wait=True, cancel_futures=True) so queued tiles get dropped on the error path instead of blocking the unwind. The pool's workers carry an xrspatial-geotiff-tile-compress thread_name_prefix so leak-detection tests can tell them apart from dask's own offload/scheduler pools. (#2276)
  • Remove read-side emission of the 13 deprecated GeoTIFF attrs (crs_name, geog_citation, datum_code, angular_units, semi_major_axis, inv_flattening, linear_units, projection_code, vertical_crs, vertical_citation, vertical_units, colormap_rgba, cmap) and bump attrs['_xrspatial_geotiff_contract'] from 1 to 2. Downstream code that read these via attrs[key] now sees KeyError; migrate to attrs.get(key) or derive the value from attrs['crs'] / attrs['crs_wkt'] ...
Read more

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