Skip to content

Add Inf/-Inf regression tests for fire module#3500

Merged
brendancol merged 3 commits into
mainfrom
deep-sweep-test-coverage-fire-2026-06-25
Jun 26, 2026
Merged

Add Inf/-Inf regression tests for fire module#3500
brendancol merged 3 commits into
mainfrom
deep-sweep-test-coverage-fire-2026-06-25

Conversation

@brendancol

Copy link
Copy Markdown
Contributor

What

Adds 28 tests covering +Inf / -Inf inputs for every public function in xrspatial.fire: dnbr, rdnbr, burn_severity_class, fireline_intensity, flame_length, rate_of_spread, and kbdi.

Why

The fire kernels skip cells only on NaN (v != v), so non-finite-but-not-NaN values flow straight through the arithmetic. That path had no test. Probing all four backends shows the behavior is consistent and well defined, for example:

  • dnbr: inf - inf -> nan, inf - finite -> inf
  • burn_severity_class: +inf -> class 7, -inf -> class 1
  • kbdi: prev = inf clamps to 800
  • rate_of_spread: slope = inf -> nan

The new tests lock this contract so a later change to the finite-value guard cannot alter behavior unnoticed.

Coverage

Each function gets a numpy contract test (exact expected values) plus four-backend parity (numpy / cupy / dask+numpy / dask+cupy). All 28 ran and passed on a CUDA host. Full test_fire.py is green (101 passed).

Test-only change. No source behavior is modified.

From the test-coverage deep sweep (Cat 2: NaN/Inf edge cases).

The fire kernels guard only against NaN (v != v), so +Inf and -Inf
inputs flow through the per-pixel arithmetic. The resulting outputs are
well defined and match across numpy, cupy, dask+numpy, and dask+cupy,
but no test covered them.

Lock that contract with 28 tests: a per-function numpy contract check
plus four-backend parity for dnbr, rdnbr, burn_severity_class,
fireline_intensity, flame_length, rate_of_spread, and kbdi. Test-only
change; no source behavior is modified.

Update the test-coverage sweep state row for fire.
Address review nit on PR #3500: the kbdi numpy Inf contract pinned a
bare 43.95906. Add a comment explaining it is the post-clamp drought-
factor re-accumulation at temp=30, annual_precip=1500. Comment-only.
@brendancol

Copy link
Copy Markdown
Contributor Author

Review: Inf/-Inf regression tests for fire

Reviewed on a CUDA host. Test-only change: 28 new tests plus a state-CSV row. No source files touched. I re-ran the file (101 passed) and checked each locked contract value against the kernels.

Blockers

None.

Suggestions

None in the added code. I hand-checked every expected value in _INF_CONTRACTS against the kernel arithmetic and all seven match:

  • dnbr: inf - inf is nan, finite - inf is -inf, so [inf, -inf, -inf, nan] is right.
  • rdnbr: p = inf sends the denominator to inf, so d / sqrt(inf) is 0 in column 3.
  • burn_severity_class: +inf falls through to class 7, -inf lands in class 1.
  • rate_of_spread: moist = inf makes eta_M nan (via inf - inf in the polynomial), so that cell is nan; wind = inf stays inf.
  • kbdi: prev = inf and temp = inf both hit the 800 clamp; precip = inf zeroes the deficit, which then re-accumulates to ~43.96.

Nits

  • The kbdi numpy contract pinned the literal 43.95906 with no explanation. Addressed in 63ad5d9 with a comment noting it is the post-clamp drought-factor re-accumulation at temp=30, annual_precip=1500.
  • Pre-existing lint in this file, not from this PR and left alone to keep the change surgical: unused imports (functools.partial, math.exp, math.tan, ANDERSON_13, three assert_numpy_equals_* helpers), an unused func lambda at line 190, and an unused shape at line 533. Better as a separate cleanup than bolted onto a coverage PR.

What looks good

  • All four backends covered with the usual decorators. The cupy and dask+cupy legs actually ran on the GPU here, not skipped.
  • The parity tests reuse the same call builders as the numpy contract, so there is one definition per function.
  • The header comment says why the tests exist (the kernels only guard on v != v, so non-finite values pass straight through) and what change would break them.

Checklist

  • Backend parity: covered, 4 backends, GPU-validated
  • Inf handling: this is the coverage being added
  • Edge cases: Inf/-Inf now tested per function
  • No source behavior change: confirmed
  • Docstrings/README: not applicable, test-only
  • flake8: added code is clean at max-line-length 100

…age-fire-2026-06-25

# Conflicts:
#	.claude/sweep-test-coverage-state.csv
@brendancol brendancol merged commit 1a16d73 into main Jun 26, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant