xarray-spatial 0.9.5__tar.gz → 0.9.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (305) hide show
  1. xarray_spatial-0.9.6/.claude/accuracy-sweep-state.json +9 -0
  2. xarray_spatial-0.9.6/.claude/commands/accuracy-sweep.md +158 -0
  3. xarray_spatial-0.9.6/.claude/performance-sweep-state.json +47 -0
  4. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/.github/workflows/benchmarks.yml +2 -2
  5. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/CHANGELOG.md +16 -0
  6. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/PKG-INFO +40 -26
  7. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/README.md +39 -25
  8. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/setup.cfg +11 -0
  9. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xarray_spatial.egg-info/PKG-INFO +40 -26
  10. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xarray_spatial.egg-info/SOURCES.txt +8 -0
  11. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/__init__.py +4 -0
  12. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/_version.py +3 -3
  13. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/accessor.py +12 -0
  14. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/classify.py +2 -2
  15. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/preview.py +3 -1
  16. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/rasterize.py +4 -1
  17. xarray_spatial-0.9.6/xrspatial/sieve.py +480 -0
  18. xarray_spatial-0.9.6/xrspatial/tests/test_dask_laziness.py +180 -0
  19. xarray_spatial-0.9.6/xrspatial/tests/test_sieve.py +502 -0
  20. xarray_spatial-0.9.6/xrspatial/tests/test_visibility.py +276 -0
  21. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_zonal.py +5 -1
  22. xarray_spatial-0.9.6/xrspatial/visibility.py +256 -0
  23. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/zonal.py +6 -3
  24. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/.claude/commands/backend-parity.md +0 -0
  25. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/.claude/commands/bench.md +0 -0
  26. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/.claude/commands/dask-notebook.md +0 -0
  27. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/.claude/commands/efficiency-audit.md +0 -0
  28. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/.claude/commands/new-issues.md +0 -0
  29. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/.claude/commands/release-major.md +0 -0
  30. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/.claude/commands/release-minor.md +0 -0
  31. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/.claude/commands/release-patch.md +0 -0
  32. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/.claude/commands/review-pr.md +0 -0
  33. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/.claude/commands/rockout.md +0 -0
  34. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/.claude/commands/sweep-performance.md +0 -0
  35. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/.claude/commands/user-guide-notebook.md +0 -0
  36. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/.claude/commands/validate.md +0 -0
  37. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/.gitattributes +0 -0
  38. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  39. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/.github/ISSUE_TEMPLATE/feature-proposal.md +0 -0
  40. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/.github/labeler.yml +0 -0
  41. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/.github/pull_request_template.md +0 -0
  42. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/.github/workflows/labeler.yml +0 -0
  43. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/.github/workflows/pypi-publish.yml +0 -0
  44. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/.github/workflows/test.yml +0 -0
  45. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/.gitignore +0 -0
  46. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/.readthedocs.yml +0 -0
  47. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/CODE_OF_CONDUCT.md +0 -0
  48. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/CONTRIBUTING.md +0 -0
  49. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/Citation-styles.md +0 -0
  50. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/LICENSE.txt +0 -0
  51. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/MANIFEST.in +0 -0
  52. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/RELEASE.md +0 -0
  53. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/codecov.yml +0 -0
  54. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/pyproject.toml +0 -0
  55. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/setup.py +0 -0
  56. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xarray_spatial.egg-info/dependency_links.txt +0 -0
  57. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xarray_spatial.egg-info/entry_points.txt +0 -0
  58. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xarray_spatial.egg-info/not-zip-safe +0 -0
  59. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xarray_spatial.egg-info/requires.txt +0 -0
  60. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xarray_spatial.egg-info/top_level.txt +0 -0
  61. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/__main__.py +0 -0
  62. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/analytics.py +0 -0
  63. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/aspect.py +0 -0
  64. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/balanced_allocation.py +0 -0
  65. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/bilateral.py +0 -0
  66. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/bump.py +0 -0
  67. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/contour.py +0 -0
  68. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/convolution.py +0 -0
  69. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/corridor.py +0 -0
  70. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/cost_distance.py +0 -0
  71. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/curvature.py +0 -0
  72. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/dasymetric.py +0 -0
  73. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/dataset_support.py +0 -0
  74. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/datasets/__init__.py +0 -0
  75. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/datasets/sentinel-2/blue_band.nc +0 -0
  76. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/datasets/sentinel-2/green_band.nc +0 -0
  77. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/datasets/sentinel-2/nir_band.nc +0 -0
  78. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/datasets/sentinel-2/red_band.nc +0 -0
  79. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/datasets/sentinel-2/swir1_band.nc +0 -0
  80. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/datasets/sentinel-2/swir2_band.nc +0 -0
  81. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/diagnostics.py +0 -0
  82. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/diffusion.py +0 -0
  83. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/edge_detection.py +0 -0
  84. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/emerging_hotspots.py +0 -0
  85. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/erosion.py +0 -0
  86. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/experimental/__init__.py +0 -0
  87. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/experimental/min_observable_height.py +0 -0
  88. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/fire.py +0 -0
  89. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/flood.py +0 -0
  90. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/focal.py +0 -0
  91. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/geodesic.py +0 -0
  92. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/geotiff/__init__.py +0 -0
  93. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/geotiff/_compression.py +0 -0
  94. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/geotiff/_dtypes.py +0 -0
  95. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/geotiff/_geotags.py +0 -0
  96. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/geotiff/_gpu_decode.py +0 -0
  97. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/geotiff/_header.py +0 -0
  98. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/geotiff/_reader.py +0 -0
  99. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/geotiff/_vrt.py +0 -0
  100. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/geotiff/_writer.py +0 -0
  101. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/geotiff/tests/__init__.py +0 -0
  102. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/geotiff/tests/bench_vs_rioxarray.py +0 -0
  103. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/geotiff/tests/conftest.py +0 -0
  104. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/geotiff/tests/test_accessor_io.py +0 -0
  105. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/geotiff/tests/test_accuracy_1081.py +0 -0
  106. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/geotiff/tests/test_cog.py +0 -0
  107. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/geotiff/tests/test_compression.py +0 -0
  108. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/geotiff/tests/test_compression_level.py +0 -0
  109. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/geotiff/tests/test_dtype_read.py +0 -0
  110. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/geotiff/tests/test_edge_cases.py +0 -0
  111. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/geotiff/tests/test_features.py +0 -0
  112. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/geotiff/tests/test_geotags.py +0 -0
  113. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/geotiff/tests/test_header.py +0 -0
  114. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/geotiff/tests/test_jpeg.py +0 -0
  115. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/geotiff/tests/test_jpeg2000.py +0 -0
  116. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/geotiff/tests/test_lerc.py +0 -0
  117. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/geotiff/tests/test_lz4.py +0 -0
  118. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/geotiff/tests/test_reader.py +0 -0
  119. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/geotiff/tests/test_streaming_write.py +0 -0
  120. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/geotiff/tests/test_vrt_write.py +0 -0
  121. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/geotiff/tests/test_writer.py +0 -0
  122. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/glcm.py +0 -0
  123. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/gpu_rtx/__init__.py +0 -0
  124. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/gpu_rtx/cuda_utils.py +0 -0
  125. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/gpu_rtx/hillshade.py +0 -0
  126. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/gpu_rtx/mesh_utils.py +0 -0
  127. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/gpu_rtx/viewshed.py +0 -0
  128. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hillshade.py +0 -0
  129. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/__init__.py +0 -0
  130. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/_boundary_store.py +0 -0
  131. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/basin_d8.py +0 -0
  132. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/fill_d8.py +0 -0
  133. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/flow_accumulation_d8.py +0 -0
  134. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/flow_accumulation_dinf.py +0 -0
  135. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/flow_accumulation_mfd.py +0 -0
  136. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/flow_direction_d8.py +0 -0
  137. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/flow_direction_dinf.py +0 -0
  138. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/flow_direction_mfd.py +0 -0
  139. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/flow_length_d8.py +0 -0
  140. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/flow_length_dinf.py +0 -0
  141. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/flow_length_mfd.py +0 -0
  142. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/flow_path_d8.py +0 -0
  143. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/flow_path_dinf.py +0 -0
  144. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/flow_path_mfd.py +0 -0
  145. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/hand_d8.py +0 -0
  146. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/hand_dinf.py +0 -0
  147. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/hand_mfd.py +0 -0
  148. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/sink_d8.py +0 -0
  149. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/snap_pour_point_d8.py +0 -0
  150. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/stream_link_d8.py +0 -0
  151. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/stream_link_dinf.py +0 -0
  152. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/stream_link_mfd.py +0 -0
  153. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/stream_order_d8.py +0 -0
  154. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/stream_order_dinf.py +0 -0
  155. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/stream_order_mfd.py +0 -0
  156. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/tests/__init__.py +0 -0
  157. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/tests/conftest.py +0 -0
  158. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/tests/test_basin_d8.py +0 -0
  159. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/tests/test_fill_d8.py +0 -0
  160. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/tests/test_flow_accumulation_d8.py +0 -0
  161. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/tests/test_flow_accumulation_dinf.py +0 -0
  162. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/tests/test_flow_accumulation_mfd.py +0 -0
  163. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/tests/test_flow_direction_d8.py +0 -0
  164. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/tests/test_flow_direction_dinf.py +0 -0
  165. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/tests/test_flow_direction_mfd.py +0 -0
  166. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/tests/test_flow_length_d8.py +0 -0
  167. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/tests/test_flow_length_dinf.py +0 -0
  168. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/tests/test_flow_length_mfd.py +0 -0
  169. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/tests/test_flow_path_d8.py +0 -0
  170. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/tests/test_flow_path_dinf.py +0 -0
  171. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/tests/test_flow_path_mfd.py +0 -0
  172. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/tests/test_hand_d8.py +0 -0
  173. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/tests/test_hand_dinf.py +0 -0
  174. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/tests/test_hand_mfd.py +0 -0
  175. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/tests/test_sink_d8.py +0 -0
  176. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/tests/test_snap_pour_point_d8.py +0 -0
  177. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/tests/test_stream_link_d8.py +0 -0
  178. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/tests/test_stream_link_dinf.py +0 -0
  179. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/tests/test_stream_link_mfd.py +0 -0
  180. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/tests/test_stream_order_d8.py +0 -0
  181. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/tests/test_stream_order_dinf.py +0 -0
  182. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/tests/test_stream_order_mfd.py +0 -0
  183. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/tests/test_twi_d8.py +0 -0
  184. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/tests/test_watershed_d8.py +0 -0
  185. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/tests/test_watershed_dinf.py +0 -0
  186. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/tests/test_watershed_mfd.py +0 -0
  187. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/twi_d8.py +0 -0
  188. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/watershed_d8.py +0 -0
  189. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/watershed_dinf.py +0 -0
  190. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/hydro/watershed_mfd.py +0 -0
  191. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/interpolate/__init__.py +0 -0
  192. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/interpolate/_idw.py +0 -0
  193. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/interpolate/_kriging.py +0 -0
  194. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/interpolate/_spline.py +0 -0
  195. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/interpolate/_validation.py +0 -0
  196. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/mahalanobis.py +0 -0
  197. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/mcda/__init__.py +0 -0
  198. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/mcda/combine.py +0 -0
  199. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/mcda/constrain.py +0 -0
  200. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/mcda/sensitivity.py +0 -0
  201. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/mcda/standardize.py +0 -0
  202. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/mcda/weights.py +0 -0
  203. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/morphology.py +0 -0
  204. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/multispectral.py +0 -0
  205. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/normalize.py +0 -0
  206. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/pathfinding.py +0 -0
  207. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/perlin.py +0 -0
  208. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/polygonize.py +0 -0
  209. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/proximity.py +0 -0
  210. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/reproject/__init__.py +0 -0
  211. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/reproject/_crs_utils.py +0 -0
  212. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/reproject/_datum_grids.py +0 -0
  213. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/reproject/_grid.py +0 -0
  214. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/reproject/_interpolate.py +0 -0
  215. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/reproject/_itrf.py +0 -0
  216. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/reproject/_lite_crs.py +0 -0
  217. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/reproject/_merge.py +0 -0
  218. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/reproject/_projections.py +0 -0
  219. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/reproject/_projections_cuda.py +0 -0
  220. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/reproject/_transform.py +0 -0
  221. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/reproject/_vertical.py +0 -0
  222. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/reproject/grids/at_bev_AT_GIS_GRID.tif +0 -0
  223. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/reproject/grids/au_icsm_A66_National_13_09_01.tif +0 -0
  224. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/reproject/grids/be_ign_bd72lb72_etrs89lb08.tif +0 -0
  225. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/reproject/grids/ch_swisstopo_CHENyx06_ETRS.tif +0 -0
  226. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/reproject/grids/de_adv_BETA2007.tif +0 -0
  227. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/reproject/grids/es_ign_SPED2ETV2.tif +0 -0
  228. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/reproject/grids/nl_nsgi_rdcorr2018.tif +0 -0
  229. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/reproject/grids/pt_dgt_D73_ETRS89_geo.tif +0 -0
  230. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/reproject/grids/uk_os_OSTN15_NTv2_OSGBtoETRS.tif +0 -0
  231. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/reproject/grids/us_nga_egm96_15.tif +0 -0
  232. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/reproject/grids/us_noaa_alaska.tif +0 -0
  233. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/reproject/grids/us_noaa_conus.tif +0 -0
  234. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/reproject/grids/us_noaa_hawaii.tif +0 -0
  235. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/reproject/grids/us_noaa_nadcon5_nad27_nad83_1986_conus.tif +0 -0
  236. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/reproject/grids/us_noaa_prvi.tif +0 -0
  237. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/sky_view_factor.py +0 -0
  238. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/slope.py +0 -0
  239. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/surface_distance.py +0 -0
  240. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/terrain.py +0 -0
  241. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/terrain_metrics.py +0 -0
  242. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/__init__.py +0 -0
  243. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/bench_reproject_vs_rioxarray.py +0 -0
  244. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/conftest.py +0 -0
  245. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/general_checks.py +0 -0
  246. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_accessor.py +0 -0
  247. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_analytics.py +0 -0
  248. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_aspect.py +0 -0
  249. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_balanced_allocation.py +0 -0
  250. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_bilateral.py +0 -0
  251. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_bump.py +0 -0
  252. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_classify.py +0 -0
  253. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_contour.py +0 -0
  254. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_corridor.py +0 -0
  255. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_cost_distance.py +0 -0
  256. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_curvature.py +0 -0
  257. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_dask_cupy_gaps.py +0 -0
  258. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_dasymetric.py +0 -0
  259. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_dataset_support.py +0 -0
  260. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_datasets.py +0 -0
  261. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_diagnostics.py +0 -0
  262. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_diffusion.py +0 -0
  263. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_edge_detection.py +0 -0
  264. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_emerging_hotspots.py +0 -0
  265. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_erosion.py +0 -0
  266. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_fire.py +0 -0
  267. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_flood.py +0 -0
  268. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_focal.py +0 -0
  269. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_fused_overlap.py +0 -0
  270. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_geodesic_aspect.py +0 -0
  271. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_geodesic_slope.py +0 -0
  272. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_glcm.py +0 -0
  273. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_glcm_metric_order.py +0 -0
  274. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_hillshade.py +0 -0
  275. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_interpolation.py +0 -0
  276. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_lite_crs.py +0 -0
  277. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_mahalanobis.py +0 -0
  278. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_mcda.py +0 -0
  279. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_min_observable_height.py +0 -0
  280. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_morphology.py +0 -0
  281. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_morphology_derived.py +0 -0
  282. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_multi_overlap.py +0 -0
  283. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_multispectral.py +0 -0
  284. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_normalize.py +0 -0
  285. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_northness_eastness.py +0 -0
  286. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_pathfinding.py +0 -0
  287. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_perlin.py +0 -0
  288. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_polygonize.py +0 -0
  289. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_preview.py +0 -0
  290. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_proximity.py +0 -0
  291. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_rasterize.py +0 -0
  292. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_rasterize_accuracy.py +0 -0
  293. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_rechunk_no_shuffle.py +0 -0
  294. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_reproject.py +0 -0
  295. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_sky_view_factor.py +0 -0
  296. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_slope.py +0 -0
  297. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_surface_distance.py +0 -0
  298. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_terrain.py +0 -0
  299. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_terrain_metrics.py +0 -0
  300. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_utils.py +0 -0
  301. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_validation.py +0 -0
  302. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/tests/test_viewshed.py +0 -0
  303. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/utils.py +0 -0
  304. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/viewshed.py +0 -0
  305. {xarray_spatial-0.9.5 → xarray_spatial-0.9.6}/xrspatial/worley.py +0 -0
