Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TESTS: expand tests for ops and plotting #663

Merged
merged 3 commits into from
May 25, 2024
Merged
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
4 changes: 0 additions & 4 deletions ants/ops/iMath.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,6 @@ def iMath_ops():
def iMath_canny(image, sigma, lower, upper):
return iMath(image, 'Canny', sigma, lower, upper)

@image_method
def iMath_distance_map(image, use_spacing=True):
return iMath(image, 'DistanceMap', use_spacing)

@image_method
def iMath_fill_holes(image, hole_type=2):
return iMath(image, 'FillHoles', hole_type)
Expand Down
3 changes: 3 additions & 0 deletions ants/ops/reorient_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ def reorient_image2(image, orientation='RAS'):
>>> mni = ants.image_read(ants.get_data('mni'))
>>> mni2 = mni.reorient_image2()
"""
if image.has_components:
return ants.merge_channels([img.reorient_image2(orientation) for img in ants.split_channels(image)])

if image.dimension != 3:
raise ValueError('image must have 3 dimensions')

Expand Down
61 changes: 13 additions & 48 deletions ants/plotting/plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,9 +205,6 @@ def rotate180_matrix(x):
def rotate90_matrix(x):
return x.T

def flip_matrix(x):
return mirror_matrix(rotate180_matrix(x))

def reorient_slice(x, axis):
if axis != 2:
x = rotate90_matrix(x)
Expand Down Expand Up @@ -235,12 +232,12 @@ def reorient_slice(x, axis):

# handle `overlay` argument
if overlay is not None:
if isinstance(overlay, str):
overlay = ants.image_read(overlay)
if vminol is None:
vminol = overlay.min()
if vmaxol is None:
vmaxol = overlay.max()
if isinstance(overlay, str):
overlay = ants.image_read(overlay)
if not ants.is_image(overlay):
raise ValueError("overlay argument must be an ANTsImage")
if overlay.components > 1:
Expand All @@ -258,32 +255,16 @@ def reorient_slice(x, axis):

# handle `domain_image_map` argument
if domain_image_map is not None:
if ants.is_image(domain_image_map):
tx = ants.new_ants_transform(
precision="float",
transform_type="AffineTransform",
dimension=image.dimension,
tx = ants.new_ants_transform(
precision="float",
transform_type="AffineTransform",
dimension=image.dimension,
)
image = ants.apply_ants_transform_to_image(tx, image, domain_image_map)
if overlay is not None:
overlay = ants.apply_ants_transform_to_image(
tx, overlay, domain_image_map, interpolation="nearestNeighbor"
)
image = ants.apply_ants_transform_to_image(tx, image, domain_image_map)
if overlay is not None:
overlay = ants.apply_ants_transform_to_image(
tx, overlay, domain_image_map, interpolation="nearestNeighbor"
)
elif isinstance(domain_image_map, (list, tuple)):
# expect an image and transformation
if len(domain_image_map) != 2:
raise ValueError("domain_image_map list or tuple must have length == 2")

dimg = domain_image_map[0]
if not ants.is_image(dimg):
raise ValueError("domain_image_map first entry should be ANTsImage")

tx = domain_image_map[1]
image = ants.apply_transforms(dimg, image, transform_list=tx)
if overlay is not None:
overlay = ants.apply_transforms(
dimg, overlay, transform_list=tx, interpolator="linear"
)

## single-channel images ##
if image.components == 1:
Expand Down Expand Up @@ -489,24 +470,8 @@ def reorient_slice(x, axis):
fig.colorbar(im, cax=cax, orientation=cbar_orient)

## multi-channel images ##
elif image.components > 1:
if not image.is_rgb:
if not image.components == 3:
raise ValueError("Multi-component images only supported if they have 3 components")

img_arr = image.numpy()
img_arr = img_arr / img_arr.max()
img_arr = np.stack(
[rotate90_matrix(img_arr[:, :, i]) for i in range(3)], axis=-1
)

fig = plt.figure()
ax = plt.subplot(111)

# plot main image
ax.imshow(img_arr, alpha=alpha)

plt.axis("off")
elif image.has_components:
raise Exception('Plotting images with components is not currently supported.')

if filename is not None:
filename = os.path.expanduser(filename)
Expand Down
21 changes: 4 additions & 17 deletions ants/plotting/plot_ortho.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,10 +220,10 @@ def reorient_slice(x, axis):

# handle `overlay` argument
if overlay is not None:
vminol = overlay.min()
vmaxol = overlay.max()
if isinstance(overlay, str):
overlay = ants.image_read(overlay)
vminol = overlay.min()
vmaxol = overlay.max()
if not ants.is_image(overlay):
raise ValueError("overlay argument must be an ANTsImage")
if overlay.components > 1:
Expand Down Expand Up @@ -302,21 +302,8 @@ def reorient_slice(x, axis):
overlay = ants.apply_ants_transform_to_image(
tx, overlay, domain_image_map, interpolation="linear"
)
elif isinstance(domain_image_map, (list, tuple)):
# expect an image and transformation
if len(domain_image_map) != 2:
raise ValueError("domain_image_map list or tuple must have length == 2")

dimg = domain_image_map[0]
if not ants.is_image(dimg):
raise ValueError("domain_image_map first entry should be ANTsImage")

tx = domain_image_map[1]
image = ants.apply_transforms(dimg, image, transform_list=tx)
if overlay is not None:
overlay = ants.apply_transforms(
dimg, overlay, transform_list=tx, interpolator="linear"
)
else:
raise Exception('The domain_image_map must be an image.')

## single-channel images ##
if image.components == 1:
Expand Down
18 changes: 2 additions & 16 deletions ants/plotting/plot_ortho_stack.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,22 +201,8 @@ def reorient_slice(x, axis):
overlays[i] = ants.apply_ants_transform_to_image(
tx, overlays[i], domain_image_map, interpolation="linear"
)
elif isinstance(domain_image_map, (list, tuple)):
# expect an image and transformation
if len(domain_image_map) != 2:
raise ValueError("domain_image_map list or tuple must have length == 2")

dimg = domain_image_map[0]
if not ants.is_image(dimg):
raise ValueError("domain_image_map first entry should be ANTsImage")

tx = domain_image_map[1]
for i in range(n_images):
images[i] = ants.apply_transforms(dimg, images[i], transform_list=tx)
if overlays[i] is not None:
overlays[i] = ants.apply_transforms(
dimg, overlays[i], transform_list=tx, interpolator="linear"
)
else:
raise Exception('The domain_image_map must be an ants image.')

# potentially find dynamic range
if scale == True:
Expand Down
54 changes: 4 additions & 50 deletions ants/utils/scalar_rgb_vector.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
from ants.internal import get_lib_fn, process_arguments
from ants.decorators import image_method

@image_method
def scalar_to_rgb(image, mask=None, filename=None, cmap='red', custom_colormap_file=None,
min_input=None, max_input=None, min_rgb_output=None, max_rgb_output=None,
vtk_lookup_table=None):
Expand All @@ -27,54 +26,9 @@ def scalar_to_rgb(image, mask=None, filename=None, cmap='red', custom_colormap_f
-------
>>> import ants
>>> img = ants.image_read(ants.get_data('r16'))
>>> img_color = img.scalar_to_rgb(cmap='jet')
>>> img_color = ants.scalar_to_rgb(img, cmap='jet')
"""

