Skip to content

Reject non-finite / float32-underflowing local_position_std - #45

Merged
edeno merged 1 commit into
mainfrom
harden-local-position-std-validation
Jul 11, 2026
Merged

edeno merged 1 commit into
mainfrom
harden-local-position-std-validation

Conversation

@edeno

@edeno edeno commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Ports the one piece of value left in #25 (closed as superseded): hardened
validation of local_position_std. The anchor-kernel and mass-balance work #25
carried already landed on main via other PRs, but main still only checks
local_position_std < 0.

Problem

_DetectorBase.__init__ gated solely on local_position_std < 0, so:

  • NaN / Inf slipped through (nan < 0 and inf < 0 are both False)
  • a positive width whose float32 square underflows to 0 — below
    sqrt(np.finfo(np.float32).tiny)1.085e-19 — passed too

Either then produced a NaN / divide-by-zero in the Local anchor kernel
(-0.5·d²/σ², evaluated in float32 where JAX flushes subnormals to zero).

Change

Raise ValidationError at construction for non-finite and float32-underflowing
widths, alongside the existing negative check. None (legacy single-bin Local)
and 0.0 (delta kernel) remain valid and unchanged — this only rejects inputs
that were already silently broken.

Consistent with the tier-1 "invalid input → raise" policy from #35.

Tests

Added to TestLocalPositionStdValidation: NaN/Inf/-Inf rejection (parametrized),
float32-square-underflow rejection, and a boundary-accept case at the threshold.
Verified they fail on main before the guard and pass after; the existing
negative-rejection test is unchanged. Full test_local_position_std.py (39) and
the test_local_spatial_uncertainty integration suite (10) pass; ruff clean.

🤖 Generated with Claude Code

_DetectorBase only checked `local_position_std < 0`, so NaN and Inf slipped
through (`nan < 0` and `inf < 0` are both False) and a positive value whose
float32 square underflows to 0 (below sqrt(float32 tiny) ~1.085e-19) passed too.
Both then produced NaN / divide-by-zero in the Local anchor kernel
(-0.5*d**2/sigma**2, evaluated in float32 with JAX flush-to-zero). Raise
ValidationError at __init__ for all three. None (legacy single-bin) and 0.0
(delta kernel) remain valid and unchanged.

Ports the validator hardening from the now-superseded PR #25; its anchor-kernel
and mass-balance work already landed on main via other PRs, and this was the only
piece main still lacked.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@edeno edeno mentioned this pull request Jul 11, 2026
8 tasks
@edeno
edeno merged commit fbf9d35 into main Jul 11, 2026
9 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