Skip to content

Fix KDE all-zero output with descending-coordinate templates#1199

Merged
brendancol merged 3 commits into
masterfrom
issue-1198
Apr 14, 2026
Merged

Fix KDE all-zero output with descending-coordinate templates#1199
brendancol merged 3 commits into
masterfrom
issue-1198

Conversation

@brendancol
Copy link
Copy Markdown
Contributor

Fixes #1198

Proposed changes

  • Fix bounding-box index calculation in _kde_cpu and _line_density_cpu to handle negative dx/dy (descending coordinate order). The old code divided by dx/dy to get pixel indices, but negative spacing flipped lo and hi so the inner loops never executed, producing all-zero output.
  • The fix computes both candidate indices and uses min/max to always get lo <= hi, regardless of spacing sign.
  • Add 10 regression tests covering descending y, descending x, both descending, all kernel types, and line_density.

Test plan

  • All 35 existing test_kde.py tests still pass
  • 10 new TestDescendingCoordinates tests pass, covering:
    • Single-point KDE with descending-y template (nonzero check)
    • Descending-y vs ascending-y match (row-flipped, exact for single point)
    • Descending-x vs ascending-x match (col-flipped)
    • Both-descending vs ascending match
    • All three kernels with descending-y and multiple points
    • line_density with descending-y (quartic exact, gaussian within atol=1e-4)
    • line_density with descending-x
  • Dask parity tests pass (Dask tiling inherits the CPU kernel fix)
  • CuPy parity tests pass (CUDA kernel was never affected since it has no bounding box)

Two security fixes for the geotiff subpackage:

1. Add a configurable max_pixels guard to read_to_array() and all
   internal read functions (_read_strips, _read_tiles, _read_cog_http).
   A crafted TIFF with fabricated header dimensions could previously
   trigger multi-TB allocations. The default limit is 1 billion pixels
   (~4 GB for float32 single-band), overridable via max_pixels kwarg.
   Fixes #1184.

2. Canonicalize VRT source filenames with os.path.realpath() after
   resolving relative paths. Previously, a VRT file with "../" in
   SourceFilename could read arbitrary files outside the VRT directory.
   Fixes #1185.
os.path.realpath() converts Unix-style paths to Windows paths on
Windows (e.g. /data/tile.tif becomes D:\data\tile.tif). Use
os.path.realpath() in the assertion so it matches the production
code's canonicalization on all platforms.
The bounding-box index calculation in _kde_cpu and _line_density_cpu
divided by dx/dy to convert coordinate offsets to pixel indices.
When dy or dx was negative (descending coordinates, common for
north-up rasters), the division flipped lo/hi so the inner loops
never executed, producing all-zero output.

Fix: compute both index endpoints and use min/max to get the correct
lo and hi regardless of spacing sign.
@brendancol brendancol added the bug Something isn't working label Apr 14, 2026
@github-actions github-actions Bot added the performance PR touches performance-sensitive code label Apr 14, 2026
@brendancol brendancol merged commit 32f28da into master Apr 14, 2026
12 checks passed
@brendancol brendancol deleted the issue-1198 branch May 5, 2026 03:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working performance PR touches performance-sensitive code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

KDE returns all zeros with descending-coordinate templates

1 participant