diff --git a/ants/ops/iMath.py b/ants/ops/iMath.py index d6fd5a60..c668753d 100644 --- a/ants/ops/iMath.py +++ b/ants/ops/iMath.py @@ -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) diff --git a/ants/ops/reorient_image.py b/ants/ops/reorient_image.py index a4079210..973dcc0e 100644 --- a/ants/ops/reorient_image.py +++ b/ants/ops/reorient_image.py @@ -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') diff --git a/ants/plotting/plot.py b/ants/plotting/plot.py index b340f66c..5771c30e 100644 --- a/ants/plotting/plot.py +++ b/ants/plotting/plot.py @@ -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) @@ -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: @@ -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: @@ -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) diff --git a/ants/plotting/plot_ortho.py b/ants/plotting/plot_ortho.py index 13ea50f5..5fa35e06 100644 --- a/ants/plotting/plot_ortho.py +++ b/ants/plotting/plot_ortho.py @@ -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: @@ -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: diff --git a/ants/plotting/plot_ortho_stack.py b/ants/plotting/plot_ortho_stack.py index 806d3873..c2832e31 100644 --- a/ants/plotting/plot_ortho_stack.py +++ b/ants/plotting/plot_ortho_stack.py @@ -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: diff --git a/ants/utils/scalar_rgb_vector.py b/ants/utils/scalar_rgb_vector.py index 30d69e21..bd17a124 100644 --- a/ants/utils/scalar_rgb_vector.py +++ b/ants/utils/scalar_rgb_vector.py @@ -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): @@ -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): @@ -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() """ @@ -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() """ diff --git a/tests/test_bugs.py b/tests/test_bugs.py index ede057e4..7df080da 100644 --- a/tests/test_bugs.py +++ b/tests/test_bugs.py @@ -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 diff --git a/tests/test_ops.py b/tests/test_ops.py index c981566d..c059c4e6 100644 --- a/tests/test_ops.py +++ b/tests/test_ops.py @@ -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 diff --git a/tests/test_plotting.py b/tests/test_plotting.py index af76353a..35e5b64f 100644 --- a/tests/test_plotting.py +++ b/tests/test_plotting.py @@ -54,6 +54,39 @@ def test_extra_plot(self): img = ants.image_read(ants.get_ants_data('mni')) ants.plot(img, overlay=img*2, reorient=True, crop=True) + def test_random(self): + img = ants.image_read(ants.get_ants_data('r16')) + img3 = ants.image_read(ants.get_data('r64')) + img2 = ants.image_read(ants.get_ants_data('mni')) + imgv = ants.merge_channels([img2]) + + ants.plot(img2, axis='x', scale=True, ncol=1) + ants.plot(img2, axis='y', scale=(0.05, 0.95)) + ants.plot(img2, axis='z', slices=[10,20,30], title='Test', cbar=True, + cbar_vertical=True) + ants.plot(img2, cbar=True, cbar_vertical=False) + ants.plot(img, black_bg=False, title='Test', cbar=True) + imgx = img2.clone() + imgx.set_spacing((10,1,1)) + ants.plot(imgx) + ants.plot(ants.get_ants_data('r16'), overlay=ants.get_data('r64'), blend=True) + with self.assertRaises(Exception): + ants.plot(ants.get_ants_data('r16'), overlay=123) + with self.assertRaises(Exception): + ants.plot(ants.get_ants_data('r16'), overlay=ants.merge_channels([img,img])) + ants.plot(ants.from_numpy(np.zeros((100,100)))) + ants.plot(img.clone('unsigned int')) + + ants.plot(img, domain_image_map=img3) + + with self.assertRaises(Exception): + ants.plot(123) + + + + + + class TestModule_plot_ortho(unittest.TestCase): @@ -78,6 +111,35 @@ def test_plot_extra(self): img = ants.image_read(ants.get_ants_data('mni')) ants.plot_ortho(img, overlay=img*2, reorient=True, crop=True) + def test_random_params(self): + img = ants.image_read(ants.get_ants_data('mni')).resample_image((4,4,4)) + img2 = ants.image_read(ants.get_data('r16')) + ants.plot_ortho(ants.get_data('mni'), overlay=ants.get_data('mni')) + with self.assertRaises(Exception): + ants.plot_ortho(123) + with self.assertRaises(Exception): + ants.plot_ortho(img2) + with self.assertRaises(Exception): + ants.plot_ortho(img, overlay=img2) + + imgx = img.clone() + imgx.set_spacing((3,3,3)) + ants.plot_ortho(img,overlay=imgx) + ants.plot_ortho(img.clone('unsigned int'),overlay=img, blend=True) + + imgx = img.clone() + imgx.set_spacing((10,1,1)) + ants.plot_ortho(imgx) + + ants.plot_ortho(img, flat=True, title='Test', text='This is a test') + ants.plot_ortho(img, title='Test', text='This is a test', cbar=True) + + with self.assertRaises(Exception): + ants.plot_ortho(img, domain_image_map=123) + + with self.assertRaises(Exception): + ants.plot_orto(ants.merge_channels([img,img])) + class TestModule_plot_ortho_stack(unittest.TestCase): @@ -178,8 +240,41 @@ def test_examples(self): rfontsize=16, cfontsize=16) +class TestModule_plot_ortho_stack(unittest.TestCase): - + def setUp(self): + pass + def tearDown(self): + pass + def test_random_ortho_stack_params(self): + img = ants.image_read(ants.get_data('mni')).resample_image((4,4,4)) + img2 = ants.image_read(ants.get_data('r16')).resample_image((4,4)) + + ants.plot_ortho_stack([ants.get_data('mni'), ants.get_data('mni')]) + ants.plot_ortho_stack([ants.get_data('mni'), ants.get_data('mni')], + overlays=[ants.get_data('mni'), ants.get_data('mni')]) + + with self.assertRaises(Exception): + ants.plot_ortho_stack([1,2,3]) + with self.assertRaises(Exception): + ants.plot_ortho_stack([img2,img2]) + with self.assertRaises(Exception): + ants.plot_ortho_stack([img,img], overlays=[img2,img2]) + with self.assertRaises(Exception): + ants.plot_ortho_stack([img,img], overlays=[1,2]) + + imgx = img.clone() + imgx.set_spacing((2,2,2)) + ants.plot_ortho_stack([img,imgx]) + + imgx.set_spacing((2,1,1)) + ants.plot_ortho_stack([imgx,img]) + + ants.plot_ortho_stack([img,img], scale=True, transpose=True, + title='Test', colpad=1, rowpad=1, + xyz_lines=True) + ants.plot_ortho_stack([img,img], scale=(0.05,0.95)) + if __name__ == '__main__': run_tests()