if filename is None:
file_is_temp = True
filename = mktemp(suffix='.png')
else:
file_is_temp = False

args = 'imageDimension inputImage outputImage mask colormap'.split(' ')
args[0] = image.dimension

if ants.is_image(image):
tmpimgfile = mktemp(suffix='.nii.gz')
image.to_file(tmpimgfile)
elif isinstance(image, str):
tmpimgfile = image
args[1] = tmpimgfile
args[2] = filename
args[3] = mask if mask is not None else image.new_image_like(np.ones(image.shape))
args[4] = cmap
if custom_colormap_file is not None:
args.append('customColormapFile=%s' % custom_colormap_file)
if min_input is not None:
args.append('minimumInput=%f' % min_input)
if max_input is not None:
args.append('maximumInput=%f' % max_input)
if min_rgb_output is not None:
args.append('minRGBOutput=%f' % min_rgb_output)
if max_rgb_output is not None:
args.append('maxRGBOutput=%f' % min_rgb_output)
if vtk_lookup_table is not None:
vtk_lookup_table = mktemp(suffix='.csv')
args.append('vtkLookupTable=%s' % vtk_lookup_table)

processed_args = process_arguments(args)
libfn = get_lib_fn('ConvertScalarImageToRGB')
libfn(processed_args)

if file_is_temp:
outimg = ants.image_read(filename, pixeltype=None)
# clean up temp files
os.remove(filename)
os.remove(tmpimgfile)