@@ -0,0 +1,9 @@
1
+ {
2
+ "inspections": {
3
+ "zonal": { "last_inspected": "2026-03-30T12:00:00Z", "issue": 1090 },
4
+ "focal": { "last_inspected": "2026-03-30T13:00:00Z", "issue": 1092 },
5
+ "multispectral": { "last_inspected": "2026-03-30T14:00:00Z", "issue": 1094 },
6
+ "proximity": { "last_inspected": "2026-03-30T15:00:00Z", "issue": null, "notes": "Direction >= boundary fragile but works due to truncated constant. Float32 truncation is design choice. No wrong-results bugs found." },
7
+ "curvature": { "last_inspected": "2026-03-30T15:00:00Z", "issue": null, "notes": "Formula matches ArcGIS reference. Backends consistent. No issues found." }
8
+ }
9
+ }
@@ -0,0 +1,158 @@
1
+ # Accuracy Sweep: Generate a Ralph Loop targeting under-inspected modules
2
+
3
+ Analyze xrspatial modules by recency and inspection history, then print a
4
+ ready-to-run `/ralph-loop` command that targets the highest-priority modules.
5
+
6
+ Optional arguments: $ARGUMENTS
7
+ (e.g. `--top 5`, `--exclude slope,aspect`, `--only-terrain`, `--reset-state`)
8
+
9
+ ---
10
+
11
+ ## Step 1 -- Gather module metadata via git
12
+
13
+ For every `.py` file directly under `xrspatial/` (skip `__init__.py`,
14
+ `_version.py`, `__main__.py`, `utils.py`, `accessor.py`, `preview.py`,
15
+ `dataset_support.py`, `diagnostics.py`, `analytics.py`), collect:
16
+
17
+ | Field | How |
18
+ |-------|-----|
19
+ | **last_modified** | `git log -1 --format=%aI -- xrspatial/<module>.py` |
20
+ | **first_commit** | `git log --diff-filter=A --format=%aI -- xrspatial/<module>.py` |
21
+ | **total_commits** | `git log --oneline -- xrspatial/<module>.py \| wc -l` |
22
+ | **recent_accuracy_commits** | `git log --oneline --grep='accuracy\|precision\|numerical\|geodesic' -- xrspatial/<module>.py` |
23
+
24
+ Store results in a temporary variable -- do NOT write intermediate files.
25
+
26
+ ## Step 2 -- Load inspection state
27
+
28
+ Read the state file at `.claude/accuracy-sweep-state.json`.
29
+
30
+ If it does not exist, treat every module as never-inspected.
31
+
32
+ If `$ARGUMENTS` contains `--reset-state`, delete the file and treat
33
+ everything as never-inspected.
34
+
35
+ The state file schema:
36
+
37
+ ```json
38
+ {
39
+ "inspections": {
40
+ "slope": { "last_inspected": "2026-03-28T14:00:00Z", "issue": 1042 },
41
+ "aspect": { "last_inspected": "2026-03-28T15:30:00Z", "issue": 1043 }
42
+ }
43
+ }
44
+ ```
45
+
46
+ ## Step 3 -- Score each module
47
+
48
+ Compute a priority score for each module. Higher = more urgent.
49
+
50
+ ```
51
+ days_since_inspected = (today - last_inspected).days # 9999 if never inspected
52
+ days_since_modified = (today - last_modified).days
53
+ total_commits = from Step 1
54
+ has_recent_accuracy_work = 1 if recent_accuracy_commits is non-empty, else 0
55
+
56
+ score = (days_since_inspected * 3)
57
+ + (total_commits * 0.5)
58
+ - (days_since_modified * 0.2)
59
+ - (has_recent_accuracy_work * 500)
60
+ ```
61
+
62
+ Rationale:
63
+ - Modules never inspected dominate (9999 * 3)
64
+ - More commits = more complex = more likely to have bugs
65
+ - Recently modified modules slightly deprioritized (someone just touched them)
66
+ - Modules with existing accuracy work heavily deprioritized
67
+
68
+ ## Step 4 -- Apply filters from $ARGUMENTS
69
+
70
+ - `--top N` -- only include the top N modules (default: 5)
71
+ - `--exclude mod1,mod2` -- remove named modules from the list
72
+ - `--only-terrain` -- restrict to slope, aspect, curvature, terrain,
73
+ terrain_metrics, hillshade, sky_view_factor
74
+ - `--only-focal` -- restrict to focal, convolution, morphology, bilateral,
75
+ edge_detection, glcm
76
+ - `--only-hydro` -- restrict to flood, cost_distance, geodesic,
77
+ surface_distance, viewshed, erosion, diffusion
78
+
79
+ ## Step 5 -- Print the results
80
+
81
+ ### 5a. Print the ranked table
82
+
83
+ Print a markdown table showing ALL scored modules (not just the selected ones),
84
+ sorted by score descending:
85
+
86
+ ```
87
+ | Rank | Module | Score | Last Inspected | Last Modified | Commits |
88
+ |------|-----------------|--------|----------------|---------------|---------|
89
+ | 1 | viewshed | 30012 | never | 45 days ago | 23 |
90
+ | 2 | flood | 29998 | never | 120 days ago | 18 |
91
+ | ... | ... | ... | ... | ... | ... |
92
+ ```
93
+
94
+ ### 5b. Print the generated ralph-loop command
95
+
96
+ Using the top N modules from the ranked list, generate and print a command
97
+ like this (adapt the module list to actual results):
98
+
99
+ ````
100
+ /ralph-loop "Survey xarray-spatial modules for numerical accuracy issues.
101
+
102
+ **Target these modules in priority order:**
103
+ 1. viewshed (xrspatial/viewshed.py) -- never inspected, 23 commits
104
+ 2. flood (xrspatial/flood.py) -- never inspected, 18 commits
105
+ 3. focal (xrspatial/focal.py) -- never inspected, 31 commits
106
+ 4. erosion (xrspatial/erosion.py) -- never inspected, 12 commits
107
+ 5. classify (xrspatial/classify.py) -- never inspected, 9 commits
108
+
109
+ **For each module, in order:**
110
+ 1. Read the source and identify potential accuracy issues:
111
+ - Floating point precision loss
112
+ - Incorrect NaN propagation
113
+ - Off-by-one errors in neighborhood operations
114
+ - Missing or wrong Earth curvature corrections
115
+ - Backend inconsistencies (numpy vs cupy vs dask results differ)
116
+ 2. Run /rockout to fix the issue end-to-end (issue, worktree, fix, tests, docs)
117
+ 3. After completing rockout for ONE module, output <promise>ITERATION DONE</promise>
118
+
119
+ If you find no accuracy issues in the current target module, skip it and move
120
+ to the next one.
121
+
122
+ If all target modules have been addressed or have no issues, output
123
+ <promise>ALL ACCURACY ISSUES FIXED</promise>." --max-iterations {N} --completion-promise "ALL ACCURACY ISSUES FIXED"
124
+ ````
125
+
126
+ Set `--max-iterations` to the number of target modules + 2 (buffer for retries).
127
+
128
+ ### 5c. Print a reminder
129
+
130
+ ```
131
+ To run this sweep: copy the command above and paste it.
132
+ To update state after a manual rockout: edit .claude/accuracy-sweep-state.json
133
+ To reset all tracking: /accuracy-sweep --reset-state
134
+ ```
135
+
136
+ ## Step 6 -- Update state (ONLY when called from inside a ralph-loop)
137
+
138
+ This step is informational. The accuracy-sweep command itself does NOT update
139
+ the state file. State is updated when `/rockout` completes -- the rockout
140
+ workflow should append to `.claude/accuracy-sweep-state.json` after creating
141
+ the issue.
142
+
143
+ To enable this, print a note reminding the user that after each rockout
144
+ iteration completes, they can manually record the inspection:
145
+
146
+ ```json
147
+ // Add to .claude/accuracy-sweep-state.json after each rockout:
148
+ { "module_name": { "last_inspected": "ISO-DATE", "issue": ISSUE_NUMBER } }
149
+ ```
150
+
151
+ ---
152
+
153
+ ## General Rules
154
+
155
+ - Do NOT modify any source files. This command is read-only analysis.
156
+ - Do NOT create GitHub issues. This command only generates the ralph-loop command.
157
+ - Keep the output concise -- the table and command are the deliverables.
158
+ - If $ARGUMENTS is empty, use defaults: top 5, no category filter, no exclusions.
@@ -0,0 +1,47 @@
1
+ {
2
+ "last_triage": "2026-03-31T18:00:00Z",
3
+ "modules": {
4
+ "reproject": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "RISKY", "bottleneck": "compute-bound", "high_count": 1, "issue": null },
5
+ "geotiff": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "SAFE", "bottleneck": "IO-bound", "high_count": 0, "issue": null, "notes": "False positive. open_geotiff(chunks=N) returns lazy dask array. to_geotiff auto-routes dask inputs to write_streaming. Eager paths are by design for numpy/cupy." },
6
+ "zonal": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "WILL OOM", "bottleneck": "memory-bound", "high_count": 4, "issue": 1110, "notes": "Memory guards improved, iterrows replaced with isin. da.unique().compute() confirmed safe (small result). regions() is inherently global - documented limitation." },
7
+ "viewshed": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "SAFE", "bottleneck": "memory-bound", "high_count": 1, "issue": null },
8
+ "rasterize": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "SAFE", "bottleneck": "graph-bound", "high_count": 1, "issue": null },
9
+ "bump": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "WILL OOM", "bottleneck": "memory-bound", "high_count": 0, "issue": null },
10
+ "normalize": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "SAFE", "bottleneck": "compute-bound", "high_count": 0, "issue": 1124, "notes": "Boolean indexing replaced with lazy nanmin/nanmax/nanmean/nanstd." },
11
+ "mahalanobis": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "WILL OOM", "bottleneck": "memory-bound", "high_count": 1, "issue": null },
12
+ "bilateral": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "SAFE", "bottleneck": "compute-bound", "high_count": 0, "issue": null },
13
+ "diffusion": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "WILL OOM", "bottleneck": "memory-bound", "high_count": 2, "issue": 1116, "notes": "Scalar diffusivity now passed as float to chunks. DataArray diffusivity passed as dask array via map_overlap." },
14
+ "cost_distance": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "WILL OOM", "bottleneck": "memory-bound", "high_count": 2, "issue": 1118, "notes": "Memory guard added + da.block assembly. Finite max_cost path (map_overlap) was already safe." },
15
+ "sky_view_factor": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "SAFE", "bottleneck": "compute-bound", "high_count": 0, "issue": null },
16
+ "worley": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "SAFE", "bottleneck": "compute-bound", "high_count": 0, "issue": null },
17
+ "flood": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "SAFE", "bottleneck": "compute-bound", "high_count": 0, "issue": null },
18
+ "aspect": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "SAFE", "bottleneck": "compute-bound", "high_count": 0, "issue": 1122, "notes": "northness/eastness now use da.cos/sin on dask arrays." },
19
+ "terrain": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "RISKY", "bottleneck": "compute-bound", "high_count": 0, "issue": null },
20
+ "terrain_metrics": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "SAFE", "bottleneck": "memory-bound", "high_count": 0, "issue": null },
21
+ "slope": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "SAFE", "bottleneck": "compute-bound", "high_count": 0, "issue": null },
22
+ "perlin": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "WILL OOM", "bottleneck": "memory-bound", "high_count": 0, "issue": null },
23
+ "curvature": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "SAFE", "bottleneck": "compute-bound", "high_count": 0, "issue": null },
24
+ "hillshade": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "SAFE", "bottleneck": "compute-bound", "high_count": 0, "issue": null },
25
+ "contour": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "SAFE", "bottleneck": "compute-bound", "high_count": 0, "issue": null },
26
+ "pathfinding": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "SAFE", "bottleneck": "compute-bound", "high_count": 1, "issue": null },
27
+ "erosion": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "WILL OOM", "bottleneck": "memory-bound", "high_count": 2, "issue": 1120, "notes": "Memory guard added. Algorithm inherently global." },
28
+ "geodesic": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "N/A", "bottleneck": "compute-bound", "high_count": 0, "issue": null },
29
+ "balanced_allocation": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "WILL OOM", "bottleneck": "memory-bound", "high_count": 3, "issue": 1114, "notes": "Lazy source extraction + memory guard. Algorithm is inherently O(N*size) - documented limitation." },
30
+ "corridor": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "SAFE", "bottleneck": "compute-bound", "high_count": 0, "issue": null },
31
+ "polygonize": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "SAFE", "bottleneck": "compute-bound", "high_count": 0, "issue": null },
32
+ "edge_detection": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "SAFE", "bottleneck": "compute-bound", "high_count": 0, "issue": null },
33
+ "multispectral": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "SAFE", "bottleneck": "compute-bound", "high_count": 0, "issue": null },
34
+ "fire": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "SAFE", "bottleneck": "compute-bound", "high_count": 0, "issue": null },
35
+ "proximity": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "WILL OOM", "bottleneck": "memory-bound", "high_count": 3, "issue": 1111, "notes": "Memory guard added to line-sweep path. KDTree path (EUCLIDEAN/MANHATTAN + scipy) already had guards. GREAT_CIRCLE unbounded path already guarded." },
36
+ "emerging_hotspots": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "SAFE", "bottleneck": "compute-bound", "high_count": 0, "issue": null },
37
+ "dasymetric": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "SAFE", "bottleneck": "memory-bound", "high_count": 0, "issue": 1126, "notes": "Memory guard added to validate_disaggregation. Core disaggregate uses map_blocks." },
38
+ "classify": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "SAFE", "bottleneck": "compute-bound", "high_count": 0, "issue": null },
39
+ "convolution": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "SAFE", "bottleneck": "compute-bound", "high_count": 0, "issue": null },
40
+ "morphology": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "SAFE", "bottleneck": "compute-bound", "high_count": 0, "issue": null },
41
+ "focal": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "SAFE", "bottleneck": "compute-bound", "high_count": 0, "issue": null },
42
+ "glcm": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "SAFE", "bottleneck": "compute-bound", "high_count": 1, "issue": null },
43
+ "surface_distance": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "SAFE", "bottleneck": "memory-bound", "high_count": 0, "issue": 1128, "notes": "Memory guard added to dd_grid allocation." },
44
+ "mahalanobis": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "SAFE", "bottleneck": "compute-bound", "high_count": 0, "issue": null, "notes": "False positive. Numpy path materializes by design. Dask path uses lazy reductions + map_blocks." },
45
+ "glcm": { "last_inspected": "2026-03-31T18:00:00Z", "oom_verdict": "SAFE", "bottleneck": "compute-bound", "high_count": 0, "issue": null, "notes": "Downgraded to MEDIUM. da.stack without rechunk is scheduling overhead, not OOM risk." }
46
+ }
47
+ }
@@ -37,7 +37,7 @@ jobs:
37
37
  run: |
