From 82cf17f422542f9807b180775be86b9929c65b9f Mon Sep 17 00:00:00 2001 From: Brendan Collins Date: Thu, 25 Jun 2026 11:33:05 -0700 Subject: [PATCH 1/2] fire: add Examples sections and backend-support notes to docstrings All seven public functions (dnbr, rdnbr, burn_severity_class, fireline_intensity, flame_length, rate_of_spread, kbdi) gained a runnable numpy Examples block and a line stating they support all four backends (numpy, cupy, dask+numpy, dask+cupy). Documentation only; no behavior change. Also records the fire row in the documentation sweep state CSV. --- .claude/sweep-documentation-state.csv | 1 + xrspatial/fire.py | 106 ++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) diff --git a/.claude/sweep-documentation-state.csv b/.claude/sweep-documentation-state.csv index 7c342d626..818225d59 100644 --- a/.claude/sweep-documentation-state.csv +++ b/.claude/sweep-documentation-state.csv @@ -1,2 +1,3 @@ module,last_inspected,issue,severity_max,categories_found,notes,doc_coverage +fire,2026-06-25,,MEDIUM,1;5,"all 7 public funcs (dnbr, rdnbr, burn_severity_class, fireline_intensity, flame_length, rate_of_spread, kbdi) lacked Examples section (Cat1 MEDIUM) and backend-support note (Cat5 MEDIUM); fixed in deep-sweep-documentation-fire-2026-06-25-01; repo issues disabled so no issue number; examples run and outputs match numpy backend; all 7 listed in reference/fire.rst; no Cat2/Cat3/Cat4 issues",7/7 perlin,2026-06-23,,MEDIUM,2;5,"name param undocumented (Cat2) + float-dtype requirement/ValueError undocumented, no Raises section (Cat5); fixed in deep-sweep-documentation-perlin-2026-06-23; repo has issues disabled so no issue number; example runs and output matches; 1 public func (perlin) listed in reference/surface.rst",1/1 diff --git a/xrspatial/fire.py b/xrspatial/fire.py index afafc099b..6e66f3e56 100644 --- a/xrspatial/fire.py +++ b/xrspatial/fire.py @@ -185,6 +185,9 @@ def dnbr(pre_nbr_agg: xr.DataArray, Computes ``pre_nbr - post_nbr``. Higher values indicate greater burn severity. + Supports NumPy, CuPy, Dask with NumPy, and Dask with CuPy backed + xarray DataArrays; the output backend matches the input. + Parameters ---------- pre_nbr_agg : xr.DataArray @@ -198,6 +201,18 @@ def dnbr(pre_nbr_agg: xr.DataArray, ------- xr.DataArray dNBR values (float32). + + Examples + -------- + .. sourcecode:: python + + >>> import numpy as np, xarray as xr + >>> from xrspatial.fire import dnbr + >>> pre = xr.DataArray(np.array([[0.5, 0.6], [0.4, 0.3]], dtype='f4')) + >>> post = xr.DataArray(np.array([[0.1, 0.2], [0.5, 0.1]], dtype='f4')) + >>> dnbr(pre, post).values + array([[ 0.4 , 0.40000004], + [-0.09999999, 0.20000002]], dtype=float32) """ _validate_raster(pre_nbr_agg, func_name='dnbr', name='pre_nbr_agg') _validate_raster(post_nbr_agg, func_name='dnbr', name='post_nbr_agg') @@ -280,6 +295,9 @@ def rdnbr(dnbr_agg: xr.DataArray, pre-fire vegetation density so that burn severity is comparable across different vegetation types. + Supports NumPy, CuPy, Dask with NumPy, and Dask with CuPy backed + xarray DataArrays; the output backend matches the input. + Parameters ---------- dnbr_agg : xr.DataArray @@ -294,6 +312,20 @@ def rdnbr(dnbr_agg: xr.DataArray, xr.DataArray RdNBR values (float32). Pixels where ``abs(pre_NBR) < 1e-7`` are set to NaN to avoid division by near-zero. + + Examples + -------- + .. sourcecode:: python + + >>> import numpy as np, xarray as xr + >>> from xrspatial.fire import rdnbr + >>> dnbr_agg = xr.DataArray( + ... np.array([[0.4, 0.3], [0.1, 0.2]], dtype='f4')) + >>> pre = xr.DataArray( + ... np.array([[500., 200.], [300., 400.]], dtype='f4')) + >>> rdnbr(dnbr_agg, pre).values + array([[0.56568545, 0.6708204 ], + [0.18257418, 0.31622776]], dtype=float32) """ _validate_raster(dnbr_agg, func_name='rdnbr', name='dnbr_agg') _validate_raster(pre_nbr_agg, func_name='rdnbr', name='pre_nbr_agg') @@ -408,6 +440,9 @@ def burn_severity_class(dnbr_agg: xr.DataArray, 3 = unburned, 4 = low severity, 5 = moderate-low, 6 = moderate-high, 7 = high severity. 0 = nodata. + Supports NumPy, CuPy, Dask with NumPy, and Dask with CuPy backed + xarray DataArrays; the output backend matches the input. + Parameters ---------- dnbr_agg : xr.DataArray or xr.Dataset @@ -419,6 +454,18 @@ def burn_severity_class(dnbr_agg: xr.DataArray, ------- xr.DataArray int8 class labels (0-7). + + Examples + -------- + .. sourcecode:: python + + >>> import numpy as np, xarray as xr + >>> from xrspatial.fire import burn_severity_class + >>> dnbr_agg = xr.DataArray( + ... np.array([[-0.3, 0.05], [0.3, 0.7]], dtype='f4')) + >>> burn_severity_class(dnbr_agg).values + array([[1, 3], + [5, 7]], dtype=int8) """ _validate_raster(dnbr_agg, func_name='burn_severity_class', name='dnbr_agg') @@ -492,6 +539,9 @@ def fireline_intensity(fuel_consumed_agg: xr.DataArray, ``I = H * w * R`` where *H* is heat content (kJ/kg), *w* is fuel consumed (kg/m^2), and *R* is rate of spread (m/s). + Supports NumPy, CuPy, Dask with NumPy, and Dask with CuPy backed + xarray DataArrays; the output backend matches the input. + Parameters ---------- fuel_consumed_agg : xr.DataArray @@ -507,6 +557,17 @@ def fireline_intensity(fuel_consumed_agg: xr.DataArray, ------- xr.DataArray Fireline intensity in kW/m (float32). + + Examples + -------- + .. sourcecode:: python + + >>> import numpy as np, xarray as xr + >>> from xrspatial.fire import fireline_intensity + >>> fuel = xr.DataArray(np.array([[2.0, 0.5]], dtype='f4')) + >>> spread = xr.DataArray(np.array([[0.1, 0.2]], dtype='f4')) + >>> fireline_intensity(fuel, spread).values + array([[3600., 1800.]], dtype=float32) """ _validate_raster(fuel_consumed_agg, func_name='fireline_intensity', name='fuel_consumed_agg') @@ -592,6 +653,9 @@ def flame_length(intensity_agg: xr.DataArray, Uses Byram's equation: ``L = 0.0775 * I^0.46``. Negative or zero intensity yields zero flame length. + Supports NumPy, CuPy, Dask with NumPy, and Dask with CuPy backed + xarray DataArrays; the output backend matches the input. + Parameters ---------- intensity_agg : xr.DataArray or xr.Dataset @@ -603,6 +667,16 @@ def flame_length(intensity_agg: xr.DataArray, ------- xr.DataArray Flame length in metres (float32). + + Examples + -------- + .. sourcecode:: python + + >>> import numpy as np, xarray as xr + >>> from xrspatial.fire import flame_length + >>> intensity = xr.DataArray(np.array([[100., 500.]], dtype='f4')) + >>> flame_length(intensity).values + array([[0.6446169, 1.3515369]], dtype=float32) """ _validate_raster(intensity_agg, func_name='flame_length', name='intensity_agg') @@ -779,6 +853,9 @@ def rate_of_spread(slope_agg: xr.DataArray, Uses the Anderson 13 fuel model lookup table and computes per-pixel spread rate from slope, wind speed, and fuel moisture. + Supports NumPy, CuPy, Dask with NumPy, and Dask with CuPy backed + xarray DataArrays; the output backend matches the input. + Parameters ---------- slope_agg : xr.DataArray @@ -796,6 +873,19 @@ def rate_of_spread(slope_agg: xr.DataArray, ------- xr.DataArray Rate of spread in m/min (float32). + + Examples + -------- + .. sourcecode:: python + + >>> import numpy as np, xarray as xr + >>> from xrspatial.fire import rate_of_spread + >>> slope = xr.DataArray(np.full((2, 2), 10.0, dtype='f4')) + >>> wind = xr.DataArray(np.full((2, 2), 10.0, dtype='f4')) + >>> moisture = xr.DataArray(np.full((2, 2), 0.06, dtype='f4')) + >>> rate_of_spread(slope, wind, moisture, fuel_model=1).values + array([[106.6344, 106.6344], + [106.6344, 106.6344]], dtype=float32) """ _validate_raster(slope_agg, func_name='rate_of_spread', name='slope_agg') @@ -949,6 +1039,9 @@ def kbdi(kbdi_prev_agg: xr.DataArray, Advances the KBDI by one day given previous KBDI, daily max temperature, and daily precipitation. + Supports NumPy, CuPy, Dask with NumPy, and Dask with CuPy backed + xarray DataArrays; the output backend matches the input. + Parameters ---------- kbdi_prev_agg : xr.DataArray @@ -966,6 +1059,19 @@ def kbdi(kbdi_prev_agg: xr.DataArray, ------- xr.DataArray Updated KBDI values (float32), clamped to 0-800. + + Examples + -------- + .. sourcecode:: python + + >>> import numpy as np, xarray as xr + >>> from xrspatial.fire import kbdi + >>> prev = xr.DataArray(np.full((2, 2), 100.0, dtype='f4')) + >>> max_temp = xr.DataArray(np.full((2, 2), 30.0, dtype='f4')) + >>> precip = xr.DataArray(np.zeros((2, 2), dtype='f4')) + >>> kbdi(prev, max_temp, precip, annual_precip=1000.0).values + array([[138.4605, 138.4605], + [138.4605, 138.4605]], dtype=float32) """ _validate_raster(kbdi_prev_agg, func_name='kbdi', name='kbdi_prev_agg') _validate_raster(max_temp_agg, func_name='kbdi', name='max_temp_agg') From 4e7fc83fd395e7823839b2de9fb4877db26828e9 Mon Sep 17 00:00:00 2001 From: Brendan Collins Date: Thu, 25 Jun 2026 12:49:17 -0700 Subject: [PATCH 2/2] fire: use public top-level imports in docstring examples Address PR review: the Examples imported via the module path (from xrspatial.fire import X); switch to the public top-level export (from xrspatial import X) so the copy-paste path matches the public API and the rest of the docs. Outputs unchanged and still verified. --- xrspatial/fire.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/xrspatial/fire.py b/xrspatial/fire.py index 6e66f3e56..d53dd10e8 100644 --- a/xrspatial/fire.py +++ b/xrspatial/fire.py @@ -207,7 +207,7 @@ def dnbr(pre_nbr_agg: xr.DataArray, .. sourcecode:: python >>> import numpy as np, xarray as xr - >>> from xrspatial.fire import dnbr + >>> from xrspatial import dnbr >>> pre = xr.DataArray(np.array([[0.5, 0.6], [0.4, 0.3]], dtype='f4')) >>> post = xr.DataArray(np.array([[0.1, 0.2], [0.5, 0.1]], dtype='f4')) >>> dnbr(pre, post).values @@ -318,7 +318,7 @@ def rdnbr(dnbr_agg: xr.DataArray, .. sourcecode:: python >>> import numpy as np, xarray as xr - >>> from xrspatial.fire import rdnbr + >>> from xrspatial import rdnbr >>> dnbr_agg = xr.DataArray( ... np.array([[0.4, 0.3], [0.1, 0.2]], dtype='f4')) >>> pre = xr.DataArray( @@ -460,7 +460,7 @@ def burn_severity_class(dnbr_agg: xr.DataArray, .. sourcecode:: python >>> import numpy as np, xarray as xr - >>> from xrspatial.fire import burn_severity_class + >>> from xrspatial import burn_severity_class >>> dnbr_agg = xr.DataArray( ... np.array([[-0.3, 0.05], [0.3, 0.7]], dtype='f4')) >>> burn_severity_class(dnbr_agg).values @@ -563,7 +563,7 @@ def fireline_intensity(fuel_consumed_agg: xr.DataArray, .. sourcecode:: python >>> import numpy as np, xarray as xr - >>> from xrspatial.fire import fireline_intensity + >>> from xrspatial import fireline_intensity >>> fuel = xr.DataArray(np.array([[2.0, 0.5]], dtype='f4')) >>> spread = xr.DataArray(np.array([[0.1, 0.2]], dtype='f4')) >>> fireline_intensity(fuel, spread).values @@ -673,7 +673,7 @@ def flame_length(intensity_agg: xr.DataArray, .. sourcecode:: python >>> import numpy as np, xarray as xr - >>> from xrspatial.fire import flame_length + >>> from xrspatial import flame_length >>> intensity = xr.DataArray(np.array([[100., 500.]], dtype='f4')) >>> flame_length(intensity).values array([[0.6446169, 1.3515369]], dtype=float32) @@ -879,7 +879,7 @@ def rate_of_spread(slope_agg: xr.DataArray, .. sourcecode:: python >>> import numpy as np, xarray as xr - >>> from xrspatial.fire import rate_of_spread + >>> from xrspatial import rate_of_spread >>> slope = xr.DataArray(np.full((2, 2), 10.0, dtype='f4')) >>> wind = xr.DataArray(np.full((2, 2), 10.0, dtype='f4')) >>> moisture = xr.DataArray(np.full((2, 2), 0.06, dtype='f4')) @@ -1065,7 +1065,7 @@ def kbdi(kbdi_prev_agg: xr.DataArray, .. sourcecode:: python >>> import numpy as np, xarray as xr - >>> from xrspatial.fire import kbdi + >>> from xrspatial import kbdi >>> prev = xr.DataArray(np.full((2, 2), 100.0, dtype='f4')) >>> max_temp = xr.DataArray(np.full((2, 2), 30.0, dtype='f4')) >>> precip = xr.DataArray(np.zeros((2, 2), dtype='f4'))