xarray-spatial 0.10.4__tar.gz → 0.10.5__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.
- xarray_spatial-0.10.5/.claude/sweep-test-coverage-state.csv +17 -0
- xarray_spatial-0.10.5/.kilo/command/backend-parity.md +159 -0
- xarray_spatial-0.10.5/.kilo/command/bench.md +127 -0
- xarray_spatial-0.10.5/.kilo/command/dask-notebook.md +148 -0
- xarray_spatial-0.10.5/.kilo/command/deep-sweep.md +438 -0
- xarray_spatial-0.10.5/.kilo/command/efficiency-audit.md +274 -0
- xarray_spatial-0.10.5/.kilo/command/new-issues.md +113 -0
- xarray_spatial-0.10.5/.kilo/command/ready-to-merge.md +153 -0
- xarray_spatial-0.10.5/.kilo/command/release-major.md +146 -0
- xarray_spatial-0.10.5/.kilo/command/release-minor.md +146 -0
- xarray_spatial-0.10.5/.kilo/command/release-patch.md +146 -0
- xarray_spatial-0.10.5/.kilo/command/review-contributor-pr.md +332 -0
- xarray_spatial-0.10.5/.kilo/command/review-pr.md +249 -0
- xarray_spatial-0.10.5/.kilo/command/rockout.md +377 -0
- xarray_spatial-0.10.5/.kilo/command/sweep-accuracy.md +335 -0
- xarray_spatial-0.10.5/.kilo/command/sweep-api-consistency.md +291 -0
- xarray_spatial-0.10.5/.kilo/command/sweep-metadata.md +334 -0
- xarray_spatial-0.10.5/.kilo/command/sweep-performance.md +366 -0
- xarray_spatial-0.10.5/.kilo/command/sweep-security.md +334 -0
- xarray_spatial-0.10.5/.kilo/command/sweep-style.md +315 -0
- xarray_spatial-0.10.5/.kilo/command/sweep-test-coverage.md +293 -0
- xarray_spatial-0.10.5/.kilo/command/user-guide-notebook.md +203 -0
- xarray_spatial-0.10.5/.kilo/command/validate.md +216 -0
- xarray_spatial-0.10.5/.kilo/sweep-accuracy-state.csv +39 -0
- xarray_spatial-0.10.5/.kilo/sweep-api-consistency-state.csv +10 -0
- xarray_spatial-0.10.5/.kilo/sweep-metadata-state.csv +12 -0
- xarray_spatial-0.10.5/.kilo/sweep-performance-state.csv +49 -0
- xarray_spatial-0.10.5/.kilo/sweep-security-state.csv +49 -0
- xarray_spatial-0.10.5/.kilo/sweep-style-state.csv +14 -0
- xarray_spatial-0.10.5/.kilo/sweep-test-coverage-state.csv +17 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/CHANGELOG.md +32 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/PKG-INFO +6 -6
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/README.md +5 -5
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xarray_spatial.egg-info/PKG-INFO +6 -6
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xarray_spatial.egg-info/SOURCES.txt +32 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/_version.py +3 -3
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/accessor.py +92 -34
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/contour.py +47 -1
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/__init__.py +261 -124
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/_attrs.py +168 -22
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/_backends/_gpu_helpers.py +7 -7
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/_backends/dask.py +83 -48
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/_backends/gpu.py +57 -56
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/_backends/vrt.py +133 -71
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/_cog_http.py +3 -3
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/_coords.py +2 -2
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/_crs.py +3 -3
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/_decode.py +1 -1
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/_errors.py +23 -1
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/_geotags.py +43 -8
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/_gpu_decode.py +11 -2
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/_reader.py +6 -6
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/_runtime.py +17 -9
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/_validation.py +40 -25
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/_vrt.py +57 -6
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/_vrt_validation.py +4 -4
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/_writer.py +38 -24
- xarray_spatial-0.10.5/xrspatial/geotiff/_writers/__init__.py +7 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/_writers/eager.py +171 -153
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/_writers/gpu.py +34 -34
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/_writers/vrt.py +49 -52
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/attrs/test_contract.py +3 -3
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/test_dask_numpy.py +3 -5
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/test_eager_numpy.py +2 -4
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/test_fsspec.py +2 -4
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/test_vrt.py +5 -5
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/gpu/test_codec.py +52 -49
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/gpu/test_kernels_and_kwargs.py +251 -240
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/gpu/test_reader.py +100 -99
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/gpu/test_writer.py +196 -68
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/integration/test_dask_pipeline.py +36 -36
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/integration/test_gpu_pipeline.py +4 -4
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/integration/test_http_sources.py +23 -23
- xarray_spatial-0.10.5/xrspatial/geotiff/tests/parity/test_api_consolidation.py +130 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/parity/test_backend_matrix.py +14 -13
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/parity/test_finalization.py +67 -67
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/parity/test_pixel_equality.py +34 -34
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/parity/test_reference.py +14 -14
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/parity/test_signature_contract.py +22 -21
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/read/test_basic.py +19 -18
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/read/test_coords.py +2 -2
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/read/test_crs.py +1 -1
- xarray_spatial-0.10.5/xrspatial/geotiff/tests/read/test_degenerate_shapes.py +150 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/read/test_dtypes.py +22 -22
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/read/test_endianness.py +5 -5
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/read/test_georef.py +11 -11
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/read/test_nodata.py +177 -121
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/read/test_overview.py +45 -45
- xarray_spatial-0.10.5/xrspatial/geotiff/tests/read/test_rioxarray_compat_2961.py +494 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/read/test_tiling.py +9 -8
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/release_gates/test_features.py +49 -44
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/release_gates/test_stable_features.py +23 -11
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/test_edge_cases.py +2 -2
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/test_polish.py +16 -16
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/test_round_trip.py +6 -6
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/test_security.py +2 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/test_stable_only_bbox_ordering_2869.py +2 -3
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/test_stable_only_remote_2821.py +10 -10
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/unit/test_codec_roundtrip.py +43 -9
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/unit/test_geotags.py +0 -6
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/unit/test_ifd.py +3 -3
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/unit/test_input_validation.py +59 -59
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/unit/test_metadata.py +19 -19
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/unit/test_photometric.py +22 -22
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/unit/test_predictor.py +4 -4
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/unit/test_safe_xml.py +1 -1
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/unit/test_signatures.py +218 -164
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/vrt/test_dtype_conversion.py +53 -53
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/vrt/test_metadata.py +187 -95
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/vrt/test_missing_sources.py +194 -44
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/vrt/test_parity.py +48 -47
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/vrt/test_source_opt_ins_2672.py +8 -8
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/vrt/test_validation.py +32 -32
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/vrt/test_window.py +36 -36
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/write/test_basic.py +280 -92
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/write/test_bigtiff.py +3 -3
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/write/test_cog.py +10 -10
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/write/test_crs.py +2 -2
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/write/test_nodata.py +58 -33
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/write/test_overview.py +12 -12
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/write/test_streaming.py +1 -1
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/write/test_vrt_atomic.py +28 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_accessor.py +102 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_contour.py +120 -0
- xarray_spatial-0.10.4/.claude/sweep-test-coverage-state.csv +0 -91
- xarray_spatial-0.10.4/xrspatial/geotiff/_writers/__init__.py +0 -7
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.claude/commands/backend-parity.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.claude/commands/bench.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.claude/commands/dask-notebook.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.claude/commands/deep-sweep.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.claude/commands/efficiency-audit.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.claude/commands/new-issues.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.claude/commands/ready-to-merge.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.claude/commands/release-major.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.claude/commands/release-minor.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.claude/commands/release-patch.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.claude/commands/review-contributor-pr.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.claude/commands/review-pr.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.claude/commands/rockout.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.claude/commands/sweep-accuracy.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.claude/commands/sweep-api-consistency.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.claude/commands/sweep-metadata.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.claude/commands/sweep-performance.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.claude/commands/sweep-security.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.claude/commands/sweep-style.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.claude/commands/sweep-test-coverage.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.claude/commands/user-guide-notebook.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.claude/commands/validate.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.claude/sweep-accuracy-state.csv +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.claude/sweep-api-consistency-state.csv +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.claude/sweep-metadata-state.csv +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.claude/sweep-performance-state.csv +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.claude/sweep-security-state.csv +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.claude/sweep-style-state.csv +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.codex/commands/backend-parity.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.codex/commands/bench.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.codex/commands/dask-notebook.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.codex/commands/deep-sweep.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.codex/commands/efficiency-audit.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.codex/commands/new-issues.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.codex/commands/ready-to-merge.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.codex/commands/release-major.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.codex/commands/release-minor.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.codex/commands/release-patch.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.codex/commands/review-contributor-pr.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.codex/commands/review-pr.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.codex/commands/rockout.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.codex/commands/sweep-accuracy.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.codex/commands/sweep-api-consistency.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.codex/commands/sweep-metadata.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.codex/commands/sweep-performance.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.codex/commands/sweep-security.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.codex/commands/sweep-style.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.codex/commands/sweep-test-coverage.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.codex/commands/user-guide-notebook.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.codex/commands/validate.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.codex/sweep-accuracy-state.csv +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.codex/sweep-api-consistency-state.csv +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.codex/sweep-metadata-state.csv +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.codex/sweep-performance-state.csv +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.codex/sweep-security-state.csv +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.codex/sweep-style-state.csv +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.codex/sweep-test-coverage-state.csv +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.efficiency-audit-baseline.json +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.efficiency-audit-baseline.prev.json +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.gitattributes +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.github/ISSUE_TEMPLATE/feature-proposal.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.github/ISSUE_TEMPLATE/new-contributor.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.github/labeler.yml +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.github/pull_request_template.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.github/workflows/benchmarks.yml +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.github/workflows/copilot-review.yml +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.github/workflows/labeler.yml +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.github/workflows/pypi-publish.yml +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.github/workflows/test-cog-validator.yml +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.github/workflows/test-geotiff-corpus.yml +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.github/workflows/test.yml +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.github/workflows/welcome-contributor.yml +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.gitignore +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/.readthedocs.yml +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/AI_POLICY.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/CLAUDE.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/CODE_OF_CONDUCT.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/CONTRIBUTING.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/Citation-styles.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/LICENSE.txt +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/MANIFEST.in +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/RELEASE.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/codecov.yml +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/pyproject.toml +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/setup.cfg +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/setup.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xarray_spatial.egg-info/dependency_links.txt +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xarray_spatial.egg-info/entry_points.txt +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xarray_spatial.egg-info/not-zip-safe +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xarray_spatial.egg-info/requires.txt +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xarray_spatial.egg-info/top_level.txt +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/__init__.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/__main__.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/analytics.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/aspect.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/balanced_allocation.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/bilateral.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/bump.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/classify.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/convolution.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/corridor.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/cost_distance.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/curvature.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/dasymetric.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/dataset_support.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/datasets/__init__.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/datasets/sentinel-2/blue_band.nc +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/datasets/sentinel-2/green_band.nc +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/datasets/sentinel-2/nir_band.nc +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/datasets/sentinel-2/red_band.nc +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/datasets/sentinel-2/swir1_band.nc +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/datasets/sentinel-2/swir2_band.nc +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/diagnostics.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/diffusion.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/edge_detection.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/emerging_hotspots.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/erosion.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/experimental/__init__.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/experimental/min_observable_height.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/fire.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/flood.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/focal.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geodesic.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/_backends/__init__.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/_compression.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/_dtypes.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/_encode.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/_header.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/_layout.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/_nodata.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/_overview.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/_overview_kernels.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/_safe_xml.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/_sidecar.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/_sources.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/_write_layout.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/__init__.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/_geotiff_fixtures.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/_helpers/__init__.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/_helpers/markers.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/_helpers/tiff_builders.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/_helpers/tiff_surgery.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/attrs/__init__.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/bench_vs_rioxarray.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/conftest.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/README.md +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/__init__.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/_marks.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/_oracle.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/fixtures/cog_internal_overview_uint16.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/fixtures/compression_deflate_predictor2_uint16.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/fixtures/compression_deflate_predictor3_float32.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/fixtures/compression_jpeg_uint8_ycbcr.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/fixtures/compression_lerc_float32.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/fixtures/compression_lzw_predictor2_int16.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/fixtures/compression_none_uint8.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/fixtures/crs_citation_only.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/fixtures/crs_epsg_3857.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/fixtures/crs_wkt_utm10n.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/fixtures/dtype_float32.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/fixtures/dtype_float64.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/fixtures/dtype_int16.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/fixtures/dtype_int32.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/fixtures/dtype_int8.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/fixtures/dtype_uint16.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/fixtures/dtype_uint32.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/fixtures/dtype_uint8.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/fixtures/extra_tags_uint16.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/fixtures/gdal_metadata_namespaced_uint16.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/fixtures/nodata_int_sentinel_uint16.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/fixtures/nodata_miniswhite_uint8.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/fixtures/nodata_nan_float32.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/fixtures/overview_external_ovr_uint16.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/fixtures/overview_external_ovr_uint16.tif.ovr +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/fixtures/overview_internal_uint16.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/fixtures/planar_separate_uint8_rgb.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/fixtures/sparse_tiled_uint16.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/fixtures/stripped_be_uint16.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/fixtures/stripped_le_uint16.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/fixtures/tiled_be_uint16.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/fixtures/tiled_le_uint16.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/generate.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/manifest.yaml +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/test_compression.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/test_corpus_determinism.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/test_dask_gpu.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/test_dtype_variants.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/test_gpu.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/test_http.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/test_layout_endian.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/test_manifest.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/test_metadata_tags.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/test_nodata_sentinels.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/test_oracle.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/golden_corpus/test_overview_cog.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/gpu/__init__.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/integration/__init__.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/integration/test_sidecar.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/parity/__init__.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/read/__init__.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/read/test_bbox_2555.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/read/test_bbox_vrt_2668.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/read/test_compression.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/read/test_streaming.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/release_gates/__init__.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/test_fuzz_hypothesis.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/test_shutdown_cleanup_2486.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/unit/__init__.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/unit/test_compression.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/unit/test_header.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/vrt/__init__.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/geotiff/tests/write/__init__.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/glcm.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/gpu_rtx/__init__.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/gpu_rtx/_memory.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/gpu_rtx/cuda_utils.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/gpu_rtx/hillshade.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/gpu_rtx/mesh_utils.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/gpu_rtx/viewshed.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hillshade.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/__init__.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/_boundary_store.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/basin_d8.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/fill_d8.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/flow_accumulation_d8.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/flow_accumulation_dinf.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/flow_accumulation_mfd.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/flow_direction_d8.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/flow_direction_dinf.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/flow_direction_mfd.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/flow_length_d8.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/flow_length_dinf.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/flow_length_mfd.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/flow_path_d8.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/flow_path_dinf.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/flow_path_mfd.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/hand_d8.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/hand_dinf.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/hand_mfd.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/sink_d8.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/snap_pour_point_d8.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/stream_link_d8.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/stream_link_dinf.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/stream_link_mfd.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/stream_order_d8.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/stream_order_dinf.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/stream_order_mfd.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/__init__.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/conftest.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/test_basin_d8.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/test_fill_d8.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/test_flow_accumulation_d8.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/test_flow_accumulation_dinf.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/test_flow_accumulation_mfd.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/test_flow_direction_d8.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/test_flow_direction_dinf.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/test_flow_direction_mfd.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/test_flow_length_d8.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/test_flow_length_dinf.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/test_flow_length_mfd.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/test_flow_path_d8.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/test_flow_path_dinf.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/test_flow_path_mfd.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/test_hand_d8.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/test_hand_dinf.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/test_hand_mfd.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/test_sink_d8.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/test_snap_pour_point_d8.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/test_stream_link_d8.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/test_stream_link_dinf.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/test_stream_link_mfd.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/test_stream_order_d8.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/test_stream_order_dinf.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/test_stream_order_mfd.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/test_twi_d8.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/test_validate_cellsize.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/test_validate_mfd_companion_shape.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/test_validate_mfd_fractions.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/test_validate_scalar_params.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/test_validate_secondary_args.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/test_watershed_d8.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/test_watershed_dinf.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/tests/test_watershed_mfd.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/twi_d8.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/watershed_d8.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/watershed_dinf.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/hydro/watershed_mfd.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/interpolate/__init__.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/interpolate/_idw.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/interpolate/_kriging.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/interpolate/_spline.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/interpolate/_validation.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/kde.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/mahalanobis.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/mcda/__init__.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/mcda/combine.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/mcda/constrain.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/mcda/sensitivity.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/mcda/standardize.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/mcda/weights.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/morphology.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/multispectral.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/normalize.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/pathfinding.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/perlin.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/polygon_clip.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/polygonize.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/preview.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/proximity.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/rasterize.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/reproject/__init__.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/reproject/_crs_utils.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/reproject/_datum_grids.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/reproject/_grid.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/reproject/_interpolate.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/reproject/_itrf.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/reproject/_lite_crs.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/reproject/_merge.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/reproject/_projections.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/reproject/_projections_cuda.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/reproject/_transform.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/reproject/_vertical.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/reproject/grids/at_bev_AT_GIS_GRID.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/reproject/grids/au_icsm_A66_National_13_09_01.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/reproject/grids/be_ign_bd72lb72_etrs89lb08.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/reproject/grids/ch_swisstopo_CHENyx06_ETRS.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/reproject/grids/de_adv_BETA2007.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/reproject/grids/es_ign_SPED2ETV2.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/reproject/grids/nl_nsgi_rdcorr2018.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/reproject/grids/pt_dgt_D73_ETRS89_geo.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/reproject/grids/uk_os_OSTN15_NTv2_OSGBtoETRS.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/reproject/grids/us_nga_egm96_15.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/reproject/grids/us_noaa_alaska.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/reproject/grids/us_noaa_conus.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/reproject/grids/us_noaa_hawaii.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/reproject/grids/us_noaa_nadcon5_nad27_nad83_1986_conus.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/reproject/grids/us_noaa_prvi.tif +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/resample.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/sieve.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/sky_view_factor.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/slope.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/surface_distance.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/terrain.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/terrain_metrics.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/__init__.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/bench_reproject_vs_rioxarray.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/conftest.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/general_checks.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_analytics.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_aspect.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_balanced_allocation.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_bilateral.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_bump.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_classify.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_convolution.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_corridor.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_cost_distance.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_curvature.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_dask_cupy_gaps.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_dask_laziness.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_dasymetric.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_dataset_support.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_datasets.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_diagnostics.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_diffusion.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_edge_detection.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_emerging_hotspots.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_erosion.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_fire.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_flood.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_focal.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_fused_overlap.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_geodesic_aspect.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_geodesic_slope.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_glcm.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_glcm_metric_order.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_gpu_rtx_has_rtx.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_gpu_rtx_memory.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_gpu_rtx_mesh.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_hillshade.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_hypsometric_integral.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_interpolation.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_kde.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_lite_crs.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_mahalanobis.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_mcda.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_min_observable_height.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_morphology.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_morphology_derived.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_multi_overlap.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_multispectral.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_normalize.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_northness_eastness.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_optional_shapely.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_pathfinding.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_perlin.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_polygon_clip.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_polygonize.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_polygonize_atol_rtol_backend_coverage_2026_05_27.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_polygonize_coverage_2026_05_19.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_polygonize_dask_row_batch_2608.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_polygonize_issue_2172.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_polygonize_issue_2583.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_polygonize_issue_2606.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_polygonize_issue_2666.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_polygonize_mask_dtype_coverage_2026_05_29.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_preview.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_proximity.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_rasterize.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_rasterize_accuracy.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_rasterize_all_touched_supercover_2169.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_rasterize_coverage_2026_05_17.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_rasterize_coverage_2026_05_21.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_rasterize_coverage_2026_05_27.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_rasterize_coverage_2026_05_29.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_rasterize_descending_x_2568.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_rasterize_gpu_race_2167.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_rasterize_nan_int_fill_2504.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_rasterize_nan_propagation_2255.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_rasterize_partial_dims_2569.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_rasterize_props_hoist_2506.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_rasterize_resolution_exact_2573.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_rasterize_resolution_validation_2576.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_rasterize_signature_annot_2250.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_rasterize_signed_step_2566.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_rasterize_tile_props_slice_2020.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_rechunk_no_shuffle.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_reproject.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_reproject_coverage_2026_05_27.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_reproject_cupy_gate_2564.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_resample.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_resample_coverage_2026_05_27.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_resample_cupy_agg_fallback_2615.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_resample_input_validation_2574.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_resample_irregular_coords_2663.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_resample_signature_annot_2544.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_sieve.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_sieve_gdal_parity.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_sky_view_factor.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_slope.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_surface_distance.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_terrain.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_terrain_metrics.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_utils.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_validation.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_viewshed.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_visibility.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_zonal.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/tests/test_zonal_backend_coverage_2026_05_27.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/utils.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/viewshed.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/visibility.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/worley.py +0 -0
- {xarray_spatial-0.10.4 → xarray_spatial-0.10.5}/xrspatial/zonal.py +0 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module,last_inspected,issue,severity_max,categories_found,notes
|
|
2
|
+
aspect,2026-06-02,2742;2829,HIGH,3;4,"#2742: degenerate shapes (1x1/Nx1/1xN) + geodesic boundary modes; tests added all 4 backends, GPU-validated. #2829: northness/eastness method='geodesic' branch was untested (planar only); added correctness (diagonal surface where planar!=geodesic) + 4-backend parity, GPU-validated. all-NaN planar/geodesic returns all-NaN (correct). Inf input -> silent -1/flat on spike cell: possible source bug, out of scope for test-only sweep, not filed. Dedup: rectangular-cell oracle #2781 + cell-size #2780 already merged, not duplicated."
|
|
3
|
+
contour,2026-05-29,2704;2710,HIGH,2;5,"Pass 1 (2026-05-29): added TestInfHandling, TestCRSPropagation, TestNonDefaultDims to test_contour.py (5 passed + 2 strict-xfail on a CUDA host; full file 29 passed, 2 xfailed). All four backends (numpy / cupy / dask+numpy / dask+cupy) were already exercised with cross-backend segment-equality assertions (TestBackendEquivalence), and ran green locally on the CUDA host -- Cat 1 well covered, no new backend tests needed. Cat 2 HIGH (Inf): the marching-squares NaN-skip guard at contour.py:67 uses x!=x which does not catch infinity, so a finite level near a +/-inf corner leaks NaN coordinates into the output. Filed source bug #2704 and added two xfail(strict=True) tests pinning it (+inf and -inf) plus test_inf_far_level_no_crossing covering the safe path where the inf quad classifies as all-above (idx 15) and is skipped before any interpolation. Cat 5 MEDIUM: no test asserted gdf.crs propagation from agg.attrs['crs'] (contour.py:660) -- added test_geopandas_crs_from_attrs (to_epsg()==5070) + test_geopandas_no_crs_attr. Cat 5 MEDIUM: the index-to-coordinate transform (contour.py:644-654) reads agg.dims[0]/[1] coords but no test used non-y/x dims -- added test_lat_lon_dims_coordinate_transform + test_lat_lon_matches_yx_equivalent. PR #2710 (test-only, source untouched). LOW (documented, not fixed): non-square cellsize (cellsize_x != cellsize_y) never exercised -- all tests use res (0.5,0.5); levels=None early-return on all-NaN/all-equal works (probed) but only the explicit-levels all-NaN path is asserted. Cat 3 1x1/Nx1/1xN are rejected by the >=2x2 validation guard and that rejection is already tested (test_too_small, test_minimum_raster)."
|
|
4
|
+
focal,2026-05-29,2732,HIGH,1,"Pass (2026-05-29): added test_hotspots_dask_cupy to test_focal.py closing Cat 1 HIGH backend-coverage gap. hotspots() registers dask_cupy_func=_hotspots_dask_cupy (focal.py L1414) but no test invoked it, while mean/apply/focal_stats each have a dedicated dask+cupy test. New test compares dask+cupy vs numpy on chunk interior (matches test_apply_dask_cupy/test_focal_stats_dask_cupy style). RUN on CUDA host: passes; spy confirmed routing through _hotspots_dask_cupy; path matches numpy exactly so no source fix needed. LOW (documented not fixed): Inf/-Inf inputs untested across focal funcs; 1x1 raster not explicitly tested for mean/apply/hotspots (focal_stats 1x1 covered by test_variety_single_cell). Issue #2732."
|
|
5
|
+
geotiff,2026-06-06,2984,MEDIUM,1;3,"Pass 20 (2026-06-06, deep-sweep test-coverage): filed #2984 and added test_writer.py degenerate-shape GPU write coverage (Cat 1 backend + Cat 3 geometric edge). Read side already covers 1x1/1xN/Nx1 on all 4 backends (read/test_degenerate_shapes.py) and the dask streaming writer covers them (integration/test_dask_pipeline.py); the GPU write path was the gap (smallest shape in gpu/test_writer.py was 2x2). Added test_write_geotiff_gpu_degenerate_round_trip (1x1/1xN/Nx1 x none/deflate) + test_to_geotiff_dask_gpu_degenerate_round_trip (dask+cupy via gpu=True). 9 new tests RUN+passing on a CUDA host. Verified paths work first (not a source bug); transform supplied explicitly via attrs. Wider tree audit (~92k test LOC vs ~33k source): rioxarray-compat (#2961), bbox NaN/Inf/rotated, 8-backend parity matrix, codec round-trips already covered -- no other real gaps. | Pass (2026-06-05 test-coverage sweep): mature module (~31k src / ~124k test LOC, 9 test dirs). Exhaustive existing coverage -- parity/test_backend_matrix.py runs all 4 backends + VRT + HTTP + fsspec; golden_corpus full-manifest parity; read_rioxarray_compat_2961 covers masked/mask_and_scale/parse_coordinates/default_name on eager+dask. Cat1+Cat3 gap found (MEDIUM): degenerate-shape READS (1x1/1xN/Nx1) were tested only on the eager numpy reader (test_edge_cases.py) and the dask streaming WRITE path (integration/test_dask_pipeline.py); the windowed dask READ (chunks=) and GPU READ (gpu=True) on a single-pixel dimension were never exercised (smallest dask-read source in read/test_tiling is 8x8/2x32, parity fixtures 32x32/64x64). Probed: paths work today, no source bug -- pure coverage gap. Added read/test_degenerate_shapes.py (18 tests): dask read x{chunks 1,3,4} x{1x1,1xN,Nx1} + coord/transform/crs parity + GPU read + dask+gpu read. GPU cells RAN and PASSED on this CUDA host (grid-size-1 launch validated). Fixture supplies explicit attrs['transform'] (writer cannot infer pixel size from a 1-element coord axis). Branch deep-sweep-test-coverage-geotiff-degenerate-read-01. NOTE: pre-existing union-merge CRLF/duplicate-record corruption in this CSV left untouched -- appended one clean record; DictReader last-write-wins picks this one."
|
|
6
|
+
idw,2026-06-04,2919,HIGH,1;4,"cupy/dask+cupy backends untested (Cat1 HIGH); GPU k-reject error path untested (Cat4 MED). Added 6 GPU tests, validated on CUDA host. Inf-in-points (Cat2) and attrs-preservation (Cat5) are LOW, documented not fixed."
|
|
7
|
+
interpolate-kriging,2026-06-04,2920;2921,HIGH,1;2;3;4;5,"Single public fn kriging(); all 4 backends already had cross-backend parity tests (numpy/cupy/dask+numpy/dask+cupy) incl. cupy & dask+cupy variance -- ran green on CUDA host. Gaps closed (test-only, #2921): Cat1 dask+numpy return_variance branch (_chunk_var) was untested -> added test_dask_return_variance_matches_numpy (atol=1e-12, var ~1e-14). Cat4 nlags only default(15) tested -> added non-default nlags=5 + invalid paths (nlags=0/-1 ValueError, nlags=2.5 TypeError). Cat2/3 two-point <3-lag-bins UserWarning branch -> test_two_point_warns_few_lag_bins. Cat2 all-NaN kriging input -> test_kriging_all_nan_points (only idw covered before). Cat5 output metadata (coords/dims/attrs/name) untested -> added test_output_metadata. Single-point kriging CRASHES (zero-size array reduction in _experimental_variogram, N=1) -- real source bug filed #2920; added xfail(strict, raises=ValueError) test_single_point documenting expected graceful behavior; source fix left to #2920 (test-only PR). LOW/not filed: singular-matrix K_inv-is-None all-NaN branch is defensive and unreachable via public API. GPU-validated."
|
|
8
|
+
interpolate_spline,2026-06-04,,HIGH,1;3;5,scope=spline-only; cupy+dask_cupy spline backends untested (_tps_cuda_kernel) | n==2 affine branch + metadata untested | added 4 tests to TestSpline all pass on CUDA host | issue-create denied by classifier no GH issue
|
|
9
|
+
module,last_inspected,issue,severity_max,categories_found,notes
|
|
10
|
+
polygonize,2026-05-29,2623,MEDIUM,4,"Pass 3 (2026-05-29): added test_polygonize_mask_dtype_coverage_2026_05_29.py (41 passed, 8 xfailed on a CUDA host). Closes Cat 4 MEDIUM parameter-coverage gap: mask= is documented to accept bool/integer/float values but every prior test passed only a bool mask. Integer masks (int32/int64) now pinned against the same-backend bool-mask output on all four backends x both raster dtypes x connectivity 4/8; float-mask-on-integer-raster also pinned. Each backend is compared to its OWN bool reference to isolate mask-dtype from the unrelated numpy-vs-dask hole-vs-single-ring representation difference. Mutation (drop the not-mask[ij] exclusion in _calculate_regions) flips 11 tests red incl. the pixel-exclusion sanity anchor; clean md5 restore. Surfaced source bug #2623: a float-dtype mask on a float-dtype raster raises TypeError at polygonize.py:918 (mask & nan_mask; bitwise_and undefined for float&bool; cupy/dask route floats through _polygonize_numpy so they crash too; int masks coerce fine). 8 float-mask cases marked xfail(strict, raises=TypeError) referencing #2623. Test-only; source untouched. | Pass 2 (2026-05-27): added test_polygonize_atol_rtol_backend_coverage_2026_05_27.py with 15 tests, all passing on a CUDA host. Closes Cat 4 MEDIUM parameter-coverage gap on atol/rtol forwarding through the cupy and dask+cupy backends. atol/rtol were exposed by #2173 / #2194 and thread through _polygonize_cupy (polygonize.py:808) and _polygonize_dask (polygonize.py:1719); the dask path further plumbs them into dask.delayed(_polygonize_chunk)(...) at lines 1748-1754 and into _bucket_key_for_value for cross-chunk merge bucketing at lines 1757-1758. Pre-existing tests covered non-default atol/rtol only on numpy and dask+numpy. The cupy and dask+cupy dispatchers were untested -- a regression dropping the kwargs there would silently change the float polygon count and would not be caught. Same dispatcher-silently-drops-kwarg pattern fixed by #1561 / #1605 / #1685 / #1810 / #1974 on adjacent GeoTIFF surfaces. 15 tests: cupy strict-equality + default-tolerance pin on _REPRO_2173, dask+cupy strict-equality single-chunk + multi-chunk (engages cross-chunk merge bucket) + default-tolerance multi-chunk pin, cupy intermediate-atol small/large pair, dask+cupy intermediate-atol single/multi-chunk small + single-chunk large, cupy integer atol-ignored matrix, dask+cupy integer atol-ignored single-chunk + multi-chunk, cupy rtol-only large/small matrix. Mutation against _polygonize_cupy float branch (drop atol/rtol kwargs in the _polygonize_numpy forward call at polygonize.py:823-825) flips 3 of 5 cupy tests red; mutation against dask.delayed(_polygonize_chunk)(...) at polygonize.py:1748-1754 (drop atol, rtol args) flips 2 of 6 dask+cupy tests red. Confirmed clean restore via md5sum. Source untouched. Filed issue #2537 (test-only). Cat 4 MEDIUM (parameter coverage on cupy + dask+cupy atol/rtol forwarding). Pass 1 (2026-05-19): added test_polygonize_coverage_2026_05_19.py with 58 tests, all passing on a CUDA host. Closes Cat 3 HIGH 1x1 / Nx1 single-column geometric gaps (Nx1 exercises the nx==1 padding path at polygonize.py:565 and the cupy nx==1 numpy-fallback at polygonize.py:671), Cat 3 MEDIUM 1xN single-row and all-equal-value rasters on all four backends. Closes Cat 2 HIGH NaN parity for cupy + dask+cupy (numpy/dask were already covered by test_polygonize_nan_pixels_excluded*), Cat 2 MEDIUM all-NaN raster on all four backends, Cat 2 HIGH +/-Inf pins on all four backends. Filed source-bug issue #2155: numpy/dask/dask+cupy backends silently absorb Inf cells into adjacent finite polygons because _is_close reduces abs(inf-inf) to nan; cupy backend handles Inf correctly. Pins lock the asymmetric behaviour so the fix is visible. Closes Cat 1 MEDIUM simplify_tolerance + mask= parity gaps on dask+cupy backend (numpy/cupy/dask were already covered). Closes Cat 4 MEDIUM column_name non-default value across geopandas/spatialpandas/geojson return types and Cat 4 MEDIUM validation error paths (bad connectivity, bad transform length, mask shape mismatch, mask underlying-type mismatch). Cat 5 N/A: polygonize returns lists/dataframes, not a DataArray with attrs to propagate."
|
|
11
|
+
proximity,2026-06-02,2692,HIGH,1;2;3;4;5,"Pass 2 (2026-06-02): added 18 tests to test_proximity.py closing the two MEDIUM gaps Pass 1 left open, all RUN and passing on a CUDA host across numpy/cupy/dask+numpy/dask+cupy (15 cross-backend + 3 error-path). Source untouched. Cat 4 MEDIUM (error path): _process raises ValueError when raster.dims != (y, x) (proximity.py:1043) but no test exercised the swapped x/y guard; test_wrong_dim_order_raises pins it for proximity/allocation/direction. Cat 2 MEDIUM (all-NaN input): Pass 1 noted all-NaN/all-zero on eager numpy+cupy was unpinned; test_all_nan_raster_all_nan_output pins an all-NaN 6x6 raster -> all-NaN float32 output on all four backends x three functions. Remaining LOW (documented): invalid distance_metric string silently falls back to EUCLIDEAN (proximity.py:1049-1051). || PREVIOUS: Pass 1 (2026-05-29): added 65 tests to test_proximity.py closing three coverage gaps, all RUN and passing on a CUDA host (numpy/cupy/dask+numpy/dask+cupy). Issue #2692, PR opened. Source untouched. Cat 3 HIGH: degenerate raster shapes (1x1 single pixel, Nx1 column strip, 1xN row strip) had zero coverage for proximity/allocation/direction on any backend; they stress the line-sweep kernel boundaries (_process_proximity_line) and the GPU brute-force kernel grid sizing (_proximity_cuda_kernel via cuda_args). Pinned all three shapes x three functions x four backends against hand-checked expected values; mutation of a pinned direction expectation confirms teeth. Cat 1/4 HIGH: allocation and direction only ran EUCLIDEAN across backends; MANHATTAN and GREAT_CIRCLE were cross-backend-tested for proximity only. Pinned both metrics x two functions x four backends against the numpy baseline (all match). Cat 5 MEDIUM: no test set non-empty res/crs attrs so the attrs-preservation assertion in general_output_checks compared two empty dicts. proximity reads attrs['res'] via get_dataarray_resolution for bounded-dask chunk padding, so added attrs round-trip tests on four backends plus a bounded-dask test where a res attr matching the coordinate spacing must equal the numpy baseline. A res attr that lies about the spacing mis-sizes the map_overlap depth; source fragility, not a test gap, left for a separate accuracy issue. Cat 2 (NaN/Inf input) already covered by the shared test_raster fixture (embeds np.inf and np.nan, runs on four backends). Remaining LOW: all-NaN / all-zero input on eager numpy+cupy not directly pinned."
|
|
12
|
+
rasterize,2026-05-29,2614,MEDIUM,4,"Pass 4 (2026-05-29): added test_rasterize_coverage_2026_05_29.py with 11 tests, all passing (pure-Python validation paths, no CUDA needed); filed issue #2614 and opened a test-only PR. Closes Cat 4 MEDIUM error-path gaps that all three prior passes left untouched. (1) Partial width/height: the (width is None) != (height is None) guard in rasterize() raises ValueError naming the given and missing dimension, documented in the docstring, but neither the width-only nor height-only branch had a test; pin both directions plus the width-only+resolution case proving the guard fires before the resolution branch. (2) resolution= input type/shape validation: the type/shape branches (non-number/non-sequence string|dict; wrong-ndim numpy array; wrong-length sequence len 1|3|4; non-numeric elements) had no coverage -- test_rasterize.py's test_invalid_resolution_scalar/tuple only exercise non-finite/non-positive VALUES, not these type/shape guards, so a regression loosening or reordering them would ship silently; pin each branch to its message plus a positive control that a 1-D length-2 numpy array is still accepted. Source untouched."
|
|
13
|
+
reproject,2026-05-29,2618,HIGH,3,"Pass 2026-05-29: reproject already has a deep suite (369 tests in test_reproject.py + coverage/gate files) covering all 4 backends, NaN/Inf/all-NaN/all-Inf, 1x1/2x2, metadata, vertical shift, bounds_policy x backends, integer nodata x backends. Gaps found: Cat 3 HIGH single-row (1xN) and single-col (Nx1) strip rasters never tested (hit size<2 branch of _validate_regular_axis + degenerate resampling axis); Cat 3 MEDIUM constant-value/zero-gradient raster never reprojected. Added TestDegenerateShapeReproject (12 tests): 1xN+Nx1 strips x numpy/dask/cupy/dask+cupy, constant raster numpy value-preservation + cross-backend parity. All 12 executed and passed on a CUDA host. Test-only, no source change (#2618). LOW (documented only): _merge._merge_arrays_cupy imported but never called by merge() (host-bounces via _merge_arrays_numpy) - dead-code source observation not a test gap; non-square cellsize reproject only covered via resolution-tuple validation errors not a successful anisotropic run."
|
|
14
|
+
resample,2026-05-29,2547;2615,HIGH,1;2;3;5,"Pass 2 (2026-05-29): added test_resample_cupy_agg_fallback_2615.py (6 tests, all passing on CUDA host). Closes Cat 1 MEDIUM backend-coverage gap: the cupy eager aggregate CPU fallback for average/min/max at a NON-integer downsample factor (_run_cupy fy==int(fy) branch in resample.py ~L957-973) was never exercised; existing TestCuPyParity used 12x12 scale 0.5 (integer factor 2 -> GPU reshape path) and only median/mode hit the host fallback. New tests use 10x10 scale 0.3 (factor 3.33) for average/min/max parity vs numpy plus a NaN-masked variant. Issue #2615. Module is otherwise very thoroughly covered (test_resample.py + 3 supplementary files); no remaining HIGH gaps found. Pass 1 (2026-05-27): added test_resample_coverage_2026_05_27.py with 70 tests (68 passing, 2 skipped). Closes Cat 3 HIGH Nx1 single-column gap across numpy/cupy/dask+numpy/dask+cupy x 8 methods (nearest/bilinear/cubic/average/min/max/median/mode) plus Nx1 upsample-nearest parity and Nx1 cross-backend aggregate parity. Closes Cat 2 MEDIUM NaN-parity gap on cupy and dask+cupy (existing TestCuPyParity/TestDaskCuPyParity used random data without NaN; the weight-mask gate and spline-prepad had no GPU NaN coverage). Closes Cat 3 MEDIUM all-equal-value raster across 8 methods (downsample) and 3 interp methods (upsample) plus a constant-with-NaN aggregate variant. Closes Cat 5 MEDIUM non-default dim-name propagation: lat/lon, latitude/longitude, and (channel, lat, lon) 3D round-trip without being renamed to y/x; per-dim attrs (units) preserved. Closes Cat 3 MEDIUM empty-raster behaviour pin: 0-row and 0-col rasters raise (currently IndexError) -- contract covered. Filed source-bug issue #2547: cubic on dask backends fails for Nx1 / arrays smaller than depth=16; the 2 skipped tests in this file gate on that fix landing. Source untouched."
|
|
15
|
+
slope,2026-05-29,2697,MEDIUM,3,"PR #2703: added degenerate-shape tests (1x1/1xN/Nx1) for all 4 planar backends + geodesic; no live bug, pins all-NaN+shape contract. CUDA host: cupy/dask+cupy ran. Backend/NaN/param/metadata coverage already complete."
|
|
16
|
+
viewshed,2026-05-29,2693,HIGH,1;2;5,"Pass 1 (2026-05-29): added 4 new test groups to test_viewshed.py (13 new tests + 1 xfail, all passing/xfailing on a CUDA+RTX host). Closes Cat 1 HIGH backend-coverage gap: the dask+cupy dispatch path in _viewshed_dask (Tier B) and _viewshed_windowed (max_distance) was registered but never invoked by any test -- added test_viewshed_dask_cupy_flat (analytical-angle parity, atol 0.03) and test_viewshed_dask_cupy_max_distance (windowed GPU run; observer cell 180, corners INVISIBLE). Both use non-zero flat terrain (1.3) because the RTX mesh builder rejects an all-zero raster (#1378). Closes Cat 5 HIGH metadata-preservation gap: only the numpy test_viewshed called general_output_checks; the cupy/dask/dask+cupy and max_distance paths never asserted attrs/coords/dims/array-type preservation. Added parametrised test_viewshed_metadata_preserved over {numpy,cupy,dask+numpy,dask+cupy} x {full, max_distance=2.0}: asserts attrs==, dims==, shape==, x/y coords allclose; runs general_output_checks (full type parity) for all backends except dask+cupy. Closes Cat 2 HIGH NaN-input gap and surfaced source bug #2693: viewshed on a numpy raster crashes with ValueError 'node not found' from _delete_from_tree when a NaN cell sits at certain positions (e.g. (2,4) in a 5x5 with observer at (2,2)), while NaN at (1,1)/(0,0)/(4,4) runs fine. Added test_viewshed_nan_input_supported_positions (parametrised working positions, asserts observer=180 and NaN cell is INVISIBLE/NaN) plus test_viewshed_nan_input_crashing_position (xfail strict, raises, links #2693). Noted but NOT fixed (source change out of scope for test sweep): the dask+cupy backend does not preserve the cupy backing -- _viewshed_dask computes then rewraps via da.from_array(result_np), so the output computes to numpy not cupy; general_output_checks is skipped for dask+cupy for that reason (candidate for the metadata/backend-parity sweep). LOW (documented only): non-square cell sizes; 1x1 and 1xN geometry covered behaviourally by probing (run without error). Test-only PR; viewshed.py untouched."
|
|
17
|
+
zonal,2026-05-29,2619,MEDIUM,1,"Pass 2 (2026-05-29): one Cat 1 MEDIUM backend-coverage gap remained after pass 1 -- 3D crosstab on cupy / dask+cupy. The 3D GPU paths (_crosstab_cupy / _crosstab_dask_cupy with a 3D categorical values array, layer=, agg='count') were reachable and correct but untested; the existing 3D crosstab tests (test_crosstab_3d_count, test_crosstab_3d_agg_method, test_nodata_values_crosstab_3d) only parametrize numpy / dask+numpy. Added 3 parity tests to test_zonal_backend_coverage_2026_05_27.py (test_crosstab_3d_count_cupy_matches_numpy, test_crosstab_3d_count_dask_cupy_matches_numpy, test_crosstab_3d_nodata_cupy_matches_numpy) asserting cupy and dask+cupy results match numpy for agg='count' including a nodata_values case. All passed live on a CUDA host. Issue #2619, PR #2625. Test-only, no source change. Remaining LOW (documented, not fixed): get_full_extent has no direct unit test (exercised indirectly via suggest_zonal_canvas); non-square cellsize handling not exercised. Pass 1 (2026-05-27): added test_zonal_backend_coverage_2026_05_27.py with 32 tests, all passing on a CUDA host. Closes Cat 1 HIGH backend-coverage gaps: crosstab cupy + dask+cupy (_crosstab_cupy / _crosstab_dask_cupy were dispatched but never invoked by tests), regions cupy + dask+cupy (_regions_cupy via cupyx.scipy.ndimage + _regions_dask_cupy), trim dask+numpy + cupy + dask+cupy (_trim_bounds_dask isnan path and cupy data.get() path), crop dask+numpy + cupy + dask+cupy (_crop_bounds_dask + cupy data.get() path), apply 3D cupy + dask+cupy (per-layer kernel launch over the third axis in _apply_cupy and _apply_dask_cupy). Existing test_zonal.py covered only numpy + dask+numpy for crosstab/regions/trim/crop and 2D-only for cupy apply. Closes Cat 3 MEDIUM 1x1 / 1xN / Nx1 strip edge cases for trim, crop, and regions. Closes Cat 4 LOW pins: regions(neighborhood=6) ValueError, suggest_zonal_canvas(crs='Geographic') aspect-ratio pin and invalid-crs KeyError, crosstab cupy zone_ids/cat_ids filter, crosstab cupy agg='percentage'. Closes Cat 5 MEDIUM: regions coords/attrs propagation across numpy + dask+numpy, trim/crop name='trim'/'crop' default + attrs preservation. Also pins the documented numpy-vs-dask trim asymmetry on NaN sentinel (numpy _trim does equality which never matches NaN; dask _trim_bounds_dask has dedicated isnan branch). Mutation against the cupy.asnumpy() conversion in _crosstab_cupy flipped test_crosstab_cupy_matches_numpy red. Source untouched."
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# Backend Parity: Cross-Backend Consistency Audit
|
|
2
|
+
|
|
3
|
+
Verify that all implemented backends produce consistent results for a given
|
|
4
|
+
function or set of functions. The prompt is: {{ARGUMENTS}}
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Step 1 -- Identify targets
|
|
9
|
+
|
|
10
|
+
1. If {{ARGUMENTS}} names specific functions (e.g. `slope`, `aspect`), use those.
|
|
11
|
+
2. If {{ARGUMENTS}} names a category (e.g. `hydrology`, `surface`, `focal`), read
|
|
12
|
+
`README.md` to find all functions in that category.
|
|
13
|
+
3. If {{ARGUMENTS}} is empty or says "all", scan the full feature matrix in `README.md`
|
|
14
|
+
and test every function that claims support for 2+ backends.
|
|
15
|
+
4. For each function, read its source file and find the `ArrayTypeFunctionMapping`
|
|
16
|
+
call to determine which backends are actually implemented (not just what the
|
|
17
|
+
README claims).
|
|
18
|
+
|
|
19
|
+
## Step 2 -- Build test inputs
|
|
20
|
+
|
|
21
|
+
For each target function, create test rasters at three scales:
|
|
22
|
+
|
|
23
|
+
| Name | Size | Purpose |
|
|
24
|
+
|---------|---------|--------------------------------------------------|
|
|
25
|
+
| tiny | 8x6 | Fast, easy to inspect cell-by-cell |
|
|
26
|
+
| medium | 64x64 | Catches chunk-boundary artifacts in dask |
|
|
27
|
+
| large | 256x256 | Stress test, exposes numerical accumulation drift |
|
|
28
|
+
|
|
29
|
+
For each size, generate two variants:
|
|
30
|
+
- **Clean:** no NaN, realistic value range for the function
|
|
31
|
+
(e.g. 0-5000m for elevation, 0-1 for NDVI inputs)
|
|
32
|
+
- **Dirty:** 5-10% random NaN, some extreme values near dtype limits
|
|
33
|
+
|
|
34
|
+
Use `np.random.default_rng(42)` for reproducibility. For functions that require
|
|
35
|
+
specific input structure (e.g. `flow_direction` needs a DEM with drainage, not
|
|
36
|
+
random noise), use the project's `perlin` module or a synthetic cone/valley.
|
|
37
|
+
|
|
38
|
+
Also test with at least two dtypes: `float32` and `float64`.
|
|
39
|
+
|
|
40
|
+
## Step 3 -- Run every backend
|
|
41
|
+
|
|
42
|
+
For each function, input variant, and dtype:
|
|
43
|
+
|
|
44
|
+
1. **NumPy:** `create_test_raster(data, backend='numpy')` -- always the baseline.
|
|
45
|
+
2. **Dask+NumPy:** test with two chunk configurations:
|
|
46
|
+
- `chunks=(size//2, size//2)` -- even split
|
|
47
|
+
- `chunks=(size//3, size//3)` -- ragged remainder
|
|
48
|
+
3. **CuPy:** `create_test_raster(data, backend='cupy')` -- skip if CUDA unavailable.
|
|
49
|
+
4. **Dask+CuPy:** `create_test_raster(data, backend='dask+cupy')` -- skip if CUDA
|
|
50
|
+
unavailable.
|
|
51
|
+
|
|
52
|
+
If the function has parameter variants (e.g. `boundary`, `method`), test the
|
|
53
|
+
default parameters first. If {{ARGUMENTS}} includes "thorough", also sweep all
|
|
54
|
+
parameter combinations.
|
|
55
|
+
|
|
56
|
+
## Step 4 -- Pairwise comparison
|
|
57
|
+
|
|
58
|
+
For every non-NumPy result, compare against the NumPy baseline. Extract data using
|
|
59
|
+
the project conventions:
|
|
60
|
+
- Dask: `.data.compute()`
|
|
61
|
+
- CuPy: `.data.get()`
|
|
62
|
+
- Dask+CuPy: `.data.compute().get()`
|
|
63
|
+
|
|
64
|
+
For each pair, compute and record:
|
|
65
|
+
|
|
66
|
+
### 4a. Value agreement
|
|
67
|
+
```python
|
|
68
|
+
abs_diff = np.abs(result - baseline)
|
|
69
|
+
max_abs = np.nanmax(abs_diff)
|
|
70
|
+
rel_diff = abs_diff / (np.abs(baseline) + 1e-30) # avoid div-by-zero
|
|
71
|
+
max_rel = np.nanmax(rel_diff)
|
|
72
|
+
mean_abs = np.nanmean(abs_diff)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### 4b. NaN mask agreement
|
|
76
|
+
```python
|
|
77
|
+
nan_match = np.array_equal(np.isnan(result), np.isnan(baseline))
|
|
78
|
+
nan_only_in_result = np.sum(np.isnan(result) & ~np.isnan(baseline))
|
|
79
|
+
nan_only_in_baseline = np.sum(np.isnan(baseline) & ~np.isnan(result))
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### 4c. Metadata preservation
|
|
83
|
+
Using `general_output_checks` from `general_checks.py`:
|
|
84
|
+
- Output type matches input type (DataArray backed by the same array type)
|
|
85
|
+
- Shape, dims, coords, attrs preserved
|
|
86
|
+
|
|
87
|
+
### 4d. Pass/fail thresholds
|
|
88
|
+
|
|
89
|
+
| Comparison | rtol | atol |
|
|
90
|
+
|-----------------------|----------|----------|
|
|
91
|
+
| NumPy vs Dask+NumPy | 1e-5 | 0 |
|
|
92
|
+
| NumPy vs CuPy | 1e-6 | 1e-6 |
|
|
93
|
+
| NumPy vs Dask+CuPy | 1e-6 | 1e-6 |
|
|
94
|
+
|
|
95
|
+
A comparison **fails** if `max_abs > atol` AND `max_rel > rtol`, or if NaN masks
|
|
96
|
+
disagree.
|
|
97
|
+
|
|
98
|
+
## Step 5 -- Chunk boundary analysis
|
|
99
|
+
|
|
100
|
+
Dask backends are the most likely source of parity issues due to `map_overlap`
|
|
101
|
+
boundary handling. For any Dask comparison that fails or is borderline:
|
|
102
|
+
|
|
103
|
+
1. Identify which cells diverge from the NumPy result.
|
|
104
|
+
2. Map those cells to chunk boundaries (cells within `depth` pixels of a chunk edge).
|
|
105
|
+
3. Report what percentage of divergent cells are at chunk boundaries vs interior.
|
|
106
|
+
4. If all divergence is at boundaries, the issue is likely in the `map_overlap`
|
|
107
|
+
`depth` or `boundary` parameter. Say so explicitly.
|
|
108
|
+
|
|
109
|
+
## Step 6 -- Generate the report
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
## Backend Parity Report
|
|
113
|
+
|
|
114
|
+
### Functions tested
|
|
115
|
+
| Function | Backends implemented | Source file |
|
|
116
|
+
|---------------------|---------------------------|--------------------------|
|
|
117
|
+
| slope | numpy, cupy, dask, dask+cupy | xrspatial/slope.py |
|
|
118
|
+
| ... | ... | ... |
|
|
119
|
+
|
|
120
|
+
### Parity Matrix
|
|
121
|
+
|
|
122
|
+
#### <function_name>
|
|
123
|
+
| Comparison | Input | Dtype | Max |Δ| | Max |Δ/ref| | NaN match | Metadata | Status |
|
|
124
|
+
|-----------------------|-------------|---------|----------|------------|-----------|----------|--------|
|
|
125
|
+
| NumPy vs Dask+NumPy | tiny clean | float32 | ... | ... | yes | ok | PASS |
|
|
126
|
+
| NumPy vs Dask+NumPy | medium dirty| float64 | ... | ... | yes | ok | PASS |
|
|
127
|
+
| NumPy vs CuPy | tiny clean | float32 | ... | ... | no (3) | ok | FAIL |
|
|
128
|
+
| ... | ... | ... | ... | ... | ... | ... | ... |
|
|
129
|
+
|
|
130
|
+
### Failures
|
|
131
|
+
For each FAIL row:
|
|
132
|
+
- Which cells diverged
|
|
133
|
+
- Whether divergence correlates with chunk boundaries (Dask) or specific
|
|
134
|
+
input values (CuPy)
|
|
135
|
+
- Likely root cause
|
|
136
|
+
- Suggested fix
|
|
137
|
+
|
|
138
|
+
### Summary
|
|
139
|
+
- Functions tested: N
|
|
140
|
+
- Total comparisons: N
|
|
141
|
+
- Passed: N
|
|
142
|
+
- Failed: N
|
|
143
|
+
- Skipped (no CUDA): N
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## General rules
|
|
149
|
+
|
|
150
|
+
- Do not modify any source or test files. This command is read-only.
|
|
151
|
+
- Use `create_test_raster` from `general_checks.py` for all raster construction.
|
|
152
|
+
- Any temporary files must include the function name for uniqueness.
|
|
153
|
+
- If CUDA is unavailable, skip CuPy and Dask+CuPy gracefully. Report them
|
|
154
|
+
as SKIPPED, not FAIL.
|
|
155
|
+
- If {{ARGUMENTS}} includes "fix", still do not auto-fix. Report the issue and ask.
|
|
156
|
+
- If a function is not in `ArrayTypeFunctionMapping` (e.g. it only has a numpy
|
|
157
|
+
path), note it as "single-backend only" and skip parity checks for it.
|
|
158
|
+
- If {{ARGUMENTS}} includes a specific tolerance (e.g. `rtol=1e-3`), override the
|
|
159
|
+
defaults in the threshold table.
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# Bench: Local Performance Comparison
|
|
2
|
+
|
|
3
|
+
Run ASV benchmarks for the current branch against main and report regressions
|
|
4
|
+
and improvements. The prompt is: {{ARGUMENTS}}
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Step 1 -- Identify what changed
|
|
9
|
+
|
|
10
|
+
1. If {{ARGUMENTS}} names specific benchmark classes or functions (e.g. `Slope`,
|
|
11
|
+
`flow_accumulation`), use those directly.
|
|
12
|
+
2. If {{ARGUMENTS}} is empty or says "auto", run `git diff origin/main --name-only`
|
|
13
|
+
to find changed source files under `xrspatial/`. Map each changed file to the
|
|
14
|
+
corresponding benchmark module in `benchmarks/benchmarks/`. Use the filename
|
|
15
|
+
and imports to match (e.g. changes to `slope.py` map to `benchmarks/benchmarks/slope.py`).
|
|
16
|
+
3. If no benchmark exists for the changed code, note this in the report and
|
|
17
|
+
suggest whether one should be added.
|
|
18
|
+
|
|
19
|
+
## Step 2 -- Check prerequisites
|
|
20
|
+
|
|
21
|
+
1. Verify ASV is installed: `python -c "import asv"`. If missing, tell the user
|
|
22
|
+
to install it (`pip install asv`) and stop.
|
|
23
|
+
2. Verify the benchmarks directory exists at `benchmarks/`.
|
|
24
|
+
3. Read `benchmarks/asv.conf.json` to confirm the project name and branch settings.
|
|
25
|
+
4. Check whether the ASV machine file exists (`.asv/machine.json`). If not, run
|
|
26
|
+
`cd benchmarks && asv machine --yes` to initialize it.
|
|
27
|
+
|
|
28
|
+
## Step 3 -- Run the comparison
|
|
29
|
+
|
|
30
|
+
Run ASV in continuous-comparison mode from the `benchmarks/` directory:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
cd benchmarks && asv continuous origin/main HEAD -b "<regex>" -e
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Where `<regex>` is a pattern matching the benchmark classes identified in Step 1
|
|
37
|
+
(e.g. `Slope|Aspect` or `FlowAccumulation`). The `-e` flag shows stderr on failure.
|
|
38
|
+
|
|
39
|
+
If {{ARGUMENTS}} contains "quick", add `--quick` to run each benchmark only once
|
|
40
|
+
(faster but noisier).
|
|
41
|
+
|
|
42
|
+
If {{ARGUMENTS}} contains "full", omit the `-b` filter to run all benchmarks.
|
|
43
|
+
|
|
44
|
+
## Step 4 -- Parse and interpret results
|
|
45
|
+
|
|
46
|
+
ASV continuous outputs lines like:
|
|
47
|
+
```
|
|
48
|
+
BENCHMARKS NOT SIGNIFICANTLY CHANGED.
|
|
49
|
+
```
|
|
50
|
+
or:
|
|
51
|
+
```
|
|
52
|
+
REGRESSION: benchmarks.slope.Slope.time_numpy 3.45ms -> 5.67ms (1.64x)
|
|
53
|
+
IMPROVED: benchmarks.slope.Slope.time_dask 8.12ms -> 4.23ms (0.52x)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Parse the output and classify each result:
|
|
57
|
+
|
|
58
|
+
| Category | Criteria |
|
|
59
|
+
|--------------|-----------------------------|
|
|
60
|
+
| REGRESSION | Ratio > 1.2x (matches CI) |
|
|
61
|
+
| IMPROVED | Ratio < 0.8x |
|
|
62
|
+
| UNCHANGED | Between 0.8x and 1.2x |
|
|
63
|
+
|
|
64
|
+
## Step 5 -- Generate the report
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
## Benchmark Report: <branch> vs main
|
|
68
|
+
|
|
69
|
+
### Changed files
|
|
70
|
+
- <list of changed source files>
|
|
71
|
+
|
|
72
|
+
### Benchmarks run
|
|
73
|
+
- <list of benchmark classes/functions matched>
|
|
74
|
+
|
|
75
|
+
### Results
|
|
76
|
+
|
|
77
|
+
| Benchmark | main | HEAD | Ratio | Status |
|
|
78
|
+
|------------------------------------|-----------|-----------|-------|------------|
|
|
79
|
+
| slope.Slope.time_numpy | 3.45 ms | 3.51 ms | 1.02x | UNCHANGED |
|
|
80
|
+
| slope.Slope.time_dask_numpy | 8.12 ms | 4.23 ms | 0.52x | IMPROVED |
|
|
81
|
+
| ... | ... | ... | ... | ... |
|
|
82
|
+
|
|
83
|
+
### Regressions
|
|
84
|
+
<details for each regression: which benchmark, how much slower, likely cause>
|
|
85
|
+
|
|
86
|
+
### Improvements
|
|
87
|
+
<details for each improvement>
|
|
88
|
+
|
|
89
|
+
### Missing benchmarks
|
|
90
|
+
<list any changed functions that have no benchmark coverage>
|
|
91
|
+
|
|
92
|
+
### Recommendation
|
|
93
|
+
- [ ] Safe to merge (no regressions)
|
|
94
|
+
- [ ] Add "performance" label to PR (regressions found, CI will recheck)
|
|
95
|
+
- [ ] Consider adding benchmarks for: <uncovered functions>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Step 6 -- Suggest benchmark additions (if gaps found)
|
|
99
|
+
|
|
100
|
+
If Step 1 found changed functions with no benchmark coverage:
|
|
101
|
+
|
|
102
|
+
1. Read an existing benchmark file in `benchmarks/benchmarks/` that covers a
|
|
103
|
+
similar function (same category or same backend pattern).
|
|
104
|
+
2. Describe what a new benchmark should test:
|
|
105
|
+
- Which function and parameter variants
|
|
106
|
+
- Suggested array sizes (match `common.py` conventions)
|
|
107
|
+
- Which backends to benchmark (numpy at minimum, dask if applicable)
|
|
108
|
+
3. Ask the user whether they want you to write the benchmark file.
|
|
109
|
+
|
|
110
|
+
Do NOT write benchmark files automatically. Report the gap and propose, then wait.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## General rules
|
|
115
|
+
|
|
116
|
+
- Always run benchmarks from the `benchmarks/` directory, not the project root.
|
|
117
|
+
- The regression threshold is 1.2x, matching `.github/workflows/benchmarks.yml`.
|
|
118
|
+
Do not change this unless {{ARGUMENTS}} overrides it.
|
|
119
|
+
- If ASV setup or machine detection fails, report the error clearly and suggest
|
|
120
|
+
the fix. Do not retry in a loop.
|
|
121
|
+
- If benchmarks take longer than 5 minutes per class, note the elapsed time so
|
|
122
|
+
the user can plan accordingly.
|
|
123
|
+
- Do not modify any source, test, or benchmark files. This command is read-only
|
|
124
|
+
analysis (unless the user explicitly asks for a benchmark to be written in
|
|
125
|
+
response to Step 6).
|
|
126
|
+
- If {{ARGUMENTS}} says "compare <branch1> <branch2>", run
|
|
127
|
+
`asv continuous <branch1> <branch2>` instead of the default origin/main vs HEAD.
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# Dask ETL Notebook
|
|
2
|
+
|
|
3
|
+
Create a Jupyter notebook that sets up a Dask distributed LocalCluster and walks
|
|
4
|
+
through an ETL (Extract, Transform, Load) workflow. The prompt is: {{ARGUMENTS}}
|
|
5
|
+
|
|
6
|
+
Use the prompt to determine the data domain, transformations, and output format.
|
|
7
|
+
If no prompt is given, use a geospatial raster ETL as the default domain
|
|
8
|
+
(consistent with the xarray-spatial project).
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Notebook structure
|
|
13
|
+
|
|
14
|
+
Every Dask ETL notebook follows this cell sequence:
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
0 [markdown] # Title + one-line description of the pipeline
|
|
18
|
+
1 [markdown] ### Overview (what the pipeline does, what you'll learn)
|
|
19
|
+
2 [markdown] One-liner about the imports
|
|
20
|
+
3 [code ] Imports
|
|
21
|
+
4 [markdown] ## Cluster Setup
|
|
22
|
+
5 [code ] Create and inspect a dask.distributed LocalCluster + Client
|
|
23
|
+
6 [markdown] Brief note on the dashboard URL and how to read it
|
|
24
|
+
7 [markdown] ## Extract
|
|
25
|
+
8 [code ] Load or generate source data as lazy Dask arrays
|
|
26
|
+
9 [markdown] Describe the raw data: shape, dtype, chunk layout
|
|
27
|
+
10 [code ] Inspect / visualize a sample of the raw data
|
|
28
|
+
11 [markdown] ## Transform
|
|
29
|
+
12 [code ] Apply transformations (filtering, rechunking, computation)
|
|
30
|
+
13 [markdown] Explain what the transform does and why it benefits from Dask
|
|
31
|
+
14 [code ] (Optional) Additional transform step(s)
|
|
32
|
+
15 [markdown] ## Load
|
|
33
|
+
16 [code ] Write results to disk (Zarr, Parquet, GeoTIFF, etc.)
|
|
34
|
+
17 [markdown] Confirm output and show summary statistics
|
|
35
|
+
18 [code ] Read back and verify the output
|
|
36
|
+
19 [markdown] ## Cleanup
|
|
37
|
+
20 [code ] Close the client and cluster
|
|
38
|
+
21 [markdown] ### Summary + next steps
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Sections can be repeated or extended when the prompt calls for more transform
|
|
42
|
+
steps. The core requirement is that every notebook has all five phases: Cluster
|
|
43
|
+
Setup, Extract, Transform, Load, Cleanup.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Cluster Setup cell
|
|
48
|
+
|
|
49
|
+
Always use this pattern for the cluster:
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
from dask.distributed import Client, LocalCluster
|
|
53
|
+
|
|
54
|
+
cluster = LocalCluster(
|
|
55
|
+
n_workers=4,
|
|
56
|
+
threads_per_worker=2,
|
|
57
|
+
memory_limit="2GB",
|
|
58
|
+
)
|
|
59
|
+
client = Client(cluster)
|
|
60
|
+
client
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Include a markdown cell after the cluster cell noting:
|
|
64
|
+
- The dashboard link (usually `http://localhost:8787/status`)
|
|
65
|
+
- That `n_workers` and `memory_limit` should be tuned for the machine
|
|
66
|
+
|
|
67
|
+
If the prompt asks for a specific cluster configuration (GPU workers, adaptive
|
|
68
|
+
scaling, remote scheduler), adjust accordingly but keep the default simple.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Code conventions
|
|
73
|
+
|
|
74
|
+
### Imports
|
|
75
|
+
|
|
76
|
+
Standard import block for a Dask ETL notebook:
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
import numpy as np
|
|
80
|
+
import xarray as xr
|
|
81
|
+
import dask
|
|
82
|
+
import dask.array as da
|
|
83
|
+
from dask.distributed import Client, LocalCluster
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Add extras only when needed (e.g. `import pandas as pd`, `import rioxarray`,
|
|
87
|
+
`from xrspatial import slope`). Keep the import cell minimal.
|
|
88
|
+
|
|
89
|
+
### Dask best practices to demonstrate
|
|
90
|
+
|
|
91
|
+
- **Lazy by default**: build the computation graph before calling `.compute()`.
|
|
92
|
+
Show the repr of a lazy array at least once so the reader sees the task graph.
|
|
93
|
+
- **Chunking**: explain chunk choices. Use `dask.array.from_array(..., chunks=)`
|
|
94
|
+
or `xr.open_dataset(..., chunks={})` depending on the source.
|
|
95
|
+
- **Avoid full materialization mid-pipeline**: no `.values` or `.compute()` until
|
|
96
|
+
the Load phase unless there is a good reason (and if so, explain why).
|
|
97
|
+
- **Persist when reused**: if an intermediate result is used in multiple
|
|
98
|
+
downstream steps, call `client.persist(result)` and explain why.
|
|
99
|
+
- **Progress feedback**: use `dask.diagnostics.ProgressBar` or point the reader
|
|
100
|
+
to the dashboard.
|
|
101
|
+
|
|
102
|
+
### Data handling
|
|
103
|
+
|
|
104
|
+
- Generate or load data lazily. For synthetic data, use `dask.array.random` or
|
|
105
|
+
wrap numpy arrays with `da.from_array(..., chunks=...)`.
|
|
106
|
+
- For file-based sources, prefer `xr.open_dataset` / `xr.open_mfdataset` with
|
|
107
|
+
explicit `chunks=` to get lazy Dask-backed arrays.
|
|
108
|
+
- For the Load phase, prefer Zarr (`to_zarr()`) as the default output format
|
|
109
|
+
since it supports parallel writes natively. Mention Parquet or GeoTIFF as
|
|
110
|
+
alternatives when relevant.
|
|
111
|
+
|
|
112
|
+
### Cleanup
|
|
113
|
+
|
|
114
|
+
Always close the client and cluster at the end:
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
client.close()
|
|
118
|
+
cluster.close()
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Writing rules
|
|
124
|
+
|
|
125
|
+
1. **Run all markdown cells and code comments through [TOOL: humanize].**
|
|
126
|
+
2. Never use em dashes.
|
|
127
|
+
3. Short and direct. Technical but not sterile.
|
|
128
|
+
4. Title cell (h1): describe the pipeline, e.g.
|
|
129
|
+
`Dask ETL: Raster Slope Analysis at Scale` or
|
|
130
|
+
`Dask ETL: Aggregating Sensor Readings to Parquet`.
|
|
131
|
+
5. Overview cell: 2-3 sentences on what the pipeline does and what Dask concepts
|
|
132
|
+
the reader will pick up. No hype.
|
|
133
|
+
6. Each phase (Extract, Transform, Load) gets a brief markdown intro (2-4
|
|
134
|
+
sentences) explaining what happens and why.
|
|
135
|
+
7. Use inline comments in code cells sparingly. Let the markdown cells carry the
|
|
136
|
+
explanation.
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Checklist
|
|
141
|
+
|
|
142
|
+
When creating the notebook:
|
|
143
|
+
|
|
144
|
+
1. Pick a data domain from the prompt (or default to geospatial raster).
|
|
145
|
+
2. Write the full cell sequence following the structure above.
|
|
146
|
+
3. Verify all code cells are syntactically correct and self-contained.
|
|
147
|
+
4. Run all markdown through [TOOL: humanize].
|
|
148
|
+
5. Ensure the notebook cleans up after itself (cluster closed, temp files noted).
|