Skip to content

Commit 5b8696b

Browse files
committed
Add visibility_frequency wrapper (#1145)
1 parent 17128ac commit 5b8696b

File tree

2 files changed

+49
-0
lines changed

2 files changed

+49
-0
lines changed

xrspatial/tests/test_visibility.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,3 +245,32 @@ def test_preserves_coords_and_dims(self):
245245
np.testing.assert_array_equal(result.coords['y'].values,
246246
raster.coords['y'].values)
247247
assert result.attrs.get('crs') == 'EPSG:4326'
248+
249+
250+
from xrspatial.visibility import visibility_frequency
251+
252+
253+
class TestVisibilityFrequency:
254+
def test_flat_terrain_all_ones(self):
255+
data = np.zeros((10, 10), dtype=float)
256+
raster = _make_raster(data)
257+
observers = [
258+
{'x': 2.0, 'y': 2.0, 'observer_elev': 10},
259+
{'x': 7.0, 'y': 7.0, 'observer_elev': 10},
260+
]
261+
result = visibility_frequency(raster, observers)
262+
assert result.dtype == np.float64
263+
np.testing.assert_allclose(result.values, 1.0)
264+
265+
def test_equals_cumulative_divided_by_n(self):
266+
data = np.random.RandomState(7).rand(15, 15).astype(float) * 100
267+
raster = _make_raster(data)
268+
observers = [
269+
{'x': 3.0, 'y': 3.0, 'observer_elev': 50},
270+
{'x': 10.0, 'y': 10.0, 'observer_elev': 50},
271+
{'x': 7.0, 'y': 2.0, 'observer_elev': 50},
272+
]
273+
freq = visibility_frequency(raster, observers)
274+
cum = cumulative_viewshed(raster, observers)
275+
expected = cum.values.astype(np.float64) / 3.0
276+
np.testing.assert_allclose(freq.values, expected)

xrspatial/visibility.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,3 +234,23 @@ def cumulative_viewshed(
234234

235235
return xarray.DataArray(count, coords=raster.coords,
236236
dims=raster.dims, attrs=raster.attrs)
237+
238+
239+
def visibility_frequency(
240+
raster: xarray.DataArray,
241+
observers: list,
242+
target_elev: float = 0,
243+
max_distance: float = None,
244+
) -> xarray.DataArray:
245+
"""Fraction of observers that can see each cell.
246+
247+
Parameters are the same as :func:`cumulative_viewshed`.
248+
249+
Returns
250+
-------
251+
xarray.DataArray
252+
Float64 raster with values in [0, 1].
253+
"""
254+
cum = cumulative_viewshed(raster, observers, target_elev, max_distance)
255+
freq = cum.astype(np.float64) / len(observers)
256+
return freq

0 commit comments

Comments
 (0)