38
38
  asv continuous origin/master HEAD \
39
39
  --factor $ASV_FACTOR \
40
- --bench "^(Slope|Proximity|Zonal|CostDistance|Focal)" \
40
+ --bench "^(Slope|Proximity|Zonal|CostDistance|Focal|Rescale|Standardize|Diffusion|Dasymetric)" \
41
41
  | tee bench_output.txt
42
42
 
43
43
  - name: Run benchmarks (push to master)
@@ -45,7 +45,7 @@ jobs:
45
45
  working-directory: benchmarks
46
46
  run: |
47
47
  asv run HEAD^! \
48
- --bench "^(Slope|Proximity|Zonal|CostDistance|Focal)" \
48
+ --bench "^(Slope|Proximity|Zonal|CostDistance|Focal|Rescale|Standardize|Diffusion|Dasymetric)" \
49
49
  | tee bench_output.txt
50
50
 
51
51
  - name: Check for regressions
@@ -2,6 +2,22 @@
2
2
  -----------
3
3
 
4
4
 
5
+ ### Version 0.9.6 - 2026-04-05
6
+
7
+ #### New features
8
+ - Multi-observer viewshed and line-of-sight profiles (#1145) (#1160)
9
+ - Sieve filter for removing small raster clumps (#1159)
10
+
11
+ #### Bug fixes and improvements
12
+ - Faster sieve labeling, with convergence warning (#1163)
13
+ - Dask laziness docs and regression tests (#1164) (#1165)
14
+ - Fix README feature matrix to match codebase (#1155) (#1158)
15
+ - Fix 196 test-suite warnings (#1148) (#1157)
16
+ - ASV benchmarks for 6 modules changed in v0.9.5 (#1156)
17
+ - Caveat and assumption admonitions in docs (#1134)
18
+ - Miscellaneous code sweeps (#1161)
19
+
20
+
5
21
  ### Version 0.9.5 - 2026-03-31
6
22
 
7
23
  #### Bug fixes and improvements
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xarray-spatial
3
- Version: 0.9.5
3
+ Version: 0.9.6
4
4
  Summary: xarray-based spatial analysis tools
5
5
  Home-page: https://github.com/xarray-contrib/xarray-spatial
6
6
  Author: Xarray-Spatial Developers
@@ -153,7 +153,7 @@ Dynamic: license-file
153
153
 
154
154
  -------
155
155
 
156
- Xarray-Spatial is a Python library for raster analysis built on xarray. It has 100+ functions for surface analysis, hydrology (D8, D-infinity, MFD), fire behavior, flood modeling, multispectral indices, proximity, classification, pathfinding, and interpolation. Functions dispatch automatically across four backends (NumPy, Dask, CuPy, Dask+CuPy). A built-in GeoTIFF/COG reader and writer handles raster I/O without GDAL.
156
+ Xarray-Spatial is a Python library for raster analysis built on xarray. It has 150+ functions for surface analysis, hydrology (D8, D-infinity, MFD), fire behavior, flood modeling, multispectral indices, proximity, classification, pathfinding, and interpolation. Functions dispatch automatically across four backends (NumPy, Dask, CuPy, Dask+CuPy). A built-in GeoTIFF/COG reader and writer handles raster I/O without GDAL.
157
157
 
158
158
  ### Installation
159
159
  ```bash
@@ -200,7 +200,7 @@ In the GIS world, rasters are used for representing continuous phenomena (e.g. e
200
200
  #### Supported Spatial Functions with Supported Inputs
201
201
  ✅ = native backend &nbsp;&nbsp; 🔄 = accepted (CPU fallback)
202
202
 
203
- [Classification](#classification) · [Diffusion](#diffusion) · [Focal](#focal) · [Morphological](#morphological) · [Fire](#fire) · [Multispectral](#multispectral) · [Multivariate](#multivariate) · [MCDA](#multi-criteria-decision-analysis-mcda) · [Pathfinding](#pathfinding) · [Proximity](#proximity) · [Reproject / Merge](#reproject--merge) · [Raster / Vector Conversion](#raster--vector-conversion) · [Surface](#surface) · [Hydrology](#hydrology) · [Flood](#flood) · [Interpolation](#interpolation) · [Dasymetric](#dasymetric) · [Zonal](#zonal) · [Utilities](#utilities)
203
+ [GeoTIFF / COG I/O](#geotiff--cog-io) · [Classification](#classification) · [Diffusion](#diffusion) · [Focal](#focal) · [Morphological](#morphological) · [Fire](#fire) · [Multispectral](#multispectral) · [Multivariate](#multivariate) · [MCDA](#multi-criteria-decision-analysis-mcda) · [Pathfinding](#pathfinding) · [Proximity](#proximity) · [Reproject / Merge](#reproject--merge) · [Raster / Vector Conversion](#raster--vector-conversion) · [Surface](#surface) · [Hydrology](#hydrology) · [Flood](#flood) · [Interpolation](#interpolation) · [Dasymetric](#dasymetric) · [Zonal](#zonal) · [Utilities](#utilities)
204
204
 
205
205
  -------
206
206
  ### **GeoTIFF / COG I/O**
@@ -381,7 +381,10 @@ Same-CRS tiles skip reprojection entirely and are placed by direct coordinate al
381
381
  | [TPI](xrspatial/terrain_metrics.py) | Computes Topographic Position Index (center minus mean of neighbors) | Weiss 2001 | ✅️ | ✅️ | ✅️ | ✅️ |
382
382
  | [TRI](xrspatial/terrain_metrics.py) | Computes Terrain Ruggedness Index (local elevation variation) | Riley et al. 1999 | ✅️ | ✅️ | ✅️ | ✅️ |
383
383
  | [Landforms](xrspatial/terrain_metrics.py) | Classifies terrain into 10 landform types using the Weiss (2001) TPI scheme | Weiss 2001 | ✅️ | ✅️ | ✅️ | ✅️ |
384
- | [Viewshed](xrspatial/viewshed.py) | Determines visible cells from a given observer point on terrain | GRASS GIS r.viewshed | ✅️ | ✅️ | ✅️ | ✅️ |
384
+ | [Viewshed](xrspatial/viewshed.py) | Determines visible cells from a given observer point on terrain | GRASS GIS r.viewshed | ✅️ | ✅️ | 🔄 | 🔄 |
385
+ | [Cumulative Viewshed](xrspatial/visibility.py) | Counts how many observers can see each cell | Custom | ✅️ | 🔄 | 🔄 | 🔄 |
386
+ | [Visibility Frequency](xrspatial/visibility.py) | Fraction of observers with line-of-sight to each cell | Custom | ✅️ | 🔄 | 🔄 | 🔄 |
387
+ | [Line of Sight](xrspatial/visibility.py) | Elevation profile and visibility along a point-to-point transect | Custom | ✅️ | 🔄 | 🔄 | 🔄 |
385
388
  | [Min Observable Height](xrspatial/experimental/min_observable_height.py) | Finds the minimum observer height needed to see each cell *(experimental)* | Custom | ✅️ | | | |
386
389
  | [Perlin Noise](xrspatial/perlin.py) | Generates smooth continuous random noise for procedural textures | Perlin 1985 | ✅️ | ✅️ | ✅️ | ✅️ |
387
390
  | [Worley Noise](xrspatial/worley.py) | Generates cellular (Voronoi) noise returning distance to the nearest feature point | Worley 1996 | ✅️ | ✅️ | ✅️ | ✅️ |
@@ -394,27 +397,35 @@ Same-CRS tiles skip reprojection entirely and are placed by direct coordinate al
394
397
 
395
398
  | Name | Description | Source | NumPy xr.DataArray | Dask xr.DataArray | CuPy GPU xr.DataArray | Dask GPU xr.DataArray |
396
399
  |:----------:|:------------|:------:|:----------------------:|:--------------------:|:-------------------:|:------:|
397
- | [Flow Direction (D8)](xrspatial/flow_direction.py) | Computes D8 flow direction from each cell toward the steepest downhill neighbor | O'Callaghan & Mark 1984 | ✅️ | ✅️ | ✅️ | ✅️ |
398
- | [Flow Direction (Dinf)](xrspatial/flow_direction_dinf.py) | Computes D-infinity flow direction as a continuous angle toward the steepest downslope facet | Tarboton 1997 | ✅️ | ✅️ | ✅️ | ✅️ |
399
- | [Flow Direction (MFD)](xrspatial/flow_direction_mfd.py) | Partitions flow to all downslope neighbors with an adaptive exponent (Qin et al. 2007) | Qin et al. 2007 | ✅️ | ✅️ | ✅️ | ✅️ |
400
- | [Flow Accumulation (D8)](xrspatial/flow_accumulation.py) | Counts upstream cells draining through each cell in a D8 flow direction grid | Jenson & Domingue 1988 | ✅️ | ✅️ | ✅️ | ✅️ |
401
- | [Flow Accumulation (Dinf)](xrspatial/flow_accumulation_dinf.py) | Accumulates upstream area by splitting flow proportionally between two neighbors (Tarboton 1997) | Tarboton 1997 | ✅️ | ✅️ | ✅️ | 🔄 |
402
- | [Flow Accumulation (MFD)](xrspatial/flow_accumulation_mfd.py) | Accumulates upstream area through all MFD flow paths weighted by directional fractions | Qin et al. 2007 | ✅️ | ✅️ | ✅️ | 🔄 |
403
- | [Flow Length (D8)](xrspatial/flow_length.py) | Computes D8 flow path length from each cell to outlet (downstream) or from divide (upstream) | Standard (D8 tracing) | ✅️ | ✅️ | ✅️ | 🔄 |
404
- | [Flow Length (Dinf)](xrspatial/flow_length_dinf.py) | Proportion-weighted flow path length using D-inf angle decomposition (downstream or upstream) | Tarboton 1997 | ✅️ | ✅️ | ✅️ | 🔄 |
405
- | [Flow Length (MFD)](xrspatial/flow_length_mfd.py) | Proportion-weighted flow path length using MFD fractions (downstream or upstream) | Qin et al. 2007 | ✅️ | ✅️ | ✅️ | 🔄 |
406
- | [Watershed](xrspatial/watershed.py) | Labels each cell with the pour point it drains to via D8 flow direction | Standard (D8 tracing) | ✅️ | ✅️ | ✅️ | ✅️ |
407
- | [Basins](xrspatial/watershed.py) | Delineates drainage basins by labeling each cell with its outlet ID | Standard (D8 tracing) | ✅️ | ✅️ | ✅️ | ✅️ |
408
- | [Stream Order](xrspatial/stream_order.py) | Assigns Strahler or Shreve stream order to cells in a drainage network | Strahler 1957, Shreve 1966 | ✅️ | ✅️ | ✅️ | ✅️ |
409
- | [Stream Order (Dinf)](xrspatial/stream_order_dinf.py) | Strahler/Shreve stream ordering on D-infinity flow direction grids | Tarboton 1997 | ✅️ | ✅️ | ✅️ | ✅️ |
410
- | [Stream Order (MFD)](xrspatial/stream_order_mfd.py) | Strahler/Shreve stream ordering on MFD fraction grids | Freeman 1991 | ✅️ | ✅️ | ✅️ | ✅️ |
411
- | [Stream Link](xrspatial/stream_link.py) | Assigns unique IDs to each stream segment between junctions | Standard | ✅️ | ✅️ | ✅️ | ✅️ |
412
- | [Stream Link (Dinf)](xrspatial/stream_link_dinf.py) | Stream link segmentation on D-infinity flow direction grids | Tarboton 1997 | ✅️ | ✅️ | ✅️ | ✅️ |
413
- | [Stream Link (MFD)](xrspatial/stream_link_mfd.py) | Stream link segmentation on MFD fraction grids | Freeman 1991 | ✅️ | ✅️ | ✅️ | ✅️ |
414
- | [Snap Pour Point](xrspatial/snap_pour_point.py) | Snaps pour points to the highest-accumulation cell within a search radius | Custom | ✅️ | ✅️ | ✅️ | ✅️ |
415
- | [Flow Path](xrspatial/flow_path.py) | Traces downstream flow paths from start points through a D8 direction grid | Standard (D8 tracing) | ✅️ | ✅️ | 🔄 | 🔄 |
416
- | [HAND](xrspatial/hand.py) | Computes Height Above Nearest Drainage by tracing D8 flow to the nearest stream cell | Nobre et al. 2011 | ✅️ | ✅️ | 🔄 | 🔄 |
417
- | [TWI](xrspatial/twi.py) | Topographic Wetness Index: ln(specific catchment area / tan(slope)) | Beven & Kirkby 1979 | ✅️ | ✅️ | ✅️ | 🔄 |
400
+ | [Flow Direction (D8)](xrspatial/hydro/flow_direction_d8.py) | Computes D8 flow direction from each cell toward the steepest downhill neighbor | O'Callaghan & Mark 1984 | ✅️ | ✅️ | ✅️ | ✅️ |
401
+ | [Flow Direction (Dinf)](xrspatial/hydro/flow_direction_dinf.py) | Computes D-infinity flow direction as a continuous angle toward the steepest downslope facet | Tarboton 1997 | ✅️ | ✅️ | ✅️ | ✅️ |
402
+ | [Flow Direction (MFD)](xrspatial/hydro/flow_direction_mfd.py) | Partitions flow to all downslope neighbors with an adaptive exponent (Qin et al. 2007) | Qin et al. 2007 | ✅️ | ✅️ | ✅️ | ✅️ |
403
+ | [Flow Accumulation (D8)](xrspatial/hydro/flow_accumulation_d8.py) | Counts upstream cells draining through each cell in a D8 flow direction grid | Jenson & Domingue 1988 | ✅️ | ✅️ | ✅️ | ✅️ |
404
+ | [Flow Accumulation (Dinf)](xrspatial/hydro/flow_accumulation_dinf.py) | Accumulates upstream area by splitting flow proportionally between two neighbors (Tarboton 1997) | Tarboton 1997 | ✅️ | ✅️ | ✅️ | 🔄 |
405
+ | [Flow Accumulation (MFD)](xrspatial/hydro/flow_accumulation_mfd.py) | Accumulates upstream area through all MFD flow paths weighted by directional fractions | Qin et al. 2007 | ✅️ | ✅️ | ✅️ | 🔄 |
406
+ | [Flow Length (D8)](xrspatial/hydro/flow_length_d8.py) | Computes D8 flow path length from each cell to outlet (downstream) or from divide (upstream) | Standard (D8 tracing) | ✅️ | ✅️ | ✅️ | 🔄 |
407
+ | [Flow Length (Dinf)](xrspatial/hydro/flow_length_dinf.py) | Proportion-weighted flow path length using D-inf angle decomposition (downstream or upstream) | Tarboton 1997 | ✅️ | ✅️ | ✅️ | 🔄 |
408
+ | [Flow Length (MFD)](xrspatial/hydro/flow_length_mfd.py) | Proportion-weighted flow path length using MFD fractions (downstream or upstream) | Qin et al. 2007 | ✅️ | ✅️ | ✅️ | 🔄 |
409
+ | [Fill (D8)](xrspatial/hydro/fill_d8.py) | Fills depressions in a DEM using Planchon-Darboux iterative flooding | Planchon & Darboux 2002 | ✅️ | ✅️ | ✅️ | ✅️ |
410
+ | [Sink (D8)](xrspatial/hydro/sink_d8.py) | Identifies and labels depression cells in a D8 flow direction grid | Standard (D8 tracing) | ✅️ | ✅️ | ✅️ | ✅️ |
411
+ | [Watershed (D8)](xrspatial/hydro/watershed_d8.py) | Labels each cell with the pour point it drains to via D8 flow direction | Standard (D8 tracing) | ✅️ | ✅️ | ✅️ | ✅️ |
412
+ | [Watershed (Dinf)](xrspatial/hydro/watershed_dinf.py) | Labels each cell with the pour point it drains to via D-infinity flow direction | Tarboton 1997 | ✅️ | ✅️ | 🔄 | 🔄 |
413
+ | [Watershed (MFD)](xrspatial/hydro/watershed_mfd.py) | Labels each cell with the pour point it drains to via MFD fractions | Qin et al. 2007 | ✅️ | ✅️ | 🔄 | 🔄 |
414
+ | [Basins](xrspatial/hydro/watershed_d8.py) | Delineates drainage basins by labeling each cell with its outlet ID | Standard (D8 tracing) | ✅️ | ✅️ | ✅️ | ✅️ |
415
+ | [Stream Order (D8)](xrspatial/hydro/stream_order_d8.py) | Assigns Strahler or Shreve stream order to cells in a drainage network | Strahler 1957, Shreve 1966 | ✅️ | ✅️ | ✅️ | ✅️ |
416
+ | [Stream Order (Dinf)](xrspatial/hydro/stream_order_dinf.py) | Strahler/Shreve stream ordering on D-infinity flow direction grids | Tarboton 1997 | ✅️ | ✅️ | ✅️ | ✅️ |
417
+ | [Stream Order (MFD)](xrspatial/hydro/stream_order_mfd.py) | Strahler/Shreve stream ordering on MFD fraction grids | Freeman 1991 | ✅️ | ✅️ | ✅️ | ✅️ |
418
+ | [Stream Link (D8)](xrspatial/hydro/stream_link_d8.py) | Assigns unique IDs to each stream segment between junctions | Standard | ✅️ | ✅️ | ✅️ | ✅️ |
419
+ | [Stream Link (Dinf)](xrspatial/hydro/stream_link_dinf.py) | Stream link segmentation on D-infinity flow direction grids | Tarboton 1997 | ✅️ | ✅️ | ✅️ | ✅️ |
420
+ | [Stream Link (MFD)](xrspatial/hydro/stream_link_mfd.py) | Stream link segmentation on MFD fraction grids | Freeman 1991 | ✅️ | ✅️ | ✅️ | ✅️ |
421
+ | [Snap Pour Point](xrspatial/hydro/snap_pour_point_d8.py) | Snaps pour points to the highest-accumulation cell within a search radius | Custom | ✅️ | ✅️ | ✅️ | ✅️ |
422
+ | [Flow Path (D8)](xrspatial/hydro/flow_path_d8.py) | Traces downstream flow paths from start points through a D8 direction grid | Standard (D8 tracing) | ✅️ | ✅️ | 🔄 | 🔄 |
423
+ | [Flow Path (Dinf)](xrspatial/hydro/flow_path_dinf.py) | Traces downstream flow paths using D-infinity dominant neighbor | Tarboton 1997 | ✅️ | ✅️ | 🔄 | 🔄 |
424
+ | [Flow Path (MFD)](xrspatial/hydro/flow_path_mfd.py) | Traces downstream flow paths through MFD fraction-weighted neighbors | Qin et al. 2007 | ✅️ | ✅️ | 🔄 | 🔄 |
425
+ | [HAND (D8)](xrspatial/hydro/hand_d8.py) | Computes Height Above Nearest Drainage by tracing D8 flow to the nearest stream cell | Nobre et al. 2011 | ✅️ | ✅️ | 🔄 | 🔄 |
426
+ | [HAND (Dinf)](xrspatial/hydro/hand_dinf.py) | Computes Height Above Nearest Drainage using D-infinity flow direction | Nobre et al. 2011 | ✅️ | ✅️ | 🔄 | 🔄 |
427
+ | [HAND (MFD)](xrspatial/hydro/hand_mfd.py) | Computes Height Above Nearest Drainage using MFD fractions | Nobre et al. 2011 | ✅️ | ✅️ | 🔄 | 🔄 |
428
+ | [TWI](xrspatial/hydro/twi_d8.py) | Topographic Wetness Index: ln(specific catchment area / tan(slope)) | Beven & Kirkby 1979 | ✅️ | ✅️ | ✅️ | 🔄 |
418
429
 
419
430
  -----------
420
431
 
@@ -462,6 +473,7 @@ Same-CRS tiles skip reprojection entirely and are placed by direct coordinate al
462
473
 
463
474
  | Name | Description | Source | NumPy xr.DataArray | Dask xr.DataArray | CuPy GPU xr.DataArray | Dask GPU xr.DataArray |
464
475
  |:----------:|:------------|:------:|:----------------------:|:--------------------:|:-------------------:|:------:|
476
+ | [Binary](xrspatial/classify.py) | Binarizes values by membership in a target set (1 if match, 0 otherwise) | Standard | ✅️ | ✅️ | ✅️ | ✅️ |
465
477
  | [Box Plot](xrspatial/classify.py) | Classifies values into bins based on box plot quartile boundaries | PySAL mapclassify | ✅️ |✅ | ✅ | 🔄 |
466
478
  | [Equal Interval](xrspatial/classify.py) | Divides the value range into equal-width bins | PySAL mapclassify | ✅️ |✅ | ✅ |✅ |
467
479
  | [Head/Tail Breaks](xrspatial/classify.py) | Classifies heavy-tailed distributions using recursive mean splitting | PySAL mapclassify | ✅️ |✅ | 🔄 | 🔄 |
@@ -543,6 +555,7 @@ Same-CRS tiles skip reprojection entirely and are placed by direct coordinate al
543
555
  | [Gradient](xrspatial/morphology.py) | Dilation minus erosion (edge detection) | Standard (morphology) | ✅️ | ✅️ | ✅️ | ✅️ |
544
556
  | [White Top-hat](xrspatial/morphology.py) | Original minus opening (isolate bright features) | Standard (morphology) | ✅️ | ✅️ | ✅️ | ✅️ |
545
557
  | [Black Top-hat](xrspatial/morphology.py) | Closing minus original (isolate dark features) | Standard (morphology) | ✅️ | ✅️ | ✅️ | ✅️ |
558
+ | [Sieve](xrspatial/sieve.py) | Remove small connected clumps from classified rasters | GDAL sieve | ✅️ | ✅️ | 🔄 | 🔄 |
546
559
 
547
560
  -------
548
561
 
@@ -618,7 +631,8 @@ Same-CRS tiles skip reprojection entirely and are placed by direct coordinate al
618
631
  | Name | Description | Source | NumPy xr.DataArray | Dask xr.DataArray | CuPy GPU xr.DataArray | Dask GPU xr.DataArray |
619
632
  |:----------:|:------------|:------:|:----------------------:|:--------------------:|:-------------------:|:------:|
620
633
  | [Disaggregate](xrspatial/dasymetric.py) | Redistributes zonal totals to pixels using an ancillary weight surface | Mennis 2003 | ✅️ | ✅️ | ✅️ | ✅️ |
621
- | [Pycnophylactic](xrspatial/dasymetric.py) | Tobler's pycnophylactic interpolation preserving zone totals via Laplacian smoothing | Tobler 1979 | ✅️ | | | |
634
+ | [Pycnophylactic](xrspatial/dasymetric.py) | Tobler's pycnophylactic interpolation preserving zone totals via Laplacian smoothing | Tobler 1979 | ✅️ | | 🔄 | |
635
+ | [Validate Disaggregation](xrspatial/dasymetric.py) | Checks that disaggregated pixel sums match the original zone totals | Standard | ✅️ | ✅️ | 🔄 | 🔄 |
622
636
 
623
637
  -----------
624
638
 
@@ -87,7 +87,7 @@
87
87
 
88
88
  -------
89
89
 
90
- Xarray-Spatial is a Python library for raster analysis built on xarray. It has 100+ functions for surface analysis, hydrology (D8, D-infinity, MFD), fire behavior, flood modeling, multispectral indices, proximity, classification, pathfinding, and interpolation. Functions dispatch automatically across four backends (NumPy, Dask, CuPy, Dask+CuPy). A built-in GeoTIFF/COG reader and writer handles raster I/O without GDAL.
90
+ Xarray-Spatial is a Python library for raster analysis built on xarray. It has 150+ functions for surface analysis, hydrology (D8, D-infinity, MFD), fire behavior, flood modeling, multispectral indices, proximity, classification, pathfinding, and interpolation. Functions dispatch automatically across four backends (NumPy, Dask, CuPy, Dask+CuPy). A built-in GeoTIFF/COG reader and writer handles raster I/O without GDAL.
91
91
 
92
92
  ### Installation
93
93
  ```bash
@@ -134,7 +134,7 @@ In the GIS world, rasters are used for representing continuous phenomena (e.g. e
134
134
  #### Supported Spatial Functions with Supported Inputs
135
135
  ✅ = native backend &nbsp;&nbsp; 🔄 = accepted (CPU fallback)
136
136
 
137
- [Classification](#classification) · [Diffusion](#diffusion) · [Focal](#focal) · [Morphological](#morphological) · [Fire](#fire) · [Multispectral](#multispectral) · [Multivariate](#multivariate) · [MCDA](#multi-criteria-decision-analysis-mcda) · [Pathfinding](#pathfinding) · [Proximity](#proximity) · [Reproject / Merge](#reproject--merge) · [Raster / Vector Conversion](#raster--vector-conversion) · [Surface](#surface) · [Hydrology](#hydrology) · [Flood](#flood) · [Interpolation](#interpolation) · [Dasymetric](#dasymetric) · [Zonal](#zonal) · [Utilities](#utilities)
137
+ [GeoTIFF / COG I/O](#geotiff--cog-io) · [Classification](#classification) · [Diffusion](#diffusion) · [Focal](#focal) · [Morphological](#morphological) · [Fire](#fire) · [Multispectral](#multispectral) · [Multivariate](#multivariate) · [MCDA](#multi-criteria-decision-analysis-mcda) · [Pathfinding](#pathfinding) · [Proximity](#proximity) · [Reproject / Merge](#reproject--merge) · [Raster / Vector Conversion](#raster--vector-conversion) · [Surface](#surface) · [Hydrology](#hydrology) · [Flood](#flood) · [Interpolation](#interpolation) · [Dasymetric](#dasymetric) · [Zonal](#zonal) · [Utilities](#utilities)
138
138
 
139
139
  -------
140
140
  ### **GeoTIFF / COG I/O**
@@ -315,7 +315,10 @@ Same-CRS tiles skip reprojection entirely and are placed by direct coordinate al
315
315
  | [TPI](xrspatial/terrain_metrics.py) | Computes Topographic Position Index (center minus mean of neighbors) | Weiss 2001 | ✅️ | ✅️ | ✅️ | ✅️ |
316
316
  | [TRI](xrspatial/terrain_metrics.py) | Computes Terrain Ruggedness Index (local elevation variation) | Riley et al. 1999 | ✅️ | ✅️ | ✅️ | ✅️ |
317
317
  | [Landforms](xrspatial/terrain_metrics.py) | Classifies terrain into 10 landform types using the Weiss (2001) TPI scheme | Weiss 2001 | ✅️ | ✅️ | ✅️ | ✅️ |
318
- | [Viewshed](xrspatial/viewshed.py) | Determines visible cells from a given observer point on terrain | GRASS GIS r.viewshed | ✅️ | ✅️ | ✅️ | ✅️ |
318
+ | [Viewshed](xrspatial/viewshed.py) | Determines visible cells from a given observer point on terrain | GRASS GIS r.viewshed | ✅️ | ✅️ | 🔄 | 🔄 |
319
+ | [Cumulative Viewshed](xrspatial/visibility.py) | Counts how many observers can see each cell | Custom | ✅️ | 🔄 | 🔄 | 🔄 |
320
+ | [Visibility Frequency](xrspatial/visibility.py) | Fraction of observers with line-of-sight to each cell | Custom | ✅️ | 🔄 | 🔄 | 🔄 |
321
+ | [Line of Sight](xrspatial/visibility.py) | Elevation profile and visibility along a point-to-point transect | Custom | ✅️ | 🔄 | 🔄 | 🔄 |
319
322
  | [Min Observable Height](xrspatial/experimental/min_observable_height.py) | Finds the minimum observer height needed to see each cell *(experimental)* | Custom | ✅️ | | | |
320
323
  | [Perlin Noise](xrspatial/perlin.py) | Generates smooth continuous random noise for procedural textures | Perlin 1985 | ✅️ | ✅️ | ✅️ | ✅️ |
321
324
  | [Worley Noise](xrspatial/worley.py) | Generates cellular (Voronoi) noise returning distance to the nearest feature point | Worley 1996 | ✅️ | ✅️ | ✅️ | ✅️ |
@@ -328,27 +331,35 @@ Same-CRS tiles skip reprojection entirely and are placed by direct coordinate al
328
331
 
329
332
  | Name | Description | Source | NumPy xr.DataArray | Dask xr.DataArray | CuPy GPU xr.DataArray | Dask GPU xr.DataArray |
330
333
  |:----------:|:------------|:------:|:----------------------:|:--------------------:|:-------------------:|:------:|
331
- | [Flow Direction (D8)](xrspatial/flow_direction.py) | Computes D8 flow direction from each cell toward the steepest downhill neighbor | O'Callaghan & Mark 1984 | ✅️ | ✅️ | ✅️ | ✅️ |
332
- | [Flow Direction (Dinf)](xrspatial/flow_direction_dinf.py) | Computes D-infinity flow direction as a continuous angle toward the steepest downslope facet | Tarboton 1997 | ✅️ | ✅️ | ✅️ | ✅️ |
333
- | [Flow Direction (MFD)](xrspatial/flow_direction_mfd.py) | Partitions flow to all downslope neighbors with an adaptive exponent (Qin et al. 2007) | Qin et al. 2007 | ✅️ | ✅️ | ✅️ | ✅️ |
334
- | [Flow Accumulation (D8)](xrspatial/flow_accumulation.py) | Counts upstream cells draining through each cell in a D8 flow direction grid | Jenson & Domingue 1988 | ✅️ | ✅️ | ✅️ | ✅️ |
335
- | [Flow Accumulation (Dinf)](xrspatial/flow_accumulation_dinf.py) | Accumulates upstream area by splitting flow proportionally between two neighbors (Tarboton 1997) | Tarboton 1997 | ✅️ | ✅️ | ✅️ | 🔄 |
336
- | [Flow Accumulation (MFD)](xrspatial/flow_accumulation_mfd.py) | Accumulates upstream area through all MFD flow paths weighted by directional fractions | Qin et al. 2007 | ✅️ | ✅️ | ✅️ | 🔄 |
337
- | [Flow Length (D8)](xrspatial/flow_length.py) | Computes D8 flow path length from each cell to outlet (downstream) or from divide (upstream) | Standard (D8 tracing) | ✅️ | ✅️ | ✅️ | 🔄 |
338
- | [Flow Length (Dinf)](xrspatial/flow_length_dinf.py) | Proportion-weighted flow path length using D-inf angle decomposition (downstream or upstream) | Tarboton 1997 | ✅️ | ✅️ | ✅️ | 🔄 |
339
- | [Flow Length (MFD)](xrspatial/flow_length_mfd.py) | Proportion-weighted flow path length using MFD fractions (downstream or upstream) | Qin et al. 2007 | ✅️ | ✅️ | ✅️ | 🔄 |
340
- | [Watershed](xrspatial/watershed.py) | Labels each cell with the pour point it drains to via D8 flow direction | Standard (D8 tracing) | ✅️ | ✅️ | ✅️ | ✅️ |
341
- | [Basins](xrspatial/watershed.py) | Delineates drainage basins by labeling each cell with its outlet ID | Standard (D8 tracing) | ✅️ | ✅️ | ✅️ | ✅️ |
342
- | [Stream Order](xrspatial/stream_order.py) | Assigns Strahler or Shreve stream order to cells in a drainage network | Strahler 1957, Shreve 1966 | ✅️ | ✅️ | ✅️ | ✅️ |
343
- | [Stream Order (Dinf)](xrspatial/stream_order_dinf.py) | Strahler/Shreve stream ordering on D-infinity flow direction grids | Tarboton 1997 | ✅️ | ✅️ | ✅️ | ✅️ |
344
- | [Stream Order (MFD)](xrspatial/stream_order_mfd.py) | Strahler/Shreve stream ordering on MFD fraction grids | Freeman 1991 | ✅️ | ✅️ | ✅️ | ✅️ |
345
- | [Stream Link](xrspatial/stream_link.py) | Assigns unique IDs to each stream segment between junctions | Standard | ✅️ | ✅️ | ✅️ | ✅️ |
346
- | [Stream Link (Dinf)](xrspatial/stream_link_dinf.py) | Stream link segmentation on D-infinity flow direction grids | Tarboton 1997 | ✅️ | ✅️ | ✅️ | ✅️ |
347
- | [Stream Link (MFD)](xrspatial/stream_link_mfd.py) | Stream link segmentation on MFD fraction grids | Freeman 1991 | ✅️ | ✅️ | ✅️ | ✅️ |
348
- | [Snap Pour Point](xrspatial/snap_pour_point.py) | Snaps pour points to the highest-accumulation cell within a search radius | Custom | ✅️ | ✅️ | ✅️ | ✅️ |
349
- | [Flow Path](xrspatial/flow_path.py) | Traces downstream flow paths from start points through a D8 direction grid | Standard (D8 tracing) | ✅️ | ✅️ | 🔄 | 🔄 |
350
- | [HAND](xrspatial/hand.py) | Computes Height Above Nearest Drainage by tracing D8 flow to the nearest stream cell | Nobre et al. 2011 | ✅️ | ✅️ | 🔄 | 🔄 |
351
- | [TWI](xrspatial/twi.py) | Topographic Wetness Index: ln(specific catchment area / tan(slope)) | Beven & Kirkby 1979 | ✅️ | ✅️ | ✅️ | 🔄 |
334
+ | [Flow Direction (D8)](xrspatial/hydro/flow_direction_d8.py) | Computes D8 flow direction from each cell toward the steepest downhill neighbor | O'Callaghan & Mark 1984 | ✅️ | ✅️ | ✅️ | ✅️ |
335
+ | [Flow Direction (Dinf)](xrspatial/hydro/flow_direction_dinf.py) | Computes D-infinity flow direction as a continuous angle toward the steepest downslope facet | Tarboton 1997 | ✅️ | ✅️ | ✅️ | ✅️ |
336
+ | [Flow Direction (MFD)](xrspatial/hydro/flow_direction_mfd.py) | Partitions flow to all downslope neighbors with an adaptive exponent (Qin et al. 2007) | Qin et al. 2007 | ✅️ | ✅️ | ✅️ | ✅️ |
337
+ | [Flow Accumulation (D8)](xrspatial/hydro/flow_accumulation_d8.py) | Counts upstream cells draining through each cell in a D8 flow direction grid | Jenson & Domingue 1988 | ✅️ | ✅️ | ✅️ | ✅️ |
338
+ | [Flow Accumulation (Dinf)](xrspatial/hydro/flow_accumulation_dinf.py) | Accumulates upstream area by splitting flow proportionally between two neighbors (Tarboton 1997) | Tarboton 1997 | ✅️ | ✅️ | ✅️ | 🔄 |
339
+ | [Flow Accumulation (MFD)](xrspatial/hydro/flow_accumulation_mfd.py) | Accumulates upstream area through all MFD flow paths weighted by directional fractions | Qin et al. 2007 | ✅️ | ✅️ | ✅️ | 🔄 |
340
+ | [Flow Length (D8)](xrspatial/hydro/flow_length_d8.py) | Computes D8 flow path length from each cell to outlet (downstream) or from divide (upstream) | Standard (D8 tracing) | ✅️ | ✅️ | ✅️ | 🔄 |
341
+ | [Flow Length (Dinf)](xrspatial/hydro/flow_length_dinf.py) | Proportion-weighted flow path length using D-inf angle decomposition (downstream or upstream) | Tarboton 1997 | ✅️ | ✅️ | ✅️ | 🔄 |
342
+ | [Flow Length (MFD)](xrspatial/hydro/flow_length_mfd.py) | Proportion-weighted flow path length using MFD fractions (downstream or upstream) | Qin et al. 2007 | ✅️ | ✅️ | ✅️ | 🔄 |
343
+ | [Fill (D8)](xrspatial/hydro/fill_d8.py) | Fills depressions in a DEM using Planchon-Darboux iterative flooding | Planchon & Darboux 2002 | ✅️ | ✅️ | ✅️ | ✅️ |
344
+ | [Sink (D8)](xrspatial/hydro/sink_d8.py) | Identifies and labels depression cells in a D8 flow direction grid | Standard (D8 tracing) | ✅️ | ✅️ | ✅️ | ✅️ |
345
+ | [Watershed (D8)](xrspatial/hydro/watershed_d8.py) | Labels each cell with the pour point it drains to via D8 flow direction | Standard (D8 tracing) | ✅️ | ✅️ | ✅️ | ✅️ |
346
+ | [Watershed (Dinf)](xrspatial/hydro/watershed_dinf.py) | Labels each cell with the pour point it drains to via D-infinity flow direction | Tarboton 1997 | ✅️ | ✅️ | 🔄 | 🔄 |
347
+ | [Watershed (MFD)](xrspatial/hydro/watershed_mfd.py) | Labels each cell with the pour point it drains to via MFD fractions | Qin et al. 2007 | ✅️ | ✅️ | 🔄 | 🔄 |
348
+ | [Basins](xrspatial/hydro/watershed_d8.py) | Delineates drainage basins by labeling each cell with its outlet ID | Standard (D8 tracing) | ✅️ | ✅️ | ✅️ | ✅️ |
349
+ | [Stream Order (D8)](xrspatial/hydro/stream_order_d8.py) | Assigns Strahler or Shreve stream order to cells in a drainage network | Strahler 1957, Shreve 1966 | ✅️ | ✅️ | ✅️ | ✅️ |
350
+ | [Stream Order (Dinf)](xrspatial/hydro/stream_order_dinf.py) | Strahler/Shreve stream ordering on D-infinity flow direction grids | Tarboton 1997 | ✅️ | ✅️ | ✅️ | ✅️ |
351
+ | [Stream Order (MFD)](xrspatial/hydro/stream_order_mfd.py) | Strahler/Shreve stream ordering on MFD fraction grids | Freeman 1991 | ✅️ | ✅️ | ✅️ | ✅️ |
352
+ | [Stream Link (D8)](xrspatial/hydro/stream_link_d8.py) | Assigns unique IDs to each stream segment between junctions | Standard | ✅️ | ✅️ | ✅️ | ✅️ |
353
+ | [Stream Link (Dinf)](xrspatial/hydro/stream_link_dinf.py) | Stream link segmentation on D-infinity flow direction grids | Tarboton 1997 | ✅️ | ✅️ | ✅️ | ✅️ |
354
+ | [Stream Link (MFD)](xrspatial/hydro/stream_link_mfd.py) | Stream link segmentation on MFD fraction grids | Freeman 1991 | ✅️ | ✅️ | ✅️ | ✅️ |
355
+ | [Snap Pour Point](xrspatial/hydro/snap_pour_point_d8.py) | Snaps pour points to the highest-accumulation cell within a search radius | Custom | ✅️ | ✅️ | ✅️ | ✅️ |
356
+ | [Flow Path (D8)](xrspatial/hydro/flow_path_d8.py) | Traces downstream flow paths from start points through a D8 direction grid | Standard (D8 tracing) | ✅️ | ✅️ | 🔄 | 🔄 |
357
+ | [Flow Path (Dinf)](xrspatial/hydro/flow_path_dinf.py) | Traces downstream flow paths using D-infinity dominant neighbor | Tarboton 1997 | ✅️ | ✅️ | 🔄 | 🔄 |
358
+ | [Flow Path (MFD)](xrspatial/hydro/flow_path_mfd.py) | Traces downstream flow paths through MFD fraction-weighted neighbors | Qin et al. 2007 | ✅️ | ✅️ | 🔄 | 🔄 |
359
+ | [HAND (D8)](xrspatial/hydro/hand_d8.py) | Computes Height Above Nearest Drainage by tracing D8 flow to the nearest stream cell | Nobre et al. 2011 | ✅️ | ✅️ | 🔄 | 🔄 |
360
+ | [HAND (Dinf)](xrspatial/hydro/hand_dinf.py) | Computes Height Above Nearest Drainage using D-infinity flow direction | Nobre et al. 2011 | ✅️ | ✅️ | 🔄 | 🔄 |
361
+ | [HAND (MFD)](xrspatial/hydro/hand_mfd.py) | Computes Height Above Nearest Drainage using MFD fractions | Nobre et al. 2011 | ✅️ | ✅️ | 🔄 | 🔄 |
362
+ | [TWI](xrspatial/hydro/twi_d8.py) | Topographic Wetness Index: ln(specific catchment area / tan(slope)) | Beven & Kirkby 1979 | ✅️ | ✅️ | ✅️ | 🔄 |
352
363
 
353
364
  -----------
354
365
 
@@ -396,6 +407,7 @@ Same-CRS tiles skip reprojection entirely and are placed by direct coordinate al
396
407
 
397
408
  | Name | Description | Source | NumPy xr.DataArray | Dask xr.DataArray | CuPy GPU xr.DataArray | Dask GPU xr.DataArray |
398
409
  |:----------:|:------------|:------:|:----------------------:|:--------------------:|:-------------------:|:------:|
410
+ | [Binary](xrspatial/classify.py) | Binarizes values by membership in a target set (1 if match, 0 otherwise) | Standard | ✅️ | ✅️ | ✅️ | ✅️ |
399
411
  | [Box Plot](xrspatial/classify.py) | Classifies values into bins based on box plot quartile boundaries | PySAL mapclassify | ✅️ |✅ | ✅ | 🔄 |
400
412
  | [Equal Interval](xrspatial/classify.py) | Divides the value range into equal-width bins | PySAL mapclassify | ✅️ |✅ | ✅ |✅ |
401
413
  | [Head/Tail Breaks](xrspatial/classify.py) | Classifies heavy-tailed distributions using recursive mean splitting | PySAL mapclassify | ✅️ |✅ | 🔄 | 🔄 |
@@ -477,6 +489,7 @@ Same-CRS tiles skip reprojection entirely and are placed by direct coordinate al
477
489
  | [Gradient](xrspatial/morphology.py) | Dilation minus erosion (edge detection) | Standard (morphology) | ✅️ | ✅️ | ✅️ | ✅️ |
478
490
  | [White Top-hat](xrspatial/morphology.py) | Original minus opening (isolate bright features) | Standard (morphology) | ✅️ | ✅️ | ✅️ | ✅️ |
479
491
  | [Black Top-hat](xrspatial/morphology.py) | Closing minus original (isolate dark features) | Standard (morphology) | ✅️ | ✅️ | ✅️ | ✅️ |
492
+ | [Sieve](xrspatial/sieve.py) | Remove small connected clumps from classified rasters | GDAL sieve | ✅️ | ✅️ | 🔄 | 🔄 |
480
493
 
481
494
  -------
482
495
 
@@ -552,7 +565,8 @@ Same-CRS tiles skip reprojection entirely and are placed by direct coordinate al
552
565
  | Name | Description | Source | NumPy xr.DataArray | Dask xr.DataArray | CuPy GPU xr.DataArray | Dask GPU xr.DataArray |
553
566
  |:----------:|:------------|:------:|:----------------------:|:--------------------:|:-------------------:|:------:|
554
567
  | [Disaggregate](xrspatial/dasymetric.py) | Redistributes zonal totals to pixels using an ancillary weight surface | Mennis 2003 | ✅️ | ✅️ | ✅️ | ✅️ |
555
- | [Pycnophylactic](xrspatial/dasymetric.py) | Tobler's pycnophylactic interpolation preserving zone totals via Laplacian smoothing | Tobler 1979 | ✅️ | | | |
568
+ | [Pycnophylactic](xrspatial/dasymetric.py) | Tobler's pycnophylactic interpolation preserving zone totals via Laplacian smoothing | Tobler 1979 | ✅️ | | 🔄 | |
569
+ | [Validate Disaggregation](xrspatial/dasymetric.py) | Checks that disaggregated pixel sums match the original zone totals | Standard | ✅️ | ✅️ | 🔄 | 🔄 |
556
570
 
557
571
  -----------
558
572
 
@@ -87,6 +87,17 @@ max-line-length = 100
87
87
  [tool:pytest]
88
88
  filterwarnings =
89
89
  ignore::numba.core.errors.NumbaPerformanceWarning
90
+ ignore::numba.core.errors.NumbaPendingDeprecationWarning
91
+ ignore:You will likely lose important projection information:UserWarning:pyproj
92
+ ignore:cost_distance. max_cost is infinite:UserWarning:xrspatial
93
+ ignore:surface_distance. max_distance is infinite:UserWarning:xrspatial
94
+ ignore:proximity. target coordinates exceed:ResourceWarning:xrspatial
95
+ ignore:Covariance of the parameters could not be estimated:scipy.optimize.OptimizeWarning
96
+ ignore:'oneOf' deprecated:DeprecationWarning:matplotlib
97
+ ignore:'parseString' deprecated:DeprecationWarning:matplotlib
98
+ ignore:'resetCache' deprecated:DeprecationWarning:matplotlib
99
+ ignore:'enablePackrat' deprecated:DeprecationWarning:matplotlib
100
+ ignore:'asyncio.AbstractEventLoopPolicy' is deprecated:DeprecationWarning:pytest_asyncio
90
101
 
91
102
  [isort]
92
103
  line_length = 100