diff --git a/skimage/novice/_novice.py b/skimage/novice/_novice.py index 767bb22a..72f06855 100644 --- a/skimage/novice/_novice.py +++ b/skimage/novice/_novice.py @@ -38,26 +38,25 @@ def _verify_picture_index(index): if isinstance(dim_slice, int): index[i] = dim_slice = slice(dim_slice, dim_slice + 1) - if dim_slice.start is not None and dim_slice.start < 0: - raise IndexError("Negative slicing not supported") - - if dim_slice.stop is not None and dim_slice.stop < 0: - raise IndexError("Negative slicing not supported") - if dim_slice.step is not None and dim_slice.step != 1: raise IndexError("Only a step size of 1 is supported") return tuple(index) +def rgb_transpose(array): + """Return RGB array with first 2 axes transposed.""" + return np.transpose(array, (1, 0, 2)) + + def array_to_xy_origin(image): """Return view of image transformed from array to Cartesian origin.""" - return np.transpose(image[::-1], (1, 0, 2)) + return rgb_transpose(image[::-1]) def xy_to_array_origin(image): """Return view of image transformed from Cartesian to array origin.""" - return np.transpose(image[:, ::-1], (1, 0, 2)) + return rgb_transpose(image[:, ::-1]) class Pixel(object): @@ -151,6 +150,10 @@ class Pixel(object): self._picture.xy_array[self._x, self._y] = self.rgb self._picture._array_modified() + def __eq__(self, other): + if isinstance(other, Pixel): + return self.rgb == other.rgb + def __repr__(self): args = self.red, self.green, self.blue return "Pixel(red={0}, green={1}, blue={2})".format(*args) @@ -396,8 +399,6 @@ class Picture(object): """Return `Picture`s for slices and `Pixel`s for indexes.""" xy_index = _verify_picture_index(xy_index) if all(isinstance(index, int) for index in xy_index): - if any(index < 0 for index in xy_index): - raise IndexError("Negative indices not supported") return self._makepixel(*xy_index) else: return Picture(xy_array=self.xy_array[xy_index]) diff --git a/skimage/novice/tests/test_novice.py b/skimage/novice/tests/test_novice.py index 40e572a0..214492b4 100644 --- a/skimage/novice/tests/test_novice.py +++ b/skimage/novice/tests/test_novice.py @@ -4,7 +4,8 @@ import tempfile import numpy as np from numpy.testing import assert_equal, raises, assert_allclose from skimage import novice -from skimage.novice._novice import array_to_xy_origin, xy_to_array_origin +from skimage.novice._novice import (array_to_xy_origin, xy_to_array_origin, + rgb_transpose) from skimage import data_dir @@ -164,7 +165,7 @@ def test_picture_slice(): assert_allclose(subpic.array, array[x_slice, :]) -def test_slicing(): +def test_move_slice(): h, w = 3, 12 array = _array_2d_to_RGB(np.linspace(0, 255, h * w).reshape(h, w)) array = array.astype(np.uint8) @@ -184,6 +185,26 @@ def test_slicing(): assert pic[:rest, :] == pic_orig[cut:, :] +def test_negative_index(): + n = 10 + array = _array_2d_to_RGB(np.arange(0, n)[np.newaxis, :]) + # Test both x and y indices. + pic = novice.Picture(array=array) + assert pic[-1, 0] == pic[n - 1, 0] + pic = novice.Picture(array=rgb_transpose(array)) + assert pic[0, -1] == pic[0, n - 1] + + +def test_negative_slice(): + n = 10 + array = _array_2d_to_RGB(np.arange(0, n)[np.newaxis, :]) + # Test both x and y slices. + pic = novice.Picture(array=array) + assert pic[-3:, 0] == pic[n - 3:, 0] + pic = novice.Picture(array=rgb_transpose(array)) + assert pic[0, -3:] == pic[0, n - 3:] + + @raises(IndexError) def test_1d_getitem_raises(): pic = novice.Picture.from_size((1, 1)) @@ -214,18 +235,6 @@ def test_getitem_with_step_raises(): pic[::2, ::2] -@raises(IndexError) -def test_negative_index_raises(): - pic = novice.Picture.from_size((1, 1)) - pic[-1, -1] - - -@raises(IndexError) -def test_negative_slice_raises(): - pic = novice.Picture.from_size((1, 1)) - pic[-1:, -1:] - - @raises(IndexError) def test_out_of_bounds_indexing(): pic = novice.open(SMALL_IMAGE_PATH)