return outimg
else:
os.remove(tmpimgfile)
raise Exception('This function is currently not supported.')

@image_method
def rgb_to_vector(image):
Expand All @@ -94,7 +48,7 @@ def rgb_to_vector(image):
-------
>>> import ants
>>> mni = ants.image_read(ants.get_data('mni'))
>>> mni_rgb = mni.scalar_to_rgb()
>>> mni_rgb = ants.scalar_to_rgb(mni)
>>> mni_vector = mni.rgb_to_vector()
>>> mni_rgb2 = mni.vector_to_rgb()
"""
Expand Down Expand Up @@ -124,7 +78,7 @@ def vector_to_rgb(image):
-------
>>> import ants
>>> img = ants.image_read(ants.get_data('r16'), pixeltype='unsigned char')
>>> img_rgb = img.clone().scalar_to_rgb()
>>> img_rgb = ants.scalar_to_rgb(img.clone())
>>> img_vec = img_rgb.rgb_to_vector()
>>> img_rgb2 = img_vec.vector_to_rgb()
"""
Expand Down
7 changes: 7 additions & 0 deletions tests/test_bugs.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,13 @@ def test_bspline_image_with_2d_weights(self):
number_of_fitting_levels=number_of_fitting_levels,
mesh_size=1)


def test_scalar_rgb_missing(self):
import ants
img = ants.image_read(ants.get_data('r16'))
with self.assertRaises(Exception):
img_color = ants.scalar_to_rgb(img, cmap='jet')

def test_bspline_zeros(self):
import ants
import numpy as np
Expand Down
33 changes: 33 additions & 0 deletions tests/test_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,39 @@
import numpy.testing as nptest


class Test_iMath(unittest.TestCase):


def setUp(self):
pass

def tearDown(self):
pass

def test_functions(self):
image = ants.image_read(ants.get_data('r16'))
ants.iMath_canny(image, sigma=2, lower=0, upper=1)
ants.iMath_fill_holes(image, hole_type=2)
ants.iMath_GC(image, radius=1)
ants.iMath_GD(image, radius=1)
ants.iMath_GE(image, radius=1)
ants.iMath_GO(image, radius=1)
ants.iMath_get_largest_component(image, min_size=50)
ants.iMath_grad(image, sigma=0.5, normalize=False)
ants.iMath_histogram_equalization(image, alpha=0.5, beta=0.5)
ants.iMath_laplacian(image, sigma=0.5, normalize=False)
ants.iMath_MC(image, radius=1, value=1, shape=1, parametric=False, lines=3, thickness=1, include_center=False)
ants.iMath_MD(image, radius=1, value=1, shape=1, parametric=False, lines=3, thickness=1, include_center=False)
ants.iMath_ME(image, radius=1, value=1, shape=1, parametric=False, lines=3, thickness=1, include_center=False)
ants.iMath_MO(image, radius=1, value=1, shape=1, parametric=False, lines=3, thickness=1, include_center=False)
ants.iMath_maurer_distance(image, foreground=1)
ants.iMath_normalize(image)
ants.iMath_pad(image, padding=2)
ants.iMath_perona_malik(image, conductance=0.25, n_iterations=1)
ants.iMath_sharpen(image)
ants.iMath_truncate_intensity(image, lower_q=0.05, upper_q=0.95, n_bins=64)


class Test_slice_image(unittest.TestCase):
"""
Test ants.ANTsImage class
Expand Down
Loading