From 960c9d9c635ba840d708e9e237376587d6c23b6c Mon Sep 17 00:00:00 2001 From: Florian Pfaff <6773539+FlorianPfaff@users.noreply.github.com> Date: Tue, 25 Aug 2026 18:30:27 +0800 Subject: [PATCH 1/2] Reject invalid replay-grid log likelihoods --- src/pyrecest/filters/replay_grid_likelihood.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/pyrecest/filters/replay_grid_likelihood.py b/src/pyrecest/filters/replay_grid_likelihood.py index 322cc6104b..e0cc987e8c 100644 --- a/src/pyrecest/filters/replay_grid_likelihood.py +++ b/src/pyrecest/filters/replay_grid_likelihood.py @@ -254,9 +254,10 @@ def adaptive_position_proposal_probability( def grid_proposal_weights(log_likelihood) -> np.ndarray: - """Convert finite grid log likelihoods to normalized proposal weights.""" + """Convert valid grid log likelihoods to normalized proposal weights.""" values = np.asarray(log_likelihood, dtype=float) + _validate_grid_log_likelihood_values(values) finite = np.isfinite(values) if not np.any(finite): raise ValueError("all grid log-likelihoods are non-finite") @@ -356,9 +357,15 @@ def _coerce_grid_values(values, expected_size: int) -> np.ndarray: values = np.asarray(values, dtype=float) if values.shape != (expected_size,): raise ValueError(f"log_likelihood must have shape ({expected_size},)") + _validate_grid_log_likelihood_values(values) return values +def _validate_grid_log_likelihood_values(values: np.ndarray) -> None: + if np.any(np.isnan(values) | np.isposinf(values)): + raise ValueError("log_likelihood must contain finite values or -np.inf") + + def _linear_rectilinear_grid_values( positions: np.ndarray, values: np.ndarray, @@ -433,8 +440,8 @@ def _nearest_grid_values( indices = _nearest_bin_indices(positions[finite_positions], bin_tree) nearest_values = values[indices] - # A non-finite grid value represents zero or undefined likelihood. Borrowing - # the minimum finite value from another bin would create spurious mass. + # A -inf grid value represents zero likelihood. Borrowing the minimum finite + # value from another bin would create spurious mass. nearest_values = np.where( np.isfinite(nearest_values), nearest_values, float(log_zero) ) From bcb54abcf7861c0e6cd8e55a14c21024be323849 Mon Sep 17 00:00:00 2001 From: Florian Pfaff <6773539+FlorianPfaff@users.noreply.github.com> Date: Tue, 25 Aug 2026 18:30:44 +0800 Subject: [PATCH 2/2] Add replay-grid nonfinite likelihood regressions --- ...t_replay_grid_log_likelihood_validation.py | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 tests/filters/test_replay_grid_log_likelihood_validation.py diff --git a/tests/filters/test_replay_grid_log_likelihood_validation.py b/tests/filters/test_replay_grid_log_likelihood_validation.py new file mode 100644 index 0000000000..fa3f46887c --- /dev/null +++ b/tests/filters/test_replay_grid_log_likelihood_validation.py @@ -0,0 +1,47 @@ +import unittest + +import numpy as np + +# pylint: disable=no-name-in-module +from pyrecest.filters import grid_proposal_weights, replay_grid_log_likelihood_values + + +class TestReplayGridLogLikelihoodValidation(unittest.TestCase): + def test_rejects_nan_and_positive_infinity(self): + bin_centers = np.asarray([[0.0], [1.0]]) + positions = np.asarray([[0.0]]) + + for invalid_value in (np.nan, np.inf): + log_likelihood = np.asarray([0.0, invalid_value]) + with self.subTest(invalid_value=invalid_value, api="lookup"): + with self.assertRaisesRegex( + ValueError, "finite values or -np.inf" + ): + replay_grid_log_likelihood_values( + positions, + log_likelihood, + bin_centers, + interpolation="nearest", + ) + with self.subTest(invalid_value=invalid_value, api="proposal"): + with self.assertRaisesRegex( + ValueError, "finite values or -np.inf" + ): + grid_proposal_weights(log_likelihood) + + def test_negative_infinity_remains_zero_likelihood(self): + bin_centers = np.asarray([[0.0], [1.0]]) + log_likelihood = np.asarray([0.0, -np.inf]) + + np.testing.assert_allclose(grid_proposal_weights(log_likelihood), [1.0, 0.0]) + looked_up = replay_grid_log_likelihood_values( + np.asarray([[1.0]]), + log_likelihood, + bin_centers, + interpolation="nearest", + ) + self.assertTrue(np.isneginf(looked_up[0])) + + +if __name__ == "__main__": + unittest.main()