Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions src/pyrecest/distributions/circle/von_mises_distribution.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,13 @@ def sample(self, n):
raise ValueError("n must be a positive integer.")
n = int(n)
return mod(
array(vonmises.rvs(kappa=float(self.kappa), loc=float(self.mu), size=n)),
array(
vonmises.rvs(
kappa=self._as_float_scalar(self.kappa, "kappa"),
loc=self._as_float_scalar(self.mu, "mu"),
size=n,
)
),
2.0 * pi,
)

Expand Down Expand Up @@ -155,8 +161,12 @@ def to_minus_pi_to_pi_range(angle):

@staticmethod
def _as_float_scalar(value, name: str) -> float:
value_array = array(value)
if value_array.shape not in ((), (1,)):
raise ValueError(f"{name} must be a scalar.")

try:
scalar = float(value)
scalar = float(value_array.reshape(()))
except (TypeError, ValueError) as exc:
raise ValueError(f"{name} must be a scalar.") from exc

Expand Down
3 changes: 1 addition & 2 deletions src/pyrecest/filters/bingham_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,6 @@ def update_identity(self, bv, z):
for i in range(n):
m_conj = self._conjugate(bv.M[:, i])
bv.M[:, i] = self._compose(z, m_conj)

self.filter_state = self.filter_state.multiply(bv)

def get_point_estimate(self):
Expand All @@ -178,7 +177,7 @@ def _conjugate(q):
For q = [w, x, y, z], conjugate = [w, -x, -y, -z].
For q = [a, b], conjugate = [a, -b].
"""
result = copy.copy(q)
result = pyrecest.backend.copy(q)
result[1:] = -result[1:]
return result

Expand Down
22 changes: 22 additions & 0 deletions tests/distributions/test_von_mises_length_one_scalars.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import numpy as np

from pyrecest.backend import array, to_numpy
from pyrecest.distributions import VonMisesDistribution


def test_set_mean_accepts_length_one_backend_array():
dist = VonMisesDistribution(array(0.0), array(2.0))

shifted = dist.set_mean(array([1.0]))
density_at_mode = np.asarray(to_numpy(shifted.pdf(array([1.0]))))

assert np.all(np.isfinite(density_at_mode))
assert np.all(density_at_mode > 0.0)


def test_sample_accepts_length_one_parameter_arrays():
dist = VonMisesDistribution(array([0.3]), array([2.0]))

samples = dist.sample(3)

assert samples.shape == (3,)
25 changes: 25 additions & 0 deletions tests/filters/test_bingham_filter_conjugate_independence.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import unittest

import numpy.testing as npt

import pyrecest.backend
from pyrecest.backend import array, to_numpy
from pyrecest.filters.bingham_filter import BinghamFilter


class TestBinghamFilterConjugateIndependence(unittest.TestCase):
@unittest.skipIf(
pyrecest.backend.__backend_name__ == "jax",
reason="BinghamFilter is not supported on the JAX backend",
)
def test_conjugate_does_not_mutate_input(self):
quaternion = array([1.0, 2.0, 3.0, 4.0])

conjugated = BinghamFilter._conjugate(quaternion)

npt.assert_allclose(to_numpy(quaternion), [1.0, 2.0, 3.0, 4.0])
npt.assert_allclose(to_numpy(conjugated), [1.0, -2.0, -3.0, -4.0])


if __name__ == "__main__":
unittest.main()
Loading