Skip to content

Numba-ize visibility module loops for performance #1177

@brendancol

Description

@brendancol

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:

  1. 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).

  2. 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)?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions