Skip to content

Commit

Permalink
restore _inertia_eigvals_to_axes_lengths_3D for use in test case
Browse files Browse the repository at this point in the history
  • Loading branch information
grlee77 committed Mar 4, 2025
1 parent df640e3 commit 597784a
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 4 deletions.
4 changes: 1 addition & 3 deletions python/cucim/src/cucim/skimage/measure/_regionprops.py
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,6 @@ def axis_major_length(self):
l1 = self.inertia_tensor_eigvals[0]
return 4 * math.sqrt(l1)
elif self._ndim == 3:
# equivalent to _inertia_eigvals_to_axes_lengths_3D(ev)[0]
ev = self.inertia_tensor_eigvals
return math.sqrt(10 * (ev[0] + ev[1] - ev[2]))
else:
Expand All @@ -578,11 +577,10 @@ def axis_minor_length(self):
l2 = self.inertia_tensor_eigvals[-1]
return 4 * math.sqrt(l2)
elif self._ndim == 3:
# equivalent to _inertia_eigvals_to_axes_lengths_3D(ev)[-1]
ev = self.inertia_tensor_eigvals
# use max to avoid possibly very small negative value due to
# numeric error
return math.sqrt(max(10 * (-ev[0] + ev[1] + ev[2]), 0.0))
return math.sqrt(10 * max(-ev[0] + ev[1] + ev[2], 0.0))
else:
raise ValueError("axis_minor_length only available in 2D and 3D")

Expand Down
46 changes: 45 additions & 1 deletion python/cucim/src/cucim/skimage/measure/tests/test_regionprops.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
COL_DTYPES,
OBJECT_COLUMNS,
PROPS,
_inertia_eigvals_to_axes_lengths_3D,
_parse_docs,
_props_to_dict,
_require_intensity_image,
Expand Down Expand Up @@ -1402,6 +1401,51 @@ def test_multichannel():
assert_array_equal(p, p_multi[..., 1])


def _inertia_eigvals_to_axes_lengths_3D(inertia_tensor_eigvals):
"""Compute ellipsoid axis lengths from inertia tensor eigenvalues.
Parameters
---------
inertia_tensor_eigvals : sequence of float
A sequence of 3 floating point eigenvalues, sorted in descending order.
Returns
-------
axis_lengths : list of float
The ellipsoid axis lengths sorted in descending order.
Notes
-----
Let a >= b >= c be the ellipsoid semi-axes and s1 >= s2 >= s3 be the
inertia tensor eigenvalues.
The inertia tensor eigenvalues are given for a solid ellipsoid in [1]_.
s1 = 1 / 5 * (a**2 + b**2)
s2 = 1 / 5 * (a**2 + c**2)
s3 = 1 / 5 * (b**2 + c**2)
Rearranging to solve for a, b, c in terms of s1, s2, s3 gives
a = math.sqrt(5 / 2 * ( s1 + s2 - s3))
b = math.sqrt(5 / 2 * ( s1 - s2 + s3))
c = math.sqrt(5 / 2 * (-s1 + s2 + s3))
We can then simply replace sqrt(5/2) by sqrt(10) to get the full axes
lengths rather than the semi-axes lengths.
References
----------
..[1] https://en.wikipedia.org/wiki/List_of_moments_of_inertia#List_of_3D_inertia_tensors
""" # noqa: E501
axis_lengths = []
for ax in range(2, -1, -1):
w = sum(
v * -1 if i == ax else v
for i, v in enumerate(inertia_tensor_eigvals)
)
axis_lengths.append(math.sqrt(10 * w))
return axis_lengths


def test_3d_ellipsoid_axis_lengths():
"""Verify that estimated axis lengths are correct.
Expand Down

0 comments on commit 597784a

Please sign in to comment.