From e7b7bfa5ea4e37409c1a0f8d8269edec5809a5e8 Mon Sep 17 00:00:00 2001 From: Florian Pfaff <6773539+FlorianPfaff@users.noreply.github.com> Date: Mon, 13 Jul 2026 11:54:11 +0200 Subject: [PATCH 1/2] Preserve signed ellipse axes in extent conversion --- src/pyrecest/tracking/ellipse_geometry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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) From 7b1fbe2d3510679e3c22ca19be6237fc94a6072e Mon Sep 17 00:00:00 2001 From: Florian Pfaff <6773539+FlorianPfaff@users.noreply.github.com> Date: Mon, 13 Jul 2026 11:54:24 +0200 Subject: [PATCH 2/2] Test signed ellipse-axis extent invariance --- .../test_ellipse_extent_negative_axes.py | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 tests/tracking/test_ellipse_extent_negative_axes.py 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, + )