diff --git a/src/pyrecest/tracking/ellipse_geometry.py b/src/pyrecest/tracking/ellipse_geometry.py index 12b41bdfb5..163e55f633 100644 --- a/src/pyrecest/tracking/ellipse_geometry.py +++ b/src/pyrecest/tracking/ellipse_geometry.py @@ -146,7 +146,7 @@ def wrap_ellipse_angle_to_reference(reference, theta): def ellipse_extent_matrix(orientation, semi_axes): """Return the SPD extent matrix encoded by ``orientation`` and semi-axes.""" - semi_axes = maximum(asarray(semi_axes).reshape(2), 0.0) + semi_axes = backend_abs(asarray(semi_axes).reshape(2)) rotation = rotation_matrix_2d(orientation) return symmetrize(rotation @ diag(semi_axes**2) @ rotation.T) diff --git a/tests/tracking/test_ellipse_extent_negative_axes.py b/tests/tracking/test_ellipse_extent_negative_axes.py new file mode 100644 index 0000000000..f603891cdb --- /dev/null +++ b/tests/tracking/test_ellipse_extent_negative_axes.py @@ -0,0 +1,25 @@ +from __future__ import annotations + +import numpy as np +import numpy.testing as npt + +from pyrecest.tracking import ellipse_extent_matrix, extent_matrix_from_shape + + +def test_extent_matrix_is_invariant_to_axis_sign_representation() -> None: + theta = 0.3 + positive_axes = np.array([3.0, 1.0]) + signed_axes = np.array([-3.0, -1.0]) + + expected = ellipse_extent_matrix(theta, positive_axes) + + npt.assert_allclose( + ellipse_extent_matrix(theta, signed_axes), + expected, + atol=1e-12, + ) + npt.assert_allclose( + extent_matrix_from_shape(np.array([theta, *signed_axes])), + expected, + atol=1e-12, + )