Skip to content

min_observable_height(): no memory guard on boolean visibility stack #1317

@brendancol

Description

@brendancol

Description

min_observable_height() in xrspatial/experimental/min_observable_height.py allocates a 3-D boolean stack sized directly from input dimensions and the binary-search step count, with no memory check.

Line 122-124:

visibility_stack = np.empty(
    (n_steps, *raster.shape), dtype=np.bool_
)

n_steps = ceil(log2(max_height / precision)) + 1. For default args (max_height=100, precision=1.0) n_steps is 8, but a caller can drive it much higher: max_height=1e9, precision=1e-9 gives n_steps=60. Combined with a 50000x50000 raster, that's ~150 GB of bool stack before anything errors.

Each viewshed call inside the loop also allocates a (H, W) float64 grid (~20 GB on a 50000x50000 raster), but viewshed has its own per-call allocation. The public-API guard here covers the boolean-stack allocation that is unique to this function.

The public API also misses _validate_raster(), so non-DataArray, non-2D, non-numeric inputs fall through to the loop and crash deep inside viewshed. That is a separate Cat 6 issue (MEDIUM, documented only).

Same asymmetric-guard pattern already used in sky_view_factor #1300, sieve #1296, kde #1287, resample #1295, focal #1284, geodesic #1283, mahalanobis #1288, true_color #1291, diffuse #1267, erode #1275, emerging_hotspots #1274, dasymetric #1261.

Expected behavior

min_observable_height() raises MemoryError with a clear message when the projected boolean-stack working set exceeds available memory, before any allocation runs.

Proposed fix

Add _available_memory_bytes() and _check_memory(n_steps, rows, cols) helpers (1 byte/cell for bool dtype, 50% threshold). Call from the public function after computing n_steps and before np.empty.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions