From 0036dc9775de0260d56ac55197c9fbb812ec9113 Mon Sep 17 00:00:00 2001 From: "Jonathan J. Helmus" Date: Fri, 20 Jul 2012 15:09:18 -0400 Subject: [PATCH 1/4] ImageCollection now supports slicing --- skimage/io/collection.py | 54 +++++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/skimage/io/collection.py b/skimage/io/collection.py index e698b52b..e83a5b18 100644 --- a/skimage/io/collection.py +++ b/skimage/io/collection.py @@ -5,6 +5,7 @@ from __future__ import with_statement __all__ = ['MultiImage', 'ImageCollection', 'imread'] from glob import glob +from copy import copy import numpy as np from ._io import imread @@ -250,29 +251,58 @@ class ImageCollection(object): return self._conserve_memory def __getitem__(self, n): - """Return image n in the collection. + """Return selected image(s) in the collection. Loading is done on demand. Parameters ---------- - n : int - The image number to be returned. + n : int or slice + Slice selecting images for the new ImageCollection or the image + number to be returned. Returns ------- - img : ndarray - The `n`-th image in the collection. + img : ImageCollection or ndarray + Imagecollection of the selected images or an ndarray if a single + image is specified. """ - n = self._check_imgnum(n) - idx = n % len(self.data) + if type(n) not in [int, slice]: + raise TypeError('slicing must be an int or slice object') + + if type(n) is int: + n = self._check_imgnum(n) + idx = n % len(self.data) - if (self.conserve_memory and n != self._cached) or \ - (self.data[idx] is None): - self.data[idx] = self.load_func(self.files[n]) - self._cached = n + if (self.conserve_memory and n != self._cached) or \ + (self.data[idx] is None): + self.data[idx] = self.load_func(self.files[n]) + self._cached = n - return self.data[idx] + return self.data[idx] + + else: # slice object was provided + fidx = range(len(self.files))[n] + fidx.sort() + if len(fidx) == 1: # only one item requested + return self.__getitem__(fidx[0]) + else: + # create a new ImageCollection object, any loaded image data + # in the original ImageCollection will be copied by reference + # to the new object. Image data loaded after this creation + # are not linked. + newIC = copy(self) + newIC._files = [self.files[i] for i in fidx] + if self.conserve_memory: + if self._cached in fidx: + newIC._cached = fidx[self._cached] + newIC.data = np.copy(self.data) + else: + newIC.data = np.empty(1, dtype=object) + else: + newIC.data = self.data[fidx] + + return newIC def _check_imgnum(self, n): """Check that the given image number is valid.""" From 5101aa2a389c005e3be0eba22c5c5c168493fcf4 Mon Sep 17 00:00:00 2001 From: "Jonathan J. Helmus" Date: Fri, 20 Jul 2012 15:23:25 -0400 Subject: [PATCH 2/4] added test for ImageCollection slicing --- skimage/io/tests/test_collection.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/skimage/io/tests/test_collection.py b/skimage/io/tests/test_collection.py index 0d420ae7..36e78e13 100644 --- a/skimage/io/tests/test_collection.py +++ b/skimage/io/tests/test_collection.py @@ -43,6 +43,12 @@ class TestImageCollection(): assert_raises(IndexError, return_img, num) assert_raises(IndexError, return_img, -num - 1) + def test_slicing(self): + assert type(self.collection[:] is ImageCollection) + assert len(self.collection[:]) == 2 + assert_array_almost_equal(self.collection[0], self.collection[:1]) + assert_array_almost_equal(self.collection[1], self.collection[1:]) + def test_files_property(self): assert isinstance(self.collection.files, list) From dceb7b6c7d80654cebb8b0aaefb1e8fd95e9b704 Mon Sep 17 00:00:00 2001 From: "Jonathan J. Helmus" Date: Fri, 20 Jul 2012 15:39:40 -0400 Subject: [PATCH 3/4] variable name changes and small fixes --- skimage/io/collection.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/skimage/io/collection.py b/skimage/io/collection.py index e83a5b18..a78dbd14 100644 --- a/skimage/io/collection.py +++ b/skimage/io/collection.py @@ -267,8 +267,11 @@ class ImageCollection(object): Imagecollection of the selected images or an ndarray if a single image is specified. """ + if hasattr(n, '__index__'): + n = n.__index__() + if type(n) not in [int, slice]: - raise TypeError('slicing must be an int or slice object') + raise TypeError('slicing must be with an int or slice object') if type(n) is int: n = self._check_imgnum(n) @@ -283,7 +286,6 @@ class ImageCollection(object): else: # slice object was provided fidx = range(len(self.files))[n] - fidx.sort() if len(fidx) == 1: # only one item requested return self.__getitem__(fidx[0]) else: @@ -291,18 +293,19 @@ class ImageCollection(object): # in the original ImageCollection will be copied by reference # to the new object. Image data loaded after this creation # are not linked. - newIC = copy(self) - newIC._files = [self.files[i] for i in fidx] + fidx.sort() + new_ic = copy(self) + new_ic._files = [self.files[i] for i in fidx] if self.conserve_memory: if self._cached in fidx: - newIC._cached = fidx[self._cached] - newIC.data = np.copy(self.data) + new_ic._cached = fidx[self._cached] + new_ic.data = np.copy(self.data) else: - newIC.data = np.empty(1, dtype=object) + new_ic.data = np.empty(1, dtype=object) else: - newIC.data = self.data[fidx] + new_ic.data = self.data[fidx] - return newIC + return new_ic def _check_imgnum(self, n): """Check that the given image number is valid.""" From 03d037d0443a65af4ec73bfe5e217fa95af7477c Mon Sep 17 00:00:00 2001 From: Jonathan Helmus Date: Wed, 25 Jul 2012 11:11:25 -0400 Subject: [PATCH 4/4] ImageCollection now slices like other iterables --- skimage/io/collection.py | 47 +++++++++++++---------------- skimage/io/tests/test_collection.py | 10 ++++-- 2 files changed, 28 insertions(+), 29 deletions(-) diff --git a/skimage/io/collection.py b/skimage/io/collection.py index a78dbd14..9908c30d 100644 --- a/skimage/io/collection.py +++ b/skimage/io/collection.py @@ -258,14 +258,15 @@ class ImageCollection(object): Parameters ---------- n : int or slice - Slice selecting images for the new ImageCollection or the image - number to be returned. + The image number to be returned, or a slice selecting the images + and ordering to be returned in a new ImageCollection. Returns ------- - img : ImageCollection or ndarray - Imagecollection of the selected images or an ndarray if a single - image is specified. + img : ndarray or ImageCollection. + The `n`-th image in the collection, or a new ImageCollection with + the selected images. + """ if hasattr(n, '__index__'): n = n.__index__() @@ -283,29 +284,23 @@ class ImageCollection(object): self._cached = n return self.data[idx] - - else: # slice object was provided + else: + # A slice object was provided, so create a new ImageCollection + # object. Any loaded image data in the original ImageCollection + # will be copied by reference to the new object. Image data + # loaded after this creation is not linked. fidx = range(len(self.files))[n] - if len(fidx) == 1: # only one item requested - return self.__getitem__(fidx[0]) - else: - # create a new ImageCollection object, any loaded image data - # in the original ImageCollection will be copied by reference - # to the new object. Image data loaded after this creation - # are not linked. - fidx.sort() - new_ic = copy(self) - new_ic._files = [self.files[i] for i in fidx] - if self.conserve_memory: - if self._cached in fidx: - new_ic._cached = fidx[self._cached] - new_ic.data = np.copy(self.data) - else: - new_ic.data = np.empty(1, dtype=object) + new_ic = copy(self) + new_ic._files = [self.files[i] for i in fidx] + if self.conserve_memory: + if self._cached in fidx: + new_ic._cached = fidx.index(self._cached) + new_ic.data = np.copy(self.data) else: - new_ic.data = self.data[fidx] - - return new_ic + new_ic.data = np.empty(1, dtype=object) + else: + new_ic.data = self.data[fidx] + return new_ic def _check_imgnum(self, n): """Check that the given image number is valid.""" diff --git a/skimage/io/tests/test_collection.py b/skimage/io/tests/test_collection.py index 36e78e13..9db28ff7 100644 --- a/skimage/io/tests/test_collection.py +++ b/skimage/io/tests/test_collection.py @@ -44,10 +44,14 @@ class TestImageCollection(): assert_raises(IndexError, return_img, -num - 1) def test_slicing(self): - assert type(self.collection[:] is ImageCollection) + assert type(self.collection[:]) is ImageCollection assert len(self.collection[:]) == 2 - assert_array_almost_equal(self.collection[0], self.collection[:1]) - assert_array_almost_equal(self.collection[1], self.collection[1:]) + assert len(self.collection[:1]) == 1 + assert len(self.collection[1:]) == 1 + assert_array_almost_equal(self.collection[0], self.collection[:1][0]) + assert_array_almost_equal(self.collection[1], self.collection[1:][0]) + assert_array_almost_equal(self.collection[1], self.collection[::-1][0]) + assert_array_almost_equal(self.collection[0], self.collection[::-1][1]) def test_files_property(self): assert isinstance(self.collection.files, list)