Reason or problem
visibility.py has four tight loops in line_of_sight() and _bresenham_line() running as pure Python. viewshed.py next door already JIT-compiles 35 functions with @ngjit, so the visibility module sticks out.
Proposal
Design:
-
JIT-compile _bresenham_line() with @ngjit. Return a fixed-size numpy array instead of a Python list of tuples (numba nopython mode can't do list.append with tuples).
-
Pull the three inner loops out of line_of_sight() into one @ngjit kernel that computes distance, visibility, and Fresnel clearance in a single pass over numpy arrays.
Usage:
No API changes. line_of_sight(), cumulative_viewshed(), and visibility_frequency() keep their current signatures and return types.
Value:
- 3-10x speedup on
line_of_sight() for long transects
- Brings
visibility.py in line with the rest of the codebase
Stakeholders and impacts
Touches xrspatial/visibility.py only. Existing tests must still pass.
Drawbacks
- Numba-izing
_bresenham_line changes its return type from list-of-tuples to numpy array, so _extract_transect needs updating too.
Alternatives
- Only JIT the
line_of_sight loops, leave _bresenham_line as Python. Skips the Bresenham speedup but avoids the return-type change.
- Cython would work technically but doesn't match the rest of the codebase.
Unresolved questions
- Is the Bresenham JIT gain meaningful for typical transect lengths (hundreds to low-thousands of cells)?
Reason or problem
visibility.pyhas four tight loops inline_of_sight()and_bresenham_line()running as pure Python.viewshed.pynext door already JIT-compiles 35 functions with@ngjit, so the visibility module sticks out.Proposal
Design:
JIT-compile
_bresenham_line()with@ngjit. Return a fixed-size numpy array instead of a Python list of tuples (numba nopython mode can't dolist.appendwith tuples).Pull the three inner loops out of
line_of_sight()into one@ngjitkernel that computes distance, visibility, and Fresnel clearance in a single pass over numpy arrays.Usage:
No API changes.
line_of_sight(),cumulative_viewshed(), andvisibility_frequency()keep their current signatures and return types.Value:
line_of_sight()for long transectsvisibility.pyin line with the rest of the codebaseStakeholders and impacts
Touches
xrspatial/visibility.pyonly. Existing tests must still pass.Drawbacks
_bresenham_linechanges its return type from list-of-tuples to numpy array, so_extract_transectneeds updating too.Alternatives
line_of_sightloops, leave_bresenham_lineas Python. Skips the Bresenham speedup but avoids the return-type change.Unresolved questions