From bbf263d48fa9c9ec21134b19391b0adc1bb5954c Mon Sep 17 00:00:00 2001 From: Florian Pfaff <6773539+FlorianPfaff@users.noreply.github.com> Date: Tue, 18 Aug 2026 21:55:38 +0800 Subject: [PATCH 1/2] Initialize hyperhemispherical particles on manifold --- src/pyrecest/filters/hyperhemispherical_particle_filter.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/pyrecest/filters/hyperhemispherical_particle_filter.py b/src/pyrecest/filters/hyperhemispherical_particle_filter.py index f6e25b4016..3f70c9eacf 100644 --- a/src/pyrecest/filters/hyperhemispherical_particle_filter.py +++ b/src/pyrecest/filters/hyperhemispherical_particle_filter.py @@ -1,6 +1,6 @@ from numbers import Integral -from pyrecest.backend import empty +from pyrecest.backend import eye, tile from pyrecest.distributions.hypersphere_subset.abstract_hyperhemispherical_distribution import ( AbstractHyperhemisphericalDistribution, ) @@ -34,9 +34,8 @@ def __init__(self, n_particles: int, dim: int) -> None: """ n_particles = _validate_positive_integer(n_particles, "n_particles") dim = _validate_positive_integer(dim, "dim") - initial_filter_state = HyperhemisphericalDiracDistribution( - empty((n_particles, dim + 1)) - ) + initial_particles = tile(eye(dim + 1)[-1], (n_particles, 1)) + initial_filter_state = HyperhemisphericalDiracDistribution(initial_particles) HyperhemisphericalFilterMixin.__init__(self) AbstractParticleFilter.__init__(self, initial_filter_state=initial_filter_state) From 4a3ccdad05804cb3b3b0951a7a5083d6226963f4 Mon Sep 17 00:00:00 2001 From: Florian Pfaff <6773539+FlorianPfaff@users.noreply.github.com> Date: Tue, 18 Aug 2026 21:55:58 +0800 Subject: [PATCH 2/2] Add hyperhemispherical initialization regression --- .../test_hyperhemispherical_particle_filter.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/filters/test_hyperhemispherical_particle_filter.py b/tests/filters/test_hyperhemispherical_particle_filter.py index 3b142fc39e..73c271653b 100644 --- a/tests/filters/test_hyperhemispherical_particle_filter.py +++ b/tests/filters/test_hyperhemispherical_particle_filter.py @@ -4,7 +4,8 @@ import pyrecest.backend # pylint: disable=redefined-builtin,no-name-in-module,no-member -from pyrecest.backend import array, linalg, random +from pyrecest.backend import all as backend_all +from pyrecest.backend import allclose, array, linalg, random from pyrecest.distributions import HyperhemisphericalWatsonDistribution from pyrecest.distributions.hypersphere_subset.hyperhemispherical_dirac_distribution import ( HyperhemisphericalDiracDistribution, @@ -33,6 +34,14 @@ def test_initialization(self): self.assertEqual(hpf.filter_state.w.shape, (self.n_particles,)) self.assertEqual(hpf.filter_state.d.shape, (self.n_particles, 4)) + def test_initialization_uses_valid_upper_hemisphere_points(self): + hpf = HyperhemisphericalParticleFilter(5, 3) + + particle_norms = linalg.norm(hpf.filter_state.d, axis=1) + self.assertTrue(bool(allclose(particle_norms, 1.0))) + self.assertTrue(bool(backend_all(hpf.filter_state.d[:, -1] >= 0.0))) + self.assertTrue(bool(allclose(hpf.filter_state.d[:, -1], 1.0))) + def test_constructor_rejects_invalid_particle_count(self): for n_particles in (True, 0, -1, 1.5): with self.subTest(n_particles=n_particles):