Skip to content

Commit

Permalink
adjustments on tests and parameter validation
Browse files Browse the repository at this point in the history
  • Loading branch information
tvcastillod committed Mar 29, 2024
1 parent dc41684 commit f4824f6
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 40 deletions.
49 changes: 30 additions & 19 deletions fury/actor.py
Original file line number Diff line number Diff line change
Expand Up @@ -3966,15 +3966,16 @@ def odf(
opacity=1.0
):
"""
VTK actor for visualizing ODFs given an array of spherical harmonics (SH)
coefficients.
FURY actor for visualizing Orientation Distribution Functions (ODFs) given
an array of Spherical Harmonics (SH) coefficients.
Parameters
----------
centers : ndarray(N, 3)
ODFs positions.
coeffs : ndarray
2D ODFs array in SH coefficients.
coeffs : (N, M) or (N, 6) or (N, 15) or (N, 28) or (N, 45) or (N, 66) or
(N, 91) ndarray.
Corresponding SH coefficients for the ODFs.
degree: int, optional
Index of the highest used band of the spherical harmonics basis. Must
be even, at least 2 and at most 12. If None the degree is set based on
Expand All @@ -3998,29 +3999,39 @@ def odf(
centers = np.array(centers)

Check warning on line 3999 in fury/actor.py

View check run for this annotation

Codecov / codecov/patch

fury/actor.py#L3999

Added line #L3999 was not covered by tests
if centers.ndim == 1:
centers = np.array([centers])

if not isinstance(coeffs, np.ndarray):
coeffs = np.array(coeffs)

Check warning on line 4004 in fury/actor.py

View check run for this annotation

Codecov / codecov/patch

fury/actor.py#L4004

Added line #L4004 was not covered by tests
if coeffs.ndim == 1:
coeffs = np.array([coeffs])
if coeffs.ndim != 2:
if coeffs.ndim == 1:
coeffs = np.array([coeffs])

Check warning on line 4007 in fury/actor.py

View check run for this annotation

Codecov / codecov/patch

fury/actor.py#L4007

Added line #L4007 was not covered by tests
else:
raise ValueError('coeffs should be a 2D array.')

Check warning on line 4009 in fury/actor.py

View check run for this annotation

Codecov / codecov/patch

fury/actor.py#L4009

Added line #L4009 was not covered by tests
if coeffs.shape[0] != centers.shape[0]:
raise ValueError('number of odf glyphs defined does not match with '
'number of centers')

coeffs_given = coeffs.shape[-1]
max_degree = int((np.sqrt(8 * coeffs_given + 1) - 3) / 2)
if degree is None:
degree = int((np.sqrt(8 * coeffs_given + 1) - 3)/2)
elif degree % 2 != 0:
raise ValueError('degree must be even')
coeffs_needed = int(((degree + 1) * (degree + 2)) / 2)
if coeffs_given < coeffs_needed:
print('Not enough number of coefficient for SH of degree {0}. '
'Expected at least {1}'.format(degree, coeffs_needed))
degree = int((np.sqrt(8 * coeffs_given + 1) - 3)/2)
if (degree % 2 != 0):
degree -= 1
coeffs_needed = int(((degree + 1) * (degree + 2)) / 2)
coeffs = coeffs[:, :coeffs_needed]
degree = max_degree
else:
if degree % 2 != 0:
warnings.warn('Invalid degree value. Degree must be a positive '
'even number lower or equal to 12. Ignoring passed '
'value and using maximum degree supported by the '
'number of SH coefficients.')
degree = max_degree
else:
coeffs_needed = int(((degree + 1) * (degree + 2)) / 2)
if coeffs_given < coeffs_needed:
warnings.warn('Not enough number of coefficient for SH of '
'degree {0}, expected at least {1}. Ignoring '
'passed value and using maximum degree supported '
'by the number of SH coefficients.'
.format(degree, coeffs_needed))
degree = max_degree
coeffs = coeffs[:, :int(((degree + 1) * (degree + 2)) / 2)]

if not isinstance(scales, np.ndarray):
scales = np.array(scales)
Expand Down
2 changes: 1 addition & 1 deletion fury/actors/odf.py
Original file line number Diff line number Diff line change
Expand Up @@ -369,4 +369,4 @@ def sh_odf(centers, coeffs, degree, basis_type, scales, opacity):

shader_to_actor(odf_actor, "fragment", impl_code=fs_impl, block="picking")

return odf_actor
return odf_actor
22 changes: 12 additions & 10 deletions fury/tests/test_actors.py
Original file line number Diff line number Diff line change
Expand Up @@ -1889,7 +1889,7 @@ def test_odf_actor(interactive=False):
coeffs = np.array([[0.282, 0.152, -0.040, -0.112, -0.045, 0.149],
[0.285, 0.097, -0.115, 0.125, -0.001, 0.003]])
npt.assert_raises(ValueError, actor.odf, centers, coeffs)

scene = window.Scene()
centers = np.array([[0, -1, 0], [1, -1, 0], [2, -1, 0]])
coeffs = np.array([
Expand All @@ -1912,19 +1912,19 @@ def test_odf_actor(interactive=False):
report = window.analyze_scene(scene)
npt.assert_equal(report.actors, 1)
scene.clear()

# given degree is not even
npt.assert_raises(ValueError, actor.odf, centers, coeffs, degree=3)
npt.assert_warns(UserWarning, actor.odf, centers, coeffs, 3)

centers= np.array([0, 0, 0])
centers = np.array([0, 0, 0])
coeffs = np.array([
[-0.2739740312099, 0.2526670396328, 1.8922271728516, 0.2878578901291,
-0.5339795947075, -0.2620058953762, 0.1580424904823, 0.0329004973173,
-0.1322413831949, -0.1332057565451, 1.0894461870193, -0.6319401264191,
-0.0416776277125, -1.0772529840469, 0.1423762738705, 0.7941166162491,
0.7490307092667, -0.3428381681442, 0.1024847552180, -0.0219132602215,
0.0499043911695, 0.2162453681231, 0.0921059995890, -0.2611238956451,
0.2549301385880,-0.4534865319729, 0.1922748684883, -0.6200597286224]
0.2549301385880, -0.4534865319729, 0.1922748684883, -0.6200597286224]
])
odf_actor = actor.odf(centers=centers, coeffs=coeffs, degree=6)
scene.add(odf_actor)
Expand All @@ -1938,19 +1938,21 @@ def test_odf_actor(interactive=False):

odf_actor = actor.odf(centers=centers, coeffs=coeffs, degree=4)
scene.add(odf_actor)

if interactive:
window.show(scene)

report = window.analyze_scene(scene)
npt.assert_equal(report.actors, 1)
scene.clear()

odf_actor = actor.odf(centers=centers, coeffs=coeffs, degree=8)
# not enough coefficients for given degree
npt.assert_warns(UserWarning, actor.odf, centers, coeffs, 8)
scene.add(odf_actor)

if interactive:
window.show(scene)

npt.assert_equal(report.actors, 1)
scene.clear()
14 changes: 11 additions & 3 deletions fury/tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -963,13 +963,21 @@ def test_set_actor_origin():


def test_minmax_normalization():
data = np.array([[1, 2, -1, 3], [4, -1, 3, 5], [-1, 9, 8, 0]])
data1d = np.array([2, -2, 5, -1, 8])
actual_data1d = minmax_norm(data1d)
expected_data1d = np.array([[0.4, 0. , 0.7, 0.1, 1. ]])
npt.assert_array_almost_equal(actual_data1d, expected_data1d, decimal=1)

data3d = np.array([[[2, 7, 7, 9], [2, -1, -3, 5]],
[[-4, 5, 6, 0], [1, 1, -9, 3]]])
npt.assert_raises(ValueError, utils.minmax_norm, data3d)

data = np.array([[1, 2, -1, 3], [4, -1, 3, 5], [-1, 9, 8, 0]])
actual = minmax_norm(data, axis=0)
expected = np.array([[0.4, 0.3, 0, 0.6], [1, 0, 0.444, 1], [0, 1, 1, 0]])
npt.assert_array_almost_equal(actual, expected, decimal=3)
actual = minmax_norm(data, axis=1)
expected = np.array([[0.5, 0.75, 0, 1], [0.833, 0, 0.666, 1],
expected = np.array([[0.5, 0.75, 0, 1], [0.833, 0, 0.666, 1],
[0, 1, 0.9, 0.1]])
npt.assert_array_almost_equal(actual, expected, decimal=3)

Expand All @@ -978,5 +986,5 @@ def test_minmax_normalization():
expected2 = np.array([[1, 3, 9, 6]])
npt.assert_array_equal(actual2, expected2)
actual2 = minmax_norm(data2, axis=1)
expected2 = np.array([[0, 0.25 , 1, 0.625]])
expected2 = np.array([[0, 0.25, 1, 0.625]])
npt.assert_array_almost_equal(actual2, expected2, decimal=3)
Empty file added fury/texture/tests/__init__.py
Empty file.
41 changes: 41 additions & 0 deletions fury/texture/tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import numpy as np
import numpy.testing as npt
from fury.texture.utils import uv_calculations

def test_uv_calculations():
uv_coords = uv_calculations(1)
expected_uv1 = np.array([
[0.001, 0.001], [0.001, 0.999], [0.999, 0.999], [0.999, 0.001],
[0.001, 0.001], [0.001, 0.999], [0.999, 0.999], [0.999, 0.001]
])
npt.assert_array_almost_equal(uv_coords, expected_uv1, decimal=3)

uv_coords = uv_calculations(3)
expected_uv3 = np.array([
[0.001, 0.667], [0.001, 0.999], [0.999, 0.999], [0.999, 0.667],
[0.001, 0.667], [0.001, 0.999], [0.999, 0.999], [0.999, 0.667],
[0.001, 0.334], [0.001, 0.665], [0.999, 0.665], [0.999, 0.334],
[0.001, 0.334], [0.001, 0.665], [0.999, 0.665], [0.999, 0.334],
[0.001, 0.001], [0.001, 0.332], [0.999, 0.332], [0.999, 0.001],
[0.001, 0.001], [0.001, 0.332], [0.999, 0.332], [0.999, 0.001]
])
npt.assert_array_almost_equal(uv_coords, expected_uv3, decimal=3)

uv_coords = uv_calculations(7)
expected_uv7 = np.array([
[0.001, 0.858], [0.001, 0.999], [0.999, 0.999], [0.999, 0.858],
[0.001, 0.858], [0.001, 0.999], [0.999, 0.999], [0.999, 0.858],
[0.001, 0.715], [0.001, 0.856], [0.999, 0.856], [0.999, 0.715],
[0.001, 0.715], [0.001, 0.856], [0.999, 0.856], [0.999, 0.715],
[0.001, 0.572], [0.001, 0.713], [0.999, 0.713], [0.999, 0.572],
[0.001, 0.572], [0.001, 0.713], [0.999, 0.713], [0.999, 0.572],
[0.001, 0.429], [0.001, 0.570], [0.999, 0.570], [0.999, 0.429],
[0.001, 0.429], [0.001, 0.570], [0.999, 0.570], [0.999, 0.429],
[0.001, 0.286], [0.001, 0.427], [0.999, 0.427], [0.999, 0.286],
[0.001, 0.286], [0.001, 0.427], [0.999, 0.427], [0.999, 0.286],
[0.001, 0.143], [0.001, 0.284], [0.999, 0.284], [0.999, 0.143],
[0.001, 0.143], [0.001, 0.284], [0.999, 0.284], [0.999, 0.143],
[0.001, 0.001], [0.001, 0.141], [0.999, 0.141], [0.999, 0.001],
[0.001, 0.001], [0.001, 0.141], [0.999, 0.141], [0.999, 0.001]
])
npt.assert_array_almost_equal(uv_coords, expected_uv7, decimal=3)
15 changes: 14 additions & 1 deletion fury/texture/utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
def uv_calculations(n):
"""Return UV coordinates based on the number of elements.
Parameters
----------
n : int
number of elements.
Returns
-------
uvs : ndrray
UV coordinates for each element.
"""
uvs = []
for i in range(0, n):
a = (n - (i + 1)) / n
Expand All @@ -15,4 +28,4 @@ def uv_calculations(n):
[0.999, a + 0.001],
]
)
return uvs
return uvs
12 changes: 6 additions & 6 deletions fury/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1599,7 +1599,7 @@ def set_actor_origin(actor, center=None):


def minmax_norm(data, axis=1):
"""Returns the min-max normalization of data
"""Returns the min-max normalization of data along an axis.
Parameters
----------
Expand All @@ -1621,11 +1621,11 @@ def minmax_norm(data, axis=1):
elif data.ndim > 2:
raise ValueError('the dimension of the array must be 2.')

min = data.min(axis=axis)
max = data.max(axis=axis)
if np.array_equal(min, max):
minimum = data.min(axis=axis)
maximum = data.max(axis=axis)
if np.array_equal(minimum, maximum):
return data
if (axis == 0):
return (data - min)/(max - min)
return (data - minimum)/(maximum - minimum)
if (axis == 1):
return (data - min[:, None])/(max - min)[:, None]
return (data - minimum[:, None])/(maximum - minimum)[:, None]

0 comments on commit f4824f6

Please sign in to comment.