diff --git a/skimage/io/collection.py b/skimage/io/collection.py index 1e31bd1d..a2570f52 100644 --- a/skimage/io/collection.py +++ b/skimage/io/collection.py @@ -5,6 +5,7 @@ from __future__ import with_statement __all__ = ['MultiImage', 'ImageCollection', 'imread', 'concatenate_images'] from glob import glob +import re import numpy as np from ._io import imread @@ -39,6 +40,30 @@ def concatenate_images(ic): return ar +def alphanumeric_key(s): + """Convert string to list of strings and ints that gives intuitive sorting. + + Parameters + ---------- + s: string + + Returns + ------- + k: a list of strings and ints + + Examples + -------- + >>> alphanumeric_key('z23a') + ['z', 23, 'a'] + >>> filenames = ['f9.10.png', 'f9.9.png', 'f10.10.png', 'f10.9.png'] + >>> sorted(filenames) + ['f10.10.png', 'f10.9.png', 'f9.10.png', 'f9.9.png', 'e10.png'] + >>> sorted(filenames, key=alphanumeric_key) + ['e10.png', 'f9.9.png', 'f9.10.png', 'f10.9.png', 'f10.10.png'] + """ + k = [int(c) if c.isdigit() else c for c in re.split('([0-9]+)', s)] + return k + class MultiImage(object): """A class containing a single multi-frame image. @@ -260,7 +285,7 @@ class ImageCollection(object): (128, 128, 3) >>> ic = io.ImageCollection('/tmp/work/*.png:/tmp/other/*.jpg') - + """ def __init__(self, load_pattern, conserve_memory=True, load_func=None): """Load and manage a collection of images.""" @@ -269,7 +294,7 @@ class ImageCollection(object): self._files = [] for pattern in load_pattern: self._files.extend(glob(pattern)) - self._files.sort() + self._files = sorted(self._files, key=alphanumeric_key) else: self._files = load_pattern diff --git a/skimage/io/tests/test_collection.py b/skimage/io/tests/test_collection.py index 9dd266bf..219e2146 100644 --- a/skimage/io/tests/test_collection.py +++ b/skimage/io/tests/test_collection.py @@ -7,6 +7,7 @@ from numpy.testing.decorators import skipif from skimage import data_dir from skimage.io import ImageCollection, MultiImage +from skimage.io.collection import alphanumeric_key try: @@ -19,6 +20,23 @@ else: if sys.version_info[0] > 2: basestring = str +class TestAlphanumericKey(): + def setUp(self): + self.test_string = 'z23a' + self.test_str_result = ['z', 23, 'a'] + self.filenames = ['f9.10.png', 'f9.9.png', 'f10.10.png', 'f10.9.png', + 'e9.png', 'e10.png', 'em.png'] + self.sorted_filenames = \ + ['e9.png', 'e10.png', 'em.png', 'f9.9.png', 'f9.10.png', + 'f10.9.png', 'f10.10.png'] + + def test_string_split(self): + assert_equal(alphanumeric_key(self.test_string), self.test_str_result) + + def test_string_sort(self): + sorted_filenames = sorted(self.filenames, key=alphanumeric_key) + assert_equal(sorted_filenames, self.sorted_filenames) + class TestImageCollection(): pattern = [os.path.join(data_dir, pic) for pic in ['camera.png',