Skip to content

Commit

Permalink
Merge pull request #663 from ANTsX/expand-tests
Browse files Browse the repository at this point in the history
TESTS: expand tests for ops and plotting
  • Loading branch information
Nick Cullen, PhD authored May 25, 2024
2 parents b802655 + 0d84b0b commit e667c28
Show file tree
Hide file tree
Showing 9 changed files with 162 additions and 136 deletions.
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

0 comments on commit e667c28

Please sign in to